mirror of
https://github.com/mosip/inji-wallet.git
synced 2026-01-09 13:38:01 -05:00
[INJIMOB-1240] : Fix face auth consent for minified view share (#1397)
* [INJIMOB-1240] Resolve conflicts Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com> * [INJIMOB-1240] Refactor scan machine and QrLogin machine Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com> * [INJIMOB-1240] Refactor scan machine and QrLogin machine Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com> * [INJIMOB-1240] Refactor scan machine and QrLogin machine Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com> * [INJIMOB-1240]: Fix.Share with selfie pop up bug Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com> * [INJIMOB-1240]: Refactor. scanMachine and qrLoginMachine Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com> * [INJIMOB-1240]: Refactor. scanMachine and qrLoginMachine Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com> --------- Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
This commit is contained in:
@@ -21,7 +21,7 @@ import {ScanEvents} from '../machines/bleShare/scan/scanMachine';
|
|||||||
import {BOTTOM_TAB_ROUTES, ScanStackParamList} from '../routes/routesConstants';
|
import {BOTTOM_TAB_ROUTES, ScanStackParamList} from '../routes/routesConstants';
|
||||||
import {NavigationProp, useNavigation} from '@react-navigation/native';
|
import {NavigationProp, useNavigation} from '@react-navigation/native';
|
||||||
import {MainBottomTabParamList} from '../routes/main';
|
import {MainBottomTabParamList} from '../routes/main';
|
||||||
import {selectIsScanning} from '../machines/bleShare/scan/selectors';
|
import {selectIsScanning} from '../machines/bleShare/scan/scanSelectors';
|
||||||
import {
|
import {
|
||||||
VCItemEvents,
|
VCItemEvents,
|
||||||
VCItemMachine,
|
VCItemMachine,
|
||||||
|
|||||||
@@ -34,10 +34,10 @@
|
|||||||
"verifyCredential": "done.invoke.issuersMachine.verifyingCredential:invocation[0]";
|
"verifyCredential": "done.invoke.issuersMachine.verifyingCredential:invocation[0]";
|
||||||
};
|
};
|
||||||
missingImplementations: {
|
missingImplementations: {
|
||||||
actions: never;
|
actions: "getKeyPairFromStore" | "loadKeyPair" | "logDownloaded" | "resetError" | "resetLoadingReason" | "resetVerificationErrorMessage" | "sendBackupEvent" | "sendErrorEndEvent" | "sendImpressionEvent" | "sendSuccessEndEvent" | "setCredentialTypes" | "setCredentialWrapper" | "setError" | "setIssuers" | "setLoadingReasonAsDisplayIssuers" | "setLoadingReasonAsDownloadingCredentials" | "setLoadingReasonAsSettingUp" | "setMetadataInCredentialData" | "setNoInternet" | "setOIDCConfigError" | "setPrivateKey" | "setPublicKey" | "setSelectedCredentialType" | "setSelectedIssuerId" | "setSelectedIssuers" | "setTokenResponse" | "setVCMetadata" | "setVerifiableCredential" | "storeKeyPair" | "storeVcMetaContext" | "storeVcsContext" | "storeVerifiableCredentialData" | "storeVerifiableCredentialMeta" | "updateVerificationErrorMessage";
|
||||||
delays: never;
|
delays: never;
|
||||||
guards: never;
|
guards: "canSelectIssuerAgain" | "hasKeyPair" | "hasUserCancelledBiometric" | "isCustomSecureKeystore" | "isInternetConnected" | "isMultipleCredentialsSupported" | "isOIDCConfigError" | "isOIDCflowCancelled" | "isSignedIn" | "shouldFetchIssuersAgain";
|
||||||
services: never;
|
services: "checkInternet" | "downloadCredential" | "downloadCredentialTypes" | "downloadIssuerConfig" | "downloadIssuersList" | "generateKeyPair" | "invokeAuthorization" | "isUserSignedAlready" | "verifyCredential";
|
||||||
};
|
};
|
||||||
eventsCausingActions: {
|
eventsCausingActions: {
|
||||||
"getKeyPairFromStore": "TRY_AGAIN" | "done.invoke.issuersMachine.performAuthorization:invocation[0]";
|
"getKeyPairFromStore": "TRY_AGAIN" | "done.invoke.issuersMachine.performAuthorization:invocation[0]";
|
||||||
|
|||||||
170
machines/QrLogin/QrLoginActions.ts
Normal file
170
machines/QrLogin/QrLoginActions.ts
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
import { assign, send, sendParent } from "xstate";
|
||||||
|
import i18n from "../../i18n";
|
||||||
|
import { VCShareFlowType } from "../../shared/Utils";
|
||||||
|
import { parseMetadatas } from "../../shared/VCMetadata";
|
||||||
|
import { SHOW_FACE_AUTH_CONSENT_QR_LOGIN_FLOW, MY_VCS_STORE_KEY } from "../../shared/constants";
|
||||||
|
import { getBindingCertificateConstant } from "../../shared/keystore/SecureKeystore";
|
||||||
|
import { VC, linkTransactionResponse } from "../VerifiableCredential/VCMetaMachine/vc";
|
||||||
|
import { StoreEvents } from "../store";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const QrLoginActions=(model:any)=>{
|
||||||
|
|
||||||
|
return{
|
||||||
|
setShowFaceAuthConsent: model.assign({
|
||||||
|
showFaceAuthConsent: (_, event) => {
|
||||||
|
return !event.isDoNotAskAgainChecked;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
storeShowFaceAuthConsent: send(
|
||||||
|
(context, event) =>
|
||||||
|
StoreEvents.SET(SHOW_FACE_AUTH_CONSENT_QR_LOGIN_FLOW, !event.isDoNotAskAgainChecked),
|
||||||
|
{
|
||||||
|
to: context => context.serviceRefs.store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
forwardToParent: sendParent('DISMISS'),
|
||||||
|
|
||||||
|
setScanData: model.assign((context, event) => {
|
||||||
|
const linkCode = event.linkCode;
|
||||||
|
const flowType = event.flowType;
|
||||||
|
const selectedVc = event.selectedVc;
|
||||||
|
return {
|
||||||
|
...context,
|
||||||
|
linkCode: linkCode,
|
||||||
|
flowType: flowType,
|
||||||
|
selectedVc: selectedVc,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
getFaceAuthConsent: send(StoreEvents.GET(SHOW_FACE_AUTH_CONSENT_QR_LOGIN_FLOW), {
|
||||||
|
to: (context:any) => context.serviceRefs.store,
|
||||||
|
}),
|
||||||
|
|
||||||
|
updateShowFaceAuthConsent: model.assign({
|
||||||
|
showFaceAuthConsent: (_, event) => {
|
||||||
|
return event.response || event.response === null;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
// TODO: loaded VCMetadatas are not used anywhere. remove?
|
||||||
|
loadMyVcs: send(StoreEvents.GET(MY_VCS_STORE_KEY), {
|
||||||
|
to: context => context.serviceRefs.store,
|
||||||
|
}),
|
||||||
|
|
||||||
|
setMyVcs: model.assign({
|
||||||
|
myVcs: (_context, event) =>
|
||||||
|
parseMetadatas((event.response || []) as object[]),
|
||||||
|
}),
|
||||||
|
|
||||||
|
loadThumbprint: send(
|
||||||
|
context =>
|
||||||
|
StoreEvents.GET(
|
||||||
|
getBindingCertificateConstant(
|
||||||
|
context.selectedVc.walletBindingResponse?.walletBindingId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
{to: context => context.serviceRefs.store},
|
||||||
|
),
|
||||||
|
setThumbprint: assign({
|
||||||
|
thumbprint: (_context, event) => {
|
||||||
|
return (event.response || '') as string;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
resetLinkTransactionId: model.assign({
|
||||||
|
linkTransactionId: () => '',
|
||||||
|
}),
|
||||||
|
|
||||||
|
resetSelectedVoluntaryClaims: model.assign({
|
||||||
|
selectedVoluntaryClaims: () => [],
|
||||||
|
}),
|
||||||
|
|
||||||
|
setSelectedVc: assign({
|
||||||
|
selectedVc: (context, event) => {
|
||||||
|
return {...event.vc};
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
resetSelectedVc: assign({
|
||||||
|
selectedVc: {} as VC,
|
||||||
|
}),
|
||||||
|
|
||||||
|
resetFlowType: assign({
|
||||||
|
flowType: VCShareFlowType.SIMPLE_SHARE,
|
||||||
|
}),
|
||||||
|
|
||||||
|
setlinkTransactionResponse: assign({
|
||||||
|
linkTransactionResponse: (context, event) =>
|
||||||
|
event.data as linkTransactionResponse,
|
||||||
|
}),
|
||||||
|
|
||||||
|
expandLinkTransResp: assign({
|
||||||
|
authFactors: context => context.linkTransactionResponse.authFactors,
|
||||||
|
|
||||||
|
authorizeScopes: context =>
|
||||||
|
context.linkTransactionResponse.authorizeScopes,
|
||||||
|
|
||||||
|
clientName: context => context.linkTransactionResponse.clientName,
|
||||||
|
|
||||||
|
configs: context => context.linkTransactionResponse.configs,
|
||||||
|
|
||||||
|
essentialClaims: context =>
|
||||||
|
context.linkTransactionResponse.essentialClaims,
|
||||||
|
|
||||||
|
linkTransactionId: context =>
|
||||||
|
context.linkTransactionResponse.linkTransactionId,
|
||||||
|
|
||||||
|
logoUrl: context => context.linkTransactionResponse.logoUrl,
|
||||||
|
|
||||||
|
voluntaryClaims: context =>
|
||||||
|
context.linkTransactionResponse.voluntaryClaims,
|
||||||
|
}),
|
||||||
|
|
||||||
|
setClaims: context => {
|
||||||
|
context.voluntaryClaims.map(claim => {
|
||||||
|
context.isSharing[claim] = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
SetErrorMessage: assign({
|
||||||
|
errorMessage: (context, event) => {
|
||||||
|
const message = event.data.name;
|
||||||
|
const ID_ERRORS_MAP = {
|
||||||
|
invalid_link_code: 'invalidQR',
|
||||||
|
};
|
||||||
|
const errorMessage = ID_ERRORS_MAP[message]
|
||||||
|
? i18n.t(`errors.${ID_ERRORS_MAP[message]}`, {
|
||||||
|
ns: 'QrLogin',
|
||||||
|
})
|
||||||
|
: i18n.t(`errors.genericError`, {
|
||||||
|
ns: 'common',
|
||||||
|
});
|
||||||
|
|
||||||
|
return errorMessage;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
setConsentClaims: assign({
|
||||||
|
isSharing: (context, event) => {
|
||||||
|
context.isSharing[event.claim] = !event.enable;
|
||||||
|
if (!event.enable) {
|
||||||
|
context.selectedVoluntaryClaims.push(event.claim);
|
||||||
|
} else {
|
||||||
|
context.selectedVoluntaryClaims =
|
||||||
|
context.selectedVoluntaryClaims.filter(
|
||||||
|
eachClaim => eachClaim !== event.claim,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {...context.isSharing};
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
setLinkedTransactionId: assign({
|
||||||
|
linkedTransactionId: (context, event) =>
|
||||||
|
event.data.linkedTransactionId as string,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
13
machines/QrLogin/QrLoginGuards.ts
Normal file
13
machines/QrLogin/QrLoginGuards.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { VCShareFlowType } from "../../shared/Utils";
|
||||||
|
|
||||||
|
export const QrLoginGuards={
|
||||||
|
showFaceAuthConsentScreen: context => {
|
||||||
|
return context.showFaceAuthConsent;
|
||||||
|
},
|
||||||
|
|
||||||
|
isConsentAlreadyCaptured: (_, event) =>
|
||||||
|
event.data?.consentAction === 'NOCAPTURE',
|
||||||
|
|
||||||
|
isSimpleShareFlow: (context, _event) =>
|
||||||
|
context.flowType === VCShareFlowType.SIMPLE_SHARE,
|
||||||
|
}
|
||||||
277
machines/QrLogin/QrLoginMachine.ts
Normal file
277
machines/QrLogin/QrLoginMachine.ts
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
import {
|
||||||
|
ActorRefFrom,
|
||||||
|
EventFrom
|
||||||
|
} from 'xstate';
|
||||||
|
import { AppServices } from '../../shared/GlobalContext';
|
||||||
|
import { TelemetryConstants } from '../../shared/telemetry/TelemetryConstants';
|
||||||
|
import {
|
||||||
|
getEndEventData,
|
||||||
|
sendEndEvent,
|
||||||
|
} from '../../shared/telemetry/TelemetryUtils';
|
||||||
|
import { QrLoginActions } from './QrLoginActions';
|
||||||
|
import { QrLoginmodel } from './QrLoginModel';
|
||||||
|
import { QrLoginServices } from './QrLoginServices';
|
||||||
|
import { QrLoginGuards } from './QrLoginGuards';
|
||||||
|
|
||||||
|
const model = QrLoginmodel;
|
||||||
|
|
||||||
|
export const QrLoginEvents = model.events;
|
||||||
|
export type QrLoginRef = ActorRefFrom<typeof qrLoginMachine>;
|
||||||
|
|
||||||
|
export const qrLoginMachine =
|
||||||
|
/** @xstate-layout N4IgpgJg5mDOIC5QEUBOAZA9lAlgOwDocIAbMAYgGUBhAQQDl6BJegcQH0ARAeXoFEA2gAYAuolAAHTLBwAXHJjziQAD0QBGACzqATAQCs+nZv0BmABzqL50zoA0IAJ6IA7KaEFNATnPmv6oUMhHUMAX1CHNCxcQmIyck4mSgBZJMphMSQQKRl5RWU1BF1zFwIvHQrTFxdNCxcANgdnBH16j1NbdT8vfW8q9XDIjGx8AhJ8AGsAFVQAQzxYWYBjPLxyCEUwIjwAN0wJraiRwnG8abmF5dWEfD2l2dWMjOUcuQUlLMKtXQMjEwsrL5bE1EF4XOYCEJ6iEXF4ekIOppzIMQEcYmNJjN5osVu9yGBUKhMKgCBISA8AGbEgC2BDRo1O52xV3eN12mHuj1Ezyyr1WBQ0JQhmlhotMZmM+hcIIQNX0nnUhh65h06hcOhKKPphFgAAtMAB3ADqs1QeHwUHI1F4ADEmAAlZI8yTSN75T6IEIeHT+eo1Lyaeriwwy+pggiwtXw9SKjU6LXDdF6w0ms0Wq0Mah8dDO7Ku-kehBegg+9R+7yB4P6GV+dQRlwBIRqoTqjX1BPRUaUfUGviE4kZ+hZnOiF7594Coo9TSQtyqqUx9zApyINpeCNIoVaYzlUwd45jTCzCDJRwANSWsCoU249r47DvlAACrxKIJR7zx+7QIU-fLofoMaATYWjaKGLjylCOjQi4gSmJoOgNPuSY9jsSzoDgsCyFQ2Z8NQUzsGe1C5nyE6Fr4M4BkI3j6DYtEttWK4tDGEb1H6DbmEYAZschozJgaaEYVh5Bnnw9pMDaACaJFfh8P6uLRZRIoqKl0UI5gyiK9SQtobjUZu0KaLxOqoehmHYYkKRpDJuRkfJRTqRCpj1PoTYBj01QVKGPwVIBHT6AGqq1MZBAUssYC0AArrIurkDatBZoRtDoEwnA2W6cmqJ6rklr6-qVoYjHNP4kI2Jo1ENr01EBiFYVLBF0WxfFiUsGeyWpelBb2cWpbltxVahiKuVqmGXT1IG6heLV4VRTFg7Dp1dlZUWOW9flQaFTW2glrBYK0SqZaqiFtyzOMEBMBAYB4PIsiOAkSSpJQ6Qfi6tnfstf4EABQFdKYoHqKG1EECUrnmEIcJ+FC7YRKiiajCdZ0XVdN13XeUz2pJhFiRJTB0FMTC8It72FD1eUVhtIZMQF2mRjUHT1FYPTQ0MnaEKgYAAI6RXAsjUIosDI1atoOk6L15m9mW-hBX0hD9IGaGBTEIfKvTNoGOhVF4zOw6zBDs1zPN8wsgt0EO2ZE5Lq7S99ql-QrANMe4M6RqNDa6NC5hGTD2oEBseAUJZj3PZkr0ZZOAS+AQzmuZNNGefYSshAYunUdCmvaz7+vc1hFpGwL13rJs2x7AcdJw2znPZ-IeBQHnyNsncDzvE8YukcTq42GUYYtuNgFsQGMqqnWNjwSNiFeACe7e+XeuVzzuf84LBJEiSZKUjSZe61n8813X10NxyTeKC3Ifi2HhYR05LluXHrY1qYO2OanY1sciKJ4Jgl3wFk2pjhLk4AFpGhMQAfKOE4CIGQKnizA8cQwB-3PvZYoEJVT+FVCUaC-hNDeXlDYCoipwRCCIeKEKjIsSXFxO9NulsiguWdpYIMQZoK9F6DKOmX0FYQSITHHoU1p6634qmc0NcEFdWWghNh4MCBlnqGDLQ7EAxvxgeibsho+wr1EUtEmLYIQqmjvbeCKoiqrgCCWTc4JtzeA1qQo8J5zyXk0e3BAIph7jTYvBQIwQLDgWdv4Bo5UkTqjMCFfiglzKOJoX4bS4oGyIR9FUIhCdmgMz0EEqw4pApaGgTrA8dUGoxQiZOGoX0Si1CDFYAKCEkkaChKVUeHQNYNGosdXYp1iBI2unIZoocxGFCRHoKU40VT+H2n4QG8oqig3Bj4LwUIXAhW3lhPeshCmFiROucqhlYK6AXA7Zoxg6wTwgv09JHRfAhT9vAz8-9Cz+HXJUxUCIzBIiRJpaCOkRoNlMGCME8EFlzxzrvRe11Vn2RBtI1oDM-pGAsF4GsdZXJEI8n8Go41wjhCAA */
|
||||||
|
model.createMachine(
|
||||||
|
{
|
||||||
|
predictableActionArguments: true,
|
||||||
|
preserveActionOrder: true,
|
||||||
|
tsTypes: {} as import('./QrLoginMachine.typegen').Typegen0,
|
||||||
|
schema: {
|
||||||
|
context: model.initialContext,
|
||||||
|
events: {} as EventFrom<typeof model>,
|
||||||
|
},
|
||||||
|
id: 'QrLogin',
|
||||||
|
initial: 'waitingForData',
|
||||||
|
entry: ['resetSelectedVc', 'resetFlowType'],
|
||||||
|
states: {
|
||||||
|
waitingForData: {
|
||||||
|
on: {
|
||||||
|
GET: {
|
||||||
|
actions: [
|
||||||
|
'setScanData',
|
||||||
|
'resetLinkTransactionId',
|
||||||
|
'resetSelectedVoluntaryClaims',
|
||||||
|
],
|
||||||
|
target: 'checkFaceAuthConsent',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
checkFaceAuthConsent: {
|
||||||
|
entry: 'getFaceAuthConsent',
|
||||||
|
on: {
|
||||||
|
STORE_RESPONSE: {
|
||||||
|
actions: 'updateShowFaceAuthConsent',
|
||||||
|
target: 'linkTransaction',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
linkTransaction: {
|
||||||
|
invoke: {
|
||||||
|
src: 'linkTransaction',
|
||||||
|
onDone: [
|
||||||
|
{
|
||||||
|
cond: 'isSimpleShareFlow',
|
||||||
|
actions: [
|
||||||
|
'setlinkTransactionResponse',
|
||||||
|
'expandLinkTransResp',
|
||||||
|
'setClaims',
|
||||||
|
],
|
||||||
|
target: 'loadMyVcs',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cond: 'showFaceAuthConsentScreen',
|
||||||
|
target: 'faceVerificationConsent',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actions: [
|
||||||
|
'setlinkTransactionResponse',
|
||||||
|
'expandLinkTransResp',
|
||||||
|
'setClaims',
|
||||||
|
],
|
||||||
|
target: 'faceAuth',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
onError: [
|
||||||
|
{
|
||||||
|
actions: 'SetErrorMessage',
|
||||||
|
target: 'ShowError',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ShowError: {
|
||||||
|
on: {
|
||||||
|
DISMISS: {
|
||||||
|
actions: 'forwardToParent',
|
||||||
|
target: 'waitingForData',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
loadMyVcs: {
|
||||||
|
entry: 'loadMyVcs',
|
||||||
|
on: {
|
||||||
|
STORE_RESPONSE: {
|
||||||
|
actions: 'setMyVcs',
|
||||||
|
target: 'showvcList',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
showvcList: {
|
||||||
|
on: {
|
||||||
|
SELECT_VC: {
|
||||||
|
actions: 'setSelectedVc',
|
||||||
|
},
|
||||||
|
VERIFY: [
|
||||||
|
{
|
||||||
|
cond: 'showFaceAuthConsentScreen',
|
||||||
|
target: 'faceVerificationConsent',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
target: 'faceAuth',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
DISMISS: {
|
||||||
|
actions: 'forwardToParent',
|
||||||
|
target: 'waitingForData',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
faceVerificationConsent: {
|
||||||
|
on: {
|
||||||
|
FACE_VERIFICATION_CONSENT: {
|
||||||
|
actions: ['storeShowFaceAuthConsent', 'setShowFaceAuthConsent'],
|
||||||
|
target: 'faceAuth',
|
||||||
|
},
|
||||||
|
DISMISS: [{
|
||||||
|
cond:'isSimpleShareFlow',
|
||||||
|
target: 'showvcList',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actions: 'forwardToParent',
|
||||||
|
target: 'waitingForData',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
faceAuth: {
|
||||||
|
on: {
|
||||||
|
FACE_VALID: {
|
||||||
|
target: 'loadingThumbprint',
|
||||||
|
},
|
||||||
|
FACE_INVALID: {
|
||||||
|
target: 'invalidIdentity',
|
||||||
|
},
|
||||||
|
CANCEL: [
|
||||||
|
{
|
||||||
|
cond: 'isSimpleShareFlow',
|
||||||
|
target: 'showvcList',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actions: 'forwardToParent',
|
||||||
|
target: 'waitingForData',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
invalidIdentity: {
|
||||||
|
on: {
|
||||||
|
DISMISS: [
|
||||||
|
{
|
||||||
|
cond: 'isSimpleShareFlow',
|
||||||
|
target: 'showvcList',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actions: 'forwardToParent',
|
||||||
|
target: 'waitingForData',
|
||||||
|
},
|
||||||
|
,],
|
||||||
|
RETRY_VERIFICATION: {
|
||||||
|
target: 'faceAuth',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sendingAuthenticate: {
|
||||||
|
invoke: {
|
||||||
|
src: 'sendAuthenticate',
|
||||||
|
onDone: [
|
||||||
|
{
|
||||||
|
cond: 'isConsentAlreadyCaptured',
|
||||||
|
target: 'success',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
target: 'requestConsent',
|
||||||
|
actions: 'setLinkedTransactionId',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
onError: [
|
||||||
|
{
|
||||||
|
actions: 'SetErrorMessage',
|
||||||
|
target: 'ShowError',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
requestConsent: {
|
||||||
|
on: {
|
||||||
|
CONFIRM: {
|
||||||
|
target: 'sendingConsent',
|
||||||
|
},
|
||||||
|
TOGGLE_CONSENT_CLAIM: {
|
||||||
|
actions: 'setConsentClaims',
|
||||||
|
target: 'requestConsent',
|
||||||
|
},
|
||||||
|
DISMISS: {
|
||||||
|
actions: 'forwardToParent',
|
||||||
|
target: 'waitingForData',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
loadingThumbprint: {
|
||||||
|
entry: 'loadThumbprint',
|
||||||
|
on: {
|
||||||
|
STORE_RESPONSE: {
|
||||||
|
actions: 'setThumbprint',
|
||||||
|
target: 'sendingAuthenticate',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sendingConsent: {
|
||||||
|
invoke: {
|
||||||
|
src: 'sendConsent',
|
||||||
|
onDone: {
|
||||||
|
target: 'success',
|
||||||
|
},
|
||||||
|
onError: [
|
||||||
|
{
|
||||||
|
actions: 'SetErrorMessage',
|
||||||
|
target: 'ShowError',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
entry: [
|
||||||
|
() =>
|
||||||
|
sendEndEvent(
|
||||||
|
getEndEventData(
|
||||||
|
TelemetryConstants.FlowType.qrLogin,
|
||||||
|
TelemetryConstants.EndEventStatus.success,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
on: {
|
||||||
|
CONFIRM: {
|
||||||
|
target: 'done',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
done: {
|
||||||
|
type: 'final',
|
||||||
|
data: context => context,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actions:QrLoginActions(model),
|
||||||
|
services:QrLoginServices,
|
||||||
|
guards: QrLoginGuards,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export function createQrLoginMachine(serviceRefs: AppServices) {
|
||||||
|
return qrLoginMachine.withContext({
|
||||||
|
...qrLoginMachine.context,
|
||||||
|
serviceRefs,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
64
machines/QrLogin/QrLoginMachine.typegen.ts
Normal file
64
machines/QrLogin/QrLoginMachine.typegen.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
// This file was automatically generated. Edits will be overwritten
|
||||||
|
|
||||||
|
export interface Typegen0 {
|
||||||
|
'@@xstate/typegen': true;
|
||||||
|
internalEvents: {
|
||||||
|
"done.invoke.QrLogin.linkTransaction:invocation[0]": { type: "done.invoke.QrLogin.linkTransaction:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
|
"done.invoke.QrLogin.sendingAuthenticate:invocation[0]": { type: "done.invoke.QrLogin.sendingAuthenticate:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
|
"error.platform.QrLogin.linkTransaction:invocation[0]": { type: "error.platform.QrLogin.linkTransaction:invocation[0]"; data: unknown };
|
||||||
|
"error.platform.QrLogin.sendingAuthenticate:invocation[0]": { type: "error.platform.QrLogin.sendingAuthenticate:invocation[0]"; data: unknown };
|
||||||
|
"error.platform.QrLogin.sendingConsent:invocation[0]": { type: "error.platform.QrLogin.sendingConsent:invocation[0]"; data: unknown };
|
||||||
|
"xstate.init": { type: "xstate.init" };
|
||||||
|
};
|
||||||
|
invokeSrcNameMap: {
|
||||||
|
"linkTransaction": "done.invoke.QrLogin.linkTransaction:invocation[0]";
|
||||||
|
"sendAuthenticate": "done.invoke.QrLogin.sendingAuthenticate:invocation[0]";
|
||||||
|
"sendConsent": "done.invoke.QrLogin.sendingConsent:invocation[0]";
|
||||||
|
};
|
||||||
|
missingImplementations: {
|
||||||
|
actions: "SetErrorMessage" | "expandLinkTransResp" | "forwardToParent" | "getFaceAuthConsent" | "loadMyVcs" | "loadThumbprint" | "resetFlowType" | "resetLinkTransactionId" | "resetSelectedVc" | "resetSelectedVoluntaryClaims" | "setClaims" | "setConsentClaims" | "setLinkedTransactionId" | "setMyVcs" | "setScanData" | "setSelectedVc" | "setShowFaceAuthConsent" | "setThumbprint" | "setlinkTransactionResponse" | "storeShowFaceAuthConsent" | "updateShowFaceAuthConsent";
|
||||||
|
delays: never;
|
||||||
|
guards: "isConsentAlreadyCaptured" | "isSimpleShareFlow" | "showFaceAuthConsentScreen";
|
||||||
|
services: "linkTransaction" | "sendAuthenticate" | "sendConsent";
|
||||||
|
};
|
||||||
|
eventsCausingActions: {
|
||||||
|
"SetErrorMessage": "error.platform.QrLogin.linkTransaction:invocation[0]" | "error.platform.QrLogin.sendingAuthenticate:invocation[0]" | "error.platform.QrLogin.sendingConsent:invocation[0]";
|
||||||
|
"expandLinkTransResp": "done.invoke.QrLogin.linkTransaction:invocation[0]";
|
||||||
|
"forwardToParent": "CANCEL" | "DISMISS";
|
||||||
|
"getFaceAuthConsent": "GET";
|
||||||
|
"loadMyVcs": "done.invoke.QrLogin.linkTransaction:invocation[0]";
|
||||||
|
"loadThumbprint": "FACE_VALID";
|
||||||
|
"resetFlowType": "xstate.init";
|
||||||
|
"resetLinkTransactionId": "GET";
|
||||||
|
"resetSelectedVc": "xstate.init";
|
||||||
|
"resetSelectedVoluntaryClaims": "GET";
|
||||||
|
"setClaims": "done.invoke.QrLogin.linkTransaction:invocation[0]";
|
||||||
|
"setConsentClaims": "TOGGLE_CONSENT_CLAIM";
|
||||||
|
"setLinkedTransactionId": "done.invoke.QrLogin.sendingAuthenticate:invocation[0]";
|
||||||
|
"setMyVcs": "STORE_RESPONSE";
|
||||||
|
"setScanData": "GET";
|
||||||
|
"setSelectedVc": "SELECT_VC";
|
||||||
|
"setShowFaceAuthConsent": "FACE_VERIFICATION_CONSENT";
|
||||||
|
"setThumbprint": "STORE_RESPONSE";
|
||||||
|
"setlinkTransactionResponse": "done.invoke.QrLogin.linkTransaction:invocation[0]";
|
||||||
|
"storeShowFaceAuthConsent": "FACE_VERIFICATION_CONSENT";
|
||||||
|
"updateShowFaceAuthConsent": "STORE_RESPONSE";
|
||||||
|
};
|
||||||
|
eventsCausingDelays: {
|
||||||
|
|
||||||
|
};
|
||||||
|
eventsCausingGuards: {
|
||||||
|
"isConsentAlreadyCaptured": "done.invoke.QrLogin.sendingAuthenticate:invocation[0]";
|
||||||
|
"isSimpleShareFlow": "CANCEL" | "DISMISS" | "done.invoke.QrLogin.linkTransaction:invocation[0]";
|
||||||
|
"showFaceAuthConsentScreen": "VERIFY" | "done.invoke.QrLogin.linkTransaction:invocation[0]";
|
||||||
|
};
|
||||||
|
eventsCausingServices: {
|
||||||
|
"linkTransaction": "STORE_RESPONSE";
|
||||||
|
"sendAuthenticate": "STORE_RESPONSE";
|
||||||
|
"sendConsent": "CONFIRM";
|
||||||
|
};
|
||||||
|
matchesStates: "ShowError" | "checkFaceAuthConsent" | "done" | "faceAuth" | "faceVerificationConsent" | "invalidIdentity" | "linkTransaction" | "loadMyVcs" | "loadingThumbprint" | "requestConsent" | "sendingAuthenticate" | "sendingConsent" | "showvcList" | "success" | "waitingForData";
|
||||||
|
tags: never;
|
||||||
|
}
|
||||||
|
|
||||||
69
machines/QrLogin/QrLoginModel.ts
Normal file
69
machines/QrLogin/QrLoginModel.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { createModel } from "xstate/lib/model";
|
||||||
|
import { AppServices } from "../../shared/GlobalContext";
|
||||||
|
import { VCShareFlowType } from "../../shared/Utils";
|
||||||
|
import { VCMetadata } from "../../shared/VCMetadata";
|
||||||
|
import { VC, linkTransactionResponse } from "../VerifiableCredential/VCMetaMachine/vc";
|
||||||
|
|
||||||
|
const QrLoginEvents= {
|
||||||
|
SELECT_VC: (vc: VC) => ({vc}),
|
||||||
|
SCANNING_DONE: (params: string) => ({params}),
|
||||||
|
STORE_RESPONSE: (response: unknown) => ({response}),
|
||||||
|
STORE_ERROR: (error: Error) => ({error}),
|
||||||
|
TOGGLE_CONSENT_CLAIM: (enable: boolean, claim: string) => ({
|
||||||
|
enable,
|
||||||
|
claim,
|
||||||
|
}),
|
||||||
|
DISMISS: () => ({}),
|
||||||
|
CONFIRM: () => ({}),
|
||||||
|
GET: (
|
||||||
|
linkCode: string,
|
||||||
|
flowType: string,
|
||||||
|
selectedVc: VC,
|
||||||
|
faceAuthConsentGiven: boolean,
|
||||||
|
) => ({
|
||||||
|
linkCode,
|
||||||
|
flowType,
|
||||||
|
selectedVc,
|
||||||
|
faceAuthConsentGiven,
|
||||||
|
}),
|
||||||
|
VERIFY: () => ({}),
|
||||||
|
CANCEL: () => ({}),
|
||||||
|
FACE_VALID: () => ({}),
|
||||||
|
FACE_INVALID: () => ({}),
|
||||||
|
RETRY_VERIFICATION: () => ({}),
|
||||||
|
FACE_VERIFICATION_CONSENT: (isDoNotAskAgainChecked: boolean) => ({
|
||||||
|
isDoNotAskAgainChecked,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
export const QrLoginmodel = createModel(
|
||||||
|
{
|
||||||
|
serviceRefs: {} as AppServices,
|
||||||
|
selectedVc: {} as VC,
|
||||||
|
linkCode: '',
|
||||||
|
flowType: VCShareFlowType.SIMPLE_SHARE,
|
||||||
|
myVcs: [] as VCMetadata[],
|
||||||
|
thumbprint: '',
|
||||||
|
linkTransactionResponse: {} as linkTransactionResponse,
|
||||||
|
authFactors: [],
|
||||||
|
authorizeScopes: null,
|
||||||
|
clientName: {},
|
||||||
|
configs: {},
|
||||||
|
essentialClaims: [],
|
||||||
|
linkTransactionId: '',
|
||||||
|
logoUrl: '',
|
||||||
|
voluntaryClaims: [],
|
||||||
|
selectedVoluntaryClaims: [],
|
||||||
|
errorMessage: '',
|
||||||
|
domainName: '',
|
||||||
|
consentClaims: ['name', 'picture'],
|
||||||
|
isSharing: {},
|
||||||
|
linkedTransactionId: '',
|
||||||
|
showFaceAuthConsent: true as boolean,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
events:QrLoginEvents,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
117
machines/QrLogin/QrLoginSelectors.ts
Normal file
117
machines/QrLogin/QrLoginSelectors.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { StateFrom } from "xstate";
|
||||||
|
import { getMosipLogo } from "../../components/VC/common/VCUtils";
|
||||||
|
import { VCMetadata } from "../../shared/VCMetadata";
|
||||||
|
import { qrLoginMachine } from "./QrLoginMachine";
|
||||||
|
|
||||||
|
type State = StateFrom<typeof qrLoginMachine>;
|
||||||
|
|
||||||
|
export function selectMyVcs(state: State) {
|
||||||
|
return state.context.myVcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsWaitingForData(state: State) {
|
||||||
|
return state.matches('waitingForData');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectDomainName(state: State) {
|
||||||
|
return state.context.domainName;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsLinkTransaction(state: State) {
|
||||||
|
return state.matches('linkTransaction');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsloadMyVcs(state: State) {
|
||||||
|
return state.matches('loadMyVcs');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsShowingVcList(state: State) {
|
||||||
|
return state.matches('showvcList');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsisVerifyingIdentity(state: State) {
|
||||||
|
return state.matches('faceAuth');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsInvalidIdentity(state: State) {
|
||||||
|
return state.matches('invalidIdentity');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsShowError(state: State) {
|
||||||
|
return state.matches('ShowError');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsRequestConsent(state: State) {
|
||||||
|
return state.matches('requestConsent');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsSendingAuthenticate(state: State) {
|
||||||
|
return state.matches('sendingAuthenticate');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsSendingConsent(state: State) {
|
||||||
|
return state.matches('sendingConsent');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsVerifyingSuccesful(state: State) {
|
||||||
|
return state.matches('success');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectCredential(state: State) {
|
||||||
|
return new VCMetadata(state.context.selectedVc?.vcMetadata).isFromOpenId4VCI()
|
||||||
|
? state.context.selectedVc?.verifiableCredential?.credential
|
||||||
|
: state.context.selectedVc?.credential;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectVerifiableCredentialData(state: State) {
|
||||||
|
const vcMetadata = new VCMetadata(state.context.selectedVc?.vcMetadata);
|
||||||
|
return vcMetadata.isFromOpenId4VCI()
|
||||||
|
? {
|
||||||
|
vcMetadata: vcMetadata,
|
||||||
|
face: state.context.selectedVc?.verifiableCredential?.credential
|
||||||
|
?.credentialSubject?.face,
|
||||||
|
issuerLogo: state.context.selectedVc?.verifiableCredential?.issuerLogo,
|
||||||
|
wellKnown: state.context.selectedVc?.verifiableCredential?.wellKnown,
|
||||||
|
credentialTypes:
|
||||||
|
state.context.selectedVc?.verifiableCredential?.credentialTypes,
|
||||||
|
issuer: vcMetadata.issuer,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
vcMetadata: vcMetadata,
|
||||||
|
issuer: vcMetadata.issuer,
|
||||||
|
face: state.context.selectedVc?.credential?.biometrics?.face,
|
||||||
|
issuerLogo: getMosipLogo(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectLinkTransactionResponse(state: State) {
|
||||||
|
return state.context.linkTransactionResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectEssentialClaims(state: State) {
|
||||||
|
return state.context.essentialClaims;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectVoluntaryClaims(state: State) {
|
||||||
|
return state.context.voluntaryClaims;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectLogoUrl(state: State) {
|
||||||
|
return state.context.logoUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectClientName(state: State) {
|
||||||
|
return state.context.clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectErrorMessage(state: State) {
|
||||||
|
return state.context.errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsSharing(state: State) {
|
||||||
|
return state.context.isSharing;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsFaceVerificationConsent(state: State) {
|
||||||
|
return state.matches('faceVerificationConsent');
|
||||||
|
}
|
||||||
111
machines/QrLogin/QrLoginServices.ts
Normal file
111
machines/QrLogin/QrLoginServices.ts
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import {request} from '../../shared/request';
|
||||||
|
import getAllConfigurations, { API_URLS } from "../../shared/api";
|
||||||
|
import { ESIGNET_BASE_URL } from "../../shared/constants";
|
||||||
|
import { isHardwareKeystoreExists, getJWT } from "../../shared/cryptoutil/cryptoUtil";
|
||||||
|
import { getPrivateKey } from "../../shared/keystore/SecureKeystore";
|
||||||
|
|
||||||
|
export const QrLoginServices= {
|
||||||
|
linkTransaction: async context => {
|
||||||
|
const response = await request(
|
||||||
|
API_URLS.linkTransaction.method,
|
||||||
|
API_URLS.linkTransaction.buildURL(),
|
||||||
|
{
|
||||||
|
requestTime: String(new Date().toISOString()),
|
||||||
|
request: {
|
||||||
|
linkCode: context.linkCode,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ESIGNET_BASE_URL,
|
||||||
|
);
|
||||||
|
return response.response;
|
||||||
|
},
|
||||||
|
|
||||||
|
sendAuthenticate: async context => {
|
||||||
|
let privateKey;
|
||||||
|
const individualId = context.selectedVc.vcMetadata.id;
|
||||||
|
if (!isHardwareKeystoreExists) {
|
||||||
|
privateKey = await getPrivateKey(
|
||||||
|
context.selectedVc.walletBindingResponse?.walletBindingId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = await getAllConfigurations();
|
||||||
|
const header = {
|
||||||
|
alg: 'RS256',
|
||||||
|
'x5t#S256': context.thumbprint,
|
||||||
|
};
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
iss: config.issuer,
|
||||||
|
sub: individualId,
|
||||||
|
aud: config.audience,
|
||||||
|
iat: Math.floor(new Date().getTime() / 1000),
|
||||||
|
exp: Math.floor(new Date().getTime() / 1000) + 18000,
|
||||||
|
};
|
||||||
|
|
||||||
|
const jwt = await getJWT(header, payload, individualId, privateKey);
|
||||||
|
|
||||||
|
const response = await request(
|
||||||
|
API_URLS.authenticate.method,
|
||||||
|
API_URLS.authenticate.buildURL(),
|
||||||
|
{
|
||||||
|
requestTime: String(new Date().toISOString()),
|
||||||
|
request: {
|
||||||
|
linkedTransactionId: context.linkTransactionId,
|
||||||
|
individualId: individualId,
|
||||||
|
challengeList: [
|
||||||
|
{
|
||||||
|
authFactorType: 'WLA',
|
||||||
|
challenge: jwt,
|
||||||
|
format: 'jwt',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ESIGNET_BASE_URL,
|
||||||
|
);
|
||||||
|
return response.response;
|
||||||
|
},
|
||||||
|
|
||||||
|
sendConsent: async context => {
|
||||||
|
let privateKey;
|
||||||
|
const individualId = context.selectedVc.vcMetadata.id;
|
||||||
|
if (!isHardwareKeystoreExists) {
|
||||||
|
privateKey = await getPrivateKey(
|
||||||
|
context.selectedVc.walletBindingResponse?.walletBindingId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const header = {
|
||||||
|
alg: 'RS256',
|
||||||
|
'x5t#S256': context.thumbprint,
|
||||||
|
};
|
||||||
|
const payload = {
|
||||||
|
accepted_claims: context.essentialClaims
|
||||||
|
.concat(context.selectedVoluntaryClaims)
|
||||||
|
.sort(),
|
||||||
|
permitted_authorized_scopes: context.authorizeScopes,
|
||||||
|
};
|
||||||
|
|
||||||
|
const JWT = await getJWT(header, payload, individualId, privateKey);
|
||||||
|
const jwtComponents = JWT.split('.');
|
||||||
|
const detachedSignature = jwtComponents[0] + '.' + jwtComponents[2];
|
||||||
|
|
||||||
|
const resp = await request(
|
||||||
|
API_URLS.sendConsent.method,
|
||||||
|
API_URLS.sendConsent.buildURL(),
|
||||||
|
{
|
||||||
|
requestTime: String(new Date().toISOString()),
|
||||||
|
request: {
|
||||||
|
linkedTransactionId: context.linkedTransactionId,
|
||||||
|
acceptedClaims: context.essentialClaims
|
||||||
|
.concat(context.selectedVoluntaryClaims)
|
||||||
|
.sort(),
|
||||||
|
permittedAuthorizeScopes: context.authorizeScopes,
|
||||||
|
signature: detachedSignature,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ESIGNET_BASE_URL,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1,710 +0,0 @@
|
|||||||
import {
|
|
||||||
ActorRefFrom,
|
|
||||||
assign,
|
|
||||||
EventFrom,
|
|
||||||
send,
|
|
||||||
sendParent,
|
|
||||||
StateFrom,
|
|
||||||
} from 'xstate';
|
|
||||||
import {createModel} from 'xstate/lib/model';
|
|
||||||
import {AppServices} from '../shared/GlobalContext';
|
|
||||||
import {
|
|
||||||
ESIGNET_BASE_URL,
|
|
||||||
FACE_AUTH_CONSENT,
|
|
||||||
MY_VCS_STORE_KEY,
|
|
||||||
} from '../shared/constants';
|
|
||||||
import {StoreEvents} from './store';
|
|
||||||
import {
|
|
||||||
linkTransactionResponse,
|
|
||||||
VC,
|
|
||||||
} from './VerifiableCredential/VCMetaMachine/vc';
|
|
||||||
import {request} from '../shared/request';
|
|
||||||
import {
|
|
||||||
getJWT,
|
|
||||||
isHardwareKeystoreExists,
|
|
||||||
} from '../shared/cryptoutil/cryptoUtil';
|
|
||||||
import {
|
|
||||||
getBindingCertificateConstant,
|
|
||||||
getPrivateKey,
|
|
||||||
} from '../shared/keystore/SecureKeystore';
|
|
||||||
import i18n from '../i18n';
|
|
||||||
import {parseMetadatas, VCMetadata} from '../shared/VCMetadata';
|
|
||||||
import {
|
|
||||||
getEndEventData,
|
|
||||||
sendEndEvent,
|
|
||||||
} from '../shared/telemetry/TelemetryUtils';
|
|
||||||
import {TelemetryConstants} from '../shared/telemetry/TelemetryConstants';
|
|
||||||
import getAllConfigurations, {API_URLS} from '../shared/api';
|
|
||||||
import {VCShareFlowType} from '../shared/Utils';
|
|
||||||
import {getMosipLogo} from '../components/VC/common/VCUtils';
|
|
||||||
|
|
||||||
const model = createModel(
|
|
||||||
{
|
|
||||||
serviceRefs: {} as AppServices,
|
|
||||||
selectedVc: {} as VC,
|
|
||||||
linkCode: '',
|
|
||||||
flowType: VCShareFlowType.SIMPLE_SHARE,
|
|
||||||
myVcs: [] as VCMetadata[],
|
|
||||||
thumbprint: '',
|
|
||||||
linkTransactionResponse: {} as linkTransactionResponse,
|
|
||||||
authFactors: [],
|
|
||||||
authorizeScopes: null,
|
|
||||||
clientName: {},
|
|
||||||
configs: {},
|
|
||||||
essentialClaims: [],
|
|
||||||
linkTransactionId: '',
|
|
||||||
logoUrl: '',
|
|
||||||
voluntaryClaims: [],
|
|
||||||
selectedVoluntaryClaims: [],
|
|
||||||
errorMessage: '',
|
|
||||||
domainName: '',
|
|
||||||
consentClaims: ['name', 'picture'],
|
|
||||||
isSharing: {},
|
|
||||||
linkedTransactionId: '',
|
|
||||||
showFaceAuthConsent: true as boolean,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
events: {
|
|
||||||
SELECT_VC: (vc: VC) => ({vc}),
|
|
||||||
SCANNING_DONE: (params: string) => ({params}),
|
|
||||||
STORE_RESPONSE: (response: unknown) => ({response}),
|
|
||||||
STORE_ERROR: (error: Error) => ({error}),
|
|
||||||
TOGGLE_CONSENT_CLAIM: (enable: boolean, claim: string) => ({
|
|
||||||
enable,
|
|
||||||
claim,
|
|
||||||
}),
|
|
||||||
DISMISS: () => ({}),
|
|
||||||
CONFIRM: () => ({}),
|
|
||||||
GET: (
|
|
||||||
linkCode: string,
|
|
||||||
flowType: string,
|
|
||||||
selectedVc: VC,
|
|
||||||
faceAuthConsentGiven: boolean,
|
|
||||||
) => ({
|
|
||||||
linkCode,
|
|
||||||
flowType,
|
|
||||||
selectedVc,
|
|
||||||
faceAuthConsentGiven,
|
|
||||||
}),
|
|
||||||
VERIFY: () => ({}),
|
|
||||||
CANCEL: () => ({}),
|
|
||||||
FACE_VALID: () => ({}),
|
|
||||||
FACE_INVALID: () => ({}),
|
|
||||||
RETRY_VERIFICATION: () => ({}),
|
|
||||||
FACE_VERIFICATION_CONSENT: (isConsentGiven: boolean) => ({
|
|
||||||
isConsentGiven,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export const QrLoginEvents = model.events;
|
|
||||||
export type QrLoginRef = ActorRefFrom<typeof qrLoginMachine>;
|
|
||||||
|
|
||||||
export const qrLoginMachine =
|
|
||||||
/** @xstate-layout N4IgpgJg5mDOIC5QEUBOAZA9lAlgOwDocIAbMAYgGUBhAQQDl6BJegcQH0ARAeXoFEA2gAYAuolAAHTLBwAXHJjziQAD0QBGACzqATAQCs+nZv0BmABzqL50zoA0IAJ6IA7KaEFNATnPmv6oUMhHUMAX1CHNCxcQmIyck4mSgBZJMphMSQQKRl5RWU1BF1zFwIvHQrTFxdNCxcANgdnBH16j1NbdT8vfW8q9XDIjGx8AhJ8AGsAFVQAQzxYWYBjPLxyCEUwIjwAN0wJraiRwnG8abmF5dWEfD2l2dWMjOUcuQUlLMKtXQMjEwsrL5bE1EF4XOYCEJ6iEXF4ekIOppzIMQEcYmNJjN5osVu9yGBUKhMKgCBISA8AGbEgC2BDRo1O52xV3eN12mHuj1Ezyyr1WBQ0JQhmlhotMZmM+hcIIQNX0nnUhh65h06hcOhKKPphFgAAtMAB3ADqs1QeHwUHI1F4ADEmAAlZI8yTSN75T6IEIeHT+eo1Lyaeriwwy+pggiwtXw9SKjU6LXDdF6w0ms0Wq0Mah8dDO7Ku-kehBegg+9R+7yB4P6GV+dQRlwBIRqoTqjX1BPRUaUfUGviE4kZ+hZnOiF7594Coo9TSQtyqqUx9zApyINpeCNIoVaYzlUwd45jTCzCDJRwANSWsCoU249r47DvlAACrxKIJR7zx+7QIU-fLofoMaATYWjaKGLjylCOjQi4gSmJoOgNPuSY9jsSzoDgsCyFQ2Z8NQUzsGe1C5nyE6Fr4M4BkI3j6DYtEttWK4tDGEb1H6DbmEYAZschozJgaaEYVh5Bnnw9pMDaACaJFfh8P6uLRZRIoqKl0UI5gyiK9SQtobjUZu0KaLxOqoehmHYYkKRpDJuRkfJRTqRCpj1PoTYBj01QVKGPwVIBHT6AGqq1MZBAUssYC0AArrIurkDatBZoRtDoEwnA2W6cmqJ6rklr6-qVoYjHNP4kI2Jo1ENr01EBiFYVLBF0WxfFiUsGeyWpelBb2cWpbltxVahiKuVqmGXT1IG6heLV4VRTFg7Dp1dlZUWOW9flQaFTW2glrBYK0SqZaqiFtyzOMEBMBAYB4PIsiOAkSSpJQ6Qfi6tnfstf4EABQFdKYoHqKG1EECUrnmEIcJ+FC7YRKiiajCdZ0XVdN13XeUz2pJhFiRJTB0FMTC8It72FD1eUVhtIZMQF2mRjUHT1FYPTQ0MnaEKgYAAI6RXAsjUIosDI1atoOk6L15m9mW-hBX0hD9IGaGBTEIfKvTNoGOhVF4zOw6zBDs1zPN8wsgt0EO2ZE5Lq7S99ql-QrANMe4M6RqNDa6NC5hGTD2oEBseAUJZj3PZkr0ZZOAS+AQzmuZNNGefYSshAYunUdCmvaz7+vc1hFpGwL13rJs2x7AcdJw2znPZ-IeBQHnyNsncDzvE8YukcTq42GUYYtuNgFsQGMqqnWNjwSNiFeACe7e+XeuVzzuf84LBJEiSZKUjSZe61n8813X10NxyTeKC3Ifi2HhYR05LluXHrY1qYO2OanY1sciKJ4Jgl3wFk2pjhLk4AFpGhMQAfKOE4CIGQKnizA8cQwB-3PvZYoEJVT+FVCUaC-hNDeXlDYCoipwRCCIeKEKjIsSXFxO9NulsiguWdpYIMQZoK9F6DKOmX0FYQSITHHoU1p6634qmc0NcEFdWWghNh4MCBlnqGDLQ7EAxvxgeibsho+wr1EUtEmLYIQqmjvbeCKoiqrgCCWTc4JtzeA1qQo8J5zyXk0e3BAIph7jTYvBQIwQLDgWdv4Bo5UkTqjMCFfiglzKOJoX4bS4oGyIR9FUIhCdmgMz0EEqw4pApaGgTrA8dUGoxQiZOGoX0Si1CDFYAKCEkkaChKVUeHQNYNGosdXYp1iBI2unIZoocxGFCRHoKU40VT+H2n4QG8oqig3Bj4LwUIXAhW3lhPeshCmFiROucqhlYK6AXA7Zoxg6wTwgv09JHRfAhT9vAz8-9Cz+HXJUxUCIzBIiRJpaCOkRoNlMGCME8EFlzxzrvRe11Vn2RBtI1oDM-pGAsF4GsdZXJEI8n8Go41wjhCAA */
|
|
||||||
model.createMachine(
|
|
||||||
{
|
|
||||||
predictableActionArguments: true,
|
|
||||||
preserveActionOrder: true,
|
|
||||||
tsTypes: {} as import('./QrLoginMachine.typegen').Typegen0,
|
|
||||||
schema: {
|
|
||||||
context: model.initialContext,
|
|
||||||
events: {} as EventFrom<typeof model>,
|
|
||||||
},
|
|
||||||
id: 'QrLogin',
|
|
||||||
initial: 'waitingForData',
|
|
||||||
entry: ['resetSelectedVc', 'resetFlowType'],
|
|
||||||
states: {
|
|
||||||
waitingForData: {
|
|
||||||
on: {
|
|
||||||
GET: {
|
|
||||||
actions: [
|
|
||||||
'setScanData',
|
|
||||||
'setFaceAuthConsent',
|
|
||||||
'resetLinkTransactionId',
|
|
||||||
'resetSelectedVoluntaryClaims',
|
|
||||||
],
|
|
||||||
target: 'linkTransaction',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
linkTransaction: {
|
|
||||||
invoke: {
|
|
||||||
src: 'linkTransaction',
|
|
||||||
onDone: [
|
|
||||||
{
|
|
||||||
cond: 'isSimpleShareFlow',
|
|
||||||
actions: [
|
|
||||||
'setlinkTransactionResponse',
|
|
||||||
'expandLinkTransResp',
|
|
||||||
'setClaims',
|
|
||||||
],
|
|
||||||
target: 'loadMyVcs',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
actions: [
|
|
||||||
'setlinkTransactionResponse',
|
|
||||||
'expandLinkTransResp',
|
|
||||||
'setClaims',
|
|
||||||
],
|
|
||||||
target: 'faceAuth',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
onError: [
|
|
||||||
{
|
|
||||||
actions: 'SetErrorMessage',
|
|
||||||
target: 'ShowError',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ShowError: {
|
|
||||||
on: {
|
|
||||||
DISMISS: {
|
|
||||||
actions: 'forwardToParent',
|
|
||||||
target: 'waitingForData',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
loadMyVcs: {
|
|
||||||
entry: 'loadMyVcs',
|
|
||||||
on: {
|
|
||||||
STORE_RESPONSE: {
|
|
||||||
actions: 'setMyVcs',
|
|
||||||
target: 'showvcList',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
showvcList: {
|
|
||||||
on: {
|
|
||||||
SELECT_VC: {
|
|
||||||
actions: 'setSelectedVc',
|
|
||||||
},
|
|
||||||
VERIFY: [
|
|
||||||
{
|
|
||||||
cond: 'showFaceAuthConsentScreen',
|
|
||||||
target: 'faceVerificationConsent',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
target: 'faceAuth',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
DISMISS: {
|
|
||||||
actions: 'forwardToParent',
|
|
||||||
target: 'waitingForData',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
faceVerificationConsent: {
|
|
||||||
on: {
|
|
||||||
FACE_VERIFICATION_CONSENT: {
|
|
||||||
actions: ['storeShowFaceAuthConsent', 'setShowFaceAuthConsent'],
|
|
||||||
target: 'faceAuth',
|
|
||||||
},
|
|
||||||
DISMISS: {
|
|
||||||
target: 'showvcList',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
faceAuth: {
|
|
||||||
on: {
|
|
||||||
FACE_VALID: {
|
|
||||||
target: 'loadingThumbprint',
|
|
||||||
},
|
|
||||||
FACE_INVALID: {
|
|
||||||
target: 'invalidIdentity',
|
|
||||||
},
|
|
||||||
CANCEL: [
|
|
||||||
{
|
|
||||||
cond: 'isSimpleShareFlow',
|
|
||||||
target: 'showvcList',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
actions: 'forwardToParent',
|
|
||||||
target: 'waitingForData',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
invalidIdentity: {
|
|
||||||
on: {
|
|
||||||
DISMISS: {
|
|
||||||
target: 'showvcList',
|
|
||||||
},
|
|
||||||
RETRY_VERIFICATION: {
|
|
||||||
target: 'faceAuth',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
sendingAuthenticate: {
|
|
||||||
invoke: {
|
|
||||||
src: 'sendAuthenticate',
|
|
||||||
onDone: [
|
|
||||||
{
|
|
||||||
cond: 'isConsentAlreadyCaptured',
|
|
||||||
target: 'success',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
target: 'requestConsent',
|
|
||||||
actions: 'setLinkedTransactionId',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
onError: [
|
|
||||||
{
|
|
||||||
actions: 'SetErrorMessage',
|
|
||||||
target: 'ShowError',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
requestConsent: {
|
|
||||||
on: {
|
|
||||||
CONFIRM: {
|
|
||||||
target: 'sendingConsent',
|
|
||||||
},
|
|
||||||
TOGGLE_CONSENT_CLAIM: {
|
|
||||||
actions: 'setConsentClaims',
|
|
||||||
target: 'requestConsent',
|
|
||||||
},
|
|
||||||
DISMISS: {
|
|
||||||
actions: 'forwardToParent',
|
|
||||||
target: 'waitingForData',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
loadingThumbprint: {
|
|
||||||
entry: 'loadThumbprint',
|
|
||||||
on: {
|
|
||||||
STORE_RESPONSE: {
|
|
||||||
actions: 'setThumbprint',
|
|
||||||
target: 'sendingAuthenticate',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
sendingConsent: {
|
|
||||||
invoke: {
|
|
||||||
src: 'sendConsent',
|
|
||||||
onDone: {
|
|
||||||
target: 'success',
|
|
||||||
},
|
|
||||||
onError: [
|
|
||||||
{
|
|
||||||
actions: 'SetErrorMessage',
|
|
||||||
target: 'ShowError',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
success: {
|
|
||||||
entry: [
|
|
||||||
() =>
|
|
||||||
sendEndEvent(
|
|
||||||
getEndEventData(
|
|
||||||
TelemetryConstants.FlowType.qrLogin,
|
|
||||||
TelemetryConstants.EndEventStatus.success,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
on: {
|
|
||||||
CONFIRM: {
|
|
||||||
target: 'done',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
done: {
|
|
||||||
type: 'final',
|
|
||||||
data: context => context,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
actions: {
|
|
||||||
setShowFaceAuthConsent: model.assign({
|
|
||||||
showFaceAuthConsent: (_, event) => {
|
|
||||||
return !event.isConsentGiven;
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
storeShowFaceAuthConsent: send(
|
|
||||||
(context, event) =>
|
|
||||||
StoreEvents.SET(FACE_AUTH_CONSENT, !event.isConsentGiven),
|
|
||||||
{
|
|
||||||
to: context => context.serviceRefs.store,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
forwardToParent: sendParent('DISMISS'),
|
|
||||||
|
|
||||||
setScanData: model.assign((context, event) => {
|
|
||||||
const linkCode = event.linkCode;
|
|
||||||
const flowType = event.flowType;
|
|
||||||
const selectedVc = event.selectedVc;
|
|
||||||
return {
|
|
||||||
...context,
|
|
||||||
linkCode: linkCode,
|
|
||||||
flowType: flowType,
|
|
||||||
selectedVc: selectedVc,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
setFaceAuthConsent: assign({
|
|
||||||
showFaceAuthConsent: (context, event) => {
|
|
||||||
return event.faceAuthConsentGiven;
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
// TODO: loaded VCMetadatas are not used anywhere. remove?
|
|
||||||
loadMyVcs: send(StoreEvents.GET(MY_VCS_STORE_KEY), {
|
|
||||||
to: context => context.serviceRefs.store,
|
|
||||||
}),
|
|
||||||
|
|
||||||
setMyVcs: model.assign({
|
|
||||||
myVcs: (_context, event) =>
|
|
||||||
parseMetadatas((event.response || []) as object[]),
|
|
||||||
}),
|
|
||||||
|
|
||||||
loadThumbprint: send(
|
|
||||||
context =>
|
|
||||||
StoreEvents.GET(
|
|
||||||
getBindingCertificateConstant(
|
|
||||||
context.selectedVc.walletBindingResponse?.walletBindingId,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
{to: context => context.serviceRefs.store},
|
|
||||||
),
|
|
||||||
setThumbprint: assign({
|
|
||||||
thumbprint: (_context, event) => {
|
|
||||||
return (event.response || '') as string;
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
resetLinkTransactionId: model.assign({
|
|
||||||
linkTransactionId: () => '',
|
|
||||||
}),
|
|
||||||
|
|
||||||
resetSelectedVoluntaryClaims: model.assign({
|
|
||||||
selectedVoluntaryClaims: () => [],
|
|
||||||
}),
|
|
||||||
|
|
||||||
setSelectedVc: assign({
|
|
||||||
selectedVc: (context, event) => {
|
|
||||||
return {...event.vc};
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
resetSelectedVc: assign({
|
|
||||||
selectedVc: {} as VC,
|
|
||||||
}),
|
|
||||||
|
|
||||||
resetFlowType: assign({
|
|
||||||
flowType: VCShareFlowType.SIMPLE_SHARE,
|
|
||||||
}),
|
|
||||||
|
|
||||||
setlinkTransactionResponse: assign({
|
|
||||||
linkTransactionResponse: (context, event) =>
|
|
||||||
event.data as linkTransactionResponse,
|
|
||||||
}),
|
|
||||||
|
|
||||||
expandLinkTransResp: assign({
|
|
||||||
authFactors: context => context.linkTransactionResponse.authFactors,
|
|
||||||
|
|
||||||
authorizeScopes: context =>
|
|
||||||
context.linkTransactionResponse.authorizeScopes,
|
|
||||||
|
|
||||||
clientName: context => context.linkTransactionResponse.clientName,
|
|
||||||
|
|
||||||
configs: context => context.linkTransactionResponse.configs,
|
|
||||||
|
|
||||||
essentialClaims: context =>
|
|
||||||
context.linkTransactionResponse.essentialClaims,
|
|
||||||
|
|
||||||
linkTransactionId: context =>
|
|
||||||
context.linkTransactionResponse.linkTransactionId,
|
|
||||||
|
|
||||||
logoUrl: context => context.linkTransactionResponse.logoUrl,
|
|
||||||
|
|
||||||
voluntaryClaims: context =>
|
|
||||||
context.linkTransactionResponse.voluntaryClaims,
|
|
||||||
}),
|
|
||||||
|
|
||||||
setClaims: context => {
|
|
||||||
context.voluntaryClaims.map(claim => {
|
|
||||||
context.isSharing[claim] = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
SetErrorMessage: assign({
|
|
||||||
errorMessage: (context, event) => {
|
|
||||||
const message = event.data.name;
|
|
||||||
const ID_ERRORS_MAP = {
|
|
||||||
invalid_link_code: 'invalidQR',
|
|
||||||
};
|
|
||||||
const errorMessage = ID_ERRORS_MAP[message]
|
|
||||||
? i18n.t(`errors.${ID_ERRORS_MAP[message]}`, {
|
|
||||||
ns: 'QrLogin',
|
|
||||||
})
|
|
||||||
: i18n.t(`errors.genericError`, {
|
|
||||||
ns: 'common',
|
|
||||||
});
|
|
||||||
|
|
||||||
return errorMessage;
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
setConsentClaims: assign({
|
|
||||||
isSharing: (context, event) => {
|
|
||||||
context.isSharing[event.claim] = !event.enable;
|
|
||||||
if (!event.enable) {
|
|
||||||
context.selectedVoluntaryClaims.push(event.claim);
|
|
||||||
} else {
|
|
||||||
context.selectedVoluntaryClaims =
|
|
||||||
context.selectedVoluntaryClaims.filter(
|
|
||||||
eachClaim => eachClaim !== event.claim,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return {...context.isSharing};
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
setLinkedTransactionId: assign({
|
|
||||||
linkedTransactionId: (context, event) =>
|
|
||||||
event.data.linkedTransactionId as string,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
services: {
|
|
||||||
linkTransaction: async context => {
|
|
||||||
const response = await request(
|
|
||||||
API_URLS.linkTransaction.method,
|
|
||||||
API_URLS.linkTransaction.buildURL(),
|
|
||||||
{
|
|
||||||
requestTime: String(new Date().toISOString()),
|
|
||||||
request: {
|
|
||||||
linkCode: context.linkCode,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ESIGNET_BASE_URL,
|
|
||||||
);
|
|
||||||
return response.response;
|
|
||||||
},
|
|
||||||
|
|
||||||
sendAuthenticate: async context => {
|
|
||||||
let privateKey;
|
|
||||||
const individualId = context.selectedVc.vcMetadata.id;
|
|
||||||
if (!isHardwareKeystoreExists) {
|
|
||||||
privateKey = await getPrivateKey(
|
|
||||||
context.selectedVc.walletBindingResponse?.walletBindingId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var config = await getAllConfigurations();
|
|
||||||
const header = {
|
|
||||||
alg: 'RS256',
|
|
||||||
'x5t#S256': context.thumbprint,
|
|
||||||
};
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
iss: config.issuer,
|
|
||||||
sub: individualId,
|
|
||||||
aud: config.audience,
|
|
||||||
iat: Math.floor(new Date().getTime() / 1000),
|
|
||||||
exp: Math.floor(new Date().getTime() / 1000) + 18000,
|
|
||||||
};
|
|
||||||
|
|
||||||
const jwt = await getJWT(header, payload, individualId, privateKey);
|
|
||||||
|
|
||||||
const response = await request(
|
|
||||||
API_URLS.authenticate.method,
|
|
||||||
API_URLS.authenticate.buildURL(),
|
|
||||||
{
|
|
||||||
requestTime: String(new Date().toISOString()),
|
|
||||||
request: {
|
|
||||||
linkedTransactionId: context.linkTransactionId,
|
|
||||||
individualId: individualId,
|
|
||||||
challengeList: [
|
|
||||||
{
|
|
||||||
authFactorType: 'WLA',
|
|
||||||
challenge: jwt,
|
|
||||||
format: 'jwt',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ESIGNET_BASE_URL,
|
|
||||||
);
|
|
||||||
return response.response;
|
|
||||||
},
|
|
||||||
|
|
||||||
sendConsent: async context => {
|
|
||||||
let privateKey;
|
|
||||||
const individualId = context.selectedVc.vcMetadata.id;
|
|
||||||
if (!isHardwareKeystoreExists) {
|
|
||||||
privateKey = await getPrivateKey(
|
|
||||||
context.selectedVc.walletBindingResponse?.walletBindingId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const header = {
|
|
||||||
alg: 'RS256',
|
|
||||||
'x5t#S256': context.thumbprint,
|
|
||||||
};
|
|
||||||
const payload = {
|
|
||||||
accepted_claims: context.essentialClaims
|
|
||||||
.concat(context.selectedVoluntaryClaims)
|
|
||||||
.sort(),
|
|
||||||
permitted_authorized_scopes: context.authorizeScopes,
|
|
||||||
};
|
|
||||||
|
|
||||||
const JWT = await getJWT(header, payload, individualId, privateKey);
|
|
||||||
const jwtComponents = JWT.split('.');
|
|
||||||
const detachedSignature = jwtComponents[0] + '.' + jwtComponents[2];
|
|
||||||
|
|
||||||
const resp = await request(
|
|
||||||
API_URLS.sendConsent.method,
|
|
||||||
API_URLS.sendConsent.buildURL(),
|
|
||||||
{
|
|
||||||
requestTime: String(new Date().toISOString()),
|
|
||||||
request: {
|
|
||||||
linkedTransactionId: context.linkedTransactionId,
|
|
||||||
acceptedClaims: context.essentialClaims
|
|
||||||
.concat(context.selectedVoluntaryClaims)
|
|
||||||
.sort(),
|
|
||||||
permittedAuthorizeScopes: context.authorizeScopes,
|
|
||||||
signature: detachedSignature,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ESIGNET_BASE_URL,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
guards: {
|
|
||||||
showFaceAuthConsentScreen: context => {
|
|
||||||
return context.showFaceAuthConsent;
|
|
||||||
},
|
|
||||||
|
|
||||||
isConsentAlreadyCaptured: (_, event) =>
|
|
||||||
event.data?.consentAction === 'NOCAPTURE',
|
|
||||||
|
|
||||||
isSimpleShareFlow: (context, _event) =>
|
|
||||||
context.flowType === VCShareFlowType.SIMPLE_SHARE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export function createQrLoginMachine(serviceRefs: AppServices) {
|
|
||||||
return qrLoginMachine.withContext({
|
|
||||||
...qrLoginMachine.context,
|
|
||||||
serviceRefs,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
type State = StateFrom<typeof qrLoginMachine>;
|
|
||||||
|
|
||||||
export function selectMyVcs(state: State) {
|
|
||||||
return state.context.myVcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsWaitingForData(state: State) {
|
|
||||||
return state.matches('waitingForData');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectDomainName(state: State) {
|
|
||||||
return state.context.domainName;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsLinkTransaction(state: State) {
|
|
||||||
return state.matches('linkTransaction');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsloadMyVcs(state: State) {
|
|
||||||
return state.matches('loadMyVcs');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsShowingVcList(state: State) {
|
|
||||||
return state.matches('showvcList');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsisVerifyingIdentity(state: State) {
|
|
||||||
return state.matches('faceAuth');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsInvalidIdentity(state: State) {
|
|
||||||
return state.matches('invalidIdentity');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsShowError(state: State) {
|
|
||||||
return state.matches('ShowError');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsRequestConsent(state: State) {
|
|
||||||
return state.matches('requestConsent');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsSendingAuthenticate(state: State) {
|
|
||||||
return state.matches('sendingAuthenticate');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsSendingConsent(state: State) {
|
|
||||||
return state.matches('sendingConsent');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsVerifyingSuccesful(state: State) {
|
|
||||||
return state.matches('success');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectCredential(state: State) {
|
|
||||||
return new VCMetadata(state.context.selectedVc?.vcMetadata).isFromOpenId4VCI()
|
|
||||||
? state.context.selectedVc?.verifiableCredential?.credential
|
|
||||||
: state.context.selectedVc?.credential;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectVerifiableCredentialData(state: State) {
|
|
||||||
const vcMetadata = new VCMetadata(state.context.selectedVc?.vcMetadata);
|
|
||||||
return vcMetadata.isFromOpenId4VCI()
|
|
||||||
? {
|
|
||||||
vcMetadata: vcMetadata,
|
|
||||||
face: state.context.selectedVc?.verifiableCredential?.credential
|
|
||||||
?.credentialSubject?.face,
|
|
||||||
issuerLogo: state.context.selectedVc?.verifiableCredential?.issuerLogo,
|
|
||||||
wellKnown: state.context.selectedVc?.verifiableCredential?.wellKnown,
|
|
||||||
credentialTypes:
|
|
||||||
state.context.selectedVc?.verifiableCredential?.credentialTypes,
|
|
||||||
issuer: vcMetadata.issuer,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
vcMetadata: vcMetadata,
|
|
||||||
issuer: vcMetadata.issuer,
|
|
||||||
face: state.context.selectedVc?.credential?.biometrics?.face,
|
|
||||||
issuerLogo: getMosipLogo(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectLinkTransactionResponse(state: State) {
|
|
||||||
return state.context.linkTransactionResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectEssentialClaims(state: State) {
|
|
||||||
return state.context.essentialClaims;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectVoluntaryClaims(state: State) {
|
|
||||||
return state.context.voluntaryClaims;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectLogoUrl(state: State) {
|
|
||||||
return state.context.logoUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectClientName(state: State) {
|
|
||||||
return state.context.clientName;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectErrorMessage(state: State) {
|
|
||||||
return state.context.errorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsSharing(state: State) {
|
|
||||||
return state.context.isSharing;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsFaceVerificationConsent(state: State) {
|
|
||||||
return state.matches('faceVerificationConsent');
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
// This file was automatically generated. Edits will be overwritten
|
|
||||||
|
|
||||||
export interface Typegen0 {
|
|
||||||
'@@xstate/typegen': true;
|
|
||||||
internalEvents: {
|
|
||||||
'done.invoke.QrLogin.linkTransaction:invocation[0]': {
|
|
||||||
type: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
|
||||||
data: unknown;
|
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
|
||||||
};
|
|
||||||
'done.invoke.QrLogin.sendingAuthenticate:invocation[0]': {
|
|
||||||
type: 'done.invoke.QrLogin.sendingAuthenticate:invocation[0]';
|
|
||||||
data: unknown;
|
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
|
||||||
};
|
|
||||||
'error.platform.QrLogin.linkTransaction:invocation[0]': {
|
|
||||||
type: 'error.platform.QrLogin.linkTransaction:invocation[0]';
|
|
||||||
data: unknown;
|
|
||||||
};
|
|
||||||
'error.platform.QrLogin.sendingAuthenticate:invocation[0]': {
|
|
||||||
type: 'error.platform.QrLogin.sendingAuthenticate:invocation[0]';
|
|
||||||
data: unknown;
|
|
||||||
};
|
|
||||||
'error.platform.QrLogin.sendingConsent:invocation[0]': {
|
|
||||||
type: 'error.platform.QrLogin.sendingConsent:invocation[0]';
|
|
||||||
data: unknown;
|
|
||||||
};
|
|
||||||
'xstate.init': {type: 'xstate.init'};
|
|
||||||
};
|
|
||||||
invokeSrcNameMap: {
|
|
||||||
linkTransaction: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
|
||||||
sendAuthenticate: 'done.invoke.QrLogin.sendingAuthenticate:invocation[0]';
|
|
||||||
sendConsent: 'done.invoke.QrLogin.sendingConsent:invocation[0]';
|
|
||||||
};
|
|
||||||
missingImplementations: {
|
|
||||||
actions: never;
|
|
||||||
delays: never;
|
|
||||||
guards: never;
|
|
||||||
services: never;
|
|
||||||
};
|
|
||||||
eventsCausingActions: {
|
|
||||||
SetErrorMessage:
|
|
||||||
| 'error.platform.QrLogin.linkTransaction:invocation[0]'
|
|
||||||
| 'error.platform.QrLogin.sendingAuthenticate:invocation[0]'
|
|
||||||
| 'error.platform.QrLogin.sendingConsent:invocation[0]';
|
|
||||||
expandLinkTransResp: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
|
||||||
forwardToParent: 'CANCEL' | 'DISMISS';
|
|
||||||
loadMyVcs: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
|
||||||
loadThumbprint: 'FACE_VALID';
|
|
||||||
resetFlowType: 'xstate.init';
|
|
||||||
resetLinkTransactionId: 'GET';
|
|
||||||
resetSelectedVc: 'xstate.init';
|
|
||||||
resetSelectedVoluntaryClaims: 'GET';
|
|
||||||
setClaims: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
|
||||||
setConsentClaims: 'TOGGLE_CONSENT_CLAIM';
|
|
||||||
setFaceAuthConsent: 'GET';
|
|
||||||
setLinkedTransactionId: 'done.invoke.QrLogin.sendingAuthenticate:invocation[0]';
|
|
||||||
setMyVcs: 'STORE_RESPONSE';
|
|
||||||
setScanData: 'GET';
|
|
||||||
setSelectedVc: 'SELECT_VC';
|
|
||||||
setShowFaceAuthConsent: 'FACE_VERIFICATION_CONSENT';
|
|
||||||
setThumbprint: 'STORE_RESPONSE';
|
|
||||||
setlinkTransactionResponse: 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
|
||||||
storeShowFaceAuthConsent: 'FACE_VERIFICATION_CONSENT';
|
|
||||||
};
|
|
||||||
eventsCausingDelays: {};
|
|
||||||
eventsCausingGuards: {
|
|
||||||
isConsentAlreadyCaptured: 'done.invoke.QrLogin.sendingAuthenticate:invocation[0]';
|
|
||||||
isSimpleShareFlow:
|
|
||||||
| 'CANCEL'
|
|
||||||
| 'done.invoke.QrLogin.linkTransaction:invocation[0]';
|
|
||||||
showFaceAuthConsentScreen: 'VERIFY';
|
|
||||||
};
|
|
||||||
eventsCausingServices: {
|
|
||||||
linkTransaction: 'GET';
|
|
||||||
sendAuthenticate: 'STORE_RESPONSE';
|
|
||||||
sendConsent: 'CONFIRM';
|
|
||||||
};
|
|
||||||
matchesStates:
|
|
||||||
| 'ShowError'
|
|
||||||
| 'done'
|
|
||||||
| 'faceAuth'
|
|
||||||
| 'faceVerificationConsent'
|
|
||||||
| 'invalidIdentity'
|
|
||||||
| 'linkTransaction'
|
|
||||||
| 'loadMyVcs'
|
|
||||||
| 'loadingThumbprint'
|
|
||||||
| 'requestConsent'
|
|
||||||
| 'sendingAuthenticate'
|
|
||||||
| 'sendingConsent'
|
|
||||||
| 'showvcList'
|
|
||||||
| 'success'
|
|
||||||
| 'waitingForData';
|
|
||||||
tags: never;
|
|
||||||
}
|
|
||||||
@@ -1,384 +1,123 @@
|
|||||||
// This file was automatically generated. Edits will be overwritten
|
|
||||||
|
|
||||||
export interface Typegen0 {
|
// This file was automatically generated. Edits will be overwritten
|
||||||
'@@xstate/typegen': true;
|
|
||||||
internalEvents: {
|
export interface Typegen0 {
|
||||||
'': {type: ''};
|
'@@xstate/typegen': true;
|
||||||
'done.invoke.checkStatus': {
|
internalEvents: {
|
||||||
type: 'done.invoke.checkStatus';
|
"": { type: "" };
|
||||||
data: unknown;
|
"done.invoke.checkStatus": { type: "done.invoke.checkStatus"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"done.invoke.downloadCredential": { type: "done.invoke.downloadCredential"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
};
|
"done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]": { type: "done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
'done.invoke.downloadCredential': {
|
"done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]": { type: "done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
type: 'done.invoke.downloadCredential';
|
"done.invoke.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]": { type: "done.invoke.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
data: unknown;
|
"done.invoke.vc-item-machine.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]": { type: "done.invoke.vc-item-machine.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"done.invoke.vc-item-machine.verifyingCredential:invocation[0]": { type: "done.invoke.vc-item-machine.verifyingCredential:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
};
|
"done.invoke.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]": { type: "done.invoke.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
'done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]': {
|
"done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]": { type: "done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
type: 'done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]';
|
"done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]": { type: "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
data: unknown;
|
"done.invoke.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]": { type: "done.invoke.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]": { type: "done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
};
|
"error.platform.checkStatus": { type: "error.platform.checkStatus"; data: unknown };
|
||||||
'done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]': {
|
"error.platform.downloadCredential": { type: "error.platform.downloadCredential"; data: unknown };
|
||||||
type: 'done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]';
|
"error.platform.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]": { type: "error.platform.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]"; data: unknown };
|
||||||
data: unknown;
|
"error.platform.vc-item-machine.verifyingCredential:invocation[0]": { type: "error.platform.vc-item-machine.verifyingCredential:invocation[0]"; data: unknown };
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"error.platform.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]": { type: "error.platform.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]"; data: unknown };
|
||||||
};
|
"error.platform.vc-item-machine.walletBinding.addKeyPair:invocation[0]": { type: "error.platform.vc-item-machine.walletBinding.addKeyPair:invocation[0]"; data: unknown };
|
||||||
'done.invoke.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]': {
|
"error.platform.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]": { type: "error.platform.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]"; data: unknown };
|
||||||
type: 'done.invoke.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]';
|
"error.platform.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]": { type: "error.platform.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]"; data: unknown };
|
||||||
data: unknown;
|
"error.platform.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]": { type: "error.platform.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]"; data: unknown };
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"xstate.init": { type: "xstate.init" };
|
||||||
};
|
"xstate.stop": { type: "xstate.stop" };
|
||||||
'done.invoke.vc-item-machine.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]': {
|
};
|
||||||
type: 'done.invoke.vc-item-machine.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]';
|
invokeSrcNameMap: {
|
||||||
data: unknown;
|
"addWalletBindingId": "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]";
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"checkDownloadExpiryLimit": "done.invoke.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]";
|
||||||
};
|
"checkStatus": "done.invoke.checkStatus";
|
||||||
'done.invoke.vc-item-machine.verifyingCredential:invocation[0]': {
|
"downloadCredential": "done.invoke.downloadCredential";
|
||||||
type: 'done.invoke.vc-item-machine.verifyingCredential:invocation[0]';
|
"generateKeyPair": "done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]";
|
||||||
data: unknown;
|
"isUserSignedAlready": "done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]" | "done.invoke.vc-item-machine.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]";
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"loadDownloadLimitConfig": "done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]";
|
||||||
};
|
"requestBindingOTP": "done.invoke.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]" | "done.invoke.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]";
|
||||||
'done.invoke.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]': {
|
"updatePrivateKey": "done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]";
|
||||||
type: 'done.invoke.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]';
|
"verifyCredential": "done.invoke.vc-item-machine.verifyingCredential:invocation[0]";
|
||||||
data: unknown;
|
};
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
missingImplementations: {
|
||||||
};
|
actions: "addVcToInProgressDownloads" | "closeViewVcModal" | "incrementDownloadCounter" | "logDownloaded" | "logRemovedVc" | "logWalletBindingFailure" | "logWalletBindingSuccess" | "refreshAllVcs" | "removeVcFromInProgressDownloads" | "removeVcItem" | "removeVcMetaDataFromStorage" | "removeVcMetaDataFromVcMachineContext" | "requestVcContext" | "resetIsMachineInKebabPopupState" | "resetPrivateKey" | "sendActivationStartEvent" | "sendActivationSuccessEvent" | "sendBackupEvent" | "sendDownloadLimitExpire" | "sendTelemetryEvents" | "sendUserCancelledActivationFailedEndEvent" | "sendVcUpdated" | "sendVerificationError" | "sendWalletBindingErrorEvent" | "sendWalletBindingSuccess" | "setCommunicationDetails" | "setContext" | "setDownloadInterval" | "setErrorAsVerificationError" | "setErrorAsWalletBindingError" | "setMaxDownloadCount" | "setOTP" | "setPinCard" | "setPrivateKey" | "setPublicKey" | "setThumbprintForWalletBindingId" | "setVcKey" | "setVcMetadata" | "setWalletBindingResponse" | "storeContext" | "storeVcInContext" | "unSetBindingTransactionId" | "unSetError" | "unSetOTP";
|
||||||
'done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]': {
|
delays: never;
|
||||||
type: 'done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]';
|
guards: "hasCredential" | "isCustomSecureKeystore" | "isDownloadAllowed" | "isSignedIn";
|
||||||
data: unknown;
|
services: "addWalletBindingId" | "checkDownloadExpiryLimit" | "checkStatus" | "downloadCredential" | "generateKeyPair" | "isUserSignedAlready" | "loadDownloadLimitConfig" | "requestBindingOTP" | "updatePrivateKey" | "verifyCredential";
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
};
|
||||||
};
|
eventsCausingActions: {
|
||||||
'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]': {
|
"addVcToInProgressDownloads": "GET_VC_RESPONSE";
|
||||||
type: 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]';
|
"closeViewVcModal": "CLOSE_VC_MODAL" | "STORE_RESPONSE";
|
||||||
data: unknown;
|
"incrementDownloadCounter": "POLL" | "done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]";
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"logDownloaded": "STORE_RESPONSE";
|
||||||
};
|
"logRemovedVc": "STORE_RESPONSE" | "done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]";
|
||||||
'done.invoke.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]': {
|
"logWalletBindingFailure": "error.platform.vc-item-machine.walletBinding.addKeyPair:invocation[0]" | "error.platform.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]" | "error.platform.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]" | "error.platform.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]";
|
||||||
type: 'done.invoke.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]';
|
"logWalletBindingSuccess": "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]";
|
||||||
data: unknown;
|
"refreshAllVcs": "STORE_RESPONSE" | "done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]";
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"removeVcFromInProgressDownloads": "STORE_RESPONSE";
|
||||||
};
|
"removeVcItem": "CONFIRM";
|
||||||
'done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]': {
|
"removeVcMetaDataFromStorage": "STORE_ERROR" | "error.platform.vc-item-machine.verifyingCredential:invocation[0]";
|
||||||
type: 'done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
"removeVcMetaDataFromVcMachineContext": "DISMISS";
|
||||||
data: unknown;
|
"requestVcContext": "DISMISS" | "REFRESH" | "STORE_ERROR" | "xstate.init";
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"resetIsMachineInKebabPopupState": "" | "ADD_WALLET_BINDING_ID" | "CANCEL" | "CLOSE_VC_MODAL" | "DISMISS" | "REFRESH" | "REMOVE" | "SHOW_ACTIVITY" | "done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]" | "xstate.stop";
|
||||||
};
|
"resetPrivateKey": "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]";
|
||||||
'error.platform.checkStatus': {
|
"sendActivationStartEvent": "CONFIRM";
|
||||||
type: 'error.platform.checkStatus';
|
"sendActivationSuccessEvent": "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]";
|
||||||
data: unknown;
|
"sendBackupEvent": "done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]" | "done.invoke.vc-item-machine.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]";
|
||||||
};
|
"sendDownloadLimitExpire": "FAILED" | "error.platform.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]";
|
||||||
'error.platform.downloadCredential': {
|
"sendTelemetryEvents": "STORE_RESPONSE";
|
||||||
type: 'error.platform.downloadCredential';
|
"sendUserCancelledActivationFailedEndEvent": "DISMISS";
|
||||||
data: unknown;
|
"sendVcUpdated": "PIN_CARD";
|
||||||
};
|
"sendVerificationError": "STORE_RESPONSE";
|
||||||
'error.platform.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]': {
|
"sendWalletBindingErrorEvent": "error.platform.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]" | "error.platform.vc-item-machine.walletBinding.addKeyPair:invocation[0]" | "error.platform.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]" | "error.platform.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]" | "error.platform.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]";
|
||||||
type: 'error.platform.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]';
|
"sendWalletBindingSuccess": "SHOW_BINDING_STATUS";
|
||||||
data: unknown;
|
"setCommunicationDetails": "done.invoke.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]" | "done.invoke.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]";
|
||||||
};
|
"setContext": "CREDENTIAL_DOWNLOADED" | "GET_VC_RESPONSE";
|
||||||
'error.platform.vc-item-machine.verifyingCredential:invocation[0]': {
|
"setDownloadInterval": "done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]";
|
||||||
type: 'error.platform.vc-item-machine.verifyingCredential:invocation[0]';
|
"setErrorAsVerificationError": "error.platform.vc-item-machine.verifyingCredential:invocation[0]";
|
||||||
data: unknown;
|
"setErrorAsWalletBindingError": "error.platform.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]" | "error.platform.vc-item-machine.walletBinding.addKeyPair:invocation[0]" | "error.platform.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]" | "error.platform.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]" | "error.platform.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]";
|
||||||
};
|
"setMaxDownloadCount": "done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]";
|
||||||
'error.platform.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]': {
|
"setOTP": "INPUT_OTP";
|
||||||
type: 'error.platform.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]';
|
"setPinCard": "PIN_CARD";
|
||||||
data: unknown;
|
"setPrivateKey": "done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]";
|
||||||
};
|
"setPublicKey": "done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]";
|
||||||
'error.platform.vc-item-machine.walletBinding.addKeyPair:invocation[0]': {
|
"setThumbprintForWalletBindingId": "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]";
|
||||||
type: 'error.platform.vc-item-machine.walletBinding.addKeyPair:invocation[0]';
|
"setVcKey": "REMOVE";
|
||||||
data: unknown;
|
"setVcMetadata": "UPDATE_VC_METADATA";
|
||||||
};
|
"setWalletBindingResponse": "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]";
|
||||||
'error.platform.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]': {
|
"storeContext": "done.invoke.vc-item-machine.verifyingCredential:invocation[0]" | "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]";
|
||||||
type: 'error.platform.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]';
|
"storeVcInContext": "STORE_RESPONSE" | "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]";
|
||||||
data: unknown;
|
"unSetBindingTransactionId": "DISMISS";
|
||||||
};
|
"unSetError": "CANCEL" | "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]" | "done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]";
|
||||||
'error.platform.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]': {
|
"unSetOTP": "DISMISS" | "done.invoke.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]";
|
||||||
type: 'error.platform.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]';
|
};
|
||||||
data: unknown;
|
eventsCausingDelays: {
|
||||||
};
|
|
||||||
'error.platform.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]': {
|
};
|
||||||
type: 'error.platform.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
eventsCausingGuards: {
|
||||||
data: unknown;
|
"hasCredential": "GET_VC_RESPONSE";
|
||||||
};
|
"isCustomSecureKeystore": "done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]" | "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]";
|
||||||
'xstate.init': {type: 'xstate.init'};
|
"isDownloadAllowed": "POLL";
|
||||||
'xstate.stop': {type: 'xstate.stop'};
|
"isSignedIn": "done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]" | "done.invoke.vc-item-machine.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]";
|
||||||
};
|
};
|
||||||
invokeSrcNameMap: {
|
eventsCausingServices: {
|
||||||
addWalletBindingId: 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]';
|
"addWalletBindingId": "done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]";
|
||||||
checkDownloadExpiryLimit: 'done.invoke.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]';
|
"checkDownloadExpiryLimit": "POLL" | "done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]";
|
||||||
checkStatus: 'done.invoke.checkStatus';
|
"checkStatus": "done.invoke.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]";
|
||||||
downloadCredential: 'done.invoke.downloadCredential';
|
"downloadCredential": "DOWNLOAD_READY";
|
||||||
generateKeyPair: 'done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]';
|
"generateKeyPair": "INPUT_OTP";
|
||||||
isUserSignedAlready:
|
"isUserSignedAlready": "STORE_RESPONSE";
|
||||||
| 'done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]'
|
"loadDownloadLimitConfig": "GET_VC_RESPONSE" | "STORE_ERROR";
|
||||||
| 'done.invoke.vc-item-machine.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]';
|
"requestBindingOTP": "CONFIRM" | "RESEND_OTP";
|
||||||
loadDownloadLimitConfig: 'done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]';
|
"updatePrivateKey": "done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]";
|
||||||
requestBindingOTP:
|
"verifyCredential": "CREDENTIAL_DOWNLOADED";
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]'
|
};
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]';
|
matchesStates: "idle" | "kebabPopUp" | "kebabPopUp.idle" | "kebabPopUp.pinCard" | "kebabPopUp.removeWallet" | "kebabPopUp.removingVc" | "kebabPopUp.showActivities" | "kebabPopUp.triggerAutoBackup" | "loadVc" | "loadVc.loadVcFromContext" | "loadVc.loadVcFromServer" | "loadVc.loadVcFromServer.checkingStatus" | "loadVc.loadVcFromServer.downloadingCredential" | "loadVc.loadVcFromServer.loadDownloadLimitConfig" | "loadVc.loadVcFromServer.savingFailed" | "loadVc.loadVcFromServer.savingFailed.idle" | "loadVc.loadVcFromServer.savingFailed.viewingVc" | "loadVc.loadVcFromServer.verifyingDownloadLimitExpiry" | "verifyingCredential" | "verifyingCredential.handleVCVerificationFailure" | "verifyingCredential.idle" | "verifyingCredential.triggerAutoBackupForVcDownload" | "walletBinding" | "walletBinding.acceptingBindingOTP" | "walletBinding.acceptingBindingOTP.idle" | "walletBinding.acceptingBindingOTP.resendOTP" | "walletBinding.addKeyPair" | "walletBinding.addingWalletBindingId" | "walletBinding.requestingBindingOTP" | "walletBinding.showBindingWarning" | "walletBinding.showingWalletBindingError" | "walletBinding.updatingContextVariables" | "walletBinding.updatingPrivateKey" | { "kebabPopUp"?: "idle" | "pinCard" | "removeWallet" | "removingVc" | "showActivities" | "triggerAutoBackup";
|
||||||
updatePrivateKey: 'done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
"loadVc"?: "loadVcFromContext" | "loadVcFromServer" | { "loadVcFromServer"?: "checkingStatus" | "downloadingCredential" | "loadDownloadLimitConfig" | "savingFailed" | "verifyingDownloadLimitExpiry" | { "savingFailed"?: "idle" | "viewingVc"; }; };
|
||||||
verifyCredential: 'done.invoke.vc-item-machine.verifyingCredential:invocation[0]';
|
"verifyingCredential"?: "handleVCVerificationFailure" | "idle" | "triggerAutoBackupForVcDownload";
|
||||||
};
|
"walletBinding"?: "acceptingBindingOTP" | "addKeyPair" | "addingWalletBindingId" | "requestingBindingOTP" | "showBindingWarning" | "showingWalletBindingError" | "updatingContextVariables" | "updatingPrivateKey" | { "acceptingBindingOTP"?: "idle" | "resendOTP"; }; };
|
||||||
missingImplementations: {
|
tags: never;
|
||||||
actions:
|
}
|
||||||
| 'addVcToInProgressDownloads'
|
|
||||||
| 'closeViewVcModal'
|
|
||||||
| 'incrementDownloadCounter'
|
|
||||||
| 'logDownloaded'
|
|
||||||
| 'logRemovedVc'
|
|
||||||
| 'logWalletBindingFailure'
|
|
||||||
| 'logWalletBindingSuccess'
|
|
||||||
| 'refreshAllVcs'
|
|
||||||
| 'removeVcFromInProgressDownloads'
|
|
||||||
| 'removeVcItem'
|
|
||||||
| 'removeVcMetaDataFromStorage'
|
|
||||||
| 'removeVcMetaDataFromVcMachineContext'
|
|
||||||
| 'requestVcContext'
|
|
||||||
| 'resetIsMachineInKebabPopupState'
|
|
||||||
| 'resetPrivateKey'
|
|
||||||
| 'sendActivationStartEvent'
|
|
||||||
| 'sendActivationSuccessEvent'
|
|
||||||
| 'sendBackupEvent'
|
|
||||||
| 'sendDownloadLimitExpire'
|
|
||||||
| 'sendTelemetryEvents'
|
|
||||||
| 'sendUserCancelledActivationFailedEndEvent'
|
|
||||||
| 'sendVcUpdated'
|
|
||||||
| 'sendVerificationError'
|
|
||||||
| 'sendWalletBindingErrorEvent'
|
|
||||||
| 'sendWalletBindingSuccess'
|
|
||||||
| 'setCommunicationDetails'
|
|
||||||
| 'setContext'
|
|
||||||
| 'setDownloadInterval'
|
|
||||||
| 'setErrorAsVerificationError'
|
|
||||||
| 'setErrorAsWalletBindingError'
|
|
||||||
| 'setMaxDownloadCount'
|
|
||||||
| 'setOTP'
|
|
||||||
| 'setPinCard'
|
|
||||||
| 'setPrivateKey'
|
|
||||||
| 'setPublicKey'
|
|
||||||
| 'setThumbprintForWalletBindingId'
|
|
||||||
| 'setVcKey'
|
|
||||||
| 'setVcMetadata'
|
|
||||||
| 'setWalletBindingResponse'
|
|
||||||
| 'storeContext'
|
|
||||||
| 'storeVcInContext'
|
|
||||||
| 'unSetBindingTransactionId'
|
|
||||||
| 'unSetError'
|
|
||||||
| 'unSetOTP';
|
|
||||||
delays: never;
|
|
||||||
guards:
|
|
||||||
| 'hasCredential'
|
|
||||||
| 'isCustomSecureKeystore'
|
|
||||||
| 'isDownloadAllowed'
|
|
||||||
| 'isSignedIn';
|
|
||||||
services:
|
|
||||||
| 'addWalletBindingId'
|
|
||||||
| 'checkDownloadExpiryLimit'
|
|
||||||
| 'checkStatus'
|
|
||||||
| 'downloadCredential'
|
|
||||||
| 'generateKeyPair'
|
|
||||||
| 'isUserSignedAlready'
|
|
||||||
| 'loadDownloadLimitConfig'
|
|
||||||
| 'requestBindingOTP'
|
|
||||||
| 'updatePrivateKey'
|
|
||||||
| 'verifyCredential';
|
|
||||||
};
|
|
||||||
eventsCausingActions: {
|
|
||||||
addVcToInProgressDownloads: 'GET_VC_RESPONSE';
|
|
||||||
closeViewVcModal: 'CLOSE_VC_MODAL' | 'STORE_RESPONSE';
|
|
||||||
incrementDownloadCounter:
|
|
||||||
| 'POLL'
|
|
||||||
| 'done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]';
|
|
||||||
logDownloaded: 'STORE_RESPONSE';
|
|
||||||
logRemovedVc:
|
|
||||||
| 'STORE_RESPONSE'
|
|
||||||
| 'done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]';
|
|
||||||
logWalletBindingFailure:
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.addKeyPair:invocation[0]'
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]'
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]'
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
|
||||||
logWalletBindingSuccess:
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
|
||||||
refreshAllVcs:
|
|
||||||
| 'STORE_RESPONSE'
|
|
||||||
| 'done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]';
|
|
||||||
removeVcFromInProgressDownloads: 'STORE_RESPONSE';
|
|
||||||
removeVcItem: 'CONFIRM';
|
|
||||||
removeVcMetaDataFromStorage:
|
|
||||||
| 'STORE_ERROR'
|
|
||||||
| 'error.platform.vc-item-machine.verifyingCredential:invocation[0]';
|
|
||||||
removeVcMetaDataFromVcMachineContext: 'DISMISS';
|
|
||||||
requestVcContext: 'DISMISS' | 'REFRESH' | 'STORE_ERROR' | 'xstate.init';
|
|
||||||
resetIsMachineInKebabPopupState:
|
|
||||||
| ''
|
|
||||||
| 'ADD_WALLET_BINDING_ID'
|
|
||||||
| 'CANCEL'
|
|
||||||
| 'CLOSE_VC_MODAL'
|
|
||||||
| 'DISMISS'
|
|
||||||
| 'REFRESH'
|
|
||||||
| 'REMOVE'
|
|
||||||
| 'SHOW_ACTIVITY'
|
|
||||||
| 'done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]'
|
|
||||||
| 'xstate.stop';
|
|
||||||
resetPrivateKey:
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
|
||||||
sendActivationStartEvent: 'CONFIRM';
|
|
||||||
sendActivationSuccessEvent:
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
|
||||||
sendBackupEvent:
|
|
||||||
| 'done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]';
|
|
||||||
sendDownloadLimitExpire:
|
|
||||||
| 'FAILED'
|
|
||||||
| 'error.platform.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]';
|
|
||||||
sendTelemetryEvents: 'STORE_RESPONSE';
|
|
||||||
sendUserCancelledActivationFailedEndEvent: 'DISMISS';
|
|
||||||
sendVcUpdated: 'PIN_CARD';
|
|
||||||
sendVerificationError: 'STORE_RESPONSE';
|
|
||||||
sendWalletBindingErrorEvent:
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]'
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.addKeyPair:invocation[0]'
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]'
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]'
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
|
||||||
sendWalletBindingSuccess: 'SHOW_BINDING_STATUS';
|
|
||||||
setCommunicationDetails:
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]';
|
|
||||||
setContext: 'CREDENTIAL_DOWNLOADED' | 'GET_VC_RESPONSE';
|
|
||||||
setDownloadInterval: 'done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]';
|
|
||||||
setErrorAsVerificationError: 'error.platform.vc-item-machine.verifyingCredential:invocation[0]';
|
|
||||||
setErrorAsWalletBindingError:
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.acceptingBindingOTP.resendOTP:invocation[0]'
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.addKeyPair:invocation[0]'
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]'
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]'
|
|
||||||
| 'error.platform.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
|
||||||
setMaxDownloadCount: 'done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]';
|
|
||||||
setOTP: 'INPUT_OTP';
|
|
||||||
setPinCard: 'PIN_CARD';
|
|
||||||
setPrivateKey: 'done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]';
|
|
||||||
setPublicKey: 'done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]';
|
|
||||||
setThumbprintForWalletBindingId:
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
|
||||||
setVcKey: 'REMOVE';
|
|
||||||
setVcMetadata: 'UPDATE_VC_METADATA';
|
|
||||||
setWalletBindingResponse: 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]';
|
|
||||||
storeContext:
|
|
||||||
| 'done.invoke.vc-item-machine.verifyingCredential:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
|
||||||
storeVcInContext:
|
|
||||||
| 'STORE_RESPONSE'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
|
||||||
unSetBindingTransactionId: 'DISMISS';
|
|
||||||
unSetError:
|
|
||||||
| 'CANCEL'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.updatingPrivateKey:invocation[0]';
|
|
||||||
unSetOTP:
|
|
||||||
| 'DISMISS'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.requestingBindingOTP:invocation[0]';
|
|
||||||
};
|
|
||||||
eventsCausingDelays: {};
|
|
||||||
eventsCausingGuards: {
|
|
||||||
hasCredential: 'GET_VC_RESPONSE';
|
|
||||||
isCustomSecureKeystore:
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]';
|
|
||||||
isDownloadAllowed: 'POLL';
|
|
||||||
isSignedIn:
|
|
||||||
| 'done.invoke.vc-item-machine.kebabPopUp.triggerAutoBackup:invocation[0]'
|
|
||||||
| 'done.invoke.vc-item-machine.verifyingCredential.triggerAutoBackupForVcDownload:invocation[0]';
|
|
||||||
};
|
|
||||||
eventsCausingServices: {
|
|
||||||
addWalletBindingId: 'done.invoke.vc-item-machine.walletBinding.addKeyPair:invocation[0]';
|
|
||||||
checkDownloadExpiryLimit:
|
|
||||||
| 'POLL'
|
|
||||||
| 'done.invoke.vc-item-machine.loadVc.loadVcFromServer.loadDownloadLimitConfig:invocation[0]';
|
|
||||||
checkStatus: 'done.invoke.vc-item-machine.loadVc.loadVcFromServer.verifyingDownloadLimitExpiry:invocation[0]';
|
|
||||||
downloadCredential: 'DOWNLOAD_READY';
|
|
||||||
generateKeyPair: 'INPUT_OTP';
|
|
||||||
isUserSignedAlready: 'STORE_RESPONSE';
|
|
||||||
loadDownloadLimitConfig: 'GET_VC_RESPONSE' | 'STORE_ERROR';
|
|
||||||
requestBindingOTP: 'CONFIRM' | 'RESEND_OTP';
|
|
||||||
updatePrivateKey: 'done.invoke.vc-item-machine.walletBinding.addingWalletBindingId:invocation[0]';
|
|
||||||
verifyCredential: 'CREDENTIAL_DOWNLOADED';
|
|
||||||
};
|
|
||||||
matchesStates:
|
|
||||||
| 'idle'
|
|
||||||
| 'kebabPopUp'
|
|
||||||
| 'kebabPopUp.idle'
|
|
||||||
| 'kebabPopUp.pinCard'
|
|
||||||
| 'kebabPopUp.removeWallet'
|
|
||||||
| 'kebabPopUp.removingVc'
|
|
||||||
| 'kebabPopUp.showActivities'
|
|
||||||
| 'kebabPopUp.triggerAutoBackup'
|
|
||||||
| 'loadVc'
|
|
||||||
| 'loadVc.loadVcFromContext'
|
|
||||||
| 'loadVc.loadVcFromServer'
|
|
||||||
| 'loadVc.loadVcFromServer.checkingStatus'
|
|
||||||
| 'loadVc.loadVcFromServer.downloadingCredential'
|
|
||||||
| 'loadVc.loadVcFromServer.loadDownloadLimitConfig'
|
|
||||||
| 'loadVc.loadVcFromServer.savingFailed'
|
|
||||||
| 'loadVc.loadVcFromServer.savingFailed.idle'
|
|
||||||
| 'loadVc.loadVcFromServer.savingFailed.viewingVc'
|
|
||||||
| 'loadVc.loadVcFromServer.verifyingDownloadLimitExpiry'
|
|
||||||
| 'verifyingCredential'
|
|
||||||
| 'verifyingCredential.handleVCVerificationFailure'
|
|
||||||
| 'verifyingCredential.idle'
|
|
||||||
| 'verifyingCredential.triggerAutoBackupForVcDownload'
|
|
||||||
| 'walletBinding'
|
|
||||||
| 'walletBinding.acceptingBindingOTP'
|
|
||||||
| 'walletBinding.acceptingBindingOTP.idle'
|
|
||||||
| 'walletBinding.acceptingBindingOTP.resendOTP'
|
|
||||||
| 'walletBinding.addKeyPair'
|
|
||||||
| 'walletBinding.addingWalletBindingId'
|
|
||||||
| 'walletBinding.requestingBindingOTP'
|
|
||||||
| 'walletBinding.showBindingWarning'
|
|
||||||
| 'walletBinding.showingWalletBindingError'
|
|
||||||
| 'walletBinding.updatingContextVariables'
|
|
||||||
| 'walletBinding.updatingPrivateKey'
|
|
||||||
| {
|
|
||||||
kebabPopUp?:
|
|
||||||
| 'idle'
|
|
||||||
| 'pinCard'
|
|
||||||
| 'removeWallet'
|
|
||||||
| 'removingVc'
|
|
||||||
| 'showActivities'
|
|
||||||
| 'triggerAutoBackup';
|
|
||||||
loadVc?:
|
|
||||||
| 'loadVcFromContext'
|
|
||||||
| 'loadVcFromServer'
|
|
||||||
| {
|
|
||||||
loadVcFromServer?:
|
|
||||||
| 'checkingStatus'
|
|
||||||
| 'downloadingCredential'
|
|
||||||
| 'loadDownloadLimitConfig'
|
|
||||||
| 'savingFailed'
|
|
||||||
| 'verifyingDownloadLimitExpiry'
|
|
||||||
| {savingFailed?: 'idle' | 'viewingVc'};
|
|
||||||
};
|
|
||||||
verifyingCredential?:
|
|
||||||
| 'handleVCVerificationFailure'
|
|
||||||
| 'idle'
|
|
||||||
| 'triggerAutoBackupForVcDownload';
|
|
||||||
walletBinding?:
|
|
||||||
| 'acceptingBindingOTP'
|
|
||||||
| 'addKeyPair'
|
|
||||||
| 'addingWalletBindingId'
|
|
||||||
| 'requestingBindingOTP'
|
|
||||||
| 'showBindingWarning'
|
|
||||||
| 'showingWalletBindingError'
|
|
||||||
| 'updatingContextVariables'
|
|
||||||
| 'updatingPrivateKey'
|
|
||||||
| {acceptingBindingOTP?: 'idle' | 'resendOTP'};
|
|
||||||
};
|
|
||||||
tags: never;
|
|
||||||
}
|
|
||||||
@@ -1,106 +1,58 @@
|
|||||||
// This file was automatically generated. Edits will be overwritten
|
|
||||||
|
|
||||||
export interface Typegen0 {
|
// This file was automatically generated. Edits will be overwritten
|
||||||
'@@xstate/typegen': true;
|
|
||||||
internalEvents: {
|
export interface Typegen0 {
|
||||||
'done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]': {
|
'@@xstate/typegen': true;
|
||||||
type: 'done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]';
|
internalEvents: {
|
||||||
data: unknown;
|
"done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]": { type: "done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"xstate.init": { type: "xstate.init" };
|
||||||
};
|
};
|
||||||
'xstate.init': {type: 'xstate.init'};
|
invokeSrcNameMap: {
|
||||||
};
|
"isUserSignedAlready": "done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]";
|
||||||
invokeSrcNameMap: {
|
};
|
||||||
isUserSignedAlready: 'done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]';
|
missingImplementations: {
|
||||||
};
|
actions: "addVcToInProgressDownloads" | "getVcItemResponse" | "loadMyVcs" | "loadReceivedVcs" | "logTamperedVCsremoved" | "prependToMyVcsMetadata" | "removeDownloadFailedVcsFromStorage" | "removeDownloadingFailedVcsFromMyVcs" | "removeVcFromInProgressDownlods" | "removeVcFromMyVcsMetadata" | "resetDownloadFailedVcs" | "resetInProgressVcsDownloaded" | "resetTamperedVcs" | "resetVerificationErrorMessage" | "resetWalletBindingSuccess" | "sendBackupEvent" | "setDownloadedVc" | "setDownloadingFailedVcs" | "setMyVcs" | "setReceivedVcs" | "setUpdatedVcMetadatas" | "setVerificationErrorMessage" | "setWalletBindingSuccess" | "updateMyVcsMetadata";
|
||||||
missingImplementations: {
|
delays: never;
|
||||||
actions:
|
guards: "isAnyVcTampered" | "isSignedIn";
|
||||||
| 'addVcToInProgressDownloads'
|
services: "isUserSignedAlready";
|
||||||
| 'getVcItemResponse'
|
};
|
||||||
| 'loadMyVcs'
|
eventsCausingActions: {
|
||||||
| 'loadReceivedVcs'
|
"addVcToInProgressDownloads": "ADD_VC_TO_IN_PROGRESS_DOWNLOADS";
|
||||||
| 'logTamperedVCsremoved'
|
"getVcItemResponse": "GET_VC_ITEM";
|
||||||
| 'prependToMyVcsMetadata'
|
"loadMyVcs": "DOWNLOAD_LIMIT_EXPIRED" | "REFRESH_MY_VCS" | "REFRESH_RECEIVED_VCS" | "STORE_RESPONSE" | "VERIFY_VC_FAILED" | "xstate.init";
|
||||||
| 'removeDownloadFailedVcsFromStorage'
|
"loadReceivedVcs": "REFRESH_RECEIVED_VCS" | "STORE_RESPONSE";
|
||||||
| 'removeDownloadingFailedVcsFromMyVcs'
|
"logTamperedVCsremoved": "done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]";
|
||||||
| 'removeVcFromInProgressDownlods'
|
"prependToMyVcsMetadata": "VC_ADDED";
|
||||||
| 'removeVcFromMyVcsMetadata'
|
"removeDownloadFailedVcsFromStorage": "DELETE_VC";
|
||||||
| 'resetDownloadFailedVcs'
|
"removeDownloadingFailedVcsFromMyVcs": "STORE_RESPONSE";
|
||||||
| 'resetInProgressVcsDownloaded'
|
"removeVcFromInProgressDownlods": "DOWNLOAD_LIMIT_EXPIRED" | "REMOVE_VC_FROM_IN_PROGRESS_DOWNLOADS" | "VERIFY_VC_FAILED";
|
||||||
| 'resetTamperedVcs'
|
"removeVcFromMyVcsMetadata": "REMOVE_VC_FROM_CONTEXT";
|
||||||
| 'resetVerificationErrorMessage'
|
"resetDownloadFailedVcs": "STORE_RESPONSE";
|
||||||
| 'resetWalletBindingSuccess'
|
"resetInProgressVcsDownloaded": "RESET_IN_PROGRESS_VCS_DOWNLOADED";
|
||||||
| 'sendBackupEvent'
|
"resetTamperedVcs": "REMOVE_TAMPERED_VCS";
|
||||||
| 'setDownloadedVc'
|
"resetVerificationErrorMessage": "RESET_VERIFY_ERROR";
|
||||||
| 'setDownloadingFailedVcs'
|
"resetWalletBindingSuccess": "RESET_WALLET_BINDING_SUCCESS";
|
||||||
| 'setMyVcs'
|
"sendBackupEvent": "done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]";
|
||||||
| 'setReceivedVcs'
|
"setDownloadedVc": "VC_DOWNLOADED";
|
||||||
| 'setUpdatedVcMetadatas'
|
"setDownloadingFailedVcs": "DOWNLOAD_LIMIT_EXPIRED";
|
||||||
| 'setVerificationErrorMessage'
|
"setMyVcs": "STORE_RESPONSE";
|
||||||
| 'setWalletBindingSuccess'
|
"setReceivedVcs": "STORE_RESPONSE";
|
||||||
| 'updateMyVcsMetadata';
|
"setUpdatedVcMetadatas": "VC_METADATA_UPDATED";
|
||||||
delays: never;
|
"setVerificationErrorMessage": "VERIFY_VC_FAILED";
|
||||||
guards: 'isAnyVcTampered' | 'isSignedIn';
|
"setWalletBindingSuccess": "WALLET_BINDING_SUCCESS";
|
||||||
services: 'isUserSignedAlready';
|
"updateMyVcsMetadata": "VC_METADATA_UPDATED";
|
||||||
};
|
};
|
||||||
eventsCausingActions: {
|
eventsCausingDelays: {
|
||||||
addVcToInProgressDownloads: 'ADD_VC_TO_IN_PROGRESS_DOWNLOADS';
|
|
||||||
getVcItemResponse: 'GET_VC_ITEM';
|
};
|
||||||
loadMyVcs:
|
eventsCausingGuards: {
|
||||||
| 'REFRESH_MY_VCS'
|
"isAnyVcTampered": "SHOW_TAMPERED_POPUP";
|
||||||
| 'REFRESH_RECEIVED_VCS'
|
"isSignedIn": "done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]";
|
||||||
| 'STORE_RESPONSE'
|
};
|
||||||
| 'VERIFY_VC_FAILED'
|
eventsCausingServices: {
|
||||||
| 'xstate.init';
|
"isUserSignedAlready": "REMOVE_TAMPERED_VCS";
|
||||||
loadReceivedVcs: 'REFRESH_RECEIVED_VCS' | 'STORE_RESPONSE';
|
};
|
||||||
logTamperedVCsremoved: 'done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]';
|
matchesStates: "deletingFailedVcs" | "ready" | "ready.myVcs" | "ready.receivedVcs" | "ready.showTamperedPopup" | "ready.tamperedVCs" | "ready.tamperedVCs.idle" | "ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion" | { "ready"?: "myVcs" | "receivedVcs" | "showTamperedPopup" | "tamperedVCs" | { "tamperedVCs"?: "idle" | "triggerAutoBackupForTamperedVcDeletion"; }; };
|
||||||
prependToMyVcsMetadata: 'VC_ADDED';
|
tags: never;
|
||||||
removeDownloadFailedVcsFromStorage: 'DELETE_VC';
|
}
|
||||||
removeDownloadingFailedVcsFromMyVcs: 'STORE_RESPONSE';
|
|
||||||
removeVcFromInProgressDownlods:
|
|
||||||
| 'DOWNLOAD_LIMIT_EXPIRED'
|
|
||||||
| 'REMOVE_VC_FROM_IN_PROGRESS_DOWNLOADS'
|
|
||||||
| 'VERIFY_VC_FAILED';
|
|
||||||
removeVcFromMyVcsMetadata: 'REMOVE_VC_FROM_CONTEXT';
|
|
||||||
resetDownloadFailedVcs: 'STORE_RESPONSE';
|
|
||||||
resetInProgressVcsDownloaded: 'RESET_IN_PROGRESS_VCS_DOWNLOADED';
|
|
||||||
resetTamperedVcs: 'REMOVE_TAMPERED_VCS';
|
|
||||||
resetVerificationErrorMessage: 'RESET_VERIFY_ERROR';
|
|
||||||
resetWalletBindingSuccess: 'RESET_WALLET_BINDING_SUCCESS';
|
|
||||||
sendBackupEvent: 'done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]';
|
|
||||||
setDownloadedVc: 'VC_DOWNLOADED';
|
|
||||||
setDownloadingFailedVcs: 'DOWNLOAD_LIMIT_EXPIRED';
|
|
||||||
setMyVcs: 'STORE_RESPONSE';
|
|
||||||
setReceivedVcs: 'STORE_RESPONSE';
|
|
||||||
setUpdatedVcMetadatas: 'VC_METADATA_UPDATED';
|
|
||||||
setVerificationErrorMessage: 'VERIFY_VC_FAILED';
|
|
||||||
setWalletBindingSuccess: 'WALLET_BINDING_SUCCESS';
|
|
||||||
updateMyVcsMetadata: 'VC_METADATA_UPDATED';
|
|
||||||
};
|
|
||||||
eventsCausingDelays: {};
|
|
||||||
eventsCausingGuards: {
|
|
||||||
isAnyVcTampered: 'SHOW_TAMPERED_POPUP';
|
|
||||||
isSignedIn: 'done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]';
|
|
||||||
};
|
|
||||||
eventsCausingServices: {
|
|
||||||
isUserSignedAlready: 'REMOVE_TAMPERED_VCS';
|
|
||||||
};
|
|
||||||
matchesStates:
|
|
||||||
| 'deletingFailedVcs'
|
|
||||||
| 'ready'
|
|
||||||
| 'ready.myVcs'
|
|
||||||
| 'ready.receivedVcs'
|
|
||||||
| 'ready.showTamperedPopup'
|
|
||||||
| 'ready.tamperedVCs'
|
|
||||||
| 'ready.tamperedVCs.idle'
|
|
||||||
| 'ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion'
|
|
||||||
| {
|
|
||||||
ready?:
|
|
||||||
| 'myVcs'
|
|
||||||
| 'receivedVcs'
|
|
||||||
| 'showTamperedPopup'
|
|
||||||
| 'tamperedVCs'
|
|
||||||
| {tamperedVCs?: 'idle' | 'triggerAutoBackupForTamperedVcDeletion'};
|
|
||||||
};
|
|
||||||
tags: never;
|
|
||||||
}
|
|
||||||
327
machines/bleShare/scan/scanActions.ts
Normal file
327
machines/bleShare/scan/scanActions.ts
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
import { Linking } from "react-native";
|
||||||
|
import { getDeviceNameSync } from "react-native-device-info";
|
||||||
|
import { assign, spawn, send, DoneInvokeEvent } from "xstate";
|
||||||
|
import { VCShareFlowType } from "../../../shared/Utils";
|
||||||
|
import { VCMetadata } from "../../../shared/VCMetadata";
|
||||||
|
import { logState } from "../../../shared/commonUtil";
|
||||||
|
import { SHOW_FACE_AUTH_CONSENT_SHARE_FLOW, isAndroid, DEFAULT_QR_HEADER, MY_VCS_STORE_KEY, MY_LOGIN_STORE_KEY } from "../../../shared/constants";
|
||||||
|
import { getIdType } from "../../../shared/openId4VCI/Utils";
|
||||||
|
import { TelemetryConstants } from "../../../shared/telemetry/TelemetryConstants";
|
||||||
|
import { sendImpressionEvent, getImpressionEventData, sendEndEvent, getEndEventData, sendErrorEvent, getErrorEventData, sendStartEvent, getStartEventData } from "../../../shared/telemetry/TelemetryUtils";
|
||||||
|
import { createQrLoginMachine } from "../../QrLogin/QrLoginMachine";
|
||||||
|
import { VcMetaEvents } from "../../VerifiableCredential/VCMetaMachine/VCMetaEvents";
|
||||||
|
import { ActivityLogEvents } from "../../activityLog";
|
||||||
|
import { StoreEvents } from "../../store";
|
||||||
|
import tuvali from '@mosip/tuvali';
|
||||||
|
import BluetoothStateManager from 'react-native-bluetooth-state-manager';
|
||||||
|
|
||||||
|
const {wallet, EventTypes, VerificationStatus} = tuvali;
|
||||||
|
export const ScanActions =(model:any,QR_LOGIN_REF_ID:any)=>{
|
||||||
|
return{
|
||||||
|
setChildRef: assign({
|
||||||
|
QrLoginRef: (context:any) => {
|
||||||
|
const service = spawn(
|
||||||
|
createQrLoginMachine(context.serviceRefs),
|
||||||
|
QR_LOGIN_REF_ID,
|
||||||
|
);
|
||||||
|
service.subscribe(logState);
|
||||||
|
return service;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
updateShowFaceAuthConsent: model.assign({
|
||||||
|
showFaceAuthConsent: (_, event) => {
|
||||||
|
return event.response || event.response === null;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
setShowFaceAuthConsent: model.assign({
|
||||||
|
showFaceAuthConsent: (_, event) => {
|
||||||
|
return !event.isDoNotAskAgainChecked;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
getFaceAuthConsent: send(StoreEvents.GET(SHOW_FACE_AUTH_CONSENT_SHARE_FLOW), {
|
||||||
|
to: (context:any) => context.serviceRefs.store,
|
||||||
|
}),
|
||||||
|
|
||||||
|
storeShowFaceAuthConsent: send(
|
||||||
|
(context, event) =>
|
||||||
|
StoreEvents.SET(SHOW_FACE_AUTH_CONSENT_SHARE_FLOW, !event.isDoNotAskAgainChecked),
|
||||||
|
{
|
||||||
|
to: (context:any) => context.serviceRefs.store,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
sendScanData: context =>
|
||||||
|
context.QrLoginRef.send({
|
||||||
|
type: 'GET',
|
||||||
|
linkCode: context.linkCode,
|
||||||
|
flowType: context.flowType,
|
||||||
|
selectedVc: context.selectedVc,
|
||||||
|
}),
|
||||||
|
|
||||||
|
openBluetoothSettings: () => {
|
||||||
|
isAndroid()
|
||||||
|
? BluetoothStateManager.openSettings().catch()
|
||||||
|
: Linking.openURL('App-Prefs:Bluetooth');
|
||||||
|
},
|
||||||
|
|
||||||
|
openAppPermission: () => Linking.openSettings(),
|
||||||
|
|
||||||
|
enableLocation: async () => {
|
||||||
|
await Linking.sendIntent('android.settings.LOCATION_SOURCE_SETTINGS');
|
||||||
|
},
|
||||||
|
|
||||||
|
setUri: model.assign({
|
||||||
|
openId4VpUri: (_context, event) => event.params,
|
||||||
|
}),
|
||||||
|
|
||||||
|
clearUri: assign({
|
||||||
|
openId4VpUri: '',
|
||||||
|
}),
|
||||||
|
|
||||||
|
setSenderInfo: assign({
|
||||||
|
senderInfo: () => {
|
||||||
|
return {name: 'Wallet', deviceName: 'Wallet', deviceId: ''};
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
setReceiverInfo: assign({
|
||||||
|
receiverInfo: () => {
|
||||||
|
return {name: 'Verifier', deviceName: 'Verifier', deviceId: ''};
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
setReadyForBluetoothStateCheck: model.assign({
|
||||||
|
readyForBluetoothStateCheck: () => true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
setBleError: assign({
|
||||||
|
bleError: (_context, event) => event.bleError,
|
||||||
|
}),
|
||||||
|
|
||||||
|
setSelectedVc: assign({
|
||||||
|
selectedVc: (_context, event) => event.vc,
|
||||||
|
}),
|
||||||
|
|
||||||
|
resetSelectedVc: assign({
|
||||||
|
selectedVc: {},
|
||||||
|
}),
|
||||||
|
|
||||||
|
resetShowQuickShareSuccessBanner: assign({
|
||||||
|
showQuickShareSuccessBanner: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
setShowQuickShareSuccessBanner: assign({
|
||||||
|
showQuickShareSuccessBanner: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
setFlowType: assign({
|
||||||
|
flowType: (_context, event) => event.flowType,
|
||||||
|
}),
|
||||||
|
|
||||||
|
resetFlowType: assign({
|
||||||
|
flowType: VCShareFlowType.SIMPLE_SHARE,
|
||||||
|
}),
|
||||||
|
|
||||||
|
registerLoggers: assign({
|
||||||
|
loggers: () => {
|
||||||
|
if (__DEV__) {
|
||||||
|
return [
|
||||||
|
wallet.handleDataEvents(event => {
|
||||||
|
console.log(
|
||||||
|
getDeviceNameSync(),
|
||||||
|
'<Sender.Event>',
|
||||||
|
JSON.stringify(event).slice(0, 100),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
removeLoggers: assign({
|
||||||
|
loggers: ({loggers}) => {
|
||||||
|
loggers?.forEach(logger => logger.remove());
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
setShareLogTypeUnverified: model.assign({
|
||||||
|
shareLogType: 'VC_SHARED',
|
||||||
|
}),
|
||||||
|
|
||||||
|
setShareLogTypeVerified: model.assign({
|
||||||
|
shareLogType: 'PRESENCE_VERIFIED_AND_VC_SHARED',
|
||||||
|
}),
|
||||||
|
|
||||||
|
updateFaceCaptureBannerStatus: model.assign({
|
||||||
|
showFaceCaptureSuccessBanner: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
resetFaceCaptureBannerStatus: model.assign({
|
||||||
|
showFaceCaptureSuccessBanner: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
logShared: send(
|
||||||
|
(context:any) => {
|
||||||
|
const vcMetadata = context.selectedVc?.vcMetadata;
|
||||||
|
return ActivityLogEvents.LOG_ACTIVITY({
|
||||||
|
_vcKey: VCMetadata.fromVC(vcMetadata).getVcKey(),
|
||||||
|
type: context.shareLogType
|
||||||
|
? context.shareLogType
|
||||||
|
: 'VC_SHARED_WITH_VERIFICATION_CONSENT',
|
||||||
|
id: vcMetadata.id,
|
||||||
|
idType: getIdType(vcMetadata.issuer),
|
||||||
|
timestamp: Date.now(),
|
||||||
|
deviceName:
|
||||||
|
context.receiverInfo.name || context.receiverInfo.deviceName,
|
||||||
|
vcLabel: vcMetadata.id,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{to: context => context.serviceRefs.activityLog},
|
||||||
|
),
|
||||||
|
|
||||||
|
logFailedVerification: send(
|
||||||
|
context =>
|
||||||
|
ActivityLogEvents.LOG_ACTIVITY({
|
||||||
|
_vcKey: VCMetadata.fromVC(context.selectedVc).getVcKey(),
|
||||||
|
type: 'PRESENCE_VERIFICATION_FAILED',
|
||||||
|
timestamp: Date.now(),
|
||||||
|
idType: getIdType(context.selectedVc.vcMetadata.issuer),
|
||||||
|
id: context.selectedVc.vcMetadata.id,
|
||||||
|
deviceName:
|
||||||
|
context.receiverInfo.name || context.receiverInfo.deviceName,
|
||||||
|
vcLabel: context.selectedVc.vcMetadata.id,
|
||||||
|
}),
|
||||||
|
{to: context => context.serviceRefs.activityLog},
|
||||||
|
),
|
||||||
|
|
||||||
|
setLinkCode: assign({
|
||||||
|
linkCode: (_, event) =>
|
||||||
|
new URL(event.params).searchParams.get('linkCode'),
|
||||||
|
}),
|
||||||
|
setQuickShareData: assign({
|
||||||
|
quickShareData: (_, event) =>
|
||||||
|
JSON.parse(decodeData(event.params.split(DEFAULT_QR_HEADER)[1])),
|
||||||
|
}),
|
||||||
|
loadMetaDataToMemory: send(
|
||||||
|
(context:any) => {
|
||||||
|
let metadata = VCMetadata.fromVC(context.quickShareData?.meta);
|
||||||
|
return StoreEvents.PREPEND(MY_VCS_STORE_KEY, metadata);
|
||||||
|
},
|
||||||
|
{to: context => context.serviceRefs.store},
|
||||||
|
),
|
||||||
|
loadVCDataToMemory: send(
|
||||||
|
(context:any) => {
|
||||||
|
let metadata = VCMetadata.fromVC(context.quickShareData?.meta);
|
||||||
|
|
||||||
|
let verifiableCredential = metadata.isFromOpenId4VCI()
|
||||||
|
? {credential: context.quickShareData?.verifiableCredential}
|
||||||
|
: context.quickShareData?.verifiableCredential;
|
||||||
|
|
||||||
|
return StoreEvents.SET(metadata.getVcKey(), {
|
||||||
|
verifiableCredential: verifiableCredential,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{to: context => context.serviceRefs.store},
|
||||||
|
),
|
||||||
|
refreshVCs: send(VcMetaEvents.REFRESH_MY_VCS, {
|
||||||
|
to: context => context.serviceRefs.vcMeta,
|
||||||
|
}),
|
||||||
|
storeLoginItem: send(
|
||||||
|
(_context, event) => {
|
||||||
|
return StoreEvents.PREPEND(
|
||||||
|
MY_LOGIN_STORE_KEY,
|
||||||
|
(event as DoneInvokeEvent<string>).data,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
{to: (context:any) => context.serviceRefs.store},
|
||||||
|
),
|
||||||
|
|
||||||
|
storingActivityLog: send(
|
||||||
|
(_, event) =>
|
||||||
|
ActivityLogEvents.LOG_ACTIVITY({
|
||||||
|
_vcKey: '',
|
||||||
|
id: event.response.selectedVc.vcMetadata.id,
|
||||||
|
idType: getIdType(event.response.selectedVc.vcMetadata.issuer),
|
||||||
|
type: 'QRLOGIN_SUCCESFULL',
|
||||||
|
timestamp: Date.now(),
|
||||||
|
deviceName: '',
|
||||||
|
vcLabel: String(event.response.selectedVc.vcMetadata.id),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
to: (context:any) => context.serviceRefs.activityLog,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
sendVcShareSuccessEvent: () => {
|
||||||
|
sendImpressionEvent(
|
||||||
|
getImpressionEventData(
|
||||||
|
TelemetryConstants.FlowType.senderVcShare,
|
||||||
|
TelemetryConstants.Screens.vcShareSuccessPage,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
sendEndEvent(
|
||||||
|
getEndEventData(
|
||||||
|
TelemetryConstants.FlowType.senderVcShare,
|
||||||
|
TelemetryConstants.EndEventStatus.success,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
sendBLEConnectionErrorEvent: (_context, event) => {
|
||||||
|
sendErrorEvent(
|
||||||
|
getErrorEventData(
|
||||||
|
TelemetryConstants.FlowType.senderVcShare,
|
||||||
|
event.bleError.code,
|
||||||
|
event.bleError.message,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
sendEndEvent(
|
||||||
|
getEndEventData(
|
||||||
|
TelemetryConstants.FlowType.senderVcShare,
|
||||||
|
TelemetryConstants.EndEventStatus.failure,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
sendVcSharingStartEvent: () => {
|
||||||
|
sendStartEvent(
|
||||||
|
getStartEventData(TelemetryConstants.FlowType.senderVcShare),
|
||||||
|
);
|
||||||
|
sendImpressionEvent(
|
||||||
|
getImpressionEventData(
|
||||||
|
TelemetryConstants.FlowType.senderVcShare,
|
||||||
|
TelemetryConstants.Screens.scanScreen,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
sendVCShareFlowCancelEndEvent: () => {
|
||||||
|
sendEndEvent(
|
||||||
|
getEndEventData(
|
||||||
|
TelemetryConstants.FlowType.senderVcShare,
|
||||||
|
TelemetryConstants.EndEventStatus.cancel,
|
||||||
|
{comment: 'User cancelled VC share'},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
sendVCShareFlowTimeoutEndEvent: () => {
|
||||||
|
sendEndEvent(
|
||||||
|
getEndEventData(
|
||||||
|
TelemetryConstants.FlowType.senderVcShare,
|
||||||
|
TelemetryConstants.EndEventStatus.failure,
|
||||||
|
{comment: 'VC sharing timeout'},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
45
machines/bleShare/scan/scanGuards.ts
Normal file
45
machines/bleShare/scan/scanGuards.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { VCShareFlowType } from "../../../shared/Utils";
|
||||||
|
import { androidVersion, isAndroid, isIOS } from "../../../shared/constants";
|
||||||
|
|
||||||
|
export const ScanGuards = () => {
|
||||||
|
return {
|
||||||
|
showFaceAuthConsentScreen: context => {
|
||||||
|
return context.showFaceAuthConsent;
|
||||||
|
},
|
||||||
|
|
||||||
|
// sample: 'OPENID4VP://connect:?name=OVPMOSIP&key=69dc92a2cc91f02258aa8094d6e2b62877f5b6498924fbaedaaa46af30abb364'
|
||||||
|
isOpenIdQr: (_context, event) =>
|
||||||
|
event.params.startsWith('OPENID4VP://'),
|
||||||
|
// sample: 'INJIQUICKSHARE://NAKDFK:DB:JAHDIHAIDJXKABDAJDHUHW'
|
||||||
|
isQuickShare: (_context, event) =>
|
||||||
|
// event.params.startsWith(DEFAULT_QR_HEADER),
|
||||||
|
// toggling the feature for now
|
||||||
|
false,
|
||||||
|
isQrLogin: (context, event) => {
|
||||||
|
try {
|
||||||
|
let linkCode = new URL(event.params);
|
||||||
|
// sample: 'inji://landing-page-name?linkCode=sTjp0XVH3t3dGCU&linkExpireDateTime=2023-11-09T06:56:18.482Z'
|
||||||
|
return linkCode.searchParams.get('linkCode') !== null;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
uptoAndroid11: () => isAndroid() && androidVersion < 31,
|
||||||
|
|
||||||
|
isIOS: () => isIOS(),
|
||||||
|
|
||||||
|
isMinimumStorageRequiredForAuditEntryReached: (_context, event) =>
|
||||||
|
Boolean(event.data),
|
||||||
|
|
||||||
|
isFlowTypeMiniViewShareWithSelfie: context =>
|
||||||
|
context.flowType === VCShareFlowType.MINI_VIEW_SHARE_WITH_SELFIE,
|
||||||
|
|
||||||
|
isFlowTypeMiniViewShare: context =>
|
||||||
|
context.flowType === VCShareFlowType.MINI_VIEW_SHARE,
|
||||||
|
|
||||||
|
isFlowTypeSimpleShare: context =>
|
||||||
|
context.flowType === VCShareFlowType.SIMPLE_SHARE,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
@@ -1,141 +1,23 @@
|
|||||||
/* eslint-disable sonarjs/no-duplicate-string */
|
/* eslint-disable sonarjs/no-duplicate-string */
|
||||||
import tuvali from '@mosip/tuvali';
|
|
||||||
import BluetoothStateManager from 'react-native-bluetooth-state-manager';
|
|
||||||
import {
|
import {
|
||||||
ActorRefFrom,
|
|
||||||
assign,
|
|
||||||
DoneInvokeEvent,
|
|
||||||
EventFrom,
|
EventFrom,
|
||||||
send,
|
send,
|
||||||
spawn,
|
StateFrom
|
||||||
StateFrom,
|
|
||||||
} from 'xstate';
|
} from 'xstate';
|
||||||
import {createModel} from 'xstate/lib/model';
|
import { AppServices } from '../../../shared/GlobalContext';
|
||||||
import {EmitterSubscription, Linking} from 'react-native';
|
import { TelemetryConstants } from '../../../shared/telemetry/TelemetryConstants';
|
||||||
import {DeviceInfo} from '../../../components/DeviceInfoList';
|
|
||||||
import {getDeviceNameSync, isLocationEnabled} from 'react-native-device-info';
|
|
||||||
import {VC} from '../../VerifiableCredential/VCMetaMachine/vc';
|
|
||||||
import {AppServices} from '../../../shared/GlobalContext';
|
|
||||||
import {ActivityLogEvents, ActivityLogType} from '../../activityLog';
|
|
||||||
import {
|
import {
|
||||||
androidVersion,
|
|
||||||
DEFAULT_QR_HEADER,
|
|
||||||
FACE_AUTH_CONSENT,
|
|
||||||
isAndroid,
|
|
||||||
isIOS,
|
|
||||||
MY_LOGIN_STORE_KEY,
|
|
||||||
MY_VCS_STORE_KEY,
|
|
||||||
} from '../../../shared/constants';
|
|
||||||
import {subscribe} from '../../../shared/openIdBLE/walletEventHandler';
|
|
||||||
import {
|
|
||||||
check,
|
|
||||||
checkMultiple,
|
|
||||||
PERMISSIONS,
|
|
||||||
PermissionStatus,
|
|
||||||
requestMultiple,
|
|
||||||
RESULTS,
|
|
||||||
} from 'react-native-permissions';
|
|
||||||
import {
|
|
||||||
checkLocationPermissionStatus,
|
|
||||||
requestLocationPermission,
|
|
||||||
} from '../../../shared/location';
|
|
||||||
import {CameraCapturedPicture} from 'expo-camera';
|
|
||||||
import {createQrLoginMachine, qrLoginMachine} from '../../QrLoginMachine';
|
|
||||||
import {StoreEvents} from '../../store';
|
|
||||||
import {WalletDataEvent} from '@mosip/tuvali/lib/typescript/types/events';
|
|
||||||
import {BLEError} from '../types';
|
|
||||||
import Storage from '../../../shared/storage';
|
|
||||||
import {VCMetadata} from '../../../shared/VCMetadata';
|
|
||||||
import {
|
|
||||||
getEndEventData,
|
|
||||||
getErrorEventData,
|
|
||||||
getImpressionEventData,
|
|
||||||
getStartEventData,
|
getStartEventData,
|
||||||
sendEndEvent,
|
sendStartEvent
|
||||||
sendErrorEvent,
|
|
||||||
sendImpressionEvent,
|
|
||||||
sendStartEvent,
|
|
||||||
} from '../../../shared/telemetry/TelemetryUtils';
|
} from '../../../shared/telemetry/TelemetryUtils';
|
||||||
import {TelemetryConstants} from '../../../shared/telemetry/TelemetryConstants';
|
import { qrLoginMachine } from '../../QrLogin/QrLoginMachine';
|
||||||
import {logState} from '../../../shared/commonUtil';
|
|
||||||
import {VCShareFlowType} from '../../../shared/Utils';
|
|
||||||
import {getIdType} from '../../../shared/openId4VCI/Utils';
|
|
||||||
import {VcMetaEvents} from '../../VerifiableCredential/VCMetaMachine/VCMetaMachine';
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import {decodeData} from '@mosip/pixelpass';
|
import { ScanActions } from './scanActions';
|
||||||
|
import { ScanGuards } from './scanGuards';
|
||||||
|
import { ScanModel } from './scanModel';
|
||||||
|
import { ScanServices } from './scanServices';
|
||||||
|
|
||||||
const {wallet, EventTypes, VerificationStatus} = tuvali;
|
const model=ScanModel;
|
||||||
|
|
||||||
const model = createModel(
|
|
||||||
{
|
|
||||||
serviceRefs: {} as AppServices,
|
|
||||||
senderInfo: {} as DeviceInfo,
|
|
||||||
receiverInfo: {} as DeviceInfo,
|
|
||||||
selectedVc: {} as VC,
|
|
||||||
bleError: {} as BLEError,
|
|
||||||
loggers: [] as EmitterSubscription[],
|
|
||||||
vcName: '',
|
|
||||||
flowType: VCShareFlowType.SIMPLE_SHARE,
|
|
||||||
verificationImage: {} as CameraCapturedPicture,
|
|
||||||
openId4VpUri: '',
|
|
||||||
shareLogType: '' as ActivityLogType,
|
|
||||||
QrLoginRef: {} as ActorRefFrom<typeof qrLoginMachine>,
|
|
||||||
showQuickShareSuccessBanner: false,
|
|
||||||
linkCode: '',
|
|
||||||
quickShareData: {},
|
|
||||||
showFaceAuthConsent: true as boolean,
|
|
||||||
readyForBluetoothStateCheck: false,
|
|
||||||
showFaceCaptureSuccessBanner: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
events: {
|
|
||||||
SELECT_VC: (vc: VC, flowType: string) => ({vc, flowType}),
|
|
||||||
SCAN: (params: string) => ({params}),
|
|
||||||
ACCEPT_REQUEST: () => ({}),
|
|
||||||
VERIFY_AND_ACCEPT_REQUEST: () => ({}),
|
|
||||||
VC_ACCEPTED: () => ({}),
|
|
||||||
VC_REJECTED: () => ({}),
|
|
||||||
VC_SENT: () => ({}),
|
|
||||||
CANCEL: () => ({}),
|
|
||||||
CLOSE_BANNER: () => ({}),
|
|
||||||
STAY_IN_PROGRESS: () => ({}),
|
|
||||||
RETRY: () => ({}),
|
|
||||||
DISMISS: () => ({}),
|
|
||||||
DISMISS_QUICK_SHARE_BANNER: () => ({}),
|
|
||||||
GOTO_HISTORY: () => ({}),
|
|
||||||
CONNECTED: () => ({}),
|
|
||||||
DISCONNECT: () => ({}),
|
|
||||||
BLE_ERROR: (bleError: BLEError) => ({bleError}),
|
|
||||||
CONNECTION_DESTROYED: () => ({}),
|
|
||||||
SCREEN_BLUR: () => ({}),
|
|
||||||
SCREEN_FOCUS: () => ({}),
|
|
||||||
BLUETOOTH_PERMISSION_ENABLED: () => ({}),
|
|
||||||
BLUETOOTH_PERMISSION_DENIED: () => ({}),
|
|
||||||
BLUETOOTH_STATE_ENABLED: () => ({}),
|
|
||||||
BLUETOOTH_STATE_DISABLED: () => ({}),
|
|
||||||
NEARBY_ENABLED: () => ({}),
|
|
||||||
NEARBY_DISABLED: () => ({}),
|
|
||||||
GOTO_SETTINGS: () => ({}),
|
|
||||||
START_PERMISSION_CHECK: () => ({}),
|
|
||||||
LOCATION_ENABLED: () => ({}),
|
|
||||||
LOCATION_DISABLED: () => ({}),
|
|
||||||
LOCATION_REQUEST: () => ({}),
|
|
||||||
CHECK_FLOW_TYPE: () => ({}),
|
|
||||||
UPDATE_VC_NAME: (vcName: string) => ({vcName}),
|
|
||||||
STORE_RESPONSE: (response: any) => ({response}),
|
|
||||||
APP_ACTIVE: () => ({}),
|
|
||||||
FACE_VALID: () => ({}),
|
|
||||||
FACE_INVALID: () => ({}),
|
|
||||||
RETRY_VERIFICATION: () => ({}),
|
|
||||||
RESET: () => ({}),
|
|
||||||
FACE_VERIFICATION_CONSENT: (isConsentGiven: boolean) => ({
|
|
||||||
isConsentGiven,
|
|
||||||
}),
|
|
||||||
ALLOWED: () => ({}),
|
|
||||||
DENIED: () => ({}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const QR_LOGIN_REF_ID = 'QrLogin';
|
const QR_LOGIN_REF_ID = 'QrLogin';
|
||||||
export const ScanEvents = model.events;
|
export const ScanEvents = model.events;
|
||||||
|
|
||||||
@@ -167,6 +49,7 @@ export const scanMachine =
|
|||||||
actions: ['sendBLEConnectionErrorEvent', 'setBleError'],
|
actions: ['sendBLEConnectionErrorEvent', 'setBleError'],
|
||||||
},
|
},
|
||||||
RESET: {
|
RESET: {
|
||||||
|
actions:['removeLoggers', 'resetFlowType', 'resetSelectedVc'],
|
||||||
target: '.checkStorage',
|
target: '.checkStorage',
|
||||||
},
|
},
|
||||||
DISMISS: {
|
DISMISS: {
|
||||||
@@ -204,7 +87,7 @@ export const scanMachine =
|
|||||||
target: 'restrictSharingVc',
|
target: 'restrictSharingVc',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
target: 'startPermissionCheck',
|
target: 'startPermissionCheck',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -562,7 +445,7 @@ export const scanMachine =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
cond: 'isFlowTypeMiniViewShareWithSelfie',
|
cond: 'isFlowTypeMiniViewShareWithSelfie',
|
||||||
target: '.verifyingIdentity',
|
target:'.checkFaceAuthConsentForMiniView' ,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -701,6 +584,16 @@ export const scanMachine =
|
|||||||
entry: ['resetFlowType', 'resetSelectedVc'],
|
entry: ['resetFlowType', 'resetSelectedVc'],
|
||||||
always: '#scan.disconnected',
|
always: '#scan.disconnected',
|
||||||
},
|
},
|
||||||
|
checkFaceAuthConsentForMiniView: {
|
||||||
|
always:[
|
||||||
|
{
|
||||||
|
cond: 'showFaceAuthConsentScreen',
|
||||||
|
target: 'faceVerificationConsent'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
target: 'verifyingIdentity'
|
||||||
|
}
|
||||||
|
],},
|
||||||
faceVerificationConsent: {
|
faceVerificationConsent: {
|
||||||
on: {
|
on: {
|
||||||
FACE_VERIFICATION_CONSENT: {
|
FACE_VERIFICATION_CONSENT: {
|
||||||
@@ -710,9 +603,15 @@ export const scanMachine =
|
|||||||
],
|
],
|
||||||
target: 'verifyingIdentity',
|
target: 'verifyingIdentity',
|
||||||
},
|
},
|
||||||
DISMISS: {
|
DISMISS:[
|
||||||
target: '#scan.reviewing.selectingVc',
|
{
|
||||||
},
|
cond: 'isFlowTypeMiniViewShareWithSelfie',
|
||||||
|
target: '#scan.checkFaceAuthConsent',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
target: '#scan.reviewing.selectingVc',
|
||||||
|
}
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
verifyingIdentity: {
|
verifyingIdentity: {
|
||||||
@@ -860,534 +759,19 @@ export const scanMachine =
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
actions: {
|
actions: ScanActions(model,QR_LOGIN_REF_ID),
|
||||||
setChildRef: assign({
|
|
||||||
QrLoginRef: context => {
|
|
||||||
const service = spawn(
|
|
||||||
createQrLoginMachine(context.serviceRefs),
|
|
||||||
QR_LOGIN_REF_ID,
|
|
||||||
);
|
|
||||||
service.subscribe(logState);
|
|
||||||
return service;
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
updateShowFaceAuthConsent: model.assign({
|
services: ScanServices(model),
|
||||||
showFaceAuthConsent: (_, event) => {
|
|
||||||
return event.response || event.response === null;
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
setShowFaceAuthConsent: model.assign({
|
|
||||||
showFaceAuthConsent: (_, event) => {
|
|
||||||
return !event.isConsentGiven;
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
getFaceAuthConsent: send(StoreEvents.GET(FACE_AUTH_CONSENT), {
|
|
||||||
to: context => context.serviceRefs.store,
|
|
||||||
}),
|
|
||||||
|
|
||||||
storeShowFaceAuthConsent: send(
|
|
||||||
(context, event) =>
|
|
||||||
StoreEvents.SET(FACE_AUTH_CONSENT, !event.isConsentGiven),
|
|
||||||
{
|
|
||||||
to: context => context.serviceRefs.store,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
sendScanData: context =>
|
|
||||||
context.QrLoginRef.send({
|
|
||||||
type: 'GET',
|
|
||||||
linkCode: context.linkCode,
|
|
||||||
flowType: context.flowType,
|
|
||||||
selectedVc: context.selectedVc,
|
|
||||||
faceAuthConsentGiven: context.showFaceAuthConsent,
|
|
||||||
}),
|
|
||||||
|
|
||||||
openBluetoothSettings: () => {
|
|
||||||
isAndroid()
|
|
||||||
? BluetoothStateManager.openSettings().catch()
|
|
||||||
: Linking.openURL('App-Prefs:Bluetooth');
|
|
||||||
},
|
|
||||||
|
|
||||||
openAppPermission: () => Linking.openSettings(),
|
|
||||||
|
|
||||||
enableLocation: async () => {
|
|
||||||
await Linking.sendIntent('android.settings.LOCATION_SOURCE_SETTINGS');
|
|
||||||
},
|
|
||||||
|
|
||||||
setUri: model.assign({
|
|
||||||
openId4VpUri: (_context, event) => event.params,
|
|
||||||
}),
|
|
||||||
|
|
||||||
clearUri: assign({
|
|
||||||
openId4VpUri: '',
|
|
||||||
}),
|
|
||||||
|
|
||||||
setSenderInfo: assign({
|
|
||||||
senderInfo: () => {
|
|
||||||
return {name: 'Wallet', deviceName: 'Wallet', deviceId: ''};
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
setReceiverInfo: assign({
|
|
||||||
receiverInfo: () => {
|
|
||||||
return {name: 'Verifier', deviceName: 'Verifier', deviceId: ''};
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
setReadyForBluetoothStateCheck: model.assign({
|
|
||||||
readyForBluetoothStateCheck: () => true,
|
|
||||||
}),
|
|
||||||
|
|
||||||
setBleError: assign({
|
|
||||||
bleError: (_context, event) => event.bleError,
|
|
||||||
}),
|
|
||||||
|
|
||||||
setSelectedVc: assign({
|
|
||||||
selectedVc: (_context, event) => event.vc,
|
|
||||||
}),
|
|
||||||
|
|
||||||
resetSelectedVc: assign({
|
|
||||||
selectedVc: {},
|
|
||||||
}),
|
|
||||||
|
|
||||||
resetShowQuickShareSuccessBanner: assign({
|
|
||||||
showQuickShareSuccessBanner: false,
|
|
||||||
}),
|
|
||||||
|
|
||||||
setShowQuickShareSuccessBanner: assign({
|
|
||||||
showQuickShareSuccessBanner: true,
|
|
||||||
}),
|
|
||||||
|
|
||||||
setFlowType: assign({
|
|
||||||
flowType: (_context, event) => event.flowType,
|
|
||||||
}),
|
|
||||||
|
|
||||||
resetFlowType: assign({
|
|
||||||
flowType: VCShareFlowType.SIMPLE_SHARE,
|
|
||||||
}),
|
|
||||||
|
|
||||||
registerLoggers: assign({
|
|
||||||
loggers: () => {
|
|
||||||
if (__DEV__) {
|
|
||||||
return [
|
|
||||||
wallet.handleDataEvents(event => {
|
|
||||||
console.log(
|
|
||||||
getDeviceNameSync(),
|
|
||||||
'<Sender.Event>',
|
|
||||||
JSON.stringify(event).slice(0, 100),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
removeLoggers: assign({
|
|
||||||
loggers: ({loggers}) => {
|
|
||||||
loggers?.forEach(logger => logger.remove());
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
setShareLogTypeUnverified: model.assign({
|
|
||||||
shareLogType: 'VC_SHARED',
|
|
||||||
}),
|
|
||||||
|
|
||||||
setShareLogTypeVerified: model.assign({
|
|
||||||
shareLogType: 'PRESENCE_VERIFIED_AND_VC_SHARED',
|
|
||||||
}),
|
|
||||||
|
|
||||||
updateFaceCaptureBannerStatus: model.assign({
|
|
||||||
showFaceCaptureSuccessBanner: true,
|
|
||||||
}),
|
|
||||||
|
|
||||||
resetFaceCaptureBannerStatus: model.assign({
|
|
||||||
showFaceCaptureSuccessBanner: false,
|
|
||||||
}),
|
|
||||||
|
|
||||||
logShared: send(
|
|
||||||
context => {
|
|
||||||
const vcMetadata = context.selectedVc?.vcMetadata;
|
|
||||||
return ActivityLogEvents.LOG_ACTIVITY({
|
|
||||||
_vcKey: VCMetadata.fromVC(vcMetadata).getVcKey(),
|
|
||||||
type: context.shareLogType
|
|
||||||
? context.shareLogType
|
|
||||||
: 'VC_SHARED_WITH_VERIFICATION_CONSENT',
|
|
||||||
id: vcMetadata.id,
|
|
||||||
idType: getIdType(vcMetadata.issuer),
|
|
||||||
timestamp: Date.now(),
|
|
||||||
deviceName:
|
|
||||||
context.receiverInfo.name || context.receiverInfo.deviceName,
|
|
||||||
vcLabel: vcMetadata.id,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
{to: context => context.serviceRefs.activityLog},
|
|
||||||
),
|
|
||||||
|
|
||||||
logFailedVerification: send(
|
|
||||||
context =>
|
|
||||||
ActivityLogEvents.LOG_ACTIVITY({
|
|
||||||
_vcKey: VCMetadata.fromVC(context.selectedVc).getVcKey(),
|
|
||||||
type: 'PRESENCE_VERIFICATION_FAILED',
|
|
||||||
timestamp: Date.now(),
|
|
||||||
idType: getIdType(context.selectedVc.vcMetadata.issuer),
|
|
||||||
id: context.selectedVc.vcMetadata.id,
|
|
||||||
deviceName:
|
|
||||||
context.receiverInfo.name || context.receiverInfo.deviceName,
|
|
||||||
vcLabel: context.selectedVc.vcMetadata.id,
|
|
||||||
}),
|
|
||||||
{to: context => context.serviceRefs.activityLog},
|
|
||||||
),
|
|
||||||
|
|
||||||
setLinkCode: assign({
|
|
||||||
linkCode: (_, event) =>
|
|
||||||
new URL(event.params).searchParams.get('linkCode'),
|
|
||||||
}),
|
|
||||||
setQuickShareData: assign({
|
|
||||||
quickShareData: (_, event) =>
|
|
||||||
JSON.parse(decodeData(event.params.split(DEFAULT_QR_HEADER)[1])),
|
|
||||||
}),
|
|
||||||
loadMetaDataToMemory: send(
|
|
||||||
context => {
|
|
||||||
let metadata = VCMetadata.fromVC(context.quickShareData?.meta);
|
|
||||||
return StoreEvents.PREPEND(MY_VCS_STORE_KEY, metadata);
|
|
||||||
},
|
|
||||||
{to: context => context.serviceRefs.store},
|
|
||||||
),
|
|
||||||
loadVCDataToMemory: send(
|
|
||||||
context => {
|
|
||||||
let metadata = VCMetadata.fromVC(context.quickShareData?.meta);
|
|
||||||
|
|
||||||
let verifiableCredential = metadata.isFromOpenId4VCI()
|
|
||||||
? {credential: context.quickShareData?.verifiableCredential}
|
|
||||||
: context.quickShareData?.verifiableCredential;
|
|
||||||
|
|
||||||
return StoreEvents.SET(metadata.getVcKey(), {
|
|
||||||
verifiableCredential: verifiableCredential,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
{to: context => context.serviceRefs.store},
|
|
||||||
),
|
|
||||||
refreshVCs: send(VcMetaEvents.REFRESH_MY_VCS, {
|
|
||||||
to: context => context.serviceRefs.vcMeta,
|
|
||||||
}),
|
|
||||||
storeLoginItem: send(
|
|
||||||
(_context, event) => {
|
|
||||||
return StoreEvents.PREPEND(
|
|
||||||
MY_LOGIN_STORE_KEY,
|
|
||||||
(event as DoneInvokeEvent<string>).data,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
{to: context => context.serviceRefs.store},
|
|
||||||
),
|
|
||||||
|
|
||||||
storingActivityLog: send(
|
|
||||||
(_, event) =>
|
|
||||||
ActivityLogEvents.LOG_ACTIVITY({
|
|
||||||
_vcKey: '',
|
|
||||||
id: event.response.selectedVc.vcMetadata.id,
|
|
||||||
idType: getIdType(event.response.selectedVc.vcMetadata.issuer),
|
|
||||||
type: 'QRLOGIN_SUCCESFULL',
|
|
||||||
timestamp: Date.now(),
|
|
||||||
deviceName: '',
|
|
||||||
vcLabel: String(event.response.selectedVc.vcMetadata.id),
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
to: context => context.serviceRefs.activityLog,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
sendVcShareSuccessEvent: () => {
|
|
||||||
sendImpressionEvent(
|
|
||||||
getImpressionEventData(
|
|
||||||
TelemetryConstants.FlowType.senderVcShare,
|
|
||||||
TelemetryConstants.Screens.vcShareSuccessPage,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
sendEndEvent(
|
|
||||||
getEndEventData(
|
|
||||||
TelemetryConstants.FlowType.senderVcShare,
|
|
||||||
TelemetryConstants.EndEventStatus.success,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
sendBLEConnectionErrorEvent: (_context, event) => {
|
|
||||||
sendErrorEvent(
|
|
||||||
getErrorEventData(
|
|
||||||
TelemetryConstants.FlowType.senderVcShare,
|
|
||||||
event.bleError.code,
|
|
||||||
event.bleError.message,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
sendEndEvent(
|
|
||||||
getEndEventData(
|
|
||||||
TelemetryConstants.FlowType.senderVcShare,
|
|
||||||
TelemetryConstants.EndEventStatus.failure,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
sendVcSharingStartEvent: () => {
|
|
||||||
sendStartEvent(
|
|
||||||
getStartEventData(TelemetryConstants.FlowType.senderVcShare),
|
|
||||||
);
|
|
||||||
sendImpressionEvent(
|
|
||||||
getImpressionEventData(
|
|
||||||
TelemetryConstants.FlowType.senderVcShare,
|
|
||||||
TelemetryConstants.Screens.scanScreen,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
sendVCShareFlowCancelEndEvent: () => {
|
|
||||||
sendEndEvent(
|
|
||||||
getEndEventData(
|
|
||||||
TelemetryConstants.FlowType.senderVcShare,
|
|
||||||
TelemetryConstants.EndEventStatus.cancel,
|
|
||||||
{comment: 'User cancelled VC share'},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
sendVCShareFlowTimeoutEndEvent: () => {
|
|
||||||
sendEndEvent(
|
|
||||||
getEndEventData(
|
|
||||||
TelemetryConstants.FlowType.senderVcShare,
|
|
||||||
TelemetryConstants.EndEventStatus.failure,
|
|
||||||
{comment: 'VC sharing timeout'},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
services: {
|
|
||||||
checkBluetoothPermission: () => async callback => {
|
|
||||||
// wait a bit for animation to finish when app becomes active
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 250));
|
|
||||||
try {
|
|
||||||
// Passing Granted for android since permission status is always granted even if its denied.
|
|
||||||
let response: PermissionStatus = RESULTS.GRANTED;
|
|
||||||
|
|
||||||
if (isIOS()) {
|
|
||||||
response = await check(PERMISSIONS.IOS.BLUETOOTH_PERIPHERAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response === RESULTS.GRANTED) {
|
|
||||||
callback(model.events.BLUETOOTH_PERMISSION_ENABLED());
|
|
||||||
} else {
|
|
||||||
callback(model.events.BLUETOOTH_PERMISSION_DENIED());
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
checkBluetoothState: () => callback => {
|
|
||||||
const subscription = BluetoothStateManager.onStateChange(state => {
|
|
||||||
if (state === 'PoweredOn') {
|
|
||||||
callback(model.events.BLUETOOTH_STATE_ENABLED());
|
|
||||||
} else {
|
|
||||||
callback(model.events.BLUETOOTH_STATE_DISABLED());
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
return () => subscription.remove();
|
|
||||||
},
|
|
||||||
|
|
||||||
requestBluetooth: () => callback => {
|
|
||||||
BluetoothStateManager.requestToEnable()
|
|
||||||
.then(() => callback(model.events.BLUETOOTH_STATE_ENABLED()))
|
|
||||||
.catch(() => callback(model.events.BLUETOOTH_STATE_DISABLED()));
|
|
||||||
},
|
|
||||||
|
|
||||||
requestToEnableLocationPermission: () => callback => {
|
|
||||||
requestLocationPermission(
|
|
||||||
() => callback(model.events.LOCATION_ENABLED()),
|
|
||||||
() => callback(model.events.LOCATION_DISABLED()),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
monitorConnection: () => callback => {
|
|
||||||
const walletErrorCodePrefix = 'TVW';
|
|
||||||
const subscription = wallet.handleDataEvents(event => {
|
|
||||||
if (event.type === EventTypes.onDisconnected) {
|
|
||||||
callback({type: 'DISCONNECT'});
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
event.type === EventTypes.onError &&
|
|
||||||
event.code.includes(walletErrorCodePrefix)
|
|
||||||
) {
|
|
||||||
callback({
|
|
||||||
type: 'BLE_ERROR',
|
|
||||||
bleError: {message: event.message, code: event.code},
|
|
||||||
});
|
|
||||||
console.error('BLE Exception: ' + event.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => subscription.remove();
|
|
||||||
},
|
|
||||||
|
|
||||||
checkNearByDevicesPermission: () => callback => {
|
|
||||||
checkMultiple([
|
|
||||||
PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
|
|
||||||
PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
|
|
||||||
])
|
|
||||||
.then(response => {
|
|
||||||
if (
|
|
||||||
response[PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE] ===
|
|
||||||
RESULTS.GRANTED &&
|
|
||||||
response[PERMISSIONS.ANDROID.BLUETOOTH_CONNECT] ===
|
|
||||||
RESULTS.GRANTED
|
|
||||||
) {
|
|
||||||
callback(model.events.NEARBY_ENABLED());
|
|
||||||
} else {
|
|
||||||
callback(model.events.NEARBY_DISABLED());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
callback(model.events.NEARBY_DISABLED());
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
requestNearByDevicesPermission: () => callback => {
|
|
||||||
requestMultiple([
|
|
||||||
PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
|
|
||||||
PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
|
|
||||||
])
|
|
||||||
.then(response => {
|
|
||||||
if (
|
|
||||||
response[PERMISSIONS.ANDROID.BLUETOOTH_SCAN] ===
|
|
||||||
RESULTS.GRANTED &&
|
|
||||||
response[PERMISSIONS.ANDROID.BLUETOOTH_CONNECT] ===
|
|
||||||
RESULTS.GRANTED
|
|
||||||
) {
|
|
||||||
callback(model.events.NEARBY_ENABLED());
|
|
||||||
} else {
|
|
||||||
callback(model.events.NEARBY_DISABLED());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
callback(model.events.NEARBY_DISABLED());
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
checkLocationPermission: () => callback => {
|
|
||||||
checkLocationPermissionStatus(
|
|
||||||
() => callback(model.events.LOCATION_ENABLED()),
|
|
||||||
() => callback(model.events.LOCATION_DISABLED()),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
checkLocationStatus: () => async callback => {
|
|
||||||
const isEnabled: boolean = await isLocationEnabled();
|
|
||||||
if (isEnabled) {
|
|
||||||
callback(model.events.LOCATION_ENABLED());
|
|
||||||
} else {
|
|
||||||
callback(model.events.LOCATION_DISABLED());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
startConnection: context => callback => {
|
|
||||||
wallet.startConnection(context.openId4VpUri);
|
|
||||||
const statusCallback = (event: WalletDataEvent) => {
|
|
||||||
if (event.type === EventTypes.onSecureChannelEstablished) {
|
|
||||||
callback({type: 'CONNECTED'});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const subscription = subscribe(statusCallback);
|
|
||||||
return () => subscription?.remove();
|
|
||||||
},
|
|
||||||
|
|
||||||
sendVc: context => callback => {
|
|
||||||
const statusCallback = (event: WalletDataEvent) => {
|
|
||||||
if (event.type === EventTypes.onDataSent) {
|
|
||||||
callback({type: 'VC_SENT'});
|
|
||||||
} else if (event.type === EventTypes.onVerificationStatusReceived) {
|
|
||||||
callback({
|
|
||||||
type:
|
|
||||||
event.status === VerificationStatus.ACCEPTED
|
|
||||||
? 'VC_ACCEPTED'
|
|
||||||
: 'VC_REJECTED',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
wallet.sendData(
|
|
||||||
JSON.stringify({
|
|
||||||
...context.selectedVc,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
const subscription = subscribe(statusCallback);
|
|
||||||
return () => subscription?.remove();
|
|
||||||
},
|
|
||||||
|
|
||||||
disconnect: () => () => {
|
|
||||||
try {
|
|
||||||
wallet.disconnect();
|
|
||||||
} catch (e) {
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
checkStorageAvailability: () => async () => {
|
|
||||||
return Promise.resolve(
|
|
||||||
Storage.isMinimumLimitReached('minStorageRequiredForAuditEntry'),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
guards: {
|
|
||||||
showFaceAuthConsentScreen: context => {
|
|
||||||
return context.showFaceAuthConsent;
|
|
||||||
},
|
|
||||||
|
|
||||||
// sample: 'OPENID4VP://connect:?name=OVPMOSIP&key=69dc92a2cc91f02258aa8094d6e2b62877f5b6498924fbaedaaa46af30abb364'
|
|
||||||
isOpenIdQr: (_context, event) =>
|
|
||||||
event.params.startsWith('OPENID4VP://'),
|
|
||||||
// sample: 'INJIQUICKSHARE://NAKDFK:DB:JAHDIHAIDJXKABDAJDHUHW'
|
|
||||||
isQuickShare: (_context, event) =>
|
|
||||||
// event.params.startsWith(DEFAULT_QR_HEADER),
|
|
||||||
// toggling the feature for now
|
|
||||||
false,
|
|
||||||
isQrLogin: (context, event) => {
|
|
||||||
try {
|
|
||||||
let linkCode = new URL(event.params);
|
|
||||||
// sample: 'inji://landing-page-name?linkCode=sTjp0XVH3t3dGCU&linkExpireDateTime=2023-11-09T06:56:18.482Z'
|
|
||||||
return linkCode.searchParams.get('linkCode') !== null;
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
uptoAndroid11: () => isAndroid() && androidVersion < 31,
|
|
||||||
|
|
||||||
isIOS: () => isIOS(),
|
|
||||||
|
|
||||||
isMinimumStorageRequiredForAuditEntryReached: (_context, event) =>
|
|
||||||
Boolean(event.data),
|
|
||||||
|
|
||||||
isFlowTypeMiniViewShareWithSelfie: context =>
|
|
||||||
context.flowType === VCShareFlowType.MINI_VIEW_SHARE_WITH_SELFIE,
|
|
||||||
|
|
||||||
isFlowTypeMiniViewShare: context =>
|
|
||||||
context.flowType === VCShareFlowType.MINI_VIEW_SHARE,
|
|
||||||
|
|
||||||
isFlowTypeSimpleShare: context =>
|
|
||||||
context.flowType === VCShareFlowType.SIMPLE_SHARE,
|
|
||||||
},
|
|
||||||
|
|
||||||
|
guards: ScanGuards(),
|
||||||
delays: {
|
delays: {
|
||||||
DESTROY_TIMEOUT: 500,
|
DESTROY_TIMEOUT: 500,
|
||||||
CONNECTION_TIMEOUT: 5 * 1000,
|
CONNECTION_TIMEOUT: 5 * 1000,
|
||||||
SHARING_TIMEOUT: 15 * 1000,
|
SHARING_TIMEOUT: 15 * 1000,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
type State = StateFrom<typeof scanMachine>;
|
type State = StateFrom<typeof scanMachine>;
|
||||||
@@ -1399,12 +783,3 @@ export function createScanMachine(serviceRefs: AppServices) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectIsMinimumStorageRequiredForAuditEntryLimitReached(
|
|
||||||
state: State,
|
|
||||||
) {
|
|
||||||
return state.matches('restrictSharingVc');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function selectIsFaceVerificationConsent(state: State) {
|
|
||||||
return state.matches('reviewing.faceVerificationConsent');
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,238 +1,121 @@
|
|||||||
// This file was automatically generated. Edits will be overwritten
|
|
||||||
|
|
||||||
export interface Typegen0 {
|
// This file was automatically generated. Edits will be overwritten
|
||||||
'@@xstate/typegen': true;
|
|
||||||
internalEvents: {
|
export interface Typegen0 {
|
||||||
'': {type: ''};
|
'@@xstate/typegen': true;
|
||||||
'done.invoke.QrLogin': {
|
internalEvents: {
|
||||||
type: 'done.invoke.QrLogin';
|
"": { type: "" };
|
||||||
data: unknown;
|
"done.invoke.QrLogin": { type: "done.invoke.QrLogin"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"done.invoke.scan.checkStorage:invocation[0]": { type: "done.invoke.scan.checkStorage:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
};
|
"xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection": { type: "xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection" };
|
||||||
'done.invoke.scan.checkStorage:invocation[0]': {
|
"xstate.init": { type: "xstate.init" };
|
||||||
type: 'done.invoke.scan.checkStorage:invocation[0]';
|
};
|
||||||
data: unknown;
|
invokeSrcNameMap: {
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"checkBluetoothPermission": "done.invoke.scan.checkBluetoothPermission.checking:invocation[0]";
|
||||||
};
|
"checkBluetoothState": "done.invoke.scan.checkBluetoothState.checking:invocation[0]" | "done.invoke.scan.recheckBluetoothState.checking:invocation[0]";
|
||||||
'xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection': {
|
"checkLocationPermission": "done.invoke.scan.checkingLocationState.checkingPermissionStatus:invocation[0]";
|
||||||
type: 'xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection';
|
"checkLocationStatus": "done.invoke.scan.checkingLocationState.checkLocationService:invocation[0]";
|
||||||
};
|
"checkNearByDevicesPermission": "done.invoke.scan.checkNearbyDevicesPermission.checking:invocation[0]";
|
||||||
'xstate.init': {type: 'xstate.init'};
|
"checkStorageAvailability": "done.invoke.scan.checkStorage:invocation[0]";
|
||||||
};
|
"disconnect": "done.invoke.scan.clearingConnection:invocation[0]" | "done.invoke.scan.disconnectDevice:invocation[0]" | "done.invoke.scan.reviewing.disconnect:invocation[0]";
|
||||||
invokeSrcNameMap: {
|
"monitorConnection": "done.invoke.scan:invocation[0]";
|
||||||
checkBluetoothPermission: 'done.invoke.scan.checkBluetoothPermission.checking:invocation[0]';
|
"requestBluetooth": "done.invoke.scan.checkBluetoothState.requesting:invocation[0]";
|
||||||
checkBluetoothState:
|
"requestNearByDevicesPermission": "done.invoke.scan.checkNearbyDevicesPermission.requesting:invocation[0]";
|
||||||
| 'done.invoke.scan.checkBluetoothState.checking:invocation[0]'
|
"requestToEnableLocationPermission": "done.invoke.scan.checkingLocationState.requestToEnableLocation:invocation[0]";
|
||||||
| 'done.invoke.scan.recheckBluetoothState.checking:invocation[0]';
|
"sendVc": "done.invoke.scan.reviewing.sendingVc:invocation[0]";
|
||||||
checkLocationPermission: 'done.invoke.scan.checkingLocationState.checkingPermissionStatus:invocation[0]';
|
"startConnection": "done.invoke.scan.connecting:invocation[0]";
|
||||||
checkLocationStatus: 'done.invoke.scan.checkingLocationState.checkLocationService:invocation[0]';
|
};
|
||||||
checkNearByDevicesPermission: 'done.invoke.scan.checkNearbyDevicesPermission.checking:invocation[0]';
|
missingImplementations: {
|
||||||
checkStorageAvailability: 'done.invoke.scan.checkStorage:invocation[0]';
|
actions: "clearUri" | "enableLocation" | "getFaceAuthConsent" | "loadMetaDataToMemory" | "loadVCDataToMemory" | "logFailedVerification" | "logShared" | "openAppPermission" | "openBluetoothSettings" | "refreshVCs" | "registerLoggers" | "removeLoggers" | "resetFaceCaptureBannerStatus" | "resetFlowType" | "resetSelectedVc" | "resetShowQuickShareSuccessBanner" | "sendBLEConnectionErrorEvent" | "sendScanData" | "sendVCShareFlowCancelEndEvent" | "sendVCShareFlowTimeoutEndEvent" | "sendVcShareSuccessEvent" | "sendVcSharingStartEvent" | "setBleError" | "setChildRef" | "setFlowType" | "setLinkCode" | "setQuickShareData" | "setReadyForBluetoothStateCheck" | "setReceiverInfo" | "setSelectedVc" | "setSenderInfo" | "setShareLogTypeUnverified" | "setShareLogTypeVerified" | "setShowFaceAuthConsent" | "setShowQuickShareSuccessBanner" | "setUri" | "storeLoginItem" | "storeShowFaceAuthConsent" | "storingActivityLog" | "updateFaceCaptureBannerStatus" | "updateShowFaceAuthConsent";
|
||||||
disconnect:
|
delays: never;
|
||||||
| 'done.invoke.scan.clearingConnection:invocation[0]'
|
guards: "isFlowTypeMiniViewShare" | "isFlowTypeMiniViewShareWithSelfie" | "isFlowTypeSimpleShare" | "isIOS" | "isMinimumStorageRequiredForAuditEntryReached" | "isOpenIdQr" | "isQrLogin" | "isQuickShare" | "showFaceAuthConsentScreen" | "uptoAndroid11";
|
||||||
| 'done.invoke.scan.disconnectDevice:invocation[0]'
|
services: "checkBluetoothPermission" | "checkBluetoothState" | "checkLocationPermission" | "checkLocationStatus" | "checkNearByDevicesPermission" | "checkStorageAvailability" | "disconnect" | "monitorConnection" | "requestBluetooth" | "requestNearByDevicesPermission" | "requestToEnableLocationPermission" | "sendVc" | "startConnection";
|
||||||
| 'done.invoke.scan.reviewing.disconnect:invocation[0]';
|
};
|
||||||
monitorConnection: 'done.invoke.scan:invocation[0]';
|
eventsCausingActions: {
|
||||||
requestBluetooth: 'done.invoke.scan.checkBluetoothState.requesting:invocation[0]';
|
"clearUri": "STORE_RESPONSE";
|
||||||
requestNearByDevicesPermission: 'done.invoke.scan.checkNearbyDevicesPermission.requesting:invocation[0]';
|
"enableLocation": "ALLOWED" | "LOCATION_REQUEST";
|
||||||
requestToEnableLocationPermission: 'done.invoke.scan.checkingLocationState.requestToEnableLocation:invocation[0]';
|
"getFaceAuthConsent": "DISCONNECT" | "DISMISS" | "xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection";
|
||||||
sendVc: 'done.invoke.scan.reviewing.sendingVc:invocation[0]';
|
"loadMetaDataToMemory": "SCAN";
|
||||||
startConnection: 'done.invoke.scan.connecting:invocation[0]';
|
"loadVCDataToMemory": "STORE_RESPONSE";
|
||||||
};
|
"logFailedVerification": "FACE_INVALID";
|
||||||
missingImplementations: {
|
"logShared": "VC_ACCEPTED";
|
||||||
actions: never;
|
"openAppPermission": "GOTO_SETTINGS" | "LOCATION_REQUEST";
|
||||||
delays: never;
|
"openBluetoothSettings": "GOTO_SETTINGS";
|
||||||
guards: never;
|
"refreshVCs": "STORE_RESPONSE";
|
||||||
services: never;
|
"registerLoggers": "STORE_RESPONSE";
|
||||||
};
|
"removeLoggers": "DISCONNECT" | "DISMISS" | "DISMISS_QUICK_SHARE_BANNER" | "RESET" | "SCREEN_BLUR" | "STORE_RESPONSE" | "xstate.init";
|
||||||
eventsCausingActions: {
|
"resetFaceCaptureBannerStatus": "ACCEPT_REQUEST" | "CLOSE_BANNER";
|
||||||
clearUri: 'STORE_RESPONSE';
|
"resetFlowType": "DISCONNECT" | "DISMISS" | "DISMISS_QUICK_SHARE_BANNER" | "GOTO_HISTORY" | "RESET" | "SCREEN_BLUR" | "xstate.init";
|
||||||
getFaceAuthConsent:
|
"resetSelectedVc": "DISCONNECT" | "DISMISS" | "DISMISS_QUICK_SHARE_BANNER" | "GOTO_HISTORY" | "RESET" | "SCREEN_BLUR" | "xstate.init";
|
||||||
| 'DISCONNECT'
|
"resetShowQuickShareSuccessBanner": "DISMISS" | "DISMISS_QUICK_SHARE_BANNER";
|
||||||
| 'DISMISS'
|
"sendBLEConnectionErrorEvent": "BLE_ERROR";
|
||||||
| 'xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection';
|
"sendScanData": "SCAN";
|
||||||
loadMetaDataToMemory: 'SCAN';
|
"sendVCShareFlowCancelEndEvent": "CANCEL";
|
||||||
loadVCDataToMemory: 'STORE_RESPONSE';
|
"sendVCShareFlowTimeoutEndEvent": "CANCEL" | "RETRY";
|
||||||
logFailedVerification: 'FACE_INVALID';
|
"sendVcShareSuccessEvent": "VC_ACCEPTED";
|
||||||
logShared: 'VC_ACCEPTED';
|
"sendVcSharingStartEvent": "SCAN";
|
||||||
openAppPermission: 'GOTO_SETTINGS' | 'LOCATION_REQUEST';
|
"setBleError": "BLE_ERROR";
|
||||||
openBluetoothSettings: 'GOTO_SETTINGS';
|
"setChildRef": "STORE_RESPONSE";
|
||||||
refreshVCs: 'STORE_RESPONSE';
|
"setFlowType": "SELECT_VC";
|
||||||
registerLoggers: 'STORE_RESPONSE';
|
"setLinkCode": "SCAN";
|
||||||
removeLoggers:
|
"setQuickShareData": "SCAN";
|
||||||
| 'DISCONNECT'
|
"setReadyForBluetoothStateCheck": "BLUETOOTH_PERMISSION_ENABLED";
|
||||||
| 'DISMISS'
|
"setReceiverInfo": "CONNECTED";
|
||||||
| 'DISMISS_QUICK_SHARE_BANNER'
|
"setSelectedVc": "SELECT_VC";
|
||||||
| 'SCREEN_BLUR'
|
"setSenderInfo": "CONNECTED";
|
||||||
| 'STORE_RESPONSE'
|
"setShareLogTypeUnverified": "ACCEPT_REQUEST" | "CHECK_FLOW_TYPE";
|
||||||
| 'xstate.init';
|
"setShareLogTypeVerified": "FACE_VALID";
|
||||||
resetFaceCaptureBannerStatus: 'ACCEPT_REQUEST' | 'CLOSE_BANNER';
|
"setShowFaceAuthConsent": "FACE_VERIFICATION_CONSENT";
|
||||||
resetFlowType:
|
"setShowQuickShareSuccessBanner": "STORE_RESPONSE";
|
||||||
| 'DISCONNECT'
|
"setUri": "SCAN";
|
||||||
| 'DISMISS'
|
"storeLoginItem": "done.invoke.QrLogin";
|
||||||
| 'DISMISS_QUICK_SHARE_BANNER'
|
"storeShowFaceAuthConsent": "FACE_VERIFICATION_CONSENT";
|
||||||
| 'GOTO_HISTORY'
|
"storingActivityLog": "STORE_RESPONSE";
|
||||||
| 'SCREEN_BLUR'
|
"updateFaceCaptureBannerStatus": "FACE_VALID";
|
||||||
| 'xstate.init';
|
"updateShowFaceAuthConsent": "STORE_RESPONSE";
|
||||||
resetSelectedVc:
|
};
|
||||||
| 'DISCONNECT'
|
eventsCausingDelays: {
|
||||||
| 'DISMISS'
|
"CONNECTION_TIMEOUT": "SCAN";
|
||||||
| 'DISMISS_QUICK_SHARE_BANNER'
|
"DESTROY_TIMEOUT": "" | "DISMISS" | "LOCATION_ENABLED" | "RETRY";
|
||||||
| 'GOTO_HISTORY'
|
"SHARING_TIMEOUT": "ACCEPT_REQUEST" | "CHECK_FLOW_TYPE" | "FACE_VALID";
|
||||||
| 'SCREEN_BLUR'
|
};
|
||||||
| 'xstate.init';
|
eventsCausingGuards: {
|
||||||
resetShowQuickShareSuccessBanner: 'DISMISS' | 'DISMISS_QUICK_SHARE_BANNER';
|
"isFlowTypeMiniViewShare": "CHECK_FLOW_TYPE";
|
||||||
sendBLEConnectionErrorEvent: 'BLE_ERROR';
|
"isFlowTypeMiniViewShareWithSelfie": "CHECK_FLOW_TYPE" | "DISMISS";
|
||||||
sendScanData: 'SCAN';
|
"isFlowTypeSimpleShare": "CANCEL" | "CHECK_FLOW_TYPE" | "DISMISS";
|
||||||
sendVCShareFlowCancelEndEvent: 'CANCEL';
|
"isIOS": "BLUETOOTH_STATE_DISABLED" | "START_PERMISSION_CHECK";
|
||||||
sendVCShareFlowTimeoutEndEvent: 'CANCEL' | 'RETRY';
|
"isMinimumStorageRequiredForAuditEntryReached": "done.invoke.scan.checkStorage:invocation[0]";
|
||||||
sendVcShareSuccessEvent: 'VC_ACCEPTED';
|
"isOpenIdQr": "SCAN";
|
||||||
sendVcSharingStartEvent: 'SCAN';
|
"isQrLogin": "SCAN";
|
||||||
setBleError: 'BLE_ERROR';
|
"isQuickShare": "SCAN";
|
||||||
setChildRef: 'STORE_RESPONSE';
|
"showFaceAuthConsentScreen": "" | "VERIFY_AND_ACCEPT_REQUEST";
|
||||||
setFlowType: 'SELECT_VC';
|
"uptoAndroid11": "" | "START_PERMISSION_CHECK";
|
||||||
setLinkCode: 'SCAN';
|
};
|
||||||
setQuickShareData: 'SCAN';
|
eventsCausingServices: {
|
||||||
setReadyForBluetoothStateCheck: 'BLUETOOTH_PERMISSION_ENABLED';
|
"QrLogin": "SCAN";
|
||||||
setReceiverInfo: 'CONNECTED';
|
"checkBluetoothPermission": "" | "BLUETOOTH_STATE_DISABLED" | "NEARBY_ENABLED" | "START_PERMISSION_CHECK";
|
||||||
setSelectedVc: 'SELECT_VC';
|
"checkBluetoothState": "" | "APP_ACTIVE";
|
||||||
setSenderInfo: 'CONNECTED';
|
"checkLocationPermission": "LOCATION_ENABLED";
|
||||||
setShareLogTypeUnverified: 'ACCEPT_REQUEST' | 'CHECK_FLOW_TYPE';
|
"checkLocationStatus": "" | "APP_ACTIVE" | "LOCATION_REQUEST";
|
||||||
setShareLogTypeVerified: 'FACE_VALID';
|
"checkNearByDevicesPermission": "APP_ACTIVE" | "START_PERMISSION_CHECK";
|
||||||
setShowFaceAuthConsent: 'FACE_VERIFICATION_CONSENT';
|
"checkStorageAvailability": "RESET" | "SCREEN_FOCUS" | "SELECT_VC";
|
||||||
setShowQuickShareSuccessBanner: 'STORE_RESPONSE';
|
"disconnect": "" | "DISMISS" | "LOCATION_ENABLED" | "RETRY" | "SCREEN_BLUR";
|
||||||
setUri: 'SCAN';
|
"monitorConnection": "DISMISS" | "SCREEN_BLUR" | "xstate.init";
|
||||||
storeLoginItem: 'done.invoke.QrLogin';
|
"requestBluetooth": "BLUETOOTH_STATE_DISABLED";
|
||||||
storeShowFaceAuthConsent: 'FACE_VERIFICATION_CONSENT';
|
"requestNearByDevicesPermission": "NEARBY_DISABLED";
|
||||||
storingActivityLog: 'STORE_RESPONSE';
|
"requestToEnableLocationPermission": "LOCATION_DISABLED";
|
||||||
updateFaceCaptureBannerStatus: 'FACE_VALID';
|
"sendVc": "ACCEPT_REQUEST" | "CHECK_FLOW_TYPE" | "FACE_VALID";
|
||||||
updateShowFaceAuthConsent: 'STORE_RESPONSE';
|
"startConnection": "SCAN";
|
||||||
};
|
};
|
||||||
eventsCausingDelays: {
|
matchesStates: "bluetoothDenied" | "bluetoothPermissionDenied" | "checkBluetoothPermission" | "checkBluetoothPermission.checking" | "checkBluetoothPermission.enabled" | "checkBluetoothState" | "checkBluetoothState.checking" | "checkBluetoothState.enabled" | "checkBluetoothState.requesting" | "checkFaceAuthConsent" | "checkNearbyDevicesPermission" | "checkNearbyDevicesPermission.checking" | "checkNearbyDevicesPermission.enabled" | "checkNearbyDevicesPermission.requesting" | "checkStorage" | "checkingLocationState" | "checkingLocationState.LocationPermissionRationale" | "checkingLocationState.checkLocationService" | "checkingLocationState.checkingPermissionStatus" | "checkingLocationState.denied" | "checkingLocationState.disabled" | "checkingLocationState.requestToEnableLocation" | "clearingConnection" | "connecting" | "connecting.inProgress" | "connecting.timeout" | "decodeQuickShareData" | "disconnectDevice" | "disconnected" | "findingConnection" | "handlingBleError" | "inactive" | "invalid" | "loadVCS" | "loadVCS.idle" | "loadVCS.navigatingToHome" | "nearByDevicesPermissionDenied" | "recheckBluetoothState" | "recheckBluetoothState.checking" | "recheckBluetoothState.enabled" | "restrictSharingVc" | "reviewing" | "reviewing.accepted" | "reviewing.cancelling" | "reviewing.checkFaceAuthConsentForMiniView" | "reviewing.disconnect" | "reviewing.faceVerificationConsent" | "reviewing.idle" | "reviewing.invalidIdentity" | "reviewing.navigateToHistory" | "reviewing.rejected" | "reviewing.selectingVc" | "reviewing.sendingVc" | "reviewing.sendingVc.inProgress" | "reviewing.sendingVc.sent" | "reviewing.sendingVc.timeout" | "reviewing.verifyingIdentity" | "showQrLogin" | "showQrLogin.idle" | "showQrLogin.navigatingToHistory" | "showQrLogin.storing" | "startPermissionCheck" | { "checkBluetoothPermission"?: "checking" | "enabled";
|
||||||
CONNECTION_TIMEOUT: 'SCAN';
|
"checkBluetoothState"?: "checking" | "enabled" | "requesting";
|
||||||
DESTROY_TIMEOUT: '' | 'DISMISS' | 'LOCATION_ENABLED' | 'RETRY';
|
"checkNearbyDevicesPermission"?: "checking" | "enabled" | "requesting";
|
||||||
SHARING_TIMEOUT: 'ACCEPT_REQUEST' | 'CHECK_FLOW_TYPE' | 'FACE_VALID';
|
"checkingLocationState"?: "LocationPermissionRationale" | "checkLocationService" | "checkingPermissionStatus" | "denied" | "disabled" | "requestToEnableLocation";
|
||||||
};
|
"connecting"?: "inProgress" | "timeout";
|
||||||
eventsCausingGuards: {
|
"loadVCS"?: "idle" | "navigatingToHome";
|
||||||
isFlowTypeMiniViewShare: 'CHECK_FLOW_TYPE';
|
"recheckBluetoothState"?: "checking" | "enabled";
|
||||||
isFlowTypeMiniViewShareWithSelfie: 'CHECK_FLOW_TYPE';
|
"reviewing"?: "accepted" | "cancelling" | "checkFaceAuthConsentForMiniView" | "disconnect" | "faceVerificationConsent" | "idle" | "invalidIdentity" | "navigateToHistory" | "rejected" | "selectingVc" | "sendingVc" | "verifyingIdentity" | { "sendingVc"?: "inProgress" | "sent" | "timeout"; };
|
||||||
isFlowTypeSimpleShare: 'CANCEL' | 'CHECK_FLOW_TYPE' | 'DISMISS';
|
"showQrLogin"?: "idle" | "navigatingToHistory" | "storing"; };
|
||||||
isIOS: 'BLUETOOTH_STATE_DISABLED' | 'START_PERMISSION_CHECK';
|
tags: never;
|
||||||
isMinimumStorageRequiredForAuditEntryReached: 'done.invoke.scan.checkStorage:invocation[0]';
|
}
|
||||||
isOpenIdQr: 'SCAN';
|
|
||||||
isQrLogin: 'SCAN';
|
|
||||||
isQuickShare: 'SCAN';
|
|
||||||
showFaceAuthConsentScreen: 'VERIFY_AND_ACCEPT_REQUEST';
|
|
||||||
uptoAndroid11: '' | 'START_PERMISSION_CHECK';
|
|
||||||
};
|
|
||||||
eventsCausingServices: {
|
|
||||||
QrLogin: 'SCAN';
|
|
||||||
checkBluetoothPermission:
|
|
||||||
| ''
|
|
||||||
| 'BLUETOOTH_STATE_DISABLED'
|
|
||||||
| 'NEARBY_ENABLED'
|
|
||||||
| 'START_PERMISSION_CHECK';
|
|
||||||
checkBluetoothState: '' | 'APP_ACTIVE';
|
|
||||||
checkLocationPermission: 'APP_ACTIVE' | 'LOCATION_ENABLED';
|
|
||||||
checkLocationStatus: '' | 'LOCATION_REQUEST';
|
|
||||||
checkNearByDevicesPermission: 'APP_ACTIVE' | 'START_PERMISSION_CHECK';
|
|
||||||
checkStorageAvailability: 'RESET' | 'SCREEN_FOCUS' | 'SELECT_VC';
|
|
||||||
disconnect: '' | 'DISMISS' | 'LOCATION_ENABLED' | 'RETRY' | 'SCREEN_BLUR';
|
|
||||||
monitorConnection: 'DISMISS' | 'SCREEN_BLUR' | 'xstate.init';
|
|
||||||
requestBluetooth: 'BLUETOOTH_STATE_DISABLED';
|
|
||||||
requestNearByDevicesPermission: 'NEARBY_DISABLED';
|
|
||||||
requestToEnableLocationPermission: 'LOCATION_DISABLED';
|
|
||||||
sendVc: 'ACCEPT_REQUEST' | 'CHECK_FLOW_TYPE' | 'FACE_VALID';
|
|
||||||
startConnection: 'SCAN';
|
|
||||||
};
|
|
||||||
matchesStates:
|
|
||||||
| 'bluetoothDenied'
|
|
||||||
| 'bluetoothPermissionDenied'
|
|
||||||
| 'checkBluetoothPermission'
|
|
||||||
| 'checkBluetoothPermission.checking'
|
|
||||||
| 'checkBluetoothPermission.enabled'
|
|
||||||
| 'checkBluetoothState'
|
|
||||||
| 'checkBluetoothState.checking'
|
|
||||||
| 'checkBluetoothState.enabled'
|
|
||||||
| 'checkBluetoothState.requesting'
|
|
||||||
| 'checkFaceAuthConsent'
|
|
||||||
| 'checkNearbyDevicesPermission'
|
|
||||||
| 'checkNearbyDevicesPermission.checking'
|
|
||||||
| 'checkNearbyDevicesPermission.enabled'
|
|
||||||
| 'checkNearbyDevicesPermission.requesting'
|
|
||||||
| 'checkStorage'
|
|
||||||
| 'checkingLocationState'
|
|
||||||
| 'checkingLocationState.checkLocationService'
|
|
||||||
| 'checkingLocationState.checkingPermissionStatus'
|
|
||||||
| 'checkingLocationState.denied'
|
|
||||||
| 'checkingLocationState.disabled'
|
|
||||||
| 'checkingLocationState.requestToEnableLocation'
|
|
||||||
| 'clearingConnection'
|
|
||||||
| 'connecting'
|
|
||||||
| 'connecting.inProgress'
|
|
||||||
| 'connecting.timeout'
|
|
||||||
| 'decodeQuickShareData'
|
|
||||||
| 'disconnectDevice'
|
|
||||||
| 'disconnected'
|
|
||||||
| 'findingConnection'
|
|
||||||
| 'handlingBleError'
|
|
||||||
| 'inactive'
|
|
||||||
| 'invalid'
|
|
||||||
| 'loadVCS'
|
|
||||||
| 'loadVCS.idle'
|
|
||||||
| 'loadVCS.navigatingToHome'
|
|
||||||
| 'nearByDevicesPermissionDenied'
|
|
||||||
| 'recheckBluetoothState'
|
|
||||||
| 'recheckBluetoothState.checking'
|
|
||||||
| 'recheckBluetoothState.enabled'
|
|
||||||
| 'restrictSharingVc'
|
|
||||||
| 'reviewing'
|
|
||||||
| 'reviewing.accepted'
|
|
||||||
| 'reviewing.cancelling'
|
|
||||||
| 'reviewing.disconnect'
|
|
||||||
| 'reviewing.faceVerificationConsent'
|
|
||||||
| 'reviewing.idle'
|
|
||||||
| 'reviewing.invalidIdentity'
|
|
||||||
| 'reviewing.navigateToHistory'
|
|
||||||
| 'reviewing.rejected'
|
|
||||||
| 'reviewing.selectingVc'
|
|
||||||
| 'reviewing.sendingVc'
|
|
||||||
| 'reviewing.sendingVc.inProgress'
|
|
||||||
| 'reviewing.sendingVc.sent'
|
|
||||||
| 'reviewing.sendingVc.timeout'
|
|
||||||
| 'reviewing.verifyingIdentity'
|
|
||||||
| 'showQrLogin'
|
|
||||||
| 'showQrLogin.idle'
|
|
||||||
| 'showQrLogin.navigatingToHistory'
|
|
||||||
| 'showQrLogin.storing'
|
|
||||||
| 'startPermissionCheck'
|
|
||||||
| {
|
|
||||||
checkBluetoothPermission?: 'checking' | 'enabled';
|
|
||||||
checkBluetoothState?: 'checking' | 'enabled' | 'requesting';
|
|
||||||
checkNearbyDevicesPermission?: 'checking' | 'enabled' | 'requesting';
|
|
||||||
checkingLocationState?:
|
|
||||||
| 'checkLocationService'
|
|
||||||
| 'checkingPermissionStatus'
|
|
||||||
| 'denied'
|
|
||||||
| 'disabled'
|
|
||||||
| 'requestToEnableLocation';
|
|
||||||
connecting?: 'inProgress' | 'timeout';
|
|
||||||
loadVCS?: 'idle' | 'navigatingToHome';
|
|
||||||
recheckBluetoothState?: 'checking' | 'enabled';
|
|
||||||
reviewing?:
|
|
||||||
| 'accepted'
|
|
||||||
| 'cancelling'
|
|
||||||
| 'disconnect'
|
|
||||||
| 'faceVerificationConsent'
|
|
||||||
| 'idle'
|
|
||||||
| 'invalidIdentity'
|
|
||||||
| 'navigateToHistory'
|
|
||||||
| 'rejected'
|
|
||||||
| 'selectingVc'
|
|
||||||
| 'sendingVc'
|
|
||||||
| 'verifyingIdentity'
|
|
||||||
| {sendingVc?: 'inProgress' | 'sent' | 'timeout'};
|
|
||||||
showQrLogin?: 'idle' | 'navigatingToHistory' | 'storing';
|
|
||||||
};
|
|
||||||
tags: never;
|
|
||||||
}
|
|
||||||
84
machines/bleShare/scan/scanModel.ts
Normal file
84
machines/bleShare/scan/scanModel.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import { CameraCapturedPicture } from "expo-camera";
|
||||||
|
import { EmitterSubscription } from "react-native";
|
||||||
|
import { ActorRefFrom } from "xstate";
|
||||||
|
import { createModel } from "xstate/lib/model";
|
||||||
|
import { DeviceInfo } from "../../../components/DeviceInfoList";
|
||||||
|
import { AppServices } from "../../../shared/GlobalContext";
|
||||||
|
import { VCShareFlowType } from "../../../shared/Utils";
|
||||||
|
import { qrLoginMachine } from "../../QrLogin/QrLoginMachine";
|
||||||
|
import { VC } from "../../VerifiableCredential/VCMetaMachine/vc";
|
||||||
|
import { ActivityLogType } from "../../activityLog";
|
||||||
|
import { BLEError } from "../types";
|
||||||
|
|
||||||
|
const ScanEvents ={
|
||||||
|
SELECT_VC: (vc: VC, flowType: string) => ({vc, flowType}),
|
||||||
|
SCAN: (params: string) => ({params}),
|
||||||
|
ACCEPT_REQUEST: () => ({}),
|
||||||
|
VERIFY_AND_ACCEPT_REQUEST: () => ({}),
|
||||||
|
VC_ACCEPTED: () => ({}),
|
||||||
|
VC_REJECTED: () => ({}),
|
||||||
|
VC_SENT: () => ({}),
|
||||||
|
CANCEL: () => ({}),
|
||||||
|
CLOSE_BANNER: () => ({}),
|
||||||
|
STAY_IN_PROGRESS: () => ({}),
|
||||||
|
RETRY: () => ({}),
|
||||||
|
DISMISS: () => ({}),
|
||||||
|
DISMISS_QUICK_SHARE_BANNER: () => ({}),
|
||||||
|
GOTO_HISTORY: () => ({}),
|
||||||
|
CONNECTED: () => ({}),
|
||||||
|
DISCONNECT: () => ({}),
|
||||||
|
BLE_ERROR: (bleError: BLEError) => ({bleError}),
|
||||||
|
CONNECTION_DESTROYED: () => ({}),
|
||||||
|
SCREEN_BLUR: () => ({}),
|
||||||
|
SCREEN_FOCUS: () => ({}),
|
||||||
|
BLUETOOTH_PERMISSION_ENABLED: () => ({}),
|
||||||
|
BLUETOOTH_PERMISSION_DENIED: () => ({}),
|
||||||
|
BLUETOOTH_STATE_ENABLED: () => ({}),
|
||||||
|
BLUETOOTH_STATE_DISABLED: () => ({}),
|
||||||
|
NEARBY_ENABLED: () => ({}),
|
||||||
|
NEARBY_DISABLED: () => ({}),
|
||||||
|
GOTO_SETTINGS: () => ({}),
|
||||||
|
START_PERMISSION_CHECK: () => ({}),
|
||||||
|
LOCATION_ENABLED: () => ({}),
|
||||||
|
LOCATION_DISABLED: () => ({}),
|
||||||
|
LOCATION_REQUEST: () => ({}),
|
||||||
|
CHECK_FLOW_TYPE: () => ({}),
|
||||||
|
UPDATE_VC_NAME: (vcName: string) => ({vcName}),
|
||||||
|
STORE_RESPONSE: (response: any) => ({response}),
|
||||||
|
APP_ACTIVE: () => ({}),
|
||||||
|
FACE_VALID: () => ({}),
|
||||||
|
FACE_INVALID: () => ({}),
|
||||||
|
RETRY_VERIFICATION: () => ({}),
|
||||||
|
RESET: () => ({}),
|
||||||
|
FACE_VERIFICATION_CONSENT: (isDoNotAskAgainChecked: boolean) => ({
|
||||||
|
isDoNotAskAgainChecked,
|
||||||
|
}),
|
||||||
|
ALLOWED: () => ({}),
|
||||||
|
DENIED: () => ({}),
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ScanModel = createModel(
|
||||||
|
{
|
||||||
|
serviceRefs: {} as AppServices,
|
||||||
|
senderInfo: {} as DeviceInfo,
|
||||||
|
receiverInfo: {} as DeviceInfo,
|
||||||
|
selectedVc: {} as VC,
|
||||||
|
bleError: {} as BLEError,
|
||||||
|
loggers: [] as EmitterSubscription[],
|
||||||
|
vcName: '',
|
||||||
|
flowType: VCShareFlowType.SIMPLE_SHARE,
|
||||||
|
verificationImage: {} as CameraCapturedPicture,
|
||||||
|
openId4VpUri: '',
|
||||||
|
shareLogType: '' as ActivityLogType,
|
||||||
|
QrLoginRef: {} as ActorRefFrom<typeof qrLoginMachine>,
|
||||||
|
showQuickShareSuccessBanner: false,
|
||||||
|
linkCode: '',
|
||||||
|
quickShareData: {},
|
||||||
|
showFaceAuthConsent: true as boolean,
|
||||||
|
readyForBluetoothStateCheck: false,
|
||||||
|
showFaceCaptureSuccessBanner: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
events: ScanEvents,
|
||||||
|
},
|
||||||
|
);
|
||||||
@@ -117,3 +117,13 @@ export function selectIsQrLoginStoring(state: State) {
|
|||||||
export function selectIsDone(state: State) {
|
export function selectIsDone(state: State) {
|
||||||
return state.matches('reviewing.disconnect');
|
return state.matches('reviewing.disconnect');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectIsMinimumStorageRequiredForAuditEntryLimitReached(
|
||||||
|
state: State,
|
||||||
|
) {
|
||||||
|
return state.matches('restrictSharingVc');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectIsFaceVerificationConsent(state: State) {
|
||||||
|
return state.matches('reviewing.faceVerificationConsent');
|
||||||
|
}
|
||||||
197
machines/bleShare/scan/scanServices.ts
Normal file
197
machines/bleShare/scan/scanServices.ts
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
import {WalletDataEvent} from '@mosip/tuvali/lib/typescript/types/events';
|
||||||
|
import { isLocationEnabled } from "react-native-device-info";
|
||||||
|
import Storage from '../../../shared/storage';
|
||||||
|
import BluetoothStateManager from 'react-native-bluetooth-state-manager';
|
||||||
|
import tuvali from '@mosip/tuvali';
|
||||||
|
import {
|
||||||
|
check,
|
||||||
|
checkMultiple,
|
||||||
|
PERMISSIONS,
|
||||||
|
PermissionStatus,
|
||||||
|
requestMultiple,
|
||||||
|
RESULTS,
|
||||||
|
} from 'react-native-permissions';
|
||||||
|
import {subscribe} from '../../../shared/openIdBLE/walletEventHandler';
|
||||||
|
import { requestLocationPermission, checkLocationPermissionStatus } from "../../../shared/location";
|
||||||
|
import { isIOS } from "../../../shared/constants";
|
||||||
|
|
||||||
|
const {wallet, EventTypes, VerificationStatus} = tuvali;
|
||||||
|
|
||||||
|
export const ScanServices=(model:any)=>{
|
||||||
|
return { checkBluetoothPermission: () => async callback => {
|
||||||
|
// wait a bit for animation to finish when app becomes active
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 250));
|
||||||
|
try {
|
||||||
|
// Passing Granted for android since permission status is always granted even if its denied.
|
||||||
|
let response: PermissionStatus = RESULTS.GRANTED;
|
||||||
|
|
||||||
|
if (isIOS()) {
|
||||||
|
response = await check(PERMISSIONS.IOS.BLUETOOTH_PERIPHERAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response === RESULTS.GRANTED) {
|
||||||
|
callback(model.events.BLUETOOTH_PERMISSION_ENABLED());
|
||||||
|
} else {
|
||||||
|
callback(model.events.BLUETOOTH_PERMISSION_DENIED());
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
checkBluetoothState: () => callback => {
|
||||||
|
const subscription = BluetoothStateManager.onStateChange(state => {
|
||||||
|
if (state === 'PoweredOn') {
|
||||||
|
callback(model.events.BLUETOOTH_STATE_ENABLED());
|
||||||
|
} else {
|
||||||
|
callback(model.events.BLUETOOTH_STATE_DISABLED());
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
return () => subscription.remove();
|
||||||
|
},
|
||||||
|
|
||||||
|
requestBluetooth: () => callback => {
|
||||||
|
BluetoothStateManager.requestToEnable()
|
||||||
|
.then(() => callback(model.events.BLUETOOTH_STATE_ENABLED()))
|
||||||
|
.catch(() => callback(model.events.BLUETOOTH_STATE_DISABLED()));
|
||||||
|
},
|
||||||
|
|
||||||
|
requestToEnableLocationPermission: () => callback => {
|
||||||
|
requestLocationPermission(
|
||||||
|
() => callback(model.events.LOCATION_ENABLED()),
|
||||||
|
() => callback(model.events.LOCATION_DISABLED()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
monitorConnection: () => callback => {
|
||||||
|
const walletErrorCodePrefix = 'TVW';
|
||||||
|
const subscription = wallet.handleDataEvents(event => {
|
||||||
|
if (event.type === EventTypes.onDisconnected) {
|
||||||
|
callback({type: 'DISCONNECT'});
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
event.type === EventTypes.onError &&
|
||||||
|
event.code.includes(walletErrorCodePrefix)
|
||||||
|
) {
|
||||||
|
callback({
|
||||||
|
type: 'BLE_ERROR',
|
||||||
|
bleError: {message: event.message, code: event.code},
|
||||||
|
});
|
||||||
|
console.error('BLE Exception: ' + event.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => subscription.remove();
|
||||||
|
},
|
||||||
|
|
||||||
|
checkNearByDevicesPermission: () => callback => {
|
||||||
|
checkMultiple([
|
||||||
|
PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
|
||||||
|
PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
|
||||||
|
])
|
||||||
|
.then(response => {
|
||||||
|
if (
|
||||||
|
response[PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE] ===
|
||||||
|
RESULTS.GRANTED &&
|
||||||
|
response[PERMISSIONS.ANDROID.BLUETOOTH_CONNECT] ===
|
||||||
|
RESULTS.GRANTED
|
||||||
|
) {
|
||||||
|
callback(model.events.NEARBY_ENABLED());
|
||||||
|
} else {
|
||||||
|
callback(model.events.NEARBY_DISABLED());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
callback(model.events.NEARBY_DISABLED());
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
requestNearByDevicesPermission: () => callback => {
|
||||||
|
requestMultiple([
|
||||||
|
PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
|
||||||
|
PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
|
||||||
|
])
|
||||||
|
.then(response => {
|
||||||
|
if (
|
||||||
|
response[PERMISSIONS.ANDROID.BLUETOOTH_SCAN] ===
|
||||||
|
RESULTS.GRANTED &&
|
||||||
|
response[PERMISSIONS.ANDROID.BLUETOOTH_CONNECT] ===
|
||||||
|
RESULTS.GRANTED
|
||||||
|
) {
|
||||||
|
callback(model.events.NEARBY_ENABLED());
|
||||||
|
} else {
|
||||||
|
callback(model.events.NEARBY_DISABLED());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
callback(model.events.NEARBY_DISABLED());
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
checkLocationPermission: () => callback => {
|
||||||
|
checkLocationPermissionStatus(
|
||||||
|
() => callback(model.events.LOCATION_ENABLED()),
|
||||||
|
() => callback(model.events.LOCATION_DISABLED()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
checkLocationStatus: () => async callback => {
|
||||||
|
const isEnabled: boolean = await isLocationEnabled();
|
||||||
|
if (isEnabled) {
|
||||||
|
callback(model.events.LOCATION_ENABLED());
|
||||||
|
} else {
|
||||||
|
callback(model.events.LOCATION_DISABLED());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
startConnection: (context:any) => callback => {
|
||||||
|
wallet.startConnection(context.openId4VpUri);
|
||||||
|
const statusCallback = (event: WalletDataEvent) => {
|
||||||
|
if (event.type === EventTypes.onSecureChannelEstablished) {
|
||||||
|
callback({type: 'CONNECTED'});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const subscription = subscribe(statusCallback);
|
||||||
|
return () => subscription?.remove();
|
||||||
|
},
|
||||||
|
|
||||||
|
sendVc: context => callback => {
|
||||||
|
const statusCallback = (event: WalletDataEvent) => {
|
||||||
|
if (event.type === EventTypes.onDataSent) {
|
||||||
|
callback({type: 'VC_SENT'});
|
||||||
|
} else if (event.type === EventTypes.onVerificationStatusReceived) {
|
||||||
|
callback({
|
||||||
|
type:
|
||||||
|
event.status === VerificationStatus.ACCEPTED
|
||||||
|
? 'VC_ACCEPTED'
|
||||||
|
: 'VC_REJECTED',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
wallet.sendData(
|
||||||
|
JSON.stringify({
|
||||||
|
...context.selectedVc,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const subscription = subscribe(statusCallback);
|
||||||
|
return () => subscription?.remove();
|
||||||
|
},
|
||||||
|
|
||||||
|
disconnect: () => () => {
|
||||||
|
try {
|
||||||
|
console.log("inside wallet disconnect");
|
||||||
|
wallet.disconnect();
|
||||||
|
} catch (e) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
checkStorageAvailability: () => async () => {
|
||||||
|
return Promise.resolve(
|
||||||
|
Storage.isMinimumLimitReached('minStorageRequiredForAuditEntry'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
MY_VCS_STORE_KEY,
|
MY_VCS_STORE_KEY,
|
||||||
RECEIVED_VCS_STORE_KEY,
|
RECEIVED_VCS_STORE_KEY,
|
||||||
SETTINGS_STORE_KEY,
|
SETTINGS_STORE_KEY,
|
||||||
FACE_AUTH_CONSENT,
|
SHOW_FACE_AUTH_CONSENT_SHARE_FLOW,
|
||||||
ENOENT,
|
ENOENT,
|
||||||
} from '../shared/constants';
|
} from '../shared/constants';
|
||||||
import SecureKeystore from '@mosip/secure-keystore';
|
import SecureKeystore from '@mosip/secure-keystore';
|
||||||
@@ -563,7 +563,7 @@ export async function setItem(
|
|||||||
appId,
|
appId,
|
||||||
};
|
};
|
||||||
encryptedData = JSON.stringify(settings);
|
encryptedData = JSON.stringify(settings);
|
||||||
} else if (key === FACE_AUTH_CONSENT) {
|
} else if (key === SHOW_FACE_AUTH_CONSENT_SHARE_FLOW) {
|
||||||
encryptedData = JSON.stringify(value);
|
encryptedData = JSON.stringify(value);
|
||||||
} else {
|
} else {
|
||||||
encryptedData = await encryptJson(encryptionKey, JSON.stringify(value));
|
encryptedData = await encryptJson(encryptionKey, JSON.stringify(value));
|
||||||
@@ -632,7 +632,7 @@ export async function getItem(
|
|||||||
parsedData.encryptedData = JSON.parse(decryptedData);
|
parsedData.encryptedData = JSON.parse(decryptedData);
|
||||||
}
|
}
|
||||||
return parsedData;
|
return parsedData;
|
||||||
} else if (key === FACE_AUTH_CONSENT) {
|
} else if (key === SHOW_FACE_AUTH_CONSENT_SHARE_FLOW) {
|
||||||
return JSON.parse(data);
|
return JSON.parse(data);
|
||||||
}
|
}
|
||||||
decryptedData = await decryptJson(encryptionKey, data);
|
decryptedData = await decryptJson(encryptionKey, data);
|
||||||
|
|||||||
@@ -1,77 +1,48 @@
|
|||||||
// This file was automatically generated. Edits will be overwritten
|
|
||||||
|
|
||||||
export interface Typegen0 {
|
// This file was automatically generated. Edits will be overwritten
|
||||||
'@@xstate/typegen': true;
|
|
||||||
internalEvents: {
|
export interface Typegen0 {
|
||||||
'done.invoke._store': {
|
'@@xstate/typegen': true;
|
||||||
type: 'done.invoke._store';
|
internalEvents: {
|
||||||
data: unknown;
|
"done.invoke._store": { type: "done.invoke._store"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"done.invoke.store.resettingStorage:invocation[0]": { type: "done.invoke.store.resettingStorage:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
};
|
"error.platform._store": { type: "error.platform._store"; data: unknown };
|
||||||
'done.invoke.store.resettingStorage:invocation[0]': {
|
"xstate.init": { type: "xstate.init" };
|
||||||
type: 'done.invoke.store.resettingStorage:invocation[0]';
|
};
|
||||||
data: unknown;
|
invokeSrcNameMap: {
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"checkStorageInitialisedOrNot": "done.invoke.store.checkStorageInitialisation:invocation[0]";
|
||||||
};
|
"clear": "done.invoke.store.resettingStorage:invocation[0]";
|
||||||
'error.platform._store': {type: 'error.platform._store'; data: unknown};
|
"generateEncryptionKey": "done.invoke.store.generatingEncryptionKey:invocation[0]";
|
||||||
'xstate.init': {type: 'xstate.init'};
|
"getEncryptionKey": "done.invoke.store.gettingEncryptionKey:invocation[0]";
|
||||||
};
|
"hasAndroidEncryptionKey": "done.invoke.store.checkEncryptionKey:invocation[0]";
|
||||||
invokeSrcNameMap: {
|
"store": "done.invoke._store";
|
||||||
checkStorageInitialisedOrNot: 'done.invoke.store.checkStorageInitialisation:invocation[0]';
|
};
|
||||||
clear: 'done.invoke.store.resettingStorage:invocation[0]';
|
missingImplementations: {
|
||||||
generateEncryptionKey: 'done.invoke.store.generatingEncryptionKey:invocation[0]';
|
actions: never;
|
||||||
getEncryptionKey: 'done.invoke.store.gettingEncryptionKey:invocation[0]';
|
delays: never;
|
||||||
hasAndroidEncryptionKey: 'done.invoke.store.checkEncryptionKey:invocation[0]';
|
guards: never;
|
||||||
store: 'done.invoke._store';
|
services: never;
|
||||||
};
|
};
|
||||||
missingImplementations: {
|
eventsCausingActions: {
|
||||||
actions: never;
|
"forwardStoreRequest": "APPEND" | "CLEAR" | "EXPORT" | "GET" | "GET_VCS_DATA" | "PREPEND" | "REMOVE" | "REMOVE_ITEMS" | "REMOVE_VC_METADATA" | "RESTORE_BACKUP" | "SET" | "UPDATE";
|
||||||
delays: never;
|
"notifyParent": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]";
|
||||||
guards: never;
|
"setEncryptionKey": "KEY_RECEIVED";
|
||||||
services: never;
|
};
|
||||||
};
|
eventsCausingDelays: {
|
||||||
eventsCausingActions: {
|
|
||||||
forwardStoreRequest:
|
};
|
||||||
| 'APPEND'
|
eventsCausingGuards: {
|
||||||
| 'CLEAR'
|
"isCustomSecureKeystore": "KEY_RECEIVED";
|
||||||
| 'EXPORT'
|
};
|
||||||
| 'GET'
|
eventsCausingServices: {
|
||||||
| 'GET_VCS_DATA'
|
"checkStorageInitialisedOrNot": "ERROR";
|
||||||
| 'PREPEND'
|
"clear": "KEY_RECEIVED";
|
||||||
| 'REMOVE'
|
"generateEncryptionKey": "ERROR" | "IGNORE" | "READY";
|
||||||
| 'REMOVE_ITEMS'
|
"getEncryptionKey": "TRY_AGAIN";
|
||||||
| 'REMOVE_VC_METADATA'
|
"hasAndroidEncryptionKey": never;
|
||||||
| 'RESTORE_BACKUP'
|
"store": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]";
|
||||||
| 'SET'
|
};
|
||||||
| 'UPDATE';
|
matchesStates: "checkEncryptionKey" | "checkStorageInitialisation" | "failedReadingKey" | "generatingEncryptionKey" | "gettingEncryptionKey" | "ready" | "resettingStorage";
|
||||||
notifyParent:
|
tags: never;
|
||||||
| 'KEY_RECEIVED'
|
}
|
||||||
| 'READY'
|
|
||||||
| 'done.invoke.store.resettingStorage:invocation[0]';
|
|
||||||
setEncryptionKey: 'KEY_RECEIVED';
|
|
||||||
};
|
|
||||||
eventsCausingDelays: {};
|
|
||||||
eventsCausingGuards: {
|
|
||||||
isCustomSecureKeystore: 'KEY_RECEIVED';
|
|
||||||
};
|
|
||||||
eventsCausingServices: {
|
|
||||||
checkStorageInitialisedOrNot: 'ERROR';
|
|
||||||
clear: 'KEY_RECEIVED';
|
|
||||||
generateEncryptionKey: 'ERROR' | 'IGNORE' | 'READY';
|
|
||||||
getEncryptionKey: 'TRY_AGAIN';
|
|
||||||
hasAndroidEncryptionKey: never;
|
|
||||||
store:
|
|
||||||
| 'KEY_RECEIVED'
|
|
||||||
| 'READY'
|
|
||||||
| 'done.invoke.store.resettingStorage:invocation[0]';
|
|
||||||
};
|
|
||||||
matchesStates:
|
|
||||||
| 'checkEncryptionKey'
|
|
||||||
| 'checkStorageInitialisation'
|
|
||||||
| 'failedReadingKey'
|
|
||||||
| 'generatingEncryptionKey'
|
|
||||||
| 'gettingEncryptionKey'
|
|
||||||
| 'ready'
|
|
||||||
| 'resettingStorage';
|
|
||||||
tags: never;
|
|
||||||
}
|
|
||||||
@@ -1,65 +1,40 @@
|
|||||||
// This file was automatically generated. Edits will be overwritten
|
|
||||||
|
|
||||||
export interface Typegen0 {
|
// This file was automatically generated. Edits will be overwritten
|
||||||
'@@xstate/typegen': true;
|
|
||||||
internalEvents: {
|
export interface Typegen0 {
|
||||||
'done.invoke.HomeScreen.tabs.checkStorage:invocation[0]': {
|
'@@xstate/typegen': true;
|
||||||
type: 'done.invoke.HomeScreen.tabs.checkStorage:invocation[0]';
|
internalEvents: {
|
||||||
data: unknown;
|
"done.invoke.HomeScreen.tabs.checkStorage:invocation[0]": { type: "done.invoke.HomeScreen.tabs.checkStorage:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
|
||||||
__tip: 'See the XState TS docs to learn how to strongly type this.';
|
"xstate.after(100)#HomeScreen.tabs.init": { type: "xstate.after(100)#HomeScreen.tabs.init" };
|
||||||
};
|
"xstate.init": { type: "xstate.init" };
|
||||||
'xstate.after(100)#HomeScreen.tabs.init': {
|
};
|
||||||
type: 'xstate.after(100)#HomeScreen.tabs.init';
|
invokeSrcNameMap: {
|
||||||
};
|
"checkStorageAvailability": "done.invoke.HomeScreen.tabs.checkStorage:invocation[0]";
|
||||||
'xstate.init': {type: 'xstate.init'};
|
};
|
||||||
};
|
missingImplementations: {
|
||||||
invokeSrcNameMap: {
|
actions: never;
|
||||||
checkStorageAvailability: 'done.invoke.HomeScreen.tabs.checkStorage:invocation[0]';
|
delays: never;
|
||||||
};
|
guards: never;
|
||||||
missingImplementations: {
|
services: never;
|
||||||
actions: never;
|
};
|
||||||
delays: never;
|
eventsCausingActions: {
|
||||||
guards: never;
|
"resetSelectedVc": "DISMISS_MODAL" | "xstate.init";
|
||||||
services: never;
|
"sendAddEvent": "DOWNLOAD_ID";
|
||||||
};
|
"setSelectedVc": "VIEW_VC";
|
||||||
eventsCausingActions: {
|
"spawnTabActors": "xstate.init";
|
||||||
resetSelectedVc: 'DISMISS_MODAL' | 'xstate.init';
|
};
|
||||||
sendAddEvent: 'DOWNLOAD_ID';
|
eventsCausingDelays: {
|
||||||
setSelectedVc: 'VIEW_VC';
|
|
||||||
spawnTabActors: 'xstate.init';
|
};
|
||||||
};
|
eventsCausingGuards: {
|
||||||
eventsCausingDelays: {};
|
"isMinimumStorageLimitReached": "done.invoke.HomeScreen.tabs.checkStorage:invocation[0]";
|
||||||
eventsCausingGuards: {
|
};
|
||||||
isMinimumStorageLimitReached: 'done.invoke.HomeScreen.tabs.checkStorage:invocation[0]';
|
eventsCausingServices: {
|
||||||
};
|
"checkStorageAvailability": "GOTO_ISSUERS";
|
||||||
eventsCausingServices: {
|
"issuersMachine": "done.invoke.HomeScreen.tabs.checkStorage:invocation[0]";
|
||||||
checkStorageAvailability: 'GOTO_ISSUERS';
|
};
|
||||||
issuersMachine: 'done.invoke.HomeScreen.tabs.checkStorage:invocation[0]';
|
matchesStates: "modals" | "modals.none" | "modals.viewingVc" | "tabs" | "tabs.checkStorage" | "tabs.gotoIssuers" | "tabs.history" | "tabs.idle" | "tabs.init" | "tabs.myVcs" | "tabs.receivedVcs" | "tabs.storageLimitReached" | { "modals"?: "none" | "viewingVc";
|
||||||
};
|
"tabs"?: "checkStorage" | "gotoIssuers" | "history" | "idle" | "init" | "myVcs" | "receivedVcs" | "storageLimitReached"; };
|
||||||
matchesStates:
|
tags: never;
|
||||||
| 'modals'
|
}
|
||||||
| 'modals.none'
|
|
||||||
| 'modals.viewingVc'
|
|
||||||
| 'tabs'
|
|
||||||
| 'tabs.checkStorage'
|
|
||||||
| 'tabs.gotoIssuers'
|
|
||||||
| 'tabs.history'
|
|
||||||
| 'tabs.idle'
|
|
||||||
| 'tabs.init'
|
|
||||||
| 'tabs.myVcs'
|
|
||||||
| 'tabs.receivedVcs'
|
|
||||||
| 'tabs.storageLimitReached'
|
|
||||||
| {
|
|
||||||
modals?: 'none' | 'viewingVc';
|
|
||||||
tabs?:
|
|
||||||
| 'checkStorage'
|
|
||||||
| 'gotoIssuers'
|
|
||||||
| 'history'
|
|
||||||
| 'idle'
|
|
||||||
| 'init'
|
|
||||||
| 'myVcs'
|
|
||||||
| 'receivedVcs'
|
|
||||||
| 'storageLimitReached';
|
|
||||||
};
|
|
||||||
tags: never;
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@ import {Button, Centered, Column, Text} from '../../components/ui';
|
|||||||
import {Theme} from '../../components/ui/styleUtils';
|
import {Theme} from '../../components/ui/styleUtils';
|
||||||
import {useTranslation} from 'react-i18next';
|
import {useTranslation} from 'react-i18next';
|
||||||
import {useQrLogin} from './QrLoginController';
|
import {useQrLogin} from './QrLoginController';
|
||||||
import {QrLoginRef} from '../../machines/QrLoginMachine';
|
import {QrLoginRef} from '../../machines/QrLogin/QrLoginMachine';
|
||||||
import {Icon} from 'react-native-elements';
|
import {Icon} from 'react-native-elements';
|
||||||
import {Modal} from '../../components/ui/Modal';
|
import {Modal} from '../../components/ui/Modal';
|
||||||
import {VcItemContainer} from '../../components/VC/VcItemContainer';
|
import {VcItemContainer} from '../../components/VC/VcItemContainer';
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {useQrLogin} from './QrLoginController';
|
|||||||
import {Image, View} from 'react-native';
|
import {Image, View} from 'react-native';
|
||||||
import {Icon, ListItem, Switch} from 'react-native-elements';
|
import {Icon, ListItem, Switch} from 'react-native-elements';
|
||||||
import {Modal} from '../../components/ui/Modal';
|
import {Modal} from '../../components/ui/Modal';
|
||||||
import {QrLoginRef} from '../../machines/QrLoginMachine';
|
import {QrLoginRef} from '../../machines/QrLogin/QrLoginMachine';
|
||||||
import {ScrollView} from 'react-native';
|
import {ScrollView} from 'react-native';
|
||||||
import {getClientNameForCurrentLanguage} from '../../i18n';
|
import {getClientNameForCurrentLanguage} from '../../i18n';
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {MessageOverlay} from '../../components/MessageOverlay';
|
|||||||
import {MyBindedVcs} from './MyBindedVcs';
|
import {MyBindedVcs} from './MyBindedVcs';
|
||||||
import {QrLoginSuccess} from './QrLoginSuccessMessage';
|
import {QrLoginSuccess} from './QrLoginSuccessMessage';
|
||||||
import {QrConsent} from './QrConsent';
|
import {QrConsent} from './QrConsent';
|
||||||
import {QrLoginRef} from '../../machines/QrLoginMachine';
|
import {QrLoginRef} from '../../machines/QrLogin/QrLoginMachine';
|
||||||
import {Icon} from 'react-native-elements';
|
import {Icon} from 'react-native-elements';
|
||||||
import {View} from 'react-native';
|
import {View} from 'react-native';
|
||||||
import {FaceVerificationAlertOverlay} from '../Scan/FaceVerificationAlertOverlay';
|
import {FaceVerificationAlertOverlay} from '../Scan/FaceVerificationAlertOverlay';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import {useSelector} from '@xstate/react';
|
import {useSelector} from '@xstate/react';
|
||||||
import {useContext, useState} from 'react';
|
import {useContext, useState} from 'react';
|
||||||
import {ActorRefFrom} from 'xstate';
|
import {ActorRefFrom} from 'xstate';
|
||||||
|
import { QrLoginEvents } from '../../machines/QrLogin/QrLoginMachine';
|
||||||
import {
|
import {
|
||||||
QrLoginEvents,
|
|
||||||
selectClientName,
|
selectClientName,
|
||||||
selectErrorMessage,
|
selectErrorMessage,
|
||||||
selectEssentialClaims,
|
selectEssentialClaims,
|
||||||
@@ -25,7 +25,7 @@ import {
|
|||||||
selectVoluntaryClaims,
|
selectVoluntaryClaims,
|
||||||
selectCredential,
|
selectCredential,
|
||||||
selectVerifiableCredentialData,
|
selectVerifiableCredentialData,
|
||||||
} from '../../machines/QrLoginMachine';
|
} from '../../machines/QrLogin/QrLoginSelectors';
|
||||||
import {selectBindedVcsMetadata} from '../../machines/VerifiableCredential/VCMetaMachine/VCMetaSelectors';
|
import {selectBindedVcsMetadata} from '../../machines/VerifiableCredential/VCMetaMachine/VCMetaSelectors';
|
||||||
import {GlobalContext} from '../../shared/GlobalContext';
|
import {GlobalContext} from '../../shared/GlobalContext';
|
||||||
import {QrLoginProps} from './QrLogin';
|
import {QrLoginProps} from './QrLogin';
|
||||||
@@ -85,8 +85,8 @@ export function useQrLogin({service}: QrLoginProps) {
|
|||||||
const vcData = vcRef.getSnapshot().context;
|
const vcData = vcRef.getSnapshot().context;
|
||||||
service.send(QrLoginEvents.SELECT_VC(vcData));
|
service.send(QrLoginEvents.SELECT_VC(vcData));
|
||||||
},
|
},
|
||||||
FACE_VERIFICATION_CONSENT: (isConsentGiven: boolean) =>
|
FACE_VERIFICATION_CONSENT: (isDoNotAskAgainChecked: boolean) =>
|
||||||
service.send(QrLoginEvents.FACE_VERIFICATION_CONSENT(isConsentGiven)),
|
service.send(QrLoginEvents.FACE_VERIFICATION_CONSENT(isDoNotAskAgainChecked)),
|
||||||
DISMISS: () => service.send(QrLoginEvents.DISMISS()),
|
DISMISS: () => service.send(QrLoginEvents.DISMISS()),
|
||||||
SCANNING_DONE: (qrCode: string) =>
|
SCANNING_DONE: (qrCode: string) =>
|
||||||
service.send(QrLoginEvents.SCANNING_DONE(qrCode)),
|
service.send(QrLoginEvents.SCANNING_DONE(qrCode)),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {Modal} from '../../components/ui/Modal';
|
|||||||
import {Centered, Button, Text, Column} from '../../components/ui';
|
import {Centered, Button, Text, Column} from '../../components/ui';
|
||||||
import {Theme} from '../../components/ui/styleUtils';
|
import {Theme} from '../../components/ui/styleUtils';
|
||||||
import {useQrLogin} from './QrLoginController';
|
import {useQrLogin} from './QrLoginController';
|
||||||
import {QrLoginRef} from '../../machines/QrLoginMachine';
|
import {QrLoginRef} from '../../machines/QrLogin/QrLoginMachine';
|
||||||
import {getClientNameForCurrentLanguage} from '../../i18n';
|
import {getClientNameForCurrentLanguage} from '../../i18n';
|
||||||
|
|
||||||
export const QrLoginSuccess: React.FC<QrLoginSuccessProps> = props => {
|
export const QrLoginSuccess: React.FC<QrLoginSuccessProps> = props => {
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export const FaceVerificationAlertOverlay: React.FC<
|
|||||||
|
|
||||||
interface FaceVerificationAlertProps {
|
interface FaceVerificationAlertProps {
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
onConfirm: (isConsentGiven: boolean) => void;
|
onConfirm: (isDoNotAskAgainChecked: boolean) => void;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
isQrLogin?: boolean;
|
isQrLogin?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import {
|
|||||||
selectIsFaceIdentityVerified,
|
selectIsFaceIdentityVerified,
|
||||||
selectCredential,
|
selectCredential,
|
||||||
selectVerifiableCredentialData,
|
selectVerifiableCredentialData,
|
||||||
} from '../../machines/bleShare/scan/selectors';
|
} from '../../machines/bleShare/scan/scanSelectors';
|
||||||
import {
|
import {
|
||||||
selectBleError,
|
selectBleError,
|
||||||
selectIsAccepted,
|
selectIsAccepted,
|
||||||
|
|||||||
@@ -16,10 +16,13 @@ import {BannerNotificationContainer} from '../../components/BannerNotificationCo
|
|||||||
import {SharingStatusModal} from './SharingStatusModal';
|
import {SharingStatusModal} from './SharingStatusModal';
|
||||||
import {SvgImage} from '../../components/ui/svg';
|
import {SvgImage} from '../../components/ui/svg';
|
||||||
import {LocationPermissionRational} from './LocationPermissionRational';
|
import {LocationPermissionRational} from './LocationPermissionRational';
|
||||||
|
import { FaceVerificationAlertOverlay } from './FaceVerificationAlertOverlay';
|
||||||
|
import { useSendVcScreen } from './SendVcScreenController';
|
||||||
|
|
||||||
export const ScanScreen: React.FC = () => {
|
export const ScanScreen: React.FC = () => {
|
||||||
const {t} = useTranslation('ScanScreen');
|
const {t} = useTranslation('ScanScreen');
|
||||||
const controller = useScanScreen();
|
const scanScreenController = useScanScreen();
|
||||||
|
const sendVcScreenController = useSendVcScreen();
|
||||||
const [isBluetoothOn, setIsBluetoothOn] = useState(false);
|
const [isBluetoothOn, setIsBluetoothOn] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -36,13 +39,13 @@ export const ScanScreen: React.FC = () => {
|
|||||||
|
|
||||||
// TODO(kludge): skip running this hook on every render
|
// TODO(kludge): skip running this hook on every render
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (controller.isStartPermissionCheck && !controller.isEmpty)
|
if (scanScreenController.isStartPermissionCheck && !scanScreenController.isEmpty)
|
||||||
controller.START_PERMISSION_CHECK();
|
scanScreenController.START_PERMISSION_CHECK();
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (controller.isQuickShareDone) controller.GOTO_HOME();
|
if (scanScreenController.isQuickShareDone) scanScreenController.GOTO_HOME();
|
||||||
}, [controller.isQuickShareDone]);
|
}, [scanScreenController.isQuickShareDone]);
|
||||||
|
|
||||||
const openSettings = () => {
|
const openSettings = () => {
|
||||||
Linking.openSettings();
|
Linking.openSettings();
|
||||||
@@ -123,14 +126,14 @@ export const ScanScreen: React.FC = () => {
|
|||||||
testID="enableLocationServicesMessage"
|
testID="enableLocationServicesMessage"
|
||||||
align="center"
|
align="center"
|
||||||
color={Theme.Colors.errorMessage}>
|
color={Theme.Colors.errorMessage}>
|
||||||
{controller.locationError.message}
|
{scanScreenController.locationError.message}
|
||||||
</Text>
|
</Text>
|
||||||
</Centered>
|
</Centered>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
testID="enableLocationServicesButton"
|
testID="enableLocationServicesButton"
|
||||||
title={controller.locationError.button}
|
title={scanScreenController.locationError.button}
|
||||||
onPress={controller.LOCATION_REQUEST}
|
onPress={scanScreenController.LOCATION_REQUEST}
|
||||||
/>
|
/>
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
@@ -139,58 +142,58 @@ export const ScanScreen: React.FC = () => {
|
|||||||
function qrScannerComponent() {
|
function qrScannerComponent() {
|
||||||
return (
|
return (
|
||||||
<Column crossAlign="center" margin="0 0 0 -6">
|
<Column crossAlign="center" margin="0 0 0 -6">
|
||||||
<QrScanner onQrFound={controller.SCAN} title={t('scanningGuide')} />
|
<QrScanner onQrFound={scanScreenController.SCAN} title={t('scanningGuide')} />
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadQRScanner() {
|
function loadQRScanner() {
|
||||||
if (controller.isEmpty) {
|
if (scanScreenController.isEmpty) {
|
||||||
return noShareableVcText();
|
return noShareableVcText();
|
||||||
}
|
}
|
||||||
if (controller.selectIsInvalid) {
|
if (scanScreenController.selectIsInvalid) {
|
||||||
return displayInvalidQRpopup();
|
return displayInvalidQRpopup();
|
||||||
}
|
}
|
||||||
if (controller.isNearByDevicesPermissionDenied) {
|
if (scanScreenController.isNearByDevicesPermissionDenied) {
|
||||||
return allowNearbyDevicesPermissionComponent();
|
return allowNearbyDevicesPermissionComponent();
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
(controller.isBluetoothDenied || !isBluetoothOn) &&
|
(scanScreenController.isBluetoothDenied || !isBluetoothOn) &&
|
||||||
controller.isReadyForBluetoothStateCheck
|
scanScreenController.isReadyForBluetoothStateCheck
|
||||||
) {
|
) {
|
||||||
return bluetoothIsOffText();
|
return bluetoothIsOffText();
|
||||||
}
|
}
|
||||||
if (controller.isLocalPermissionRational) {
|
if (scanScreenController.isLocalPermissionRational) {
|
||||||
return (
|
return (
|
||||||
<LocationPermissionRational
|
<LocationPermissionRational
|
||||||
onConfirm={controller.ALLOWED}
|
onConfirm={scanScreenController.ALLOWED}
|
||||||
onCancel={controller.DENIED}
|
onCancel={scanScreenController.DENIED}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (controller.isLocationDisabled || controller.isLocationDenied) {
|
if (scanScreenController.isLocationDisabled || scanScreenController.isLocationDenied) {
|
||||||
return allowLocationComponent();
|
return allowLocationComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (controller.isBluetoothPermissionDenied) {
|
if (scanScreenController.isBluetoothPermissionDenied) {
|
||||||
return allowBluetoothPermissionComponent();
|
return allowBluetoothPermissionComponent();
|
||||||
}
|
}
|
||||||
if (controller.isScanning) {
|
if (scanScreenController.isScanning) {
|
||||||
return qrScannerComponent();
|
return qrScannerComponent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function displayStorageLimitReachedError(): React.ReactNode {
|
function displayStorageLimitReachedError(): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
!controller.isEmpty && (
|
!scanScreenController.isEmpty && (
|
||||||
<ErrorMessageOverlay
|
<ErrorMessageOverlay
|
||||||
testID="storageLimitReachedError"
|
testID="storageLimitReachedError"
|
||||||
isVisible={
|
isVisible={
|
||||||
controller.isMinimumStorageRequiredForAuditEntryLimitReached
|
scanScreenController.isMinimumStorageRequiredForAuditEntryLimitReached
|
||||||
}
|
}
|
||||||
translationPath={'ScanScreen'}
|
translationPath={'ScanScreen'}
|
||||||
error="errors.storageLimitReached"
|
error="errors.storageLimitReached"
|
||||||
onDismiss={controller.GOTO_HOME}
|
onDismiss={scanScreenController.GOTO_HOME}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -198,17 +201,17 @@ export const ScanScreen: React.FC = () => {
|
|||||||
|
|
||||||
function displayInvalidQRpopup(): React.ReactNode {
|
function displayInvalidQRpopup(): React.ReactNode {
|
||||||
return (
|
return (
|
||||||
!controller.isEmpty && (
|
!scanScreenController.isEmpty && (
|
||||||
<SharingStatusModal
|
<SharingStatusModal
|
||||||
isVisible={controller.selectIsInvalid}
|
isVisible={scanScreenController.selectIsInvalid}
|
||||||
testId={'invalidQrPopup'}
|
testId={'invalidQrPopup'}
|
||||||
image={SvgImage.ErrorLogo()}
|
image={SvgImage.ErrorLogo()}
|
||||||
title={t(`status.bleError.TVW_CON_001.title`)}
|
title={t(`status.bleError.TVW_CON_001.title`)}
|
||||||
message={t(`status.bleError.TVW_CON_001.message`)}
|
message={t(`status.bleError.TVW_CON_001.message`)}
|
||||||
gradientButtonTitle={t('status.bleError.retry')}
|
gradientButtonTitle={t('status.bleError.retry')}
|
||||||
clearButtonTitle={t('status.bleError.home')}
|
clearButtonTitle={t('status.bleError.home')}
|
||||||
onGradientButton={controller.DISMISS}
|
onGradientButton={scanScreenController.DISMISS}
|
||||||
onClearButton={controller.GOTO_HOME}
|
onClearButton={scanScreenController.GOTO_HOME}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -217,19 +220,24 @@ export const ScanScreen: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<Column fill backgroundColor={Theme.Colors.whiteBackgroundColor}>
|
<Column fill backgroundColor={Theme.Colors.whiteBackgroundColor}>
|
||||||
<BannerNotificationContainer />
|
<BannerNotificationContainer />
|
||||||
<Centered
|
<FaceVerificationAlertOverlay
|
||||||
|
isVisible={sendVcScreenController.isFaceVerificationConsent}
|
||||||
|
onConfirm={sendVcScreenController.FACE_VERIFICATION_CONSENT}
|
||||||
|
close={sendVcScreenController.DISMISS}
|
||||||
|
/>
|
||||||
|
<Centered
|
||||||
padding="24 0"
|
padding="24 0"
|
||||||
align="space-evenly"
|
align="space-evenly"
|
||||||
backgroundColor={Theme.Colors.whiteBackgroundColor}>
|
backgroundColor={Theme.Colors.whiteBackgroundColor}>
|
||||||
{loadQRScanner()}
|
{loadQRScanner()}
|
||||||
{controller.isQrLogin && (
|
{scanScreenController.isQrLogin && (
|
||||||
<QrLogin
|
<QrLogin
|
||||||
isVisible={controller.isQrLogin}
|
isVisible={scanScreenController.isQrLogin}
|
||||||
service={controller.isQrRef}
|
service={scanScreenController.isQrRef}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<MessageOverlay
|
<MessageOverlay
|
||||||
isVisible={controller.isQrLoginstoring}
|
isVisible={scanScreenController.isQrLoginstoring}
|
||||||
title={t('loading')}
|
title={t('loading')}
|
||||||
progress
|
progress
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
selectQrLoginRef,
|
selectQrLoginRef,
|
||||||
selectIsQuickShareDone,
|
selectIsQuickShareDone,
|
||||||
selectShowQuickShareSuccessBanner,
|
selectShowQuickShareSuccessBanner,
|
||||||
} from '../../machines/bleShare/scan/selectors';
|
} from '../../machines/bleShare/scan/scanSelectors';
|
||||||
import {
|
import {
|
||||||
selectIsBluetoothDenied,
|
selectIsBluetoothDenied,
|
||||||
selectIsNearByDevicesPermissionDenied,
|
selectIsNearByDevicesPermissionDenied,
|
||||||
@@ -24,8 +24,8 @@ import {
|
|||||||
} from '../../machines/bleShare/commonSelectors';
|
} from '../../machines/bleShare/commonSelectors';
|
||||||
import {
|
import {
|
||||||
ScanEvents,
|
ScanEvents,
|
||||||
selectIsMinimumStorageRequiredForAuditEntryLimitReached,
|
|
||||||
} from '../../machines/bleShare/scan/scanMachine';
|
} from '../../machines/bleShare/scan/scanMachine';
|
||||||
|
import { selectIsMinimumStorageRequiredForAuditEntryLimitReached } from '../../machines/bleShare/scan/scanSelectors';
|
||||||
import {BOTTOM_TAB_ROUTES} from '../../routes/routesConstants';
|
import {BOTTOM_TAB_ROUTES} from '../../routes/routesConstants';
|
||||||
import {MainBottomTabParamList} from '../../routes/routeTypes';
|
import {MainBottomTabParamList} from '../../routes/routeTypes';
|
||||||
import {useNavigation, NavigationProp} from '@react-navigation/native';
|
import {useNavigation, NavigationProp} from '@react-navigation/native';
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {useInterpret} from '@xstate/react';
|
|||||||
import {GlobalContext} from '../../shared/GlobalContext';
|
import {GlobalContext} from '../../shared/GlobalContext';
|
||||||
import {useFocusEffect} from '@react-navigation/native';
|
import {useFocusEffect} from '@react-navigation/native';
|
||||||
import {VcItemContainer} from '../../components/VC/VcItemContainer';
|
import {VcItemContainer} from '../../components/VC/VcItemContainer';
|
||||||
import {VCMetadata} from '../../shared/VCMetadata';
|
|
||||||
import {createVCItemMachine} from '../../machines/VerifiableCredential/VCItemMachine/VCItemMachine';
|
import {createVCItemMachine} from '../../machines/VerifiableCredential/VCItemMachine/VCItemMachine';
|
||||||
import {
|
import {
|
||||||
getImpressionEventData,
|
getImpressionEventData,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
selectReceiverInfo,
|
selectReceiverInfo,
|
||||||
selectVcName,
|
selectVcName,
|
||||||
selectVerifiableCredentialData,
|
selectVerifiableCredentialData,
|
||||||
} from '../../machines/bleShare/scan/selectors';
|
} from '../../machines/bleShare/scan/scanSelectors';
|
||||||
import {
|
import {
|
||||||
selectIsCancelling,
|
selectIsCancelling,
|
||||||
selectIsInvalidIdentity,
|
selectIsInvalidIdentity,
|
||||||
@@ -17,8 +17,8 @@ import {
|
|||||||
} from '../../machines/bleShare/commonSelectors';
|
} from '../../machines/bleShare/commonSelectors';
|
||||||
import {
|
import {
|
||||||
ScanEvents,
|
ScanEvents,
|
||||||
selectIsFaceVerificationConsent,
|
|
||||||
} from '../../machines/bleShare/scan/scanMachine';
|
} from '../../machines/bleShare/scan/scanMachine';
|
||||||
|
import { selectIsFaceVerificationConsent } from '../../machines/bleShare/scan/scanSelectors';
|
||||||
import {VCShareFlowType} from '../../shared/Utils';
|
import {VCShareFlowType} from '../../shared/Utils';
|
||||||
import {NavigationProp, useNavigation} from '@react-navigation/native';
|
import {NavigationProp, useNavigation} from '@react-navigation/native';
|
||||||
import {RootRouteProps} from '../../routes';
|
import {RootRouteProps} from '../../routes';
|
||||||
@@ -63,8 +63,8 @@ export function useSendVcScreen() {
|
|||||||
),
|
),
|
||||||
CANCEL: () => scanService.send(ScanEvents.CANCEL()),
|
CANCEL: () => scanService.send(ScanEvents.CANCEL()),
|
||||||
ACCEPT_REQUEST: () => scanService.send(ScanEvents.ACCEPT_REQUEST()),
|
ACCEPT_REQUEST: () => scanService.send(ScanEvents.ACCEPT_REQUEST()),
|
||||||
FACE_VERIFICATION_CONSENT: (isConsentGiven: boolean) =>
|
FACE_VERIFICATION_CONSENT: (isDoNotAskAgainChecked: boolean) =>
|
||||||
scanService.send(ScanEvents.FACE_VERIFICATION_CONSENT(isConsentGiven)),
|
scanService.send(ScanEvents.FACE_VERIFICATION_CONSENT(isDoNotAskAgainChecked)),
|
||||||
VERIFY_AND_ACCEPT_REQUEST: () =>
|
VERIFY_AND_ACCEPT_REQUEST: () =>
|
||||||
scanService.send(ScanEvents.VERIFY_AND_ACCEPT_REQUEST()),
|
scanService.send(ScanEvents.VERIFY_AND_ACCEPT_REQUEST()),
|
||||||
DISMISS: () => scanService.send(ScanEvents.DISMISS()),
|
DISMISS: () => scanService.send(ScanEvents.DISMISS()),
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ export const SETTINGS_STORE_KEY = 'settings';
|
|||||||
|
|
||||||
export const APP_ID_LENGTH = 12;
|
export const APP_ID_LENGTH = 12;
|
||||||
|
|
||||||
export const FACE_AUTH_CONSENT = 'faceAuthConsent';
|
export const SHOW_FACE_AUTH_CONSENT_SHARE_FLOW = 'showFaceAuthConsentShareFlow';
|
||||||
|
|
||||||
|
export const SHOW_FACE_AUTH_CONSENT_QR_LOGIN_FLOW='showFaceAuthConsentQrLoginFlow'
|
||||||
|
|
||||||
//Banner Status
|
//Banner Status
|
||||||
export const BANNER_TYPE_SUCCESS = 'success';
|
export const BANNER_TYPE_SUCCESS = 'success';
|
||||||
|
|||||||
Reference in New Issue
Block a user