[INJIMOB-3193]add preauth and credential offer support (#1949)

[INJIMOB-3058]temp commit2



[INJIMOB-3058]temp commit2



[INJIMOB-3058] add support for pre-auth flow by credential-offer



[INJIMOB-3187] animo working chcekpoint

Signed-off-by: Abhishek Paul <paul.apaul.abhishek.ap@gmail.com>
This commit is contained in:
abhip2565
2025-06-04 14:46:07 +05:30
committed by GitHub
parent ddf5244f32
commit bd90b342e0
63 changed files with 3510 additions and 2063 deletions

2
.env
View File

@@ -2,7 +2,7 @@
# eg . npm build android:newlogic --reset-cache
#MIMOTO_HOST=http://mock.mimoto.newlogic.dev
MIMOTO_HOST=https://api.qa-inji.mosip.net
MIMOTO_HOST=https://api.qa-inji1.mosip.net
ESIGNET_HOST=https://esignet.qa-inji.mosip.net

View File

@@ -38,7 +38,7 @@ fileignoreconfig:
- filename: screens/Home/MyVcs/GetIdInputModal.tsx
checksum: 5c736ed79a372d0ffa7c02eb33d0dc06edbbb08d120978ff287f5f06cd6c7746
- filename: shared/openId4VCI/Utils.ts
checksum: 78473ce25cd52c8d07da9ba98683bdb64ae83a9de8fa907c62f2ebeca7dd21dc
checksum: 40b9af91348c8c80e4da7920374110d56f3782aa8f1317e211bdea02efb0d943
- filename: shared/cryptoutil/cryptoUtil.ts
checksum: 281f061ae6eb722c75c2caf2bdfb5b1bf72f292b471318d972c898c5a972c65f
- filename: shared/telemetry/TelemetryConstants.js

View File

@@ -5,6 +5,8 @@ plugins {
apply plugin: "com.android.application"
apply plugin: "com.facebook.react"
apply plugin: "org.sonarqube"
apply plugin: 'kotlin-android'
configurations.all {
resolutionStrategy.force 'androidx.activity:activity-ktx:1.7.1', 'androidx.activity:activity:1.7.0', 'com.fasterxml.jackson.core:jackson-core:2.14.0'
@@ -262,6 +264,9 @@ android {
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
implementation("io.mosip:inji-openid4vp:0.3.0-SNAPSHOT"){
changing = true
exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15on'
@@ -275,7 +280,7 @@ dependencies {
implementation("io.mosip:pixelpass-aar:0.7.0-SNAPSHOT")
implementation("io.mosip:secure-keystore:0.3.0")
implementation("io.mosip:tuvali:0.5.2")
implementation("io.mosip:inji-vci-client:0.3.0-SNAPSHOT")
implementation("io.mosip:inji-vci-client:0.4.0-SNAPSHOT")
implementation("com.google.code.gson:gson:2.10.1")
implementation("io.mosip:vcverifier-aar:1.3.0-SNAPSHOT") {
exclude group: 'org.bouncycastle', module: 'bcpkix-jdk15on'

View File

@@ -0,0 +1,131 @@
package io.mosip.residentapp
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.modules.core.DeviceEventManagerModule
import com.google.gson.Gson
import kotlinx.coroutines.CompletableDeferred
object VCIClientCallbackBridge {
private var deferredProof: CompletableDeferred<String>? = null
private var deferredAuthCode: CompletableDeferred<String>? = null
private var deferredTxCode: CompletableDeferred<String>? = null
private var deferredIssuerTrustResponse: CompletableDeferred<Boolean>? = null
fun createProofDeferred(): CompletableDeferred<String> {
deferredProof = CompletableDeferred()
return deferredProof!!
}
fun createAuthCodeDeferred(): CompletableDeferred<String> {
deferredAuthCode = CompletableDeferred()
return deferredAuthCode!!
}
fun createTxCodeDeferred(): CompletableDeferred<String> {
deferredTxCode = CompletableDeferred()
return deferredTxCode!!
}
fun createIsuerTrustResponseDeferred(): CompletableDeferred<Boolean> {
deferredIssuerTrustResponse = CompletableDeferred()
return deferredIssuerTrustResponse!!
}
fun emitRequestProof(
context: ReactApplicationContext,
accessToken: String,
cNonce: String?,
issuerMetadata: Map<String, *>? = null,
credentialConfigurationId: String? = null
) {
val params =
Arguments.createMap().apply {
putString("accessToken", accessToken)
if (cNonce != null) putString("cNonce", cNonce)
if (issuerMetadata != null) {
val json = Gson().toJson(issuerMetadata)
putString("issuerMetadata", json)
}
if (credentialConfigurationId != null) {
putString("credentialConfigurationId", credentialConfigurationId)
}
}
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit("onRequestProof", params)
}
fun emitRequestAuthCode(context: ReactApplicationContext, authorizationEndpoint: String) {
val params =
Arguments.createMap().apply {
putString("authorizationEndpoint", authorizationEndpoint)
}
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit("onRequestAuthCode", params)
}
fun emitRequestTxCode(
context: ReactApplicationContext,
inputMode: String?,
description: String?,
length: Int?
) {
val params =
Arguments.createMap().apply {
putString("inputMode", inputMode)
putString("description", description)
if( length != null)
putInt("length", length)
}
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit("onRequestTxCode", params)
}
fun emitRequestIssuerTrust(context: ReactApplicationContext, issuerMetadata: Map<String, *>) {
val params =
Arguments.createMap().apply {
putString("issuerMetadata", Gson().toJson(issuerMetadata))
}
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
.emit("onCheckIssuerTrust", params)
}
@JvmStatic
fun completeProof(jwt: String) {
deferredProof?.complete(jwt)
deferredProof = null
}
@JvmStatic
fun completeAuthCode(code: String) {
deferredAuthCode?.complete(code)
deferredAuthCode = null
}
@JvmStatic
fun completeTxCode(code: String) {
deferredTxCode?.complete(code)
deferredTxCode = null
}
@JvmStatic
fun completeIssuerTrustResponse(trusted: Boolean) {
deferredIssuerTrustResponse?.complete(trusted)
deferredIssuerTrustResponse = null
}
suspend fun awaitProof(): String {
return deferredProof?.await() ?: throw IllegalStateException("No proof callback was set")
}
suspend fun awaitAuthCode(): String {
return deferredAuthCode?.await()
?: throw IllegalStateException("No auth code callback was set")
}
suspend fun awaitTxCode(): String {
return deferredTxCode?.await() ?: throw IllegalStateException("No tx code callback was set")
}
suspend fun awaitIssuerTrustResponse(): Boolean {
return deferredIssuerTrustResponse?.await()
?: throw IllegalStateException("No issuer trust response callback was set")
}
}

View File

@@ -11,27 +11,30 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.google.gson.Gson;
import java.util.Objects;
import io.mosip.residentapp.VCIClientCallbackBridge;
import io.mosip.residentapp.VCIClientBridge;
import io.mosip.vciclient.VCIClient;
import io.mosip.vciclient.constants.CredentialFormat;
import io.mosip.vciclient.credentialOffer.CredentialOffer;
import io.mosip.vciclient.credentialOffer.CredentialOfferService;
import io.mosip.vciclient.credentialResponse.CredentialResponse;
import io.mosip.vciclient.dto.IssuerMetaData;
import io.mosip.vciclient.proof.jwt.JWTProof;
import io.mosip.vciclient.proof.Proof;
import io.mosip.vciclient.issuerMetadata.IssuerMetadata;
import io.mosip.vciclient.clientMetadata.ClientMetadata;
public class InjiVciClientModule extends ReactContextBaseJavaModule {
private VCIClient vciClient;
private final ReactApplicationContext reactContext;
public InjiVciClientModule(@Nullable ReactApplicationContext reactContext) {
super(reactContext);
}
@ReactMethod
public void init(String appId) {
Log.d("InjiVciClientModule", "Initializing InjiVciClientModule with " + appId);
vciClient = new VCIClient(appId);
this.reactContext = reactContext;
VCIClientBridge.reactContext = this.reactContext;
}
@NonNull
@@ -41,42 +44,68 @@ public class InjiVciClientModule extends ReactContextBaseJavaModule {
}
@ReactMethod
public void requestCredential(ReadableMap issuerMetaData, String jwtProofValue, String accessToken, Promise promise) {
try {
IssuerMetaData constructedIssuerMetadata ;
String issuerMetadataCredentialFormat = issuerMetaData.getString("credentialFormat");
if(Objects.equals(issuerMetadataCredentialFormat, CredentialFormat.LDP_VC.getValue())){
constructedIssuerMetadata = new IssuerMetaData(
issuerMetaData.getString("credentialAudience"),
issuerMetaData.getString("credentialEndpoint"),
issuerMetaData.getInt("downloadTimeoutInMilliSeconds"),
convertReadableArrayToStringArray(issuerMetaData.getArray("credentialType")),
CredentialFormat.LDP_VC,null,null);
} else if (Objects.equals(issuerMetadataCredentialFormat, CredentialFormat.MSO_MDOC.getValue())) {
constructedIssuerMetadata = new IssuerMetaData(
issuerMetaData.getString("credentialAudience"),
issuerMetaData.getString("credentialEndpoint"),
issuerMetaData.getInt("downloadTimeoutInMilliSeconds"),
null,
CredentialFormat.MSO_MDOC, issuerMetaData.getString("doctype"),
issuerMetaData.getMap("claims").toHashMap());
} else {
throw new IllegalStateException("Unexpected value: " + issuerMetadataCredentialFormat);
}
CredentialResponse response = vciClient.requestCredential(constructedIssuerMetadata, new JWTProof(jwtProofValue)
, accessToken);
promise.resolve(response.toJsonString());
} catch (Exception exception) {
promise.reject(exception);
}
public void init(String appId) {
Log.d("InjiVciClientModule", "Initializing InjiVciClientModule with " + appId);
vciClient = new VCIClient(appId,reactContext);
}
private String[] convertReadableArrayToStringArray(ReadableArray readableArray) {
String[] stringArray = new String[readableArray.size()];
for (int i = 0; i < readableArray.size(); i++) {
stringArray[i] = readableArray.getString(i);
}
return stringArray;
@ReactMethod
public void sendProofFromJS(String jwt) {
VCIClientCallbackBridge.completeProof(jwt);
}
@ReactMethod
public void sendAuthCodeFromJS(String authCode) {
VCIClientCallbackBridge.completeAuthCode(authCode);
}
@ReactMethod
public void sendTxCodeFromJS(String txCode) {
VCIClientCallbackBridge.completeTxCode(txCode);
}
@ReactMethod
public void sendIssuerTrustResponseFromJS(Boolean trusted) {
VCIClientCallbackBridge.completeIssuerTrustResponse(trusted);
}
@ReactMethod
public void requestCredentialByOffer(String credentialOffer,String clientMetadataJson, Promise promise) {
new Thread(() -> {
try {
ClientMetadata clientMetadata= new Gson().fromJson(
clientMetadataJson, ClientMetadata.class);
CredentialResponse response = VCIClientBridge.requestCredentialByOfferSync(vciClient, credentialOffer,clientMetadata);
reactContext.runOnUiQueueThread(() -> {
promise.resolve(response != null ? response.toJsonString() : null);
});
} catch (Exception e) {
reactContext.runOnUiQueueThread(() -> {
promise.reject("OFFER_FLOW_FAILED", e.getMessage(), e);
});
}
}).start();
}
@ReactMethod
public void requestCredentialFromTrustedIssuer(String resolvedIssuerMetaJson, String clientMetadataJson, Promise promise) {
new Thread(() -> {
try {
IssuerMetadata issuerMetaData = new Gson().fromJson(
resolvedIssuerMetaJson, IssuerMetadata.class);
ClientMetadata clientMetadata= new Gson().fromJson(
clientMetadataJson, ClientMetadata.class);
CredentialResponse response = VCIClientBridge.requestCredentialFromTrustedIssuerSync(vciClient, issuerMetaData,clientMetadata);
reactContext.runOnUiQueueThread(() -> {
promise.resolve(response != null ? response.toJsonString() : null);
});
} catch (Exception e) {
reactContext.runOnUiQueueThread(() -> {
promise.reject("TRUSTED_ISSUER_FAILED", e.getMessage(), e);
});
}
}).start();
}
}

View File

@@ -0,0 +1,79 @@
package io.mosip.residentapp
import com.facebook.react.bridge.ReactApplicationContext
import io.mosip.vciclient.VCIClient
import io.mosip.vciclient.clientMetadata.ClientMetadata
import io.mosip.vciclient.credentialResponse.CredentialResponse
import io.mosip.vciclient.issuerMetadata.IssuerMetadata
import io.mosip.residentapp.VCIClientBridge
import kotlinx.coroutines.runBlocking
object VCIClientBridge {
// Must be set by the Java side (InjiVciClientModule) to emit events to JS
lateinit var reactContext: ReactApplicationContext
@JvmStatic
fun requestCredentialByOfferSync(
client: VCIClient,
offer: String,
clientMetaData: ClientMetadata
): CredentialResponse? = runBlocking {
client.requestCredentialByCredentialOffer(
credentialOffer = offer,
clientMetadata = clientMetaData,
getTxCode = { inputMode, description, length ->
VCIClientCallbackBridge.createTxCodeDeferred()
VCIClientCallbackBridge.emitRequestTxCode(VCIClientBridge.reactContext,
inputMode,
description,
length
)
VCIClientCallbackBridge.awaitTxCode()
},
getProofJwt = { accessToken, cNonce, issuerMetadata, credentialConfigurationId ->
VCIClientCallbackBridge.createProofDeferred()
VCIClientCallbackBridge.emitRequestProof(
VCIClientBridge.reactContext,
accessToken,
cNonce,
issuerMetadata,
credentialConfigurationId
)
VCIClientCallbackBridge.awaitProof()
},
getAuthCode = { endpoint ->
VCIClientCallbackBridge.createAuthCodeDeferred()
VCIClientCallbackBridge.emitRequestAuthCode(VCIClientBridge.reactContext, endpoint)
VCIClientCallbackBridge.awaitAuthCode()
},
onCheckIssuerTrust = { issuerMetadata ->
VCIClientCallbackBridge.createIsuerTrustResponseDeferred()
VCIClientCallbackBridge.emitRequestIssuerTrust(reactContext, issuerMetadata)
VCIClientCallbackBridge.awaitIssuerTrustResponse()
}
)
}
@JvmStatic
fun requestCredentialFromTrustedIssuerSync(
client: VCIClient,
resolvedIssuerMetaData: IssuerMetadata,
clientMetaData: ClientMetadata
): CredentialResponse? = runBlocking {
client.requestCredentialFromTrustedIssuer(
issuerMetadata = resolvedIssuerMetaData,
clientMetadata = clientMetaData,
getProofJwt = { accessToken, cNonce, _, _ ->
VCIClientCallbackBridge.createProofDeferred()
VCIClientCallbackBridge.emitRequestProof(reactContext, accessToken, cNonce)
VCIClientCallbackBridge.awaitProof()
},
getAuthCode = { authorizationEndpoint ->
VCIClientCallbackBridge.createAuthCodeDeferred()
VCIClientCallbackBridge.emitRequestAuthCode(reactContext, authorizationEndpoint)
VCIClientCallbackBridge.awaitAuthCode()
}
)
}
}

View File

@@ -14,11 +14,13 @@ buildscript {
google()
jcenter()
mavenCentral()
mavenLocal()
}
dependencies {
classpath("com.android.tools.build:gradle:8.2")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
}
}
@@ -26,7 +28,9 @@ buildscript {
// @generated begin expo-camera-import - expo prebuild (DO NOT MODIFY) sync-f244f4f3d8bf7229102e8f992b525b8602c74770
def expoCameraMavenPath = new File(["node", "--print", "require.resolve('expo-camera/package.json')"].execute(null, rootDir).text.trim(), "../android/maven")
allprojects { repositories {
mavenLocal()
maven{url("https://oss.sonatype.org/content/repositories/snapshots/")}
maven{url("https://central.sonatype.com/repository/maven-snapshots/")}
maven { url(expoCameraMavenPath) }
mavenCentral()
maven {url("https://repo.danubetech.com/repository/maven-public/")}

15
assets/scanIcon.svg Normal file
View File

@@ -0,0 +1,15 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.66667 9.33341V2.66675H9.33334V5.33341H5.33334V9.33341H2.66667ZM2.66667 29.3334V22.6667H5.33334V26.6667H9.33334V29.3334H2.66667ZM22.6667 29.3334V26.6667H26.6667V22.6667H29.3333V29.3334H22.6667ZM26.6667 9.33341V5.33341H22.6667V2.66675H29.3333V9.33341H26.6667ZM23.3333 23.3334H25.3333V25.3334H23.3333V23.3334ZM23.3333 19.3334H25.3333V21.3334H23.3333V19.3334ZM21.3333 21.3334H23.3333V23.3334H21.3333V21.3334ZM19.3333 23.3334H21.3333V25.3334H19.3333V23.3334ZM17.3333 21.3334H19.3333V23.3334H17.3333V21.3334ZM21.3333 17.3334H23.3333V19.3334H21.3333V17.3334ZM19.3333 19.3334H21.3333V21.3334H19.3333V19.3334ZM17.3333 17.3334H19.3333V19.3334H17.3333V17.3334ZM25.3333 6.66675V14.6667H17.3333V6.66675H25.3333ZM14.6667 17.3334V25.3334H6.66667V17.3334H14.6667ZM14.6667 6.66675V14.6667H6.66667V6.66675H14.6667ZM12.6667 23.3334V19.3334H8.66667V23.3334H12.6667ZM12.6667 12.6667V8.66675H8.66667V12.6667H12.6667ZM23.3333 12.6667V8.66675H19.3333V12.6667H23.3333Z" fill="url(#paint0_linear_532_832)"/>
<defs>
<linearGradient id="paint0_linear_532_832" x1="2.66667" y1="16.0001" x2="29.3333" y2="16.0001" gradientUnits="userSpaceOnUse">
<stop stop-color="#FF5300"/>
<stop offset="0.16" stop-color="#FB5103"/>
<stop offset="0.31" stop-color="#F04C0F"/>
<stop offset="0.46" stop-color="#DE4322"/>
<stop offset="0.61" stop-color="#C5363C"/>
<stop offset="0.75" stop-color="#A4265F"/>
<stop offset="0.9" stop-color="#7C1389"/>
<stop offset="1" stop-color="#5B03AD"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -11,13 +11,17 @@ export const PinInput: React.FC<PinInputProps> = props => {
const [focusedIndex, setFocusedIndex] = useState(0);
useEffect(() => {
if (props.onDone && values.filter(Boolean).length === inputRefs.length) {
props.onDone(values.join(''));
const current = values.join('');
props.onChange?.(current);
if (props.autosubmit && props.onDone && values.filter(Boolean).length === inputRefs.length) {
props.onDone(current);
}
}, [state]);
}, [values]);
return (
<Row width="100%" testID={props.testID} removeClippedSubviews={true}>
<Row width={`${(100 / 6) * props.length}%`} testID={props.testID} removeClippedSubviews={true}>
{inputRefs.map((input, index) => (
<TextInput
contextMenuHidden={true}
@@ -53,4 +57,6 @@ interface PinInputProps {
testID?: string;
length: number;
onDone?: (value: string) => void;
onChange?: (value: string) => void;
autosubmit?: boolean;
}

View File

@@ -69,7 +69,7 @@ export const VCCardView: React.FC<VCItemProps> = ({
credentialConfigurationId,
vcMetadata: { format },
} = verifiableCredentialData;
if (vcMetadata.issuerHost) {
if (vcMetadata) {
getCredentialIssuersWellKnownConfig(
issuer,
CARD_VIEW_DEFAULT_FIELDS,

View File

@@ -50,7 +50,7 @@ export const VCDetailView: React.FC<VCItemDetailsProps> = (
} else if (
props.verifiableCredentialData.vcMetadata.format === VCFormat.mso_mdoc
) {
const namespaces = verifiableCredential['issuerSigned']['nameSpaces'];
const namespaces = verifiableCredential['issuerSigned']?.['nameSpaces'] ?? verifiableCredential['nameSpaces']??{};
Object.keys(namespaces).forEach(namespace => {
(namespaces[namespace] as Array<Object>).forEach(element => {
availableFieldNames.push(
@@ -119,7 +119,8 @@ export const VCDetailView: React.FC<VCItemDetailsProps> = (
margin={'0 0 0 24'}
style={{flex: 1}}>
{fieldItemIterator(
props.fields,
props.fields,
props.wellknownFieldsFlag,
verifiableCredential,
props.wellknown,
wellknownDisplayProperty,
@@ -141,6 +142,7 @@ export const VCDetailView: React.FC<VCItemDetailsProps> = (
{shouldShowHrLine(verifiableCredential) &&
fieldItemIterator(
DETAIL_VIEW_BOTTOM_SECTION_FIELDS,
props.wellknownFieldsFlag,
verifiableCredential,
props.wellknown,
wellknownDisplayProperty,
@@ -240,6 +242,7 @@ export const VCDetailView: React.FC<VCItemDetailsProps> = (
export interface VCItemDetailsProps {
fields: any[];
wellknown: any;
wellknownFieldsFlag: boolean;
credential: VerifiableCredential | Credential;
verifiableCredentialData: VerifiableCredentialData;
walletBindingResponse?: WalletBindingResponse;

View File

@@ -154,7 +154,7 @@ export const getFieldName = (
}
}
}
return i18n.t(`VcDetails:${field}`);
return field;
};
export function getAddressFields() {
@@ -181,17 +181,72 @@ function getFullAddress(credential: CredentialSubject) {
.filter(Boolean)
.join(', ');
}
const renderFieldRecursively = (
key: string,
value: any,
fieldNameColor: string,
fieldValueColor: string,
parentKey = '',
depth = 0
): JSX.Element[] => {
const fullKey = parentKey ? `${parentKey}.${key}` : key;
if (value === null || value === undefined) return [];
if (Array.isArray(value)) {
return value.flatMap((item, index) =>
renderFieldRecursively(`${key}[${index}]`, item, fieldNameColor,fieldValueColor,parentKey, depth + 1)
);
} else if (typeof value === 'object') {
return Object.entries(value).flatMap(([childKey, childValue]) =>
renderFieldRecursively(childKey, childValue, fieldNameColor,fieldValueColor,fullKey, depth + 1)
);
} else {
let displayValue = String(value);
// Truncate base64 if it's an image data URI or very long string
if (displayValue.startsWith('data:image') || displayValue.length > 100) {
displayValue = displayValue.slice(0, 60) + '...';
}
return [
<Row
key={`extra-${fullKey}`}
style={{
flexDirection: 'row',
flex: 1,
paddingLeft: depth * 12, // Indent nested levels
}}
align="space-between"
margin="0 8 15 0"
>
<VCItemField
key={`extra-${fullKey}`}
fieldName={fullKey}
fieldValue={displayValue}
fieldNameColor={fieldNameColor}
fieldValueColor={fieldValueColor}
testID={`extra-${fullKey}`}
/>
</Row>,
];
}
};
export const fieldItemIterator = (
fields: any[],
wellknownFieldsFlag: boolean,
verifiableCredential: VerifiableCredential | Credential,
wellknown: any,
display: Display,
props: VCItemDetailsProps,
) => {
): JSX.Element[] => {
const fieldNameColor = display.getTextColor(Theme.Colors.DetailsLabel);
const fieldValueColor = display.getTextColor(Theme.Colors.Details);
return fields.map(field => {
const renderedFields = new Set<string>();
const renderedMainFields = fields.map(field => {
const fieldName = getFieldName(
field,
wellknown,
@@ -205,16 +260,20 @@ export const fieldItemIterator = (
display,
props.verifiableCredentialData.vcMetadata.format,
);
renderedFields.add(field);
if (
(field === 'credentialRegistry' &&
CREDENTIAL_REGISTRY_EDIT === 'false') ||
!fieldValue
)
return;
) {
return null;
}
return (
<Row
key={field}
style={{flexDirection: 'row', flex: 1}}
style={{ flexDirection: 'row', flex: 1 }}
align="space-between"
margin="0 8 15 0">
<VCItemField
@@ -228,13 +287,83 @@ export const fieldItemIterator = (
</Row>
);
});
let renderedExtraFields: JSX.Element[] = [];
if (!wellknownFieldsFlag) {
const renderedAll: JSX.Element[] = [];
// Extra fields from credentialSubject
const credentialSubjectFields =
(verifiableCredential.credentialSubject as Record<string, any>) || {};
const renderedSubjectFields = Object.entries(credentialSubjectFields)
.filter(([key]) => !renderedFields.has(key))
.flatMap(([key, value]) =>
renderFieldRecursively(key, value, fieldNameColor, fieldValueColor)
);
renderedAll.push(...renderedSubjectFields);
// Render fields from nameSpaces (mso_mdoc)
const nameSpaces: Record<string, any> =
verifiableCredential.nameSpaces ??
verifiableCredential.issuerSigned?.nameSpaces ??
verifiableCredential.issuerAuth?.nameSpaces ??
{};
const renderedNamespaceFields = Object.entries(nameSpaces).flatMap(
([namespace, entries]) => {
if (!Array.isArray(entries)) return [];
return [
<VCItemField
key={`ns-title-${namespace}`}
fieldName={(namespace)}
fieldValue=""
fieldNameColor={fieldNameColor}
fieldValueColor={fieldValueColor}
testID={`ns-title-${namespace}`}
/>,
...entries.flatMap((entry, index) => [
<VCItemField
key={`entry-heading-${namespace}-${index}`}
fieldName={"--"}
fieldValue=""
fieldNameColor={fieldNameColor}
fieldValueColor={fieldValueColor}
testID={`entry-heading-${namespace}-${index}`}
/>,
...Object.entries(entry).flatMap(([key, value]) =>
renderFieldRecursively(
key,
value,
fieldNameColor,
fieldValueColor,
`${namespace}[${index}]`,
1
)
),
]),
];
}
);
renderedAll.push(...renderedNamespaceFields);
renderedExtraFields = renderedAll;
}
return [...renderedMainFields, ...renderedExtraFields];
};
export const isVCLoaded = (
verifiableCredential: Credential | null,
fields: string[],
) => {
return verifiableCredential != null && fields.length > 0;
return verifiableCredential != null
};
export const getMosipLogo = () => {
@@ -365,4 +494,4 @@ const ProtectedCurve = {
const PROOF_TYPE_ALGORITHM_MAP = {
[-7]: 'ES256',
};
};

View File

@@ -1,36 +1,39 @@
import React from 'react';
import {Pressable, View} from 'react-native';
import {Theme} from '../ui/styleUtils';
import { Pressable, View } from 'react-native';
import { Theme } from '../ui/styleUtils';
import testIDProps from '../../shared/commonUtil';
import {Text} from '../ui';
import {displayType} from '../../machines/Issuers/IssuersMachine';
import {SvgImage} from '../ui/svg';
import { Text } from '../ui';
import { displayType } from '../../machines/Issuers/IssuersMachine';
import { SvgImage } from '../ui/svg';
export const Issuer: React.FC<IssuerProps> = (props: IssuerProps) => {
return (
<Pressable
accessible={false}
{...testIDProps(`issuer-${props.testID}`)}
onPress={props.onPress}
style={({pressed}) =>
style={({ pressed }) =>
pressed
? [
Theme.IssuersScreenStyles.issuerBoxContainerPressed,
Theme.Styles.boxShadow,
]
Theme.IssuersScreenStyles.issuerBoxContainerPressed,
Theme.Styles.boxShadow,
]
: [
Theme.IssuersScreenStyles.issuerBoxContainer,
Theme.Styles.boxShadow,
]
Theme.IssuersScreenStyles.issuerBoxContainer,
Theme.Styles.boxShadow,
]
}>
<View style={Theme.IssuersScreenStyles.issuerBoxIconContainer}>
{SvgImage.IssuerIcon(props)}
{props.displayDetails.logo
? SvgImage.IssuerIcon(props)
: SvgImage.defaultIssuerLogo(props.defaultLogo)}
</View>
<View style={Theme.IssuersScreenStyles.issuerBoxContent}>
<Text
testID={`issuerHeading-${props.testID}`}
style={Theme.IssuersScreenStyles.issuerHeading}>
{props.displayDetails.title}
{props.displayDetails.title ?? props.displayDetails.name}
</Text>
<Text
testID={`issuerDescription-${props.testID}`}
@@ -46,4 +49,5 @@ export interface IssuerProps {
displayDetails: displayType;
onPress: () => void;
testID: string;
defaultLogo?: any;
}

View File

@@ -21,10 +21,12 @@ export const Text: React.FC<TextProps> = (props: TextProps) => {
{...testIDProps(props.testID)}
style={textStyles}
numberOfLines={props.numLines}
onTextLayout={props.onTextLayout}
ellipsizeMode={props.ellipsizeMode}
accessible={props.accessible}
onPress={props.onPress}>
{props.children}
</RNText>
);
};
@@ -43,4 +45,5 @@ interface TextProps {
style?: StyleProp<TextStyle>;
accessible?: boolean | true;
onPress?: () => void;
onTextLayout?: (e: any) => void;
}

View File

@@ -98,6 +98,11 @@ export class SvgImage {
);
}
static defaultIssuerLogo(defaultLogo: any) {
const DefaultLogo=defaultLogo
return <DefaultLogo/>
}
static starIcon() {
return (
<StarIcon
@@ -593,7 +598,7 @@ export class SvgImage {
}
function getIssuerLogo(props: displayType) {
return {uri: props.logo.url};
return {uri: props.logo.url || props.logo.uri};
}
interface LogoProps {

View File

@@ -864,7 +864,7 @@ export const DefaultTheme = {
flex: 1,
fontSize: 33,
fontFamily: 'Inter_600SemiBold',
height: 40,
height: 50,
lineHeight: 28,
margin: 8,
textAlign: 'center',
@@ -876,7 +876,7 @@ export const DefaultTheme = {
flex: 1,
fontFamily: 'Inter_700Bold',
fontSize: 29,
height: 40,
height: 50,
margin: 8,
textAlign: 'center',
},
@@ -1940,6 +1940,120 @@ export const DefaultTheme = {
},
}),
TransactionCodeScreenStyle: StyleSheet.create({
showMoreButton: {
alignItems: 'flex-end',
marginTop: 6,
marginBottom: 10,
marginRight: -Dimensions.get('window').width + 150,
fontSize: 12,
fontWeight: '600',
color: Colors.Grey,
},
errorView: {
backgroundColor: '#FAEFEF',
padding: 8,
borderRadius: 10,
marginBottom: 10,
marginTop: 10,
width: '80%',
},
inputStyle: {
fontSize: 20,
fontWeight: '500',
textAlign: 'center',
},
confirmationModalView: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.4)',
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 40,
},
confirmationModalContentHeading: {
fontSize: 18,
fontWeight: '600',
textAlign: 'center',
marginBottom: 5,
},
confirmationModalContentSubHeading: {
fontSize: 14,
color: '#888',
marginTop: 12,
textAlign: 'center',
lineHeight: 20,
marginBottom: 20,
},
confirmationModalInnerView: {
backgroundColor: 'white',
borderRadius: 20,
paddingVertical: 35,
paddingHorizontal: 24,
alignItems: 'center',
},
}),
TrustIssuerScreenStyle: StyleSheet.create({
modalOverlay: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
modalContainer: {
backgroundColor: '#fff',
borderRadius: 20,
width: '100%',
padding: 20,
alignItems: 'center',
},
issuerHeader: {
padding: 10,
alignItems: 'center',
marginBottom: 16,
},
issuerLogo: {
width: 60,
height: 60,
resizeMode: 'contain',
},
issuerName: {
marginTop: 8,
fontWeight: 'bold',
fontSize: 16,
},
description: {
fontSize: 14,
color: '#666',
textAlign: 'center',
lineHeight: 20,
marginBottom: 24,
},
}),
AuthWebViewScreenStyle: StyleSheet.create({
header: {
height: 56,
paddingHorizontal: 16,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#F5F5F5',
borderBottomWidth: 1,
borderColor: '#E0E0E0',
},
headerText: {
fontSize: 18,
fontWeight: '500',
},
loader: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
}),
ICON_SMALL_SIZE: 16,
ICON_MID_SIZE: 22,
ICON_LARGE_SIZE: 33,

View File

@@ -1943,6 +1943,118 @@ export const PurpleTheme = {
paddingTop: 10,
},
}),
TransactionCodeScreenStyle: StyleSheet.create({
showMoreButton: {
alignItems: 'flex-end',
marginTop: 6,
marginBottom: 10,
marginRight: -Dimensions.get('window').width + 150,
fontSize: 12,
fontWeight: '600',
color: Colors.Grey,
},
errorView: {
backgroundColor: '#FAEFEF',
padding: 8,
borderRadius: 10,
marginBottom: 10,
marginTop: 10,
width: '80%',
},
inputStyle: {
fontSize: 20,
fontWeight: '500',
textAlign: 'center',
},
confirmationModalView: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.4)',
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 40,
},
confirmationModalContentHeading: {
fontSize: 18,
fontWeight: '600',
textAlign: 'center',
marginBottom: 5,
},
confirmationModalContentSubHeading: {
fontSize: 14,
color: '#888',
marginTop: 12,
textAlign: 'center',
lineHeight: 20,
marginBottom: 20,
},
confirmationModalInnerView: {
backgroundColor: 'white',
borderRadius: 20,
paddingVertical: 35,
paddingHorizontal: 24,
alignItems: 'center',
},
}),
TrustIssuerScreenStyle: StyleSheet.create({
modalOverlay: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
modalContainer: {
backgroundColor: '#fff',
borderRadius: 20,
width: '100%',
padding: 20,
alignItems: 'center',
},
issuerHeader: {
padding: 10,
alignItems: 'center',
marginBottom: 16,
},
issuerLogo: {
width: 60,
height: 60,
resizeMode: 'contain',
},
issuerName: {
marginTop: 8,
fontWeight: 'bold',
fontSize: 16,
},
description: {
fontSize: 14,
color: '#666',
textAlign: 'center',
lineHeight: 20,
marginBottom: 24,
},
}),
AuthWebViewScreenStyle: StyleSheet.create({
header: {
height: 56,
paddingHorizontal: 16,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#F5F5F5',
borderBottomWidth: 1,
borderColor: '#E0E0E0',
},
headerText: {
fontSize: 18,
fontWeight: '500',
},
loader: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
}),
ICON_SMALL_SIZE: 16,
ICON_MID_SIZE: 22,

View File

@@ -10,17 +10,13 @@
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
1E55C2072DB12044009DF38B /* IntentData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E55C2062DB12044009DF38B /* IntentData.swift */; };
1E55C20B2DB120C2009DF38B /* RNDeepLinkIntentModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E55C20A2DB120C2009DF38B /* RNDeepLinkIntentModule.swift */; };
1E55C20D2DB120E7009DF38B /* RNDeepLinkIntentModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E55C20C2DB120E7009DF38B /* RNDeepLinkIntentModule.m */; };
1E6875E92CA554E80086D870 /* OpenID4VP in Frameworks */ = {isa = PBXBuildFile; productRef = 1E6875E82CA554E80086D870 /* OpenID4VP */; };
1E6875EB2CA554FD0086D870 /* RNOpenID4VPModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E6875EA2CA554FD0086D870 /* RNOpenID4VPModule.m */; };
1E6875ED2CA5550F0086D870 /* RNOpenID4VPModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E6875EC2CA5550F0086D870 /* RNOpenID4VPModule.swift */; };
1EED69F92DA913D30042EAFC /* IntentData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EED69F82DA913D30042EAFC /* IntentData.swift */; };
1EED69FB2DA914130042EAFC /* RNDeepLinkIntentModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EED69FA2DA914130042EAFC /* RNDeepLinkIntentModule.swift */; };
1EED69FD2DA914D00042EAFC /* RNDeepLinkIntentModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EED69FC2DA914D00042EAFC /* RNDeepLinkIntentModule.m */; };
34873E472CD8DAF3004DE734 /* VCIClient in Frameworks */ = {isa = PBXBuildFile; productRef = 34873E462CD8DAF3004DE734 /* VCIClient */; };
34873E4D2CD8DD11004DE734 /* pixelpass in Frameworks */ = {isa = PBXBuildFile; productRef = 34873E4C2CD8DD11004DE734 /* pixelpass */; };
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
717E6FEC33D6D8A2F9B01CBC /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 1D23B9CD47CFD7F3C87D202F /* PrivacyInfo.xcprivacy */; };
73295844242A4AD3AA52D0BE /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = D98B96A488E54CBDB286B26F /* noop-file.swift */; };
@@ -38,6 +34,8 @@
9C7CDF3E2C7CBEDE00243A9A /* RNSecureKeystoreModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C7CDF3D2C7CBEDE00243A9A /* RNSecureKeystoreModule.swift */; };
9C7CDF432C7CC13500243A9A /* RNSecureKeystoreModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C7CDF422C7CC13500243A9A /* RNSecureKeystoreModule.m */; };
9CCCA19E2CF87A8400D5A461 /* securekeystore in Frameworks */ = {isa = PBXBuildFile; productRef = 9CCCA19D2CF87A8400D5A461 /* securekeystore */; };
9CFB37492DDDC9A000C199A8 /* pixelpass in Frameworks */ = {isa = PBXBuildFile; productRef = 9CFB37482DDDC9A000C199A8 /* pixelpass */; };
9CFB374C2DDDC9B500C199A8 /* VCIClient in Frameworks */ = {isa = PBXBuildFile; productRef = 9CFB374B2DDDC9B500C199A8 /* VCIClient */; };
B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; };
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
E86208152C0335C5007C3E24 /* RNVCIClientModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E86208142C0335C5007C3E24 /* RNVCIClientModule.swift */; };
@@ -72,9 +70,7 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Inji/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Inji/main.m; sourceTree = "<group>"; };
1D23B9CD47CFD7F3C87D202F /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = Inji/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
1E55C2062DB12044009DF38B /* IntentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentData.swift; sourceTree = "<group>"; };
1E55C20A2DB120C2009DF38B /* RNDeepLinkIntentModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNDeepLinkIntentModule.swift; sourceTree = "<group>"; };
1E55C20C2DB120E7009DF38B /* RNDeepLinkIntentModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNDeepLinkIntentModule.m; sourceTree = "<group>"; };
1E6875EA2CA554FD0086D870 /* RNOpenID4VPModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNOpenID4VPModule.m; sourceTree = "<group>"; };
1E6875EC2CA5550F0086D870 /* RNOpenID4VPModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNOpenID4VPModule.swift; sourceTree = "<group>"; };
1EED69F82DA913D30042EAFC /* IntentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentData.swift; sourceTree = "<group>"; };
@@ -127,11 +123,11 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
34873E472CD8DAF3004DE734 /* VCIClient in Frameworks */,
9CFB374C2DDDC9B500C199A8 /* VCIClient in Frameworks */,
9C4850432C3E5873002ECBD5 /* ios-tuvali-library in Frameworks */,
1E6875E92CA554E80086D870 /* OpenID4VP in Frameworks */,
9CCCA19E2CF87A8400D5A461 /* securekeystore in Frameworks */,
34873E4D2CD8DD11004DE734 /* pixelpass in Frameworks */,
9CFB37492DDDC9A000C199A8 /* pixelpass in Frameworks */,
96905EF65AED1B983A6B3ABC /* libPods-Inji.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -208,6 +204,7 @@
D65327D7A22EEC0BE12398D9 /* Pods */,
D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */,
462CE07025BF40E9952DCDA0 /* Resources */,
9CFB37462DDDC83900C199A8 /* Recovered References */,
);
indentWidth = 2;
sourceTree = "<group>";
@@ -230,6 +227,14 @@
name = Inji;
sourceTree = "<group>";
};
9CFB37462DDDC83900C199A8 /* Recovered References */ = {
isa = PBXGroup;
children = (
1E55C20A2DB120C2009DF38B /* RNDeepLinkIntentModule.swift */,
);
name = "Recovered References";
sourceTree = "<group>";
};
BB2F792B24A3F905000567C9 /* Supporting */ = {
isa = PBXGroup;
children = (
@@ -309,9 +314,9 @@
packageProductDependencies = (
9C4850422C3E5873002ECBD5 /* ios-tuvali-library */,
1E6875E82CA554E80086D870 /* OpenID4VP */,
34873E462CD8DAF3004DE734 /* VCIClient */,
34873E4C2CD8DD11004DE734 /* pixelpass */,
9CCCA19D2CF87A8400D5A461 /* securekeystore */,
9CFB37482DDDC9A000C199A8 /* pixelpass */,
9CFB374B2DDDC9B500C199A8 /* VCIClient */,
);
productName = Inji;
productReference = 13B07F961A680F5B00A75B9A /* Inji.app */;
@@ -340,11 +345,11 @@
);
mainGroup = 83CBB9F61A601CBA00E9B192;
packageReferences = (
34873E4B2CD8DD11004DE734 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */,
34873E452CD8DAF3004DE734 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */,
9C4850412C3E5873002ECBD5 /* XCRemoteSwiftPackageReference "tuvali-ios-swift" */,
1E6875E72CA554E80086D870 /* XCRemoteSwiftPackageReference "inji-openid4vp-ios-swift" */,
9CCCA19C2CF87A8400D5A461 /* XCRemoteSwiftPackageReference "secure-keystore-ios-swift" */,
9CFB37472DDDC99F00C199A8 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */,
9CFB374A2DDDC9B500C199A8 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */,
);
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
@@ -592,12 +597,11 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Inji/Inji.entitlements;
CODE_SIGN_IDENTITY = "Apple Distribution";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = V2ABX7953Z;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = V2ABX7953Z;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
GCC_PREPROCESSOR_DEFINITIONS = (
@@ -829,22 +833,6 @@
kind = branch;
};
};
34873E452CD8DAF3004DE734 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/inji-vci-client-ios-swift";
requirement = {
branch = develop;
kind = branch;
};
};
34873E4B2CD8DD11004DE734 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/pixelpass-ios-swift";
requirement = {
branch = develop;
kind = branch;
};
};
9C4850412C3E5873002ECBD5 /* XCRemoteSwiftPackageReference "tuvali-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/tuvali-ios-swift/";
@@ -861,6 +849,22 @@
version = 0.3.0;
};
};
9CFB37472DDDC99F00C199A8 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/pixelpass-ios-swift/";
requirement = {
branch = develop;
kind = branch;
};
};
9CFB374A2DDDC9B500C199A8 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mosip/inji-vci-client-ios-swift";
requirement = {
branch = develop;
kind = branch;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
@@ -869,16 +873,6 @@
package = 1E6875E72CA554E80086D870 /* XCRemoteSwiftPackageReference "inji-openid4vp-ios-swift" */;
productName = OpenID4VP;
};
34873E462CD8DAF3004DE734 /* VCIClient */ = {
isa = XCSwiftPackageProductDependency;
package = 34873E452CD8DAF3004DE734 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */;
productName = VCIClient;
};
34873E4C2CD8DD11004DE734 /* pixelpass */ = {
isa = XCSwiftPackageProductDependency;
package = 34873E4B2CD8DD11004DE734 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */;
productName = pixelpass;
};
9C4850422C3E5873002ECBD5 /* ios-tuvali-library */ = {
isa = XCSwiftPackageProductDependency;
package = 9C4850412C3E5873002ECBD5 /* XCRemoteSwiftPackageReference "tuvali-ios-swift" */;
@@ -889,6 +883,16 @@
package = 9CCCA19C2CF87A8400D5A461 /* XCRemoteSwiftPackageReference "secure-keystore-ios-swift" */;
productName = securekeystore;
};
9CFB37482DDDC9A000C199A8 /* pixelpass */ = {
isa = XCSwiftPackageProductDependency;
package = 9CFB37472DDDC99F00C199A8 /* XCRemoteSwiftPackageReference "pixelpass-ios-swift" */;
productName = pixelpass;
};
9CFB374B2DDDC9B500C199A8 /* VCIClient */ = {
isa = XCSwiftPackageProductDependency;
package = 9CFB374A2DDDC9B500C199A8 /* XCRemoteSwiftPackageReference "inji-vci-client-ios-swift" */;
productName = VCIClient;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;

View File

@@ -1,5 +1,5 @@
{
"originHash" : "178f6c7c607eeb08b99a4966015d08339500de64791888a2e79d6b7afae53659",
"originHash" : "2d4bd4f2ff41823478f56a65a061c28a141105b8447f22a9d1cef51048d33e76",
"pins" : [
{
"identity" : "alamofire",
@@ -51,8 +51,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/mosip/inji-openid4vp-ios-swift",
"state" : {
"branch" : "release-0.3.x",
"revision" : "58ac61a84fdef03b7a1cc9e6f4ba3c4bfd57fe61"
"branch" : "develop",
"revision" : "c83527449f97c07e6f0a0bec239f9afe477bf216"
}
},
{
@@ -60,8 +60,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/mosip/inji-vci-client-ios-swift",
"state" : {
"branch" : "release-0.3.x",
"revision" : "02f367bd2527f249145393a533f5175918c1fc8a"
"branch" : "develop",
"revision" : "8a39bbf7805af4c615904090a027fa472e5f4534"
}
},
{
@@ -76,10 +76,10 @@
{
"identity" : "pixelpass-ios-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/mosip/pixelpass-ios-swift",
"location" : "https://github.com/mosip/pixelpass-ios-swift/",
"state" : {
"branch" : "develop",
"revision" : "760438e38e01bd9deb170585f37d7c05c5c1785a"
"revision" : "78a8b507f5bd0046e273e3ba962696b44aea0e33"
}
},
{
@@ -128,5 +128,5 @@
}
}
],
"version" : 2
"version" : 3
}

View File

@@ -1189,6 +1189,27 @@ PODS:
- React-Core
- react-native-spinkit (1.4.1):
- React
- react-native-webview (13.13.5):
- DoubleConversion
- glog
- hermes-engine
- RCT-Folly (= 2024.01.01.00)
- RCTRequired
- RCTTypeSafety
- React-Codegen
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-ImageManager
- React-NativeModulesApple
- React-RCTFabric
- React-rendererdebug
- React-utils
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- React-nativeconfig (0.74.5)
- React-NativeModulesApple (0.74.5):
- glog
@@ -1587,6 +1608,7 @@ DEPENDENCIES:
- react-native-rsa-native (from `../node_modules/react-native-rsa-native`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- react-native-spinkit (from `../node_modules/react-native-spinkit`)
- react-native-webview (from `../node_modules/react-native-webview`)
- React-nativeconfig (from `../node_modules/react-native/ReactCommon`)
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
@@ -1798,6 +1820,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-safe-area-context"
react-native-spinkit:
:path: "../node_modules/react-native-spinkit"
react-native-webview:
:path: "../node_modules/react-native-webview"
React-nativeconfig:
:path: "../node_modules/react-native/ReactCommon"
React-NativeModulesApple:
@@ -1881,33 +1905,33 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
AppAuth: d4f13a8fe0baf391b2108511793e4b479691fb73
biometric-sdk-react-native: 11925e3af28eecd733efc43670c5d8b4f014cddc
biometric-sdk-react-native: d2a3a1279013cc4a7514a1b43fe557eb76e4e4c1
BiometricSdk: 303e7329404ea4d922dc14108449d10d21574f77
boost: d3f49c53809116a5d38da093a8aa78bf551aed09
BVLinearGradient: cb006ba232a1f3e4f341bb62c42d1098c284da70
BVLinearGradient: 880f91a7854faff2df62518f0281afb1c60d49a3
CatCrypto: a477899b6be4954e75be4897e732da098cc0a5a8
DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5
EASClient: 95592393d6d1e60609f0afb373191d918c687b98
EXApplication: ec862905fdab3a15bf6bd8ca1a99df7fc02d7762
EXConstants: 89d35611505a8ce02550e64e43cd05565da35f9a
EXFaceDetector: 917b279228541801bfa8ee22d867594ef84e31de
EASClient: 1509a9a6b48b932ec61667644634daf2562983b8
EXApplication: c08200c34daca7af7fd76ac4b9d606077410e8ad
EXConstants: 409690fbfd5afea964e5e9d6c4eb2c2b59222c59
EXFaceDetector: 50810192af3c2b80a53a6778b4e67af78b8e4cd5
EXJSONUtils: 30c17fd9cc364d722c0946a550dfbf1be92ef6a4
EXManifests: ebb7f551c340c0d06f3ecd9ae662e418bf68417c
Expo: ed0a748eb6be0efd2c3df7f6de3f3158a14464c9
ExpoAdapterGoogleSignIn: 97fc4b93c6b35837b5a5f2ff8ee5403548c1a4ba
ExpoAsset: 286fee7ba711ce66bf20b315e68106b13b8629fc
ExpoCamera: cf49d2d121a9f883be0f98dde15a2185a1dd42be
ExpoCrypto: c5c052d5f9f668c21975cb4caf072cec23c823fa
ExpoFileSystem: 2988caaf68b7cb706e36d382829d99811d9d76a5
ExpoFont: 38dddf823e32740c2a9f37c926a33aeca736b5c4
ExpoKeepAwake: dd02e65d49f1cfd9194640028ae2857e536eb1c9
ExpoLocalAuthentication: b94db59f55df95350223200c746b4ddf0cb7cfc0
ExpoLocalization: 1b4195ed48148c7f52ce790d3965cc19483fcbf2
ExpoModulesCore: 9ac73e2f60e0ea1d30137ca96cfc8c2aa34ef2b2
ExpoWebBrowser: cf10afe886891ab495877dada977fe6c269614a4
EXManifests: c1fab4c3237675e7b0299ea8df0bcb14baca4f42
Expo: 8c995afb875c15bf8439af0b20bcb9ed8f90d0bd
ExpoAdapterGoogleSignIn: 6c55782832b7fbdc2c27dac05ef00445c103b8f3
ExpoAsset: 323700f291684f110fb55f0d4022a3362ea9f875
ExpoCamera: 929be541d1c1319fcf32f9f5d9df8b97804346b5
ExpoCrypto: 156078f266bf28f80ecf5e2a9c3a0d6ffce07a1c
ExpoFileSystem: 80bfe850b1f9922c16905822ecbf97acd711dc51
ExpoFont: 00756e6c796d8f7ee8d211e29c8b619e75cbf238
ExpoKeepAwake: 3b8815d9dd1d419ee474df004021c69fdd316d08
ExpoLocalAuthentication: 9e02a56a4cf9868f0052656a93d4c94101a42ed7
ExpoLocalization: f04eeec2e35bed01ab61c72ee1768ec04d093d01
ExpoModulesCore: 831ece8311a489418746925820bbffdda587d6f4
ExpoWebBrowser: 7595ccac6938eb65b076385fd23d035db9ecdc8e
EXStructuredHeaders: cb8d1f698e144f4c5547b4c4963e1552f5d2b457
EXUpdates: bb1b0790e3b2adfbb193ad6a51c567a4bd2adf9f
EXUpdatesInterface: c3a9494c2173db6442c7d5ad4e5b984972760fd3
EXUpdates: 52c797a4b71b25315353041c29571cd65ecc7141
EXUpdatesInterface: 996527fd7d1a5d271eb523258d603f8f92038f24
FBLazyVector: ac12dc084d1c8ec4cc4d7b3cf1b0ebda6dab85af
fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120
glog: fdfdfe5479092de0c4bdbebedd9056951f092c4f
@@ -1920,7 +1944,7 @@ SPEC CHECKSUMS:
GTMAppAuth: 99fb010047ba3973b7026e45393f51f27ab965ae
GTMSessionFetcher: 5595ec75acf5be50814f81e9189490412bad82ba
hermes-engine: 8c1577f3fdb849cbe7729c2e7b5abc4b845e88f8
ImageColors: 869f48b27ca2afb347fd0bada3257a5f698ee55e
ImageColors: 88be684570585c07ae2750bff34eb7b78bfc53b4
MLImage: a454f9f8ecfd537783a12f9488f5be1a68820829
MLKitCommon: 3bc17c6f7d25ce3660f030350b46ae7ec9ebca6e
MLKitFaceDetection: 617cb847441868a8bfd4b48d751c9b33c1104948
@@ -1928,87 +1952,88 @@ SPEC CHECKSUMS:
MMKV: aac95d817a100479445633f2b3ed8961b4ac5043
MMKVCore: 9cfef4c48c6c46f66226fc2e4634d78490206a48
nanopb: 438bc412db1928dac798aa6fd75726007be04262
Permission-BluetoothPeripheral: aa44bde6f52530eb00c0128ee2575b68fe8abdfe
Permission-Camera: 78301f2241e8297a80089d2452adbef2add8fe56
Permission-LocationAccuracy: 7ee13967dc5272e08172f5afa40c408bf83b6196
Permission-LocationWhenInUse: 59523bb3d8b95b267baa172ecbf1f31bc672795a
Permission-BluetoothPeripheral: 2b88a131074edafd8a46a5cda4ba610ec986d2fb
Permission-Camera: 7ec9ee99704766ff9b90198183387a7f5d82b0c1
Permission-LocationAccuracy: a38ddb5c5d0b8e656f3c86e4a500f9bb88bc099d
Permission-LocationWhenInUse: 24d97eeb25d8ff9f2232e070f792eeb1360ccaf0
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
Protobuf: 0c5a9e64f38aed73b5d1ff88a20112ce195cf909
RCT-Folly: 5dc73daec3476616d19e8a53f0156176f7b55461
RCT-Folly: 02617c592a293bd6d418e0a88ff4ee1f88329b47
RCTDeprecation: 3afceddffa65aee666dafd6f0116f1d975db1584
RCTRequired: ec1239bc9d8bf63e10fb92bd8b26171a9258e0c1
RCTTypeSafety: f5ecbc86c5c5fa163c05acb7a1c5012e15b5f994
ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda
React: fc9fa7258eff606f44d58c5b233a82dc9cf09018
React-callinvoker: e3fab14d69607fb7e8e3a57e5a415aed863d3599
React-Codegen: 3963186cb6a4ef21b5e67dcf7badf359867ff6df
React-Core: c3f589f104983dec3c3eeec5e70d61aa811bc236
React-CoreModules: 864932ddae3ead5af5bfb05f9bbc2cedcb958b39
React-cxxreact: bd9146108c44e6dbb99bba4568ce7af0304a2419
React-Codegen: 6fa87b7c6b8efcd0cef4bfeaec8c8bc8a6abe75a
React-Core: 3a5fd9e781cecf87803e5b091496a606a3df774a
React-CoreModules: cbf4707dafab8f9f826ac0c63a07d0bf5d01e256
React-cxxreact: 7b188556271e3c7fdf22a04819f6a6225045b9dd
React-debug: d30893c49ae1bce4037ea5cd8bb2511d2a38d057
React-Fabric: a171830e52baf8ec2b175c6a3791e01bbb92f1fb
React-FabricImage: ad154af0067f4b5dc5a41f607e48ee343641e903
React-Fabric: 826729dd2304fda9b89ff0a579f60ba2a470bc26
React-FabricImage: 2ad1fb8ffa5778eda9ed204a7b3cdd70bc333ce7
React-featureflags: 4ae83e72d9a92452793601ac9ac7d2280e486089
React-graphics: ed7d57965140168de86835946e8f1210c72c65dc
React-hermes: 177b1efdf3b8f10f4ca12b624b83fb4d4ccb2884
React-ImageManager: 3a50d0ee0bf81b1a6f23a0c5b30388293bcd6004
React-jserrorhandler: dcd62f5ca1c724c19637595ef7f45b78018e758f
React-jsi: 0abe1b0881b67caf8d8df6a57778dd0d3bb9d9a5
React-jsiexecutor: f6ca8c04f19f6a3acaa9610f7fb728f39d6e3248
React-jsinspector: db98771eae84e6f86f0ca5d9dcc572baadbfefc0
React-jsitracing: f8367edacc50bb3f9f056a5aeafb8cee5849fafb
React-logger: 780b9ee9cec7d44eabc4093de90107c379078cb6
React-Mapbuffer: f544f00b98dbdd8cbae96dd2bdb8b47f719976e0
react-native-app-auth: 5bf64c0d0e7cbea8ff6ea0b90e4397c8dcfc656a
react-native-cloud-storage: ddc959e7ddb08ff18ce9389787aa7254d7f45ee3
react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba
react-native-image-editor: 29a86ccb509072a429c56abf73c35d63288108e5
react-native-location: 70e6bdfe4a98a80ebda57fd5b30994e48d082e99
react-native-mmkv-storage: 45287ac5851a967d15f6c59b4a8aee6331bec034
react-native-netinfo: 2e3c27627db7d49ba412bfab25834e679db41e21
react-native-restart: df7caae89026a8ab2ecdd82839978f657701f51d
react-native-rsa-native: a7931cdda1f73a8576a46d7f431378c5550f0c38
react-native-safe-area-context: df9763c5de6fa38883028e243a0b60123acb8858
react-native-spinkit: 96a74c3519fab0eded2ab8c285f774aa3f4b7944
React-graphics: 61a026e1c1e7e20d20ac9fec6f6de631732b233d
React-hermes: a7054fbcbda3957e3c5eaad06ef9bf79998d535a
React-ImageManager: 2bbd6eb2e696bc680f76f84563e4b87d241614e1
React-jserrorhandler: 56fa04d49bfbe54ddfece7916673a73ebfea286b
React-jsi: f3ce1dd2e950b6ad12b65ea3ef89168f1b94c584
React-jsiexecutor: b4df3a27973d82f9abf3c4bd0f88e042cda25f16
React-jsinspector: 97ea746c023687de7313ee289817d6991d596c7d
React-jsitracing: 3b6060bbf5317663667e1dd93560c7943ab86ccc
React-logger: 257858bd55f3a4e1bc0cf07ddc8fb9faba6f8c7c
React-Mapbuffer: 6c1cacdbf40b531f549eba249e531a7d0bfd8e7f
react-native-app-auth: 63fa4e58c5bd29aeb974d3a06a23c5858322d533
react-native-cloud-storage: 15f24d9b9f175ce07473c3af86b6add72a727c95
react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06
react-native-image-editor: b09448ba9171308ff5ac6c9f66f49ad4cbfaee06
react-native-location: 5a40ec1cc6abf2f6d94df979f98ec76c3a415681
react-native-mmkv-storage: cfb6854594cfdc5f7383a9e464bb025417d1721c
react-native-netinfo: bdb108d340cdb41875c9ced535977cac6d2ff321
react-native-restart: 45c8dca02491980f2958595333cbccd6877cb57e
react-native-rsa-native: 12132eb627797529fdb1f0d22fd0f8f9678df64a
react-native-safe-area-context: a240ad4b683349e48b1d51fed1611138d1bdad97
react-native-spinkit: da294fd828216ad211fe36a5c14c1e09f09e62db
react-native-webview: db97533d0b7534225f48ad4e0c313b83cfae8a20
React-nativeconfig: ba9a2e54e2f0882cf7882698825052793ed4c851
React-NativeModulesApple: 84aaad2b0e546d7b839837ca537f6e72804a4cad
React-NativeModulesApple: 8d11ff8955181540585c944cf48e9e7236952697
React-perflogger: ed4e0c65781521e0424f2e5e40b40cc7879d737e
React-RCTActionSheet: 49d53ff03bb5688ca4606c55859053a0cd129ea5
React-RCTAnimation: 3075449f26cb98a52bcbf51cccd0c7954e2a71db
React-RCTAppDelegate: 9a419c4dda9dd039ad851411546dd297b930c454
React-RCTBlob: e81ab773a8fc1e9dceed953e889f936a7b7b3aa6
React-RCTFabric: 47a87a3e3fa751674f7e64d0bcd58976b8c57db9
React-RCTImage: d570531201c6dce7b5b63878fa8ecec0cc311c4c
React-RCTLinking: af888972b925d2811633d47853c479e88c35eb4d
React-RCTNetwork: 5728a06ff595003eca628f43f112a804f4a9a970
React-RCTSettings: ba3665b0569714a8aaceee5c7d23b943e333fa55
React-RCTText: b733fa984f0336b072e47512898ba91214f66ddb
React-RCTVibration: 0cbcbbd8781b6f6123671bae9ee5dd20d621af6c
React-rendererdebug: 9fc8f7d0bd19f2a3fe3791982af550b5e1535ff7
React-RCTAnimation: 07b4923885c52c397c4ec103924bf6e53b42c73e
React-RCTAppDelegate: 316e295076734baf9bdf1bfac7d92ab647aed930
React-RCTBlob: 85c57b0d5e667ff8a472163ba3af0628171a64bb
React-RCTFabric: 97c1465ded4dc92841f5376a39e43e1b2c455f40
React-RCTImage: b965c85bec820e2a9c154b1fb00a2ecdd59a9c92
React-RCTLinking: 75f04a5f27c26c4e73a39c50df470820d219df79
React-RCTNetwork: c1a9143f4d5778efc92da40d83969d03912ccc24
React-RCTSettings: c6800f91c0ecd48868cd5db754b0b0a7f5ffe039
React-RCTText: b923e24f9b7250bc4f7ab154c4168ad9f8d8fc9d
React-RCTVibration: 08c4f0c917c435b3619386c25a94ee5d64c250f0
React-rendererdebug: 3cda04217d9df67b94397ee0ead8ef3d8b7e427b
React-rncore: 4013508a2f3fcf46c961919bbbd4bfdda198977e
React-RuntimeApple: a852a6e06ab20711658873f39cb10b0033bea19d
React-RuntimeCore: 12e5e176c0cb09926f3e6f37403a84d2e0f203a7
React-RuntimeApple: 447844a2bdb0a03ffd24e5b4a4b96cfc50325b88
React-RuntimeCore: 9b5bffdaccee9b707b1c2694c9044e13ff0bb087
React-runtimeexecutor: 0e688aefc14c6bc8601f4968d8d01c3fb6446844
React-RuntimeHermes: 80c03a5215520c9733764ba11cbe535053c9746d
React-runtimescheduler: 2cbd0f3625b30bba08e8768776107f6f0203159b
React-utils: 9fa4e5d0b5e6c6c85c958f19d6ef854337886417
ReactCommon: 9f285823dbe955099978d9bff65a7653ca029256
RNAppleAuthentication: 445222cf501db405f0b3713593a6d0fecc87fd05
RNArgon2: 708e188b7a4d4ec8baf62463927c47abef453a94
RNBluetoothStateManager: 221894bb59b22ec8be372740178545d0bbdb1ab6
RNCClipboard: efe1b27ad1ea378c60c8c8aabfd130961bbeb474
RNCPicker: 15ad063c72ecba748be9edea62a5bdce53090aa6
RNDeviceInfo: 98bb51ba1519cd3f19f14e7236b5bb1c312c780f
RNFS: 89de7d7f4c0f6bafa05343c578f61118c8282ed8
RNGestureHandler: 326e35460fb6c8c64a435d5d739bea90d7ed4e49
RNGoogleSignin: bee4a648cf7bfe848b3674b5d487504831a115dd
RNLocalize: d024afa9204c13885e61dc88b8190651bcaabac9
RNPermissions: 1e3fb35b2ac79aaad28788302ead31ca8230d611
RNScreens: a2d8a2555b4653d7a19706eb172f855657ac30d7
RNSecureRandom: b64d263529492a6897e236a22a2c4249aa1b53dc
RNShare: 694e19d7f74ac4c04de3a8af0649e9ccc03bd8b1
RNSVG: 0e7deccab0678200815104223aadd5ca734dd41d
RNZipArchive: 2b0d34cfe303447f5b55ae5658ec62f1ebce4ab5
React-RuntimeHermes: 4d6ef6bb0f2b0b40d59143317f6b99c82764c959
React-runtimescheduler: cfbe85c3510c541ec6dc815c7729b41304b67961
React-utils: f242eb7e7889419d979ca0e1c02ccc0ea6e43b29
ReactCommon: f7da14a8827b72704169a48c929bcde802698361
RNAppleAuthentication: e99eaf3c4c01ad8ecb6125dd6f0cfd98871685b5
RNArgon2: 1481820722fd4af1575c09f7fc9ad67c00ee8a42
RNBluetoothStateManager: ae6a26260cbdf1827b58bd3bcc563527d61e6488
RNCClipboard: 3f0451a8100393908bea5c5c5b16f96d45f30bfc
RNCPicker: 3e2c37a8328f368ce14da050cdc8231deb5fc9f9
RNDeviceInfo: 59344c19152c4b2b32283005f9737c5c64b42fba
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
RNGestureHandler: 2282cfbcf86c360d29f44ace393203afd5c6cff7
RNGoogleSignin: aac5c1ec73422109dec1da770247a1e410dcc620
RNLocalize: 298e85ce16540a11de40c1a588ead39fc5e9a072
RNPermissions: f1b49dd05fa9b83993cd05a9ee115247944d8f1a
RNScreens: b32a9ff15bea7fcdbe5dff6477bc503f792b1208
RNSecureRandom: 07efbdf2cd99efe13497433668e54acd7df49fef
RNShare: 0fad69ae2d71de9d1f7b9a43acf876886a6cb99c
RNSVG: 43b64ed39c14ce830d840903774154ca0c1f27ec
RNZipArchive: ef9451b849c45a29509bf44e65b788829ab07801
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
sqlite3: 02d1f07eaaa01f80a1c16b4b31dfcbb3345ee01a
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
@@ -2017,6 +2042,6 @@ SPEC CHECKSUMS:
Yoga: 950bbfd7e6f04790fdb51149ed51df41f329fcc8
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
PODFILE CHECKSUM: 4d2ee2cbf5f1553030d56659748bb7baece24998
PODFILE CHECKSUM: a555e3bf20e7a7fbd521747ca919066410e3af18
COCOAPODS: 1.16.2

View File

@@ -3,14 +3,34 @@
@interface RCT_EXTERN_MODULE(InjiVciClient, NSObject)
RCT_EXTERN_METHOD(init:(NSString *)appId)
// Initializes the VCIClient with a traceability ID
RCT_EXTERN_METHOD(init:(NSString *)traceabilityId)
RCT_EXTERN_METHOD(requestCredential:(id)issuerMeta
proof:(NSString *)proof
accessToken:(NSString *)accessToken
// Requests a credential using a credential offer string and client metadata (both as JSON strings)
RCT_EXTERN_METHOD(requestCredentialByOffer:(NSString *)credentialOffer
clientMetadata:(NSString *)clientMetadata
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject);
rejecter:(RCTPromiseRejectBlock)reject)
RCT_EXTERN_METHOD(requiresMainQueueSetup:(BOOL))
// Requests a credential from a trusted issuer using issuer metadata and client metadata (both as JSON strings)
RCT_EXTERN_METHOD(requestCredentialFromTrustedIssuer:(NSString *)issuerMetadata
clientMetadata:(NSString *)clientMetadata
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
// Sends proof JWT back to native side (in response to onRequestProof)
RCT_EXTERN_METHOD(sendProofFromJS:(NSString *)jwtProof)
// Sends authorization code back to native side (in response to onRequestAuthCode)
RCT_EXTERN_METHOD(sendAuthCodeFromJS:(NSString *)authCode)
// Sends tx_code back to native side (in response to onRequestTxCode)
RCT_EXTERN_METHOD(sendTxCodeFromJS:(NSString *)txCode)
// Sends issuer trust decision (true/false) back to native side (in response to onCheckIssuerTrust)
RCT_EXTERN_METHOD(sendIssuerTrustResponseFromJS:(BOOL)isTrusted)
// Required by React Native
RCT_EXTERN_METHOD(requiresMainQueueSetup:(BOOL)isRequired)
@end

View File

@@ -1,86 +1,222 @@
import Foundation
import VCIClient
import React
import VCIClient
@objc(InjiVciClient)
class RNVCIClientModule: NSObject, RCTBridgeModule {
private var vciClient: VCIClient?
private var pendingProofContinuation: ((String) -> Void)?
private var pendingAuthCodeContinuation: ((String) -> Void)?
private var pendingTxCodeContinuation: ((String) -> Void)?
private var pendingIssuerTrustDecision: ((Bool) -> Void)?
private var vciClient: VCIClient?
static func moduleName() -> String {
return "InjiVciClient"
}
@objc
func `init`(_ traceabilityId: String) {
vciClient = VCIClient(traceabilityId: traceabilityId)
static func moduleName() -> String {
return "InjiVciClient"
}
@objc
func requestCredential(_ issuerMeta: AnyObject, proof: String, accessToken: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
Task {
do {
guard let issuerMetaDict = issuerMeta as? [String: Any] else {
reject(nil, "Invalid issuerMeta format", nil)
return
}
@objc
func `init`(_ traceabilityId: String) {
vciClient = VCIClient(traceabilityId: traceabilityId)
}
@objc
func requestCredentialByOffer(
_ credentialOffer: String,
clientMetadata: String,
resolver resolve: @escaping RCTPromiseResolveBlock,
rejecter reject: @escaping RCTPromiseRejectBlock
) {
Task {
do {
guard let vciClient = vciClient else {
reject(nil, "VCIClient not initialized", nil)
return
}
guard let credentialAudience = issuerMetaDict["credentialAudience"] as? String,
let credentialEndpoint = issuerMetaDict["credentialEndpoint"] as? String,
let downloadTimeoutInMilliseconds = issuerMetaDict["downloadTimeoutInMilliSeconds"] as? Int,
let credentialFormatString = issuerMetaDict["credentialFormat"] as? String,
let credentialFormat = CredentialFormat(rawValue: credentialFormatString) else {
reject(nil, "Invalid issuerMeta format", nil)
return
}
let clientMeta = try parseClientMetadata(from: clientMetadata)
var issuerMetaObject : IssuerMeta
let response = try await vciClient.requestCredentialByCredentialOffer(
credentialOffer: credentialOffer,
clientMetadata: clientMeta,
getTxCode: { inputMode, description, length in
try await self.getTxCodeHook(
inputMode: inputMode,
description: description,
length: length
)
},
getProofJwt: { accessToken, cNonce, issuerMetadata, credentialConfigId in
try await self.getProofContinuationHook(
accessToken: accessToken,
cNonce: cNonce,
issuerMetadata: issuerMetadata,
credentialConfigId: credentialConfigId
)
},
getAuthCode: { authUrl in
try await self.getAuthCodeContinuationHook(authUrl: authUrl)
},
onCheckIssuerTrust: { issuerMetadata in
try await self.getIssuerTrustDecisionHook(issuerMetadata: issuerMetadata)
}
)
switch credentialFormat {
case .ldp_vc:
guard let credentialType = issuerMetaDict["credentialType"] as? [String] else {
reject(nil, "Invalid issuerMeta format", nil)
return
}
issuerMetaObject = IssuerMeta(
credentialAudience: credentialAudience,
credentialEndpoint: credentialEndpoint,
downloadTimeoutInMilliseconds: downloadTimeoutInMilliseconds,
credentialType: credentialType,
credentialFormat: credentialFormat
)
case .mso_mdoc:
guard let doctype = issuerMetaDict["doctype"] as? String,
let claims = issuerMetaDict["claims"] as? [String:Any] else {
reject(nil, "Invalid issuerMeta format", nil)
return
}
issuerMetaObject = IssuerMeta(
credentialAudience: credentialAudience,
credentialEndpoint: credentialEndpoint,
downloadTimeoutInMilliseconds: downloadTimeoutInMilliseconds,
credentialFormat: .mso_mdoc,
docType: doctype,
claims: claims
)
resolve(try response?.toJsonString())
} catch {
reject(nil, error.localizedDescription, nil)
}
}
}
@objc
func requestCredentialFromTrustedIssuer(
_ issuerMetadata: String,
clientMetadata: String,
resolver resolve: @escaping RCTPromiseResolveBlock,
rejecter reject: @escaping RCTPromiseRejectBlock
) {
Task {
do {
guard let vciClient = vciClient else {
reject(nil, "VCIClient not initialized", nil)
return
}
let issuer = try parseIssuerMeta(from: issuerMetadata)
let clientMeta = try parseClientMetadata(from: clientMetadata)
let response = try await vciClient.requestCredentialFromTrustedIssuer(
issuerMetadata: issuer,
clientMetadata: clientMeta,
getProofJwt: { accessToken, cNonce, issuerMetadata, credentialConfigId in
try await self.getProofContinuationHook(
accessToken: accessToken,
cNonce: cNonce,
issuerMetadata: issuerMetadata,
credentialConfigId: credentialConfigId
)
},
getAuthCode: { authUrl in
try await self.getAuthCodeContinuationHook(authUrl: authUrl)
}
)
let response = try await vciClient!.requestCredential(issuerMeta: issuerMetaObject, proof: JWTProof(jwt: proof), accessToken: accessToken)!
let responseString = try response.toJsonString()
resolve(responseString)
} catch {
reject(nil,error.localizedDescription, nil)
}
}
}
resolve(try response?.toJsonString())
} catch {
reject(nil, error.localizedDescription, nil)
}
}
}
@objc
static func requiresMainQueueSetup() -> Bool {
return true
}
private func getProofContinuationHook(
accessToken: String,
cNonce: String?,
issuerMetadata: [String: Any]?,
credentialConfigId: String?
) async throws -> String {
var issuerMetadataJson: String = ""
if let issuerMetadata = issuerMetadata {
if let data = try? JSONSerialization.data(withJSONObject: issuerMetadata, options: []),
let jsonString = String(data: data, encoding: .utf8) {
issuerMetadataJson = jsonString
}
}
if let bridge = RCTBridge.current() {
let payload: [String: Any] = [
"accessToken": accessToken,
"cNonce": cNonce ?? NSNull(),
"issuerMetadata": issuerMetadataJson,
"credentialConfigurationId": credentialConfigId ?? NSNull(),
]
bridge.eventDispatcher().sendAppEvent(withName: "onRequestProof", body: payload)
}
return try await withCheckedThrowingContinuation { continuation in
self.pendingProofContinuation = { jwt in continuation.resume(returning: jwt) }
}
}
private func getAuthCodeContinuationHook(authUrl: String) async throws -> String {
if let bridge = RCTBridge.current() {
bridge.eventDispatcher().sendAppEvent(withName: "onRequestAuthCode", body: ["authorizationEndpoint": authUrl])
}
return try await withCheckedThrowingContinuation { continuation in
self.pendingAuthCodeContinuation = { code in continuation.resume(returning: code) }
}
}
private func getTxCodeHook(inputMode: String?, description: String?, length: Int? ) async throws -> String {
if let bridge = RCTBridge.current() {
bridge.eventDispatcher().sendAppEvent(withName: "onRequestTxCode", body: [
"inputMode": inputMode,
"description": description,
"length": length
])
}
return try await withCheckedThrowingContinuation { continuation in
self.pendingTxCodeContinuation = { code in continuation.resume(returning: code) }
}
}
private func getIssuerTrustDecisionHook(issuerMetadata: [String: Any]) async throws -> Bool {
var metadataJson = ""
if let data = try? JSONSerialization.data(withJSONObject: issuerMetadata, options: []),
let string = String(data: data, encoding: .utf8) {
metadataJson = string
}
if let bridge = RCTBridge.current() {
bridge.eventDispatcher().sendAppEvent(withName: "onCheckIssuerTrust", body: ["issuerMetadata": metadataJson])
}
return try await withCheckedThrowingContinuation { continuation in
self.pendingIssuerTrustDecision = { decision in continuation.resume(returning: decision) }
}
}
@objc(sendProofFromJS:)
func sendProofFromJS(_ jwt: String) {
pendingProofContinuation?(jwt)
pendingProofContinuation = nil
}
@objc(sendAuthCodeFromJS:)
func sendAuthCodeFromJS(_ code: String) {
pendingAuthCodeContinuation?(code)
pendingAuthCodeContinuation = nil
}
@objc(sendTxCodeFromJS:)
func sendTxCodeFromJS(_ code: String) {
pendingTxCodeContinuation?(code)
pendingTxCodeContinuation = nil
}
@objc(sendIssuerTrustResponseFromJS:)
func sendIssuerTrustResponseFromJS(_ trusted: Bool) {
pendingIssuerTrustDecision?(trusted)
pendingIssuerTrustDecision = nil
}
private func parseClientMetadata(from jsonString: String) throws -> ClientMetaData {
guard let data = jsonString.data(using: .utf8) else {
throw NSError(domain: "Invalid JSON string for clientMetadata", code: 0)
}
return try JSONDecoder().decode(ClientMetaData.self, from: data)
}
private func parseIssuerMeta(from jsonString: String) throws -> IssuerMetadata {
guard let data = jsonString.data(using: .utf8) else {
throw NSError(domain: "Invalid JSON string for issuerMetadata", code: 0)
}
return try JSONDecoder().decode(IssuerMetadata.self, from: data)
}
@objc static func requiresMainQueueSetup() -> Bool {
return true
}
}

View File

@@ -208,6 +208,9 @@
"downloadingCredentials": "تنزيل بيانات الاعتماد"
}
},
"offerTitle": "امسح لتنزيل البطاقة",
"offerDescription": "امسح رمز QR لتنزيل بطاقتك فورًا.",
"download": "تنزيل البطاقة",
"errors": {
"noInternetConnection": {
"title": "لا يوجد اتصال بالإنترنت",
@@ -1045,5 +1048,30 @@
"done": "منتهي",
"keyManagementTitle": "إدارة المفتاح",
"keyManagementDesc": "اختر طريقة إنشاء المفاتيح التي تتماشى مع تفضيلاتك، مما يمنحك السيطرة على أمان بيانات اعتمادك.\nاسحب ورتب المفاتيح، حيث يكون المفتاح العلوي هو الأعلى أولوية."
},
"authWebView": {
"title": "يريد \"{{wallet}}\" استخدام \"{{domain}}\" لتسجيل الدخول",
"message": "سيسمح هذا للتطبيق والموقع بمشاركة معلوماتك.",
"cancel": "إلغاء",
"continue": "تسجيل الدخول"
},
"cancelDownloadModal": {
"heading": "هل تريد إلغاء التنزيل؟",
"subHeading": "بمجرد الإلغاء، لن يتم تنزيل بطاقتك وسيتعين عليك إعادة البدء.",
"cancel": "لا، سأنتظر",
"confirm": "نعم، إلغاء"
},
"transactionCodeScreen": {
"description": "لقد أرسلنا رمز المعاملة إلى بريدك الإلكتروني المسجل",
"placeholder": "أدخل رمز المعاملة",
"verify": "تحقق",
"emptyCodeError": "لا يمكن أن يكون الرمز فارغًا",
"invalidCharacters": "يسمح فقط بالأحرف والأرقام",
"TransactionCode": "رمز المعاملة"
},
"trustScreen": {
"description": "يرجى التأكد من أن هذه البطاقة من مصدر موثوق قبل التنزيل. بمجرد التنزيل، سيتم حفظها في محفظتك ويمكن استخدامها في أي وقت.",
"confirm": "نعم، أثق بهذا",
"cancel": "لا، أعدني"
}
}

View File

@@ -209,6 +209,9 @@
"downloadingCredentials": "Downloading Credentials"
}
},
"offerTitle": "Scan & Download Card",
"offerDescription": "Scan a QR code to instantly download your card.",
"download":" Download Card",
"errors": {
"noInternetConnection": {
"title": "No internet connection",
@@ -1065,5 +1068,30 @@
"done": "Done",
"keyManagementTitle": "Key Management",
"keyManagementDesc": "Select the key generation method that aligns with your preference, putting you in control of your credential security.\nDrag and arrange the keys, with the top one being your highest priority."
},
"authWebView": {
"title": "“{{wallet}}” Wants to Use “{{domain}}” to Sign In",
"message": "This allows the app and website to share information about you.",
"cancel": "Cancel",
"continue": "Sign In"
},
"cancelDownloadModal": {
"heading": "Do you want to cancel downloading?",
"subHeading": "Once cancelled, your card will not be downloaded and you need to reinitiate the download.",
"cancel": "No, Ill wait",
"confirm": "Yes, Cancel"
},
"transactionCodeScreen": {
"description": "Weve sent the transaction code to your registered email Id",
"placeholder": "Enter Transaction Code",
"verify": "Verify",
"emptyCodeError":"Code cannot be empty",
"invalidCharacters":"Only letters and numbers are allowed",
"TransactionCode": "Transasction Code"
},
"trustScreen": {
"description": "Please make sure this card is from a trusted source before downloading.Once downloaded, it will be saved in your wallet and can be used anytime.",
"confirm": "Yes I Trust This",
"cancel": "No, Take Me Back"
}
}

View File

@@ -208,6 +208,9 @@
"downloadingCredentials": "Nagda-download ng Mga Kredensyal"
}
},
"offerTitle": "I-scan at I-download ang Card",
"offerDescription": "I-scan ang QR code para agad ma-download ang iyong card.",
"download": "I-download ang Card",
"errors": {
"noInternetConnection": {
"title": "Pakisuri ang iyong koneksyon at subukang muli",
@@ -1048,5 +1051,30 @@
"done": "Tapos na",
"keyManagementTitle": "Pamamahala ng Key",
"keyManagementDesc": "Piliin ang paraan ng paggawa ng key na naaayon sa iyong kagustuhan, nagbibigay sa iyo ng kontrol sa seguridad ng iyong kredensyal.\nI-drag at ayusin ang mga key, kung saan ang nasa itaas ay ang may pinakamataas na priyoridad."
},
"authWebView": {
"title": "Gustong gamitin ng \"{{wallet}}\" ang \"{{domain}}\" para mag-sign in",
"message": "Pinapayagan nitong magbahagi ng impormasyon ang app at website tungkol sa iyo.",
"cancel": "Kanselahin",
"continue": "Mag-sign In"
},
"cancelDownloadModal": {
"heading": "Gusto mo bang kanselahin ang pag-download?",
"subHeading": "Kapag nakansela, hindi madadownload ang iyong card at kailangan mong simulan muli.",
"cancel": "Hindi, maghihintay ako",
"confirm": "Oo, Kanselahin"
},
"transactionCodeScreen": {
"description": "Ipinadala na namin ang transaction code sa iyong rehistradong email",
"placeholder": "Ilagay ang Transaction Code",
"verify": "I-verify",
"emptyCodeError": "Hindi puwedeng walang laman ang code",
"invalidCharacters": "Mga letra at numero lamang ang pinapayagan",
"TransactionCode": "Transaction Code"
},
"trustScreen": {
"description": "Siguraduhin na galing ito sa pinagkakatiwalaang source bago i-download. Kapag na-download, ito'y mase-save sa iyong wallet at maaaring magamit kahit kailan.",
"confirm": "Oo, Pinagkakatiwalaan Ko Ito",
"cancel": "Hindi, Bumalik Tayo"
}
}

View File

@@ -209,6 +209,9 @@
"downloadingCredentials": "क्रेडेंशियल डाउनलोड करना"
}
},
"offerTitle": "स्कैन करें और कार्ड डाउनलोड करें",
"offerDescription": "अपना कार्ड तुरंत डाउनलोड करने के लिए QR कोड स्कैन करें।",
"download": "कार्ड डाउनलोड करें",
"errors": {
"noInternetConnection": {
"title": "कोई इंटरनेट कनेक्शन नहीं",
@@ -1049,5 +1052,30 @@
"done": "हो गया",
"keyManagementTitle": "कुंजी प्रबंधन",
"keyManagementDesc": "अपनी पसंद के अनुसार कुंजी उत्पन्न करने की विधि का चयन करें, जो आपकी क्रेडेंशियल सुरक्षा पर नियंत्रण देती है।\nकुंजियों को खींचें और व्यवस्थित करें, जहाँ शीर्ष कुंजी आपकी उच्चतम प्राथमिकता होगी।"
},
"authWebView": {
"title": "\"{{wallet}}\" \"{{domain}}\" का उपयोग करके साइन इन करना चाहता है",
"message": "यह ऐप और वेबसाइट को आपकी जानकारी साझा करने की अनुमति देता है।",
"cancel": "रद्द करें",
"continue": "साइन इन करें"
},
"cancelDownloadModal": {
"heading": "क्या आप डाउनलोड रद्द करना चाहते हैं?",
"subHeading": "रद्द करने पर कार्ड डाउनलोड नहीं होगा और आपको प्रक्रिया दोबारा शुरू करनी होगी।",
"cancel": "नहीं, मैं प्रतीक्षा करूंगा",
"confirm": "हाँ, रद्द करें"
},
"transactionCodeScreen": {
"description": "हमने लेन-देन कोड आपके पंजीकृत ईमेल पर भेजा है",
"placeholder": "लेन-देन कोड दर्ज करें",
"verify": "सत्यापित करें",
"emptyCodeError": "कोड खाली नहीं हो सकता",
"invalidCharacters": "केवल अक्षर और संख्याएँ मान्य हैं",
"TransactionCode": "लेन-देन कोड"
},
"trustScreen": {
"description": "डाउनलोड करने से पहले सुनिश्चित करें कि यह कार्ड किसी भरोसेमंद स्रोत से है। डाउनलोड के बाद, यह आपके वॉलेट में सेव हो जाएगा और कभी भी इस्तेमाल किया जा सकता है।",
"confirm": "हाँ, मैं इस पर भरोसा करता हूँ",
"cancel": "नहीं, मुझे वापस ले चलो"
}
}

View File

@@ -208,6 +208,9 @@
"downloadingCredentials": "ರುಜುವಾತುಗಳನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ"
}
},
"offerTitle": "ಸ್ಕ್ಯಾನ್ ಮಾಡಿ ಮತ್ತು ಕಾರ್ಡ್ ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ",
"offerDescription": "ನಿಮ್ಮ ಕಾರ್ಡ್ ಅನ್ನು ತಕ್ಷಣವೇ ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ.",
"download": "ಕಾರ್ಡ್ ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ",
"errors": {
"noInternetConnection": {
"title": "ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವಿಲ್ಲ",
@@ -1049,5 +1052,30 @@
"done": "ಮುಗಿದಿದೆ",
"keyManagementTitle": "ಕೀ ನಿರ್ವಹಣೆ",
"keyManagementDesc": "ನಿಮ್ಮ ಆಸ್ತಿಕತೆಗಳಿಗೆ ಸರಿಹೊಂದುವ ಕೀ ಜನನ ವಿಧಾನವನ್ನು ಆಯ್ಕೆಮಾಡಿ, ಇದು ನಿಮ್ಮ ಆಧಾರ ಭದ್ರತೆಯ ಮೇಲೆ ನಿಯಂತ್ರಣವನ್ನು ನೀಡುತ್ತದೆ.\nಕೀಗಳನ್ನು ಎಳೆಯಿರಿ ಮತ್ತು ಜೋಡಿಸಿ, ಮೇಲಿನದು ನಿಮ್ಮ ಅತ್ಯುತ್ತಮ ಆದ್ಯತೆಯಾಗಿ ಇರುತ್ತದೆ."
},
"authWebView": {
"title": "\"{{wallet}}\" \"{{domain}}\" ಅನ್ನು ಬಳಸಿಕೊಂಡು ಸೈನ್ ಇನ್ ಮಾಡಲು ಬಯಸುತ್ತದೆ",
"message": "ಇದು ಅಪ್‌ ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗೆ ನಿಮ್ಮ ಬಗ್ಗೆ ಮಾಹಿತಿಯನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಅನುಮತಿಸುತ್ತದೆ.",
"cancel": "ರದ್ದುಗೊಳಿಸಿ",
"continue": "ಸೈನ್ ಇನ್ ಮಾಡಿ"
},
"cancelDownloadModal": {
"heading": "ನೀವು ಡೌನ್‌ಲೋಡ್ ರದ್ದುಗೊಳಿಸಲು ಬಯಸುವಿರಾ?",
"subHeading": "ಒಮ್ಮೆ ರದ್ದು ಮಾಡಿದ ನಂತರ, ನಿಮ್ಮ ಕಾರ್ಡ್ ಡೌನ್‌ಲೋಡ್ ಆಗುವುದಿಲ್ಲ ಮತ್ತು ನೀವು ಮತ್ತೆ ಪ್ರಾರಂಭಿಸಬೇಕಾಗುತ್ತದೆ.",
"cancel": "ಇಲ್ಲ, ನಾನು ನಿರೀಕ್ಷಿಸುತ್ತೇನೆ",
"confirm": "ಹೌದು, ರದ್ದುಗೊಳಿಸಿ"
},
"transactionCodeScreen": {
"description": "ನಾವು ವ್ಯವಹಾರದ ಕೋಡ್ ಅನ್ನು ನಿಮ್ಮ ನೋಂದಾಯಿತ ಇಮೇಲ್‌ಗೆ ಕಳುಹಿಸಿದ್ದೇವೆ",
"placeholder": "ವ್ಯವಹಾರದ ಕೋಡ್ ನಮೂದಿಸಿ",
"verify": "ಸರಿಪಡಿಸಿ",
"emptyCodeError": "ಕೋಡ್ ಖಾಲಿ ಇರಬಾರದು",
"invalidCharacters": "ಅಕ್ಷರಗಳು ಮತ್ತು ಸಂಖ್ಯೆಗಳು ಮಾತ್ರ ಅನುಮತಿಸಲಾಗಿದೆ",
"TransactionCode": "ವಹಿವಾಟು ಕೋಡ್"
},
"trustScreen": {
"description": "ಡೌನ್‌ಲೋಡ್ ಮಾಡುವ ಮೊದಲು ಈ ಕಾರ್ಡ್ ನಂಬಿಕಸ್ತ ಮೂಲದಿಂದ ಇದೆಯೆಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ. ಡೌನ್‌ಲೋಡ್ ಮಾಡಿದ ನಂತರ, ಇದು ನಿಮ್ಮ ವ್ಯಾಲೆಟ್‌ನಲ್ಲಿ ಉಳಿಯುತ್ತದೆ ಮತ್ತು ಯಾವಾಗ ಬೇಕಾದರೂ ಬಳಸಬಹುದು.",
"confirm": "ಹೌದು, ನಾನು ನಂಬುತ್ತೇನೆ",
"cancel": "ಇಲ್ಲ, ನನನ್ನು ಹಿಂದಕ್ಕೆ ಕರೆ"
}
}

View File

@@ -208,6 +208,9 @@
"downloadingCredentials": "நற்சான்றிதழ்களைப் பதிவிறக்குகிறது"
}
},
"offerTitle": "ஸ்கேன் செய்து கார்டை பதிவிறக்கவும்",
"offerDescription": "உங்கள் கார்டை உடனடியாக பதிவிறக்க QR குறியீட்டை ஸ்கேன் செய்யவும்.",
"download": "கார்டைப் பதிவிறக்கவும்",
"errors": {
"noInternetConnection": {
"title": "இணைய இணைப்பு இல்லை",
@@ -1049,5 +1052,30 @@
"done": "முடிந்தது",
"keyManagementTitle": "முக்கிய மேலாண்மை",
"keyManagementDesc": "உங்கள் விருப்பத்திற்கு ஏற்ப முக்கிய உருவாக்க முறையைத் தேர்ந்தெடுக்கவும், உங்கள் சான்றுத் தனி பாதுகாப்பை நீங்கள் கட்டுப்படுத்துகின்றீர்கள்.\nமேலுள்ள முக்கியம் உங்களின் மிக முக்கிய முன்னுரிமையாக இருக்கும் வகையில், முக்கியங்களை இழுத்து மறு வரிசைப்படுத்தவும்."
},
"authWebView": {
"title": "உங்கள் \"{{wallet}}\" \"{{domain}}\" ஐ உள்நுழைவதற்காக பயன்படுத்த விரும்புகிறது",
"message": "இந்த செயலி மற்றும் இணையதளம் உங்கள் தகவல்களை பகிர அனுமதிக்கிறது.",
"cancel": "ரத்து செய்",
"continue": "உள்நுழையவும்"
},
"cancelDownloadModal": {
"heading": "நீங்கள் பதிவிறக்கத்தை ரத்துசெய்ய விரும்புகிறீர்களா?",
"subHeading": "ஒருமுறை ரத்துசெய்தால், உங்கள் அட்டை பதிவிறக்கப்படாது. மீண்டும் தொடங்க வேண்டும்.",
"cancel": "இல்லை, நான் காத்திருப்பேன்",
"confirm": "ஆம், ரத்துசெய்"
},
"transactionCodeScreen": {
"description": "பரிவரத்து குறியீடு உங்கள் பதிவுசெய்த மின்னஞ்சலுக்கு அனுப்பப்பட்டுள்ளது",
"placeholder": "பரிவரத்து குறியீட்டை உள்ளிடவும்",
"verify": "சரிபார்க்கவும்",
"emptyCodeError": "குறியீடு காலியாக இருக்க முடியாது",
"invalidCharacters": "எழுத்துகள் மற்றும் எண்கள் மட்டும் அனுமதிக்கப்படும்",
"TransactionCode": "பரிவரத்து குறியீடு"
},
"trustScreen": {
"description": "இந்த அட்டை நம்பகமானதாக இருப்பதை உறுதிசெய்துகொள்ளுங்கள். பதிவிறக்கப்பட்ட பிறகு, இது உங்கள் பணப்பையில் சேமிக்கப்படும் மற்றும் எப்போது வேண்டுமானாலும் பயன்படுத்தலாம்.",
"confirm": "ஆம், நம்புகிறேன்",
"cancel": "இல்லை, என்னை திரும்ப அழைத்துச் செல்"
}
}

View File

@@ -1,32 +1,29 @@
import {
ErrorMessage,
getDisplayObjectForCurrentLanguage,
Issuers_Key_Ref,
OIDCErrors,
selectCredentialRequestKey,
} from '../../shared/openId4VCI/Utils';
import {
MY_VCS_STORE_KEY,
REQUEST_TIMEOUT,
isIOS,
EXPIRED_VC_ERROR_CODE,
} from '../../shared/constants';
import {assign, send} from 'xstate';
import {StoreEvents} from '../store';
import {BackupEvents} from '../backupAndRestore/backup/backupMachine';
import {getVCMetadata, VCMetadata} from '../../shared/VCMetadata';
import {isHardwareKeystoreExists} from '../../shared/cryptoutil/cryptoUtil';
import {ActivityLogEvents} from '../activityLog';
import { EXPIRED_VC_ERROR_CODE, MY_VCS_STORE_KEY, REQUEST_TIMEOUT, isIOS } from '../../shared/constants';
import { assign, send } from 'xstate';
import { StoreEvents } from '../store';
import { BackupEvents } from '../backupAndRestore/backup/backupMachine';
import { getVCMetadata, VCMetadata } from '../../shared/VCMetadata';
import { isHardwareKeystoreExists } from '../../shared/cryptoutil/cryptoUtil';
import { ActivityLogEvents } from '../activityLog';
import {
getEndEventData,
getImpressionEventData,
sendEndEvent,
sendImpressionEvent,
} from '../../shared/telemetry/TelemetryUtils';
import {TelemetryConstants} from '../../shared/telemetry/TelemetryConstants';
import {NativeModules} from 'react-native';
import {KeyTypes} from '../../shared/cryptoutil/KeyTypes';
import {VCActivityLog} from '../../components/ActivityLogEvent';
import {isNetworkError} from '../../shared/Utils';
import { TelemetryConstants } from '../../shared/telemetry/TelemetryConstants';
import { NativeModules } from 'react-native';
import { KeyTypes } from '../../shared/cryptoutil/KeyTypes';
import { VCActivityLog } from '../../components/ActivityLogEvent';
import { isNetworkError } from '../../shared/Utils';
import { issuerType } from './IssuersMachine';
const {RNSecureKeystoreModule} = NativeModules;
export const IssuersActions = (model: any) => {
@@ -36,7 +33,7 @@ export const IssuersActions = (model: any) => {
new VCMetadata({
...context.vcMetadata,
isVerified: true,
isExpired: event.data.verificationErrorCode == EXPIRED_VC_ERROR_CODE,
isExpired: event.data.verificationErrorCode == EXPIRED_VC_ERROR_CODE,
}),
}),
resetVerificationResult: assign({
@@ -48,7 +45,7 @@ export const IssuersActions = (model: any) => {
}),
}),
setIssuers: model.assign({
issuers: (_: any, event: any) => event.data,
issuers: (_: any, event: any) => event.data as issuerType[],
}),
setNoInternet: model.assign({
errorMessage: () => ErrorMessage.NO_INTERNET,
@@ -230,9 +227,10 @@ export const IssuersActions = (model: any) => {
}),
setSelectedIssuers: model.assign({
selectedIssuer: (context: any, event: any) =>
context.issuers.find(issuer => issuer.issuer_id === event.id),
}),
selectedIssuer: (context: any, event: any) => {
return context.issuers.find(issuer => issuer.issuer_id === event.id);
}
}),
updateIssuerFromWellknown: model.assign({
selectedIssuer: (context: any, event: any) => ({
@@ -241,24 +239,125 @@ export const IssuersActions = (model: any) => {
credential_endpoint: event.data.credential_endpoint,
credential_configurations_supported:
event.data.credential_configurations_supported,
display: event.data.display,
authorization_servers: event.data.authorization_servers,
}),
}),
updateAuthorizationEndpoint: model.assign({
selectedIssuer: (context: any, event: any) => ({
...context.selectedIssuer,
authorizationEndpoint: event.data,
}),
setCredential: model.assign({
credential: (_: any, event: any) => event.data,
}),
setQrData: model.assign({
qrData: (_: any, event: any) => event.data,
}),
setCredentialOfferIssuer: model.assign({
selectedIssuer: (_:any,event: any) => {
console.log("issuer::", event.issuer);
return event.issuer;
},
}),
setAccessToken: model.assign({
accessToken: (_: any, event: any) => {
return event.accessToken;
},
}),
setCNonce: model.assign({
cNonce: (_: any, event: any) => {
return event.cNonce;
},
}),
setOfferCredentialTypeContexts: model.assign({
selectedCredentialType: (context: any, event: any) => {
return event.credentialTypes[0];
},
supportedCredentialTypes: (context: any, event: any) => {
return event.credentialTypes;
},
accessToken: (context: any, event: any) => {
return event.accessToken;
},
cNonce: (context: any, event: any) => {
return event.cNonce;
},
}),
setRequestTxCode: model.assign({
isTransactionCodeRequested: (_: any, event: any) => {
return true;
},
}),
resetRequestTxCode: model.assign({
isTransactionCodeRequested: (_: any, event: any) => {
return false;
},
}),
setCredentialOfferIssuerWellknownResponse: model.assign({
selectedIssuerWellknownResponse: (_: any, event: any) => {
return event.issuerMetadata;
},
wellknownKeyTypes: (_: any, event: any) => {
const credType = Object.entries(event.credentialTypes)[0][1];
const proofTypesSupported = credType.proof_types_supported;
if (proofTypesSupported?.jwt) {
return proofTypesSupported.jwt
.proof_signing_alg_values_supported as string[];
} else {
return [KeyTypes.RS256] as string[];
}
},
}),
updateSelectedIssuerWellknownResponse: model.assign({
selectedIssuerWellknownResponse: (_: any, event: any) => event.data,
}),
setSelectedIssuerId: model.assign({
selectedIssuerId: (_: any, event: any) => event.id,
}),
setTokenResponse: model.assign({
tokenResponse: (_: any, event: any) => event.data,
setTxCode: model.assign({
txCode: (_: any, event: any) => {
return event.txCode;
},
}),
setRequestConsentToTrustIssuer: model.assign({
isConsentRequested: (_: any, event: any) => {
return true;
},
}),
setTxCodeDisplayDetails: model.assign({
txCodeInputMode: (_: any, event: any) => event.inputMode,
txCodeDescription: (_: any, event: any) => event.description,
txCodeLength: (_: any, event: any) => event.length,
}),
setIssuerDisplayDetails: model.assign({
issuerLogo: (_: any, event: any) => {
const display = getDisplayObjectForCurrentLanguage(
event.issuerMetadata.display,
);
return display.logo.url;
},
issuerName: (_: any, event: any) => {
const display = getDisplayObjectForCurrentLanguage(
event.issuerMetadata.display,
);
return display.name;
},
}),
setFlowType: model.assign({
isCredentialOfferFlow: (_: any, event: any) => {
return true;
},
}),
resetFlowType: model.assign({
isCredentialOfferFlow: (_: any, event: any) => {
return false;
},
}),
resetRequestConsentToTrustIssuer: model.assign({
isConsentRequested: (_: any, event: any) => {
return false;
},
}),
setVerifiableCredential: model.assign({
verifiableCredential: (_: any, event: any) => {
@@ -339,6 +438,10 @@ export const IssuersActions = (model: any) => {
verificationErrorMessage: () => '',
}),
resetQrData: model.assign({
qrData: () => '',
}),
sendDownloadingFailedToVcMeta: send(
(_: any) => ({
type: 'VC_DOWNLOADING_FAILED',

View File

@@ -1,4 +1,5 @@
import {CredentialTypes} from '../VerifiableCredential/VCMetaMachine/vc';
import { CredentialTypes } from '../VerifiableCredential/VCMetaMachine/vc';
import { issuerType } from './IssuersMachine';
export const IssuersEvents = {
SELECTED_ISSUER: (id: string) => ({id}),
@@ -13,4 +14,24 @@ export const IssuersEvents = {
STORE_ERROR: (error: Error, requester?: string) => ({error, requester}),
RESET_VERIFY_ERROR: () => ({}),
SELECTED_CREDENTIAL_TYPE: (credType: CredentialTypes) => ({credType}),
SCAN_CREDENTIAL_OFFER_QR_CODE: () => ({}),
QR_CODE_SCANNED: (data: string) => ({data}),
AUTH_ENDPOINT_RECEIVED: (authEndpoint: string) => ({authEndpoint}),
PROOF_REQUEST: (
accessToken: string,
cNonce: string | undefined,
issuerMetadata: object,
issuer: issuerType,
credentialtypes: CredentialTypes,
) => ({
accessToken: accessToken,
cNonce: cNonce,
issuerMetadata: issuerMetadata,
issuer: issuer,
credentialtypes: credentialtypes,
}),
TX_CODE_REQUEST: () => ({}),
TX_CODE_RECEIVED: (txCode: string) => ({txCode}),
ON_CONSENT_GIVEN: () => ({}),
TRUST_ISSUER_CONSENT_REQUEST: (issuerMetadata: object) => ({issuerMetadata})
};

View File

@@ -57,5 +57,8 @@ export const IssuersGuards = () => {
const errorMessage = event.data.message;
return errorMessage === ErrorMessage.GENERIC;
},
isCredentialOfferFlow: (context: any) => {
return context.isCredentialOfferFlow
}
};
};

File diff suppressed because one or more lines are too long

View File

@@ -1,378 +0,0 @@
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
'done.invoke.checkInternet': {
type: 'done.invoke.checkInternet';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.checkKeyPair:invocation[0]': {
type: 'done.invoke.issuersMachine.checkKeyPair:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.displayIssuers:invocation[0]': {
type: 'done.invoke.issuersMachine.displayIssuers:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.downloadCredentialTypes:invocation[0]': {
type: 'done.invoke.issuersMachine.downloadCredentialTypes:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.downloadCredentials:invocation[0]': {
type: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]': {
type: 'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.fetchAuthorizationEndpoint:invocation[0]': {
type: 'done.invoke.issuersMachine.fetchAuthorizationEndpoint:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.generateKeyPair:invocation[0]': {
type: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]': {
type: 'done.invoke.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.performAuthorization.setSelectedKey:invocation[0]': {
type: 'done.invoke.issuersMachine.performAuthorization.setSelectedKey:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.performAuthorization:invocation[0]': {
type: 'done.invoke.issuersMachine.performAuthorization:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.storing:invocation[0]': {
type: 'done.invoke.issuersMachine.storing:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.issuersMachine.verifyingCredential:invocation[0]': {
type: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'error.platform.checkInternet': {
type: 'error.platform.checkInternet';
data: unknown;
};
'error.platform.issuersMachine.displayIssuers:invocation[0]': {
type: 'error.platform.issuersMachine.displayIssuers:invocation[0]';
data: unknown;
};
'error.platform.issuersMachine.downloadCredentialTypes:invocation[0]': {
type: 'error.platform.issuersMachine.downloadCredentialTypes:invocation[0]';
data: unknown;
};
'error.platform.issuersMachine.downloadCredentials:invocation[0]': {
type: 'error.platform.issuersMachine.downloadCredentials:invocation[0]';
data: unknown;
};
'error.platform.issuersMachine.downloadIssuerWellknown:invocation[0]': {
type: 'error.platform.issuersMachine.downloadIssuerWellknown:invocation[0]';
data: unknown;
};
'error.platform.issuersMachine.fetchAuthorizationEndpoint:invocation[0]': {
type: 'error.platform.issuersMachine.fetchAuthorizationEndpoint:invocation[0]';
data: unknown;
};
'error.platform.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]': {
type: 'error.platform.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]';
data: unknown;
};
'error.platform.issuersMachine.performAuthorization.setSelectedKey:invocation[0]': {
type: 'error.platform.issuersMachine.performAuthorization.setSelectedKey:invocation[0]';
data: unknown;
};
'error.platform.issuersMachine.performAuthorization:invocation[0]': {
type: 'error.platform.issuersMachine.performAuthorization:invocation[0]';
data: unknown;
};
'error.platform.issuersMachine.verifyingCredential:invocation[0]': {
type: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
data: unknown;
};
'xstate.init': {type: 'xstate.init'};
};
invokeSrcNameMap: {
checkInternet: 'done.invoke.checkInternet';
downloadCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]';
downloadCredentialTypes: 'done.invoke.issuersMachine.downloadCredentialTypes:invocation[0]';
downloadIssuerWellknown: 'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]';
downloadIssuersList: 'done.invoke.issuersMachine.displayIssuers:invocation[0]';
fetchAuthorizationEndpoint: 'done.invoke.issuersMachine.fetchAuthorizationEndpoint:invocation[0]';
generateKeyPair: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]';
getKeyOrderList: 'done.invoke.issuersMachine.performAuthorization.setSelectedKey:invocation[0]';
getKeyPair: 'done.invoke.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]';
getSelectedKey: 'done.invoke.issuersMachine.checkKeyPair:invocation[0]';
invokeAuthorization: 'done.invoke.issuersMachine.performAuthorization:invocation[0]';
isUserSignedAlready: 'done.invoke.issuersMachine.storing:invocation[0]';
verifyCredential: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]';
};
missingImplementations: {
actions:
| 'downloadIssuerWellknown'
| 'loadKeyPair'
| 'logDownloaded'
| 'resetError'
| 'resetLoadingReason'
| 'resetSelectedCredentialType'
| 'resetVerificationErrorMessage'
| 'resetVerificationResult'
| 'sendBackupEvent'
| 'sendDownloadingFailedToVcMeta'
| 'sendErrorEndEvent'
| 'sendImpressionEvent'
| 'sendSuccessEndEvent'
| 'setCredentialTypeListDownloadFailureError'
| 'setCredentialWrapper'
| 'setError'
| 'setIssuers'
| 'setLoadingReasonAsDisplayIssuers'
| 'setLoadingReasonAsDownloadingCredentials'
| 'setLoadingReasonAsSettingUp'
| 'setMetadataInCredentialData'
| 'setNetworkOrTechnicalError'
| 'setNoInternet'
| 'setOIDCConfigError'
| 'setPrivateKey'
| 'setPublicKey'
| 'setSelectedCredentialType'
| 'setSelectedIssuerId'
| 'setSelectedIssuers'
| 'setSelectedKey'
| 'setSupportedCredentialTypes'
| 'setTokenResponse'
| 'setVCMetadata'
| 'setVerifiableCredential'
| 'setVerificationResult'
| 'storeKeyPair'
| 'storeVcMetaContext'
| 'storeVcsContext'
| 'storeVerifiableCredentialData'
| 'storeVerifiableCredentialMeta'
| 'updateAuthorizationEndpoint'
| 'updateIssuerFromWellknown'
| 'updateSelectedIssuerWellknownResponse'
| 'updateVerificationErrorMessage';
delays: never;
guards:
| 'canSelectIssuerAgain'
| 'hasKeyPair'
| 'hasUserCancelledBiometric'
| 'isCustomSecureKeystore'
| 'isGenericError'
| 'isInternetConnected'
| 'isKeyTypeNotFound'
| 'isOIDCConfigError'
| 'isOIDCflowCancelled'
| 'isSignedIn'
| 'isVerificationPendingBecauseOfNetworkIssue'
| 'shouldFetchIssuersAgain';
services:
| 'checkInternet'
| 'downloadCredential'
| 'downloadCredentialTypes'
| 'downloadIssuerWellknown'
| 'downloadIssuersList'
| 'fetchAuthorizationEndpoint'
| 'generateKeyPair'
| 'getKeyOrderList'
| 'getKeyPair'
| 'getSelectedKey'
| 'invokeAuthorization'
| 'isUserSignedAlready'
| 'verifyCredential';
};
eventsCausingActions: {
downloadIssuerWellknown: 'TRY_AGAIN';
loadKeyPair: 'done.invoke.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]';
logDownloaded:
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
resetError:
| 'RESET_ERROR'
| 'TRY_AGAIN'
| 'error.platform.issuersMachine.performAuthorization:invocation[0]';
resetLoadingReason:
| 'RESET_ERROR'
| 'done.invoke.checkInternet'
| 'done.invoke.issuersMachine.displayIssuers:invocation[0]'
| 'error.platform.issuersMachine.downloadCredentialTypes:invocation[0]'
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]'
| 'error.platform.issuersMachine.downloadIssuerWellknown:invocation[0]'
| 'error.platform.issuersMachine.fetchAuthorizationEndpoint:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization.setSelectedKey:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization:invocation[0]'
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
resetSelectedCredentialType:
| 'CANCEL'
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization.setSelectedKey:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization:invocation[0]';
resetVerificationErrorMessage: 'RESET_VERIFY_ERROR';
resetVerificationResult: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
sendBackupEvent: 'done.invoke.issuersMachine.storing:invocation[0]';
sendDownloadingFailedToVcMeta:
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization.setSelectedKey:invocation[0]';
sendErrorEndEvent: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
sendImpressionEvent: 'done.invoke.issuersMachine.displayIssuers:invocation[0]';
sendSuccessEndEvent: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]';
setCredentialTypeListDownloadFailureError: 'error.platform.issuersMachine.downloadCredentialTypes:invocation[0]';
setCredentialWrapper: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]';
setError:
| 'error.platform.issuersMachine.displayIssuers:invocation[0]'
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]'
| 'error.platform.issuersMachine.fetchAuthorizationEndpoint:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization.setSelectedKey:invocation[0]';
setIssuers: 'done.invoke.issuersMachine.displayIssuers:invocation[0]';
setLoadingReasonAsDisplayIssuers: 'TRY_AGAIN';
setLoadingReasonAsDownloadingCredentials:
| 'TRY_AGAIN'
| 'done.invoke.issuersMachine.generateKeyPair:invocation[0]'
| 'done.invoke.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]';
setLoadingReasonAsSettingUp:
| 'RESET_ERROR'
| 'SELECTED_ISSUER'
| 'TRY_AGAIN'
| 'done.invoke.issuersMachine.performAuthorization:invocation[0]';
setMetadataInCredentialData:
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
setNetworkOrTechnicalError:
| 'error.platform.issuersMachine.downloadIssuerWellknown:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization:invocation[0]';
setNoInternet: 'done.invoke.checkInternet';
setOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]';
setPrivateKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]';
setPublicKey: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]';
setSelectedCredentialType: 'SELECTED_CREDENTIAL_TYPE';
setSelectedIssuerId: 'SELECTED_ISSUER';
setSelectedIssuers: 'SELECTED_ISSUER';
setSelectedKey: 'done.invoke.issuersMachine.performAuthorization.setSelectedKey:invocation[0]';
setSupportedCredentialTypes: 'done.invoke.issuersMachine.downloadCredentialTypes:invocation[0]';
setTokenResponse: 'done.invoke.issuersMachine.performAuthorization:invocation[0]';
setVCMetadata:
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
setVerifiableCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]';
setVerificationResult: 'done.invoke.issuersMachine.verifyingCredential:invocation[0]';
storeKeyPair: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]';
storeVcMetaContext:
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
storeVcsContext:
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
storeVerifiableCredentialData:
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
storeVerifiableCredentialMeta:
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
updateAuthorizationEndpoint: 'done.invoke.issuersMachine.fetchAuthorizationEndpoint:invocation[0]';
updateIssuerFromWellknown: 'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]';
updateSelectedIssuerWellknownResponse: 'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]';
updateVerificationErrorMessage: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
};
eventsCausingDelays: {};
eventsCausingGuards: {
canSelectIssuerAgain: 'TRY_AGAIN';
hasKeyPair: 'done.invoke.issuersMachine.checkKeyPair:invocation[0]';
hasUserCancelledBiometric:
| 'error.platform.issuersMachine.downloadCredentials:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]';
isCustomSecureKeystore: 'done.invoke.issuersMachine.generateKeyPair:invocation[0]';
isGenericError: 'error.platform.issuersMachine.downloadCredentials:invocation[0]';
isInternetConnected: 'done.invoke.checkInternet';
isKeyTypeNotFound: 'error.platform.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]';
isOIDCConfigError: 'error.platform.issuersMachine.performAuthorization:invocation[0]';
isOIDCflowCancelled: 'error.platform.issuersMachine.performAuthorization:invocation[0]';
isSignedIn: 'done.invoke.issuersMachine.storing:invocation[0]';
isVerificationPendingBecauseOfNetworkIssue: 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
shouldFetchIssuersAgain: 'TRY_AGAIN';
};
eventsCausingServices: {
checkInternet:
| 'done.invoke.issuersMachine.downloadCredentialTypes:invocation[0]'
| 'done.invoke.issuersMachine.fetchAuthorizationEndpoint:invocation[0]';
downloadCredential:
| 'done.invoke.issuersMachine.checkKeyPair:invocation[0]'
| 'done.invoke.issuersMachine.generateKeyPair:invocation[0]';
downloadCredentialTypes: 'done.invoke.issuersMachine.downloadIssuerWellknown:invocation[0]';
downloadIssuerWellknown: 'SELECTED_ISSUER' | 'TRY_AGAIN';
downloadIssuersList: 'CANCEL' | 'TRY_AGAIN' | 'xstate.init';
fetchAuthorizationEndpoint: 'SELECTED_CREDENTIAL_TYPE';
generateKeyPair: 'done.invoke.issuersMachine.checkKeyPair:invocation[0]';
getKeyOrderList: 'done.invoke.issuersMachine.performAuthorization:invocation[0]';
getKeyPair:
| 'TRY_AGAIN'
| 'done.invoke.issuersMachine.performAuthorization.setSelectedKey:invocation[0]';
getSelectedKey:
| 'done.invoke.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]'
| 'error.platform.issuersMachine.performAuthorization.getKeyPairFromKeystore:invocation[0]';
invokeAuthorization: 'done.invoke.checkInternet';
isUserSignedAlready:
| 'done.invoke.issuersMachine.verifyingCredential:invocation[0]'
| 'error.platform.issuersMachine.verifyingCredential:invocation[0]';
verifyCredential: 'done.invoke.issuersMachine.downloadCredentials:invocation[0]';
};
matchesStates:
| 'checkInternet'
| 'checkKeyPair'
| 'displayIssuers'
| 'done'
| 'downloadCredentialTypes'
| 'downloadCredentials'
| 'downloadCredentials.idle'
| 'downloadCredentials.userCancelledBiometric'
| 'downloadIssuerWellknown'
| 'error'
| 'fetchAuthorizationEndpoint'
| 'fetchAuthorizationEndpoint.error'
| 'fetchAuthorizationEndpoint.idle'
| 'generateKeyPair'
| 'handleVCVerificationFailure'
| 'idle'
| 'performAuthorization'
| 'performAuthorization.getKeyPairFromKeystore'
| 'performAuthorization.idle'
| 'performAuthorization.setSelectedKey'
| 'performAuthorization.userCancelledBiometric'
| 'selectingCredentialType'
| 'selectingIssuer'
| 'storing'
| 'verifyingCredential'
| {
downloadCredentials?: 'idle' | 'userCancelledBiometric';
fetchAuthorizationEndpoint?: 'error' | 'idle';
performAuthorization?:
| 'getKeyPairFromKeystore'
| 'idle'
| 'setSelectedKey'
| 'userCancelledBiometric';
};
tags: never;
}

View File

@@ -15,6 +15,7 @@ export const IssuersModel = createModel(
{
issuers: [] as issuerType[],
selectedIssuerId: '' as string,
qrData: '' as string,
selectedIssuer: {} as issuerType,
selectedIssuerWellknownResponse: {} as IssuerWellknownResponse,
tokenResponse: {} as AuthorizeResult,
@@ -31,6 +32,19 @@ export const IssuersModel = createModel(
vcMetadata: {} as VCMetadata,
keyType: 'RS256' as string,
wellknownKeyTypes: [] as string[],
authEndpointToOpen: false as boolean,
isTransactionCodeRequested: false as boolean,
authEndpoint: '' as string,
accessToken: '' as string,
txCode: '' as string,
cNonce: '' as string,
isConsentRequested: false as boolean,
issuerLogo: '' as string,
issuerName: '' as string,
txCodeInputMode: '' as string,
txCodeDescription: '' as string,
txCodeLength: null as number | null,
isCredentialOfferFlow: false as boolean,
},
{
events: IssuersEvents,

View File

@@ -12,6 +12,14 @@ export function selectSelectedIssuer(state: State) {
return state.context.selectedIssuer;
}
export function selectAuthWebViewStatus(state: State) {
return state.context.authEndpointToOpen;
}
export function selectAuthEndPoint(state: State) {
return state.context.authEndpoint;
}
export function selectErrorMessageType(state: State) {
return state.context.errorMessage;
}
@@ -24,10 +32,37 @@ export function selectIsDownloadCredentials(state: State) {
return state.matches('downloadCredentials');
}
export function selectIsTxCodeRequested(state: State) {
return state.context.isTransactionCodeRequested;
}
export function selectIsConsentRequested(state: State) {
return state.context.isConsentRequested;
}
export function selectIssuerLogo(state: State) {
return state.context.issuerLogo;
}
export function selectIssuerName(state: State) {
return state.context.issuerName;
}
export function selectTxCodeDisplayDetails(state: State) {
const context = state.context;
return {
inputMode: context.txCodeInputMode,
description: context.txCodeDescription,
length: context.txCodeLength,
};
}
export function selectIsBiometricCancelled(state: State) {
return (
state.matches('downloadCredentials.userCancelledBiometric') ||
state.matches('performAuthorization.userCancelledBiometric')
state.matches('downloadCredentials.keyManagement.userCancelledBiometric') ||
state.matches(
'credentialDownloadFromOffer.keyManagement.userCancelledBiometric',
)
);
}
@@ -65,3 +100,11 @@ export function selectSelectingCredentialType(state: State) {
export function selectSupportedCredentialTypes(state: State) {
return state.context.supportedCredentialTypes;
}
export function selectIsQrScanning(state: State) {
return state.matches('waitingForQrScan');
}
export function selectCredentialOfferData(state: State) {
return state.context.credentialOfferData;
}

View File

@@ -1,6 +1,5 @@
import NetInfo from '@react-native-community/netinfo';
import {NativeModules} from 'react-native';
import {authorize} from 'react-native-app-auth';
import Cloud from '../../shared/CloudBackupAndRestoreUtils';
import {CACHED_API} from '../../shared/api';
import {
@@ -8,21 +7,16 @@ import {
generateKeyPair,
} from '../../shared/cryptoutil/cryptoUtil';
import {
constructAuthorizationConfiguration,
constructIssuerMetaData,
constructProofJWT,
hasKeyPair,
OIDCErrors,
updateCredentialInformation,
vcDownloadTimeout,
verifyCredentialData,
} from '../../shared/openId4VCI/Utils';
import {TelemetryConstants} from '../../shared/telemetry/TelemetryConstants';
import {
getImpressionEventData,
sendImpressionEvent,
} from '../../shared/telemetry/TelemetryUtils';
import {VciClient} from '../../shared/vciClient/VciClient';
import {issuerType} from './IssuersMachine';
import {setItem} from '../store';
import {API_CACHED_STORAGE_KEYS} from '../../shared/constants';
export const IssuersService = () => {
return {
@@ -30,106 +24,196 @@ export const IssuersService = () => {
return await Cloud.isSignedInAlready();
},
downloadIssuersList: async () => {
return await CACHED_API.fetchIssuers();
const trustedIssuersList = await CACHED_API.fetchIssuers();
return trustedIssuersList;
},
checkInternet: async () => await NetInfo.fetch(),
downloadIssuerWellknown: async (context: any) => {
const wellknownResponse = await CACHED_API.fetchIssuerWellknownConfig(
context.selectedIssuer.issuer_id,
context.selectedIssuer.credential_issuer_host,
context.selectedIssuer.id,
context.selectedIssuer.credential_issuer_host
? context.selectedIssuer.credential_issuer_host
: context.selectedIssuer.credential_issuer,
);
return wellknownResponse;
},
downloadCredentialTypes: async (context: any) => {
getCredentialTypes: async (context: any) => {
const credentialTypes = [];
for (const key in context.selectedIssuer
.credential_configurations_supported) {
credentialTypes.push({
id: key,
...context.selectedIssuer.credential_configurations_supported[key],
});
}
if (credentialTypes.length == 0)
throw new Error(
`No credential type found for issuer ${context.selectedIssuer.issuer_id}`,
);
const selectedIssuer = context.selectedIssuer;
return credentialTypes;
},
fetchAuthorizationEndpoint: async (context: any) => {
const wellknownResponse = context.selectedIssuerWellknownResponse;
const credentialIssuer = wellknownResponse['credential_issuer'];
const authorizationServers = wellknownResponse[
'authorization_servers'
] || [credentialIssuer];
const keys =
selectedIssuer.credential_configuration_ids ??
Object.keys(selectedIssuer.credential_configurations_supported);
const SUPPORTED_GRANT_TYPES = ['authorization_code'];
const DEFAULT_AUTHORIZATION_SERVER_SUPPORTED_GRANT_TYPES = [
'authorization_code',
'implicit',
];
for (const server of authorizationServers) {
try {
const authorizationServersMetadata =
await CACHED_API.fetchIssuerAuthorizationServerMetadata(server);
if (
(
authorizationServersMetadata?.['grant_types_supported'] ||
DEFAULT_AUTHORIZATION_SERVER_SUPPORTED_GRANT_TYPES
).some(grant => SUPPORTED_GRANT_TYPES.includes(grant))
) {
return authorizationServersMetadata['authorization_endpoint'];
}
} catch (error) {
console.error(`Failed to fetch metadata for ${server}:`, error);
for (const key of keys) {
if (selectedIssuer.credential_configurations_supported[key]) {
credentialTypes.push({
id: key,
...selectedIssuer.credential_configurations_supported[key],
});
}
}
throw new Error(
OIDCErrors.AUTHORIZATION_ENDPOINT_DISCOVERY.FAILED_TO_FETCH_AUTHORIZATION_ENDPOINT,
);
if (credentialTypes.length === 0) {
throw new Error(
`No credential type found for issuer ${selectedIssuer.issuer_id}`,
);
}
return credentialTypes;
},
downloadCredential: async (context: any) => {
const downloadTimeout = await vcDownloadTimeout();
const accessToken: string = context.tokenResponse?.accessToken;
const proofJWT = await constructProofJWT(
context.publicKey,
context.privateKey,
accessToken,
context.selectedIssuer,
context.keyType,
);
let credential = await VciClient.downloadCredential(
downloadCredential: (context: any) => async (sendBack: any) => {
const navigateToAuthView = (authorizationEndpoint: string) => {
sendBack({
type: 'AUTH_ENDPOINT_RECEIVED',
authEndpoint: authorizationEndpoint,
});
};
const getProofJwt= async (accessToken: string, cNonce: string) => {
sendBack({
type: 'PROOF_REQUEST',
accessToken: accessToken,
cNonce: cNonce,
})
}
const credential = await VciClient.requestCredentialFromTrustedIssuer(
constructIssuerMetaData(
context.selectedIssuer,
context.selectedCredentialType,
downloadTimeout,
),
proofJWT,
accessToken,
);
console.info(`VC download via ${context.selectedIssuerId} is successful`);
return await updateCredentialInformation(context, credential);
},
invokeAuthorization: async (context: any) => {
sendImpressionEvent(
getImpressionEventData(
TelemetryConstants.FlowType.vcDownload,
context.selectedIssuer.issuer_id +
TelemetryConstants.Screens.webViewPage,
),
);
return await authorize(
constructAuthorizationConfiguration(
context.selectedIssuer,
context.selectedCredentialType.scope,
),
{
clientId: context.selectedIssuer.client_id,
redirectUri: context.selectedIssuer.redirect_uri,
},
getProofJwt,
navigateToAuthView,
);
return updateCredentialInformation(context, credential);
},
sendTxCode: async (context: any) => {
await VciClient.client.sendTxCodeFromJS(context.txCode);
},
sendConsentGiven: async () => {
await VciClient.client.sendIssuerTrustResponseFromJS(true);
},
sendConsentNotGiven: async () => {
await VciClient.client.sendIssuerTrustResponseFromJS(false);
},
downloadCredentialFromOffer: (context: any) => async (sendBack: any) => {
const navigateToAuthView = (authorizationEndpoint: string) => {
sendBack({
type: 'AUTH_ENDPOINT_RECEIVED',
authEndpoint: authorizationEndpoint,
});
};
const getSignedProofJwt = async (
accessToken: string,
cNonce: string | null,
issuerMetadata: object,
credentialConfigurationId: string,
) => {
console.log("issuerMetadata::", issuerMetadata);
let issuer = issuerMetadata as issuerType;
issuer.issuer_id = issuer.credential_issuer;
await setItem(
API_CACHED_STORAGE_KEYS.fetchIssuerWellknownConfig(issuer.issuer_id),
issuer,
'',
);
let credentialTypes: Array<{id: string; [key: string]: any}> = [];
if (
issuer.credential_configurations_supported[credentialConfigurationId]
) {
credentialTypes.push({
id: credentialConfigurationId,
...issuer.credential_configurations_supported[
credentialConfigurationId
],
});
sendBack({
type: 'PROOF_REQUEST',
accessToken: accessToken,
cNonce: cNonce,
issuerMetadata: issuerMetadata,
issuer: issuer,
credentialTypes: credentialTypes,
});
}
};
const getTxCode = async (
inputMode: string | undefined,
description: string | undefined,
length: number | undefined,
) => {
sendBack({
type: 'TX_CODE_REQUEST',
inputMode: inputMode,
description: description,
length: length,
});
};
const requesTrustIssuerConsent = async (issuerMetadata: object) => {
const issuerMetadataObject = issuerMetadata as issuerType;
sendBack({
type: 'TRUST_ISSUER_CONSENT_REQUEST',
issuerMetadata: issuerMetadataObject,
});
};
const credential = await VciClient.requestCredentialByOffer(
context.qrData,
getTxCode,
getSignedProofJwt,
navigateToAuthView,
requesTrustIssuerConsent,
);
return credential;
},
updateCredential: async (context: any) => {
const credential = await updateCredentialInformation(
context,
context.credential,
);
return credential;
},
constructProof: async (context: any) => {
const issuerMeta = context.selectedIssuer;
const proofJWT = await constructProofJWT(
context.publicKey,
context.privateKey,
context.accessToken,
issuerMeta,
context.keyType,
true,
context.cNonce,
);
await VciClient.client.sendProofFromJS(proofJWT);
return proofJWT;
},
constructProofForTrustedIssuers: async (context: any) => {
const issuerMeta = context.selectedIssuer;
const proofJWT = await constructProofJWT(
context.publicKey,
context.privateKey,
context.accessToken,
issuerMeta,
context.keyType,
false,
context.cNonce,
);
await VciClient.client.sendProofFromJS(proofJWT);
return proofJWT;
},
getKeyOrderList: async () => {
const {RNSecureKeystoreModule} = NativeModules;
@@ -165,6 +249,7 @@ export const IssuersService = () => {
if (!verificationResult.isVerified) {
throw new Error(verificationResult.verificationErrorCode);
}
return verificationResult;
},
};

View File

@@ -1,118 +1,64 @@
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
'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.';
};
'xstate.init': {type: 'xstate.init'};
};
invokeSrcNameMap: {
isUserSignedAlready: 'done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]';
};
missingImplementations: {
actions:
| 'addVcToInProgressDownloads'
| 'getVcItemResponse'
| 'loadMyVcs'
| 'loadReceivedVcs'
| 'logTamperedVCsremoved'
| 'prependToMyVcsMetadata'
| 'removeDownloadFailedVcsFromStorage'
| 'removeDownloadingFailedVcsFromMyVcs'
| 'removeVcFromInProgressDownlods'
| 'removeVcFromMyVcsMetadata'
| 'resetDownloadCreadentialsFailed'
| 'resetDownloadCredentialsSuccess'
| 'resetDownloadFailedVcs'
| 'resetInProgressVcsDownloaded'
| 'resetTamperedVcs'
| 'resetVerificationErrorMessage'
| 'resetVerificationStatus'
| 'resetWalletBindingSuccess'
| 'sendBackupEvent'
| 'setDownloadCreadentialsFailed'
| 'setDownloadCredentialsSuccess'
| 'setDownloadedVc'
| 'setDownloadingFailedVcs'
| 'setMyVcs'
| 'setReceivedVcs'
| 'setUpdatedVcMetadatas'
| 'setVerificationErrorMessage'
| 'setVerificationStatus'
| 'setWalletBindingSuccess'
| 'updateMyVcsMetadata';
delays: never;
guards: 'isAnyVcTampered' | 'isSignedIn';
services: 'isUserSignedAlready';
};
eventsCausingActions: {
addVcToInProgressDownloads: 'ADD_VC_TO_IN_PROGRESS_DOWNLOADS';
getVcItemResponse: 'GET_VC_ITEM';
loadMyVcs:
| 'REFRESH_MY_VCS'
| 'REFRESH_RECEIVED_VCS'
| 'STORE_RESPONSE'
| 'VERIFY_VC_FAILED'
| 'xstate.init';
loadReceivedVcs: 'REFRESH_RECEIVED_VCS' | 'STORE_RESPONSE';
logTamperedVCsremoved: 'done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]';
prependToMyVcsMetadata: 'VC_ADDED';
removeDownloadFailedVcsFromStorage: 'DELETE_VC';
removeDownloadingFailedVcsFromMyVcs: 'STORE_RESPONSE';
removeVcFromInProgressDownlods:
| 'DOWNLOAD_LIMIT_EXPIRED'
| 'REMOVE_VC_FROM_IN_PROGRESS_DOWNLOADS'
| 'VERIFY_VC_FAILED';
removeVcFromMyVcsMetadata: 'REMOVE_VC_FROM_CONTEXT';
resetDownloadCreadentialsFailed: 'RESET_DOWNLOADING_FAILED';
resetDownloadCredentialsSuccess: 'RESET_DOWNLOADING_SUCCESS';
resetDownloadFailedVcs: 'STORE_RESPONSE';
resetInProgressVcsDownloaded: 'RESET_IN_PROGRESS_VCS_DOWNLOADED';
resetTamperedVcs: 'REMOVE_TAMPERED_VCS';
resetVerificationErrorMessage: 'RESET_VERIFY_ERROR';
resetVerificationStatus: 'RESET_VERIFICATION_STATUS';
resetWalletBindingSuccess: 'RESET_WALLET_BINDING_SUCCESS';
sendBackupEvent: 'done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]';
setDownloadCreadentialsFailed: 'VC_DOWNLOADING_FAILED';
setDownloadCredentialsSuccess: 'VC_DOWNLOADED';
setDownloadedVc: 'VC_DOWNLOADED';
setDownloadingFailedVcs: 'DOWNLOAD_LIMIT_EXPIRED';
setMyVcs: 'STORE_RESPONSE';
setReceivedVcs: 'STORE_RESPONSE';
setUpdatedVcMetadatas: 'VC_METADATA_UPDATED';
setVerificationErrorMessage: 'VERIFY_VC_FAILED';
setVerificationStatus: 'SET_VERIFICATION_STATUS';
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;
}
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
"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." };
"xstate.init": { type: "xstate.init" };
};
invokeSrcNameMap: {
"isUserSignedAlready": "done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]";
};
missingImplementations: {
actions: "addVcToInProgressDownloads" | "getVcItemResponse" | "loadMyVcs" | "loadReceivedVcs" | "logTamperedVCsremoved" | "prependToMyVcsMetadata" | "removeDownloadFailedVcsFromStorage" | "removeDownloadingFailedVcsFromMyVcs" | "removeVcFromInProgressDownlods" | "removeVcFromMyVcsMetadata" | "resetDownloadCreadentialsFailed" | "resetDownloadCredentialsSuccess" | "resetDownloadFailedVcs" | "resetInProgressVcsDownloaded" | "resetTamperedVcs" | "resetVerificationErrorMessage" | "resetVerificationStatus" | "resetWalletBindingSuccess" | "sendBackupEvent" | "setDownloadCreadentialsFailed" | "setDownloadCredentialsSuccess" | "setDownloadedVc" | "setDownloadingFailedVcs" | "setMyVcs" | "setReceivedVcs" | "setUpdatedVcMetadatas" | "setVerificationErrorMessage" | "setVerificationStatus" | "setWalletBindingSuccess" | "updateMyVcsMetadata";
delays: never;
guards: "isAnyVcTampered" | "isSignedIn";
services: "isUserSignedAlready";
};
eventsCausingActions: {
"addVcToInProgressDownloads": "ADD_VC_TO_IN_PROGRESS_DOWNLOADS";
"getVcItemResponse": "GET_VC_ITEM";
"loadMyVcs": "REFRESH_MY_VCS" | "REFRESH_RECEIVED_VCS" | "STORE_RESPONSE" | "VERIFY_VC_FAILED" | "xstate.init";
"loadReceivedVcs": "REFRESH_RECEIVED_VCS" | "STORE_RESPONSE";
"logTamperedVCsremoved": "done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]";
"prependToMyVcsMetadata": "VC_ADDED";
"removeDownloadFailedVcsFromStorage": "DELETE_VC";
"removeDownloadingFailedVcsFromMyVcs": "STORE_RESPONSE";
"removeVcFromInProgressDownlods": "DOWNLOAD_LIMIT_EXPIRED" | "REMOVE_VC_FROM_IN_PROGRESS_DOWNLOADS" | "VERIFY_VC_FAILED";
"removeVcFromMyVcsMetadata": "REMOVE_VC_FROM_CONTEXT";
"resetDownloadCreadentialsFailed": "RESET_DOWNLOADING_FAILED";
"resetDownloadCredentialsSuccess": "RESET_DOWNLOADING_SUCCESS";
"resetDownloadFailedVcs": "STORE_RESPONSE";
"resetInProgressVcsDownloaded": "RESET_IN_PROGRESS_VCS_DOWNLOADED";
"resetTamperedVcs": "REMOVE_TAMPERED_VCS";
"resetVerificationErrorMessage": "RESET_VERIFY_ERROR";
"resetVerificationStatus": "RESET_VERIFICATION_STATUS";
"resetWalletBindingSuccess": "RESET_WALLET_BINDING_SUCCESS";
"sendBackupEvent": "done.invoke.vcMeta.ready.tamperedVCs.triggerAutoBackupForTamperedVcDeletion:invocation[0]";
"setDownloadCreadentialsFailed": "VC_DOWNLOADING_FAILED";
"setDownloadCredentialsSuccess": "VC_DOWNLOADED";
"setDownloadedVc": "VC_DOWNLOADED";
"setDownloadingFailedVcs": "DOWNLOAD_LIMIT_EXPIRED";
"setMyVcs": "STORE_RESPONSE";
"setReceivedVcs": "STORE_RESPONSE";
"setUpdatedVcMetadatas": "VC_METADATA_UPDATED";
"setVerificationErrorMessage": "VERIFY_VC_FAILED";
"setVerificationStatus": "SET_VERIFICATION_STATUS";
"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;
}

View File

@@ -97,6 +97,7 @@ export interface CredentialTypes {
proof_types_supported: Object;
credential_definition: {
type: Object[];
context:string[]
credentialSubject: CredentialSubject;
};
doctype: string;

View File

@@ -1,4 +1,5 @@
// This file was automatically generated. Edits will be overwritten
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;

View File

@@ -0,0 +1,51 @@
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
"": { type: "" };
"done.invoke.auth.authorized:invocation[0]": { type: "done.invoke.auth.authorized:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
"done.invoke.auth.introSlider:invocation[0]": { type: "done.invoke.auth.introSlider:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
"xstate.init": { type: "xstate.init" };
};
invokeSrcNameMap: {
"generatePasscodeSalt": "done.invoke.auth.introSlider:invocation[0]";
"initializeFaceSdkModel": "done.invoke.auth.authorized:invocation[0]";
};
missingImplementations: {
actions: never;
delays: never;
guards: never;
services: never;
};
eventsCausingActions: {
"requestStoredContext": "BIOMETRIC_CANCELLED" | "xstate.init";
"setBiometrics": "SETUP_BIOMETRICS";
"setContext": "STORE_RESPONSE";
"setInitialDownloadDone": "INITIAL_DOWNLOAD_DONE";
"setIsToggleFromSettings": "CHANGE_METHOD";
"setLanguage": "SETUP_BIOMETRICS" | "SETUP_PASSCODE";
"setOnboardingDone": "ONBOARDING_DONE";
"setPasscode": "SETUP_PASSCODE";
"setPasscodeSalt": "done.invoke.auth.introSlider:invocation[0]";
"setTourGuide": "SET_TOUR_GUIDE";
"storeContext": "INITIAL_DOWNLOAD_DONE" | "ONBOARDING_DONE" | "SETUP_BIOMETRICS" | "SETUP_PASSCODE" | "STORE_RESPONSE" | "done.invoke.auth.authorized:invocation[0]" | "done.invoke.auth.introSlider:invocation[0]";
};
eventsCausingDelays: {
};
eventsCausingGuards: {
"hasBiometricSet": "";
"hasData": "STORE_RESPONSE";
"hasLanguageset": "";
"hasPasscodeSet": "";
};
eventsCausingServices: {
"generatePasscodeSalt": "SELECT";
"initializeFaceSdkModel": "LOGIN" | "SETUP_BIOMETRICS" | "SETUP_PASSCODE";
};
matchesStates: "authorized" | "checkingAuth" | "init" | "introSlider" | "languagesetup" | "savingDefaults" | "settingUp" | "unauthorized";
tags: never;
}

View File

@@ -1,378 +1,134 @@
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
'': {type: ''};
'done.invoke.QrLogin': {
type: 'done.invoke.QrLogin';
data: unknown;
__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';
};
'xstate.init': {type: 'xstate.init'};
'xstate.stop': {type: 'xstate.stop'};
};
invokeSrcNameMap: {
checkBluetoothPermission: 'done.invoke.scan.checkBluetoothPermission.checking:invocation[0]';
checkBluetoothState:
| 'done.invoke.scan.checkBluetoothState.checking:invocation[0]'
| 'done.invoke.scan.recheckBluetoothState.checking:invocation[0]';
checkLocationPermission: 'done.invoke.scan.checkingLocationState.checkingPermissionStatus:invocation[0]';
checkLocationStatus: 'done.invoke.scan.checkingLocationState.checkLocationService:invocation[0]';
checkNearByDevicesPermission: 'done.invoke.scan.checkNearbyDevicesPermission.checking:invocation[0]';
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]';
monitorConnection: 'done.invoke.scan:invocation[0]';
requestBluetooth: 'done.invoke.scan.checkBluetoothState.requesting:invocation[0]';
requestNearByDevicesPermission: 'done.invoke.scan.checkNearbyDevicesPermission.requesting:invocation[0]';
requestToEnableLocationPermission: 'done.invoke.scan.checkingLocationState.requestToEnableLocation:invocation[0]';
sendVc: 'done.invoke.scan.reviewing.sendingVc:invocation[0]';
startConnection: 'done.invoke.scan.connecting:invocation[0]';
};
missingImplementations: {
actions:
| 'clearUri'
| 'enableLocation'
| 'getFaceAuthConsent'
| 'loadMetaDataToMemory'
| 'loadVCDataToMemory'
| 'logFailedVerification'
| 'logShared'
| 'openAppPermission'
| 'openBluetoothSettings'
| 'refreshVCs'
| 'registerLoggers'
| 'removeLoggers'
| 'resetFaceCaptureBannerStatus'
| 'resetFlowType'
| 'resetIsQrLoginViaDeepLink'
| 'resetLinkCode'
| 'resetOpenID4VPFlowType'
| 'resetSelectedVc'
| 'resetShowQuickShareSuccessBanner'
| 'sendBLEConnectionErrorEvent'
| 'sendScanData'
| 'sendVCShareFlowCancelEndEvent'
| 'sendVCShareFlowTimeoutEndEvent'
| 'sendVPScanData'
| 'sendVcShareSuccessEvent'
| 'sendVcSharingStartEvent'
| 'setBleError'
| 'setFlowType'
| 'setIsQrLoginViaDeepLink'
| 'setLinkCode'
| 'setLinkCodeFromDeepLink'
| 'setOpenId4VPFlowType'
| 'setOpenId4VPRef'
| 'setQrLoginRef'
| 'setQuickShareData'
| 'setReadyForBluetoothStateCheck'
| 'setReceiverInfo'
| 'setSelectedVc'
| 'setSenderInfo'
| 'setShareLogTypeUnverified'
| 'setShareLogTypeVerified'
| 'setShowFaceAuthConsent'
| 'setShowQuickShareSuccessBanner'
| 'setUri'
| 'storeLoginItem'
| 'storeShowFaceAuthConsent'
| 'storingActivityLog'
| 'updateFaceCaptureBannerStatus'
| 'updateShowFaceAuthConsent';
delays: never;
guards:
| 'isFlowTypeMiniViewShare'
| 'isFlowTypeMiniViewShareWithSelfie'
| 'isFlowTypeSimpleShare'
| 'isIOS'
| 'isMinimumStorageRequiredForAuditEntryReached'
| 'isOnlineSharing'
| 'isOpenIdQr'
| 'isQrLogin'
| 'isQrLoginViaDeepLinking'
| 'isQuickShare'
| 'showFaceAuthConsentScreen'
| 'uptoAndroid11';
services:
| 'checkBluetoothPermission'
| 'checkBluetoothState'
| 'checkLocationPermission'
| 'checkLocationStatus'
| 'checkNearByDevicesPermission'
| 'checkStorageAvailability'
| 'disconnect'
| 'monitorConnection'
| 'requestBluetooth'
| 'requestNearByDevicesPermission'
| 'requestToEnableLocationPermission'
| 'sendVc'
| 'startConnection';
};
eventsCausingActions: {
clearUri: '';
enableLocation: 'ALLOWED' | 'LOCATION_REQUEST';
getFaceAuthConsent:
| 'DISCONNECT'
| 'DISMISS'
| 'xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection';
loadMetaDataToMemory: 'SCAN';
loadVCDataToMemory: 'STORE_RESPONSE';
logFailedVerification: 'FACE_INVALID';
logShared: 'VC_ACCEPTED';
openAppPermission: 'GOTO_SETTINGS' | 'LOCATION_REQUEST';
openBluetoothSettings: 'GOTO_SETTINGS';
refreshVCs: 'STORE_RESPONSE';
registerLoggers: '';
removeLoggers:
| ''
| 'DISCONNECT'
| 'DISMISS'
| 'DISMISS_QUICK_SHARE_BANNER'
| 'QRLOGIN_VIA_DEEP_LINK'
| 'RESET'
| 'SCREEN_BLUR'
| 'xstate.init';
resetFaceCaptureBannerStatus: '' | 'ACCEPT_REQUEST' | 'CLOSE_BANNER';
resetFlowType:
| 'DISCONNECT'
| 'DISMISS'
| 'DISMISS_QUICK_SHARE_BANNER'
| 'GOTO_HISTORY'
| 'QRLOGIN_VIA_DEEP_LINK'
| 'RESET'
| 'SCREEN_BLUR'
| 'xstate.init';
resetIsQrLoginViaDeepLink: 'DISMISS' | 'RESET';
resetLinkCode:
| 'BLE_ERROR'
| 'DISMISS'
| 'DISMISS_QUICK_SHARE_BANNER'
| 'QRLOGIN_VIA_DEEP_LINK'
| 'RESET'
| 'SCREEN_BLUR'
| 'SCREEN_FOCUS'
| 'SELECT_VC'
| 'xstate.stop';
resetOpenID4VPFlowType: 'CANCEL' | 'DISMISS' | 'RETRY' | 'SCREEN_BLUR';
resetSelectedVc:
| 'DISCONNECT'
| 'DISMISS'
| 'DISMISS_QUICK_SHARE_BANNER'
| 'GOTO_HISTORY'
| 'QRLOGIN_VIA_DEEP_LINK'
| 'RESET'
| 'SCREEN_BLUR'
| 'xstate.init';
resetShowQuickShareSuccessBanner: 'DISMISS' | 'DISMISS_QUICK_SHARE_BANNER';
sendBLEConnectionErrorEvent: 'BLE_ERROR';
sendScanData: '' | 'SCAN';
sendVCShareFlowCancelEndEvent: 'CANCEL';
sendVCShareFlowTimeoutEndEvent: 'CANCEL' | 'RETRY';
sendVPScanData: 'SCAN';
sendVcShareSuccessEvent: 'VC_ACCEPTED';
sendVcSharingStartEvent: 'SCAN';
setBleError: 'BLE_ERROR';
setFlowType: 'SELECT_VC';
setIsQrLoginViaDeepLink: 'QRLOGIN_VIA_DEEP_LINK';
setLinkCode: 'SCAN';
setLinkCodeFromDeepLink: 'QRLOGIN_VIA_DEEP_LINK';
setOpenId4VPFlowType: 'SCAN';
setOpenId4VPRef:
| 'CANCEL'
| 'DISCONNECT'
| 'DISMISS'
| 'DISMISS_QUICK_SHARE_BANNER'
| 'QRLOGIN_VIA_DEEP_LINK'
| 'RESET'
| 'RETRY'
| 'SCREEN_BLUR'
| 'SCREEN_FOCUS'
| 'SELECT_VC'
| 'xstate.init';
setQrLoginRef: 'QRLOGIN_VIA_DEEP_LINK' | 'SCAN';
setQuickShareData: 'SCAN';
setReadyForBluetoothStateCheck: 'BLUETOOTH_PERMISSION_ENABLED';
setReceiverInfo: 'CONNECTED';
setSelectedVc: 'SELECT_VC';
setSenderInfo: 'CONNECTED';
setShareLogTypeUnverified: 'ACCEPT_REQUEST' | 'CHECK_FLOW_TYPE';
setShareLogTypeVerified: 'FACE_VALID';
setShowFaceAuthConsent: 'FACE_VERIFICATION_CONSENT';
setShowQuickShareSuccessBanner: 'STORE_RESPONSE';
setUri: 'SCAN';
storeLoginItem: 'done.invoke.QrLogin';
storeShowFaceAuthConsent: 'FACE_VERIFICATION_CONSENT';
storingActivityLog: 'STORE_RESPONSE';
updateFaceCaptureBannerStatus: 'FACE_VALID';
updateShowFaceAuthConsent: 'STORE_RESPONSE';
};
eventsCausingDelays: {
CONNECTION_TIMEOUT: 'SCAN';
DESTROY_TIMEOUT: '' | 'DISMISS' | 'LOCATION_ENABLED' | 'RETRY';
SHARING_TIMEOUT: 'ACCEPT_REQUEST' | 'CHECK_FLOW_TYPE' | 'FACE_VALID';
};
eventsCausingGuards: {
isFlowTypeMiniViewShare: 'CHECK_FLOW_TYPE';
isFlowTypeMiniViewShareWithSelfie: 'CHECK_FLOW_TYPE' | 'DISMISS';
isFlowTypeSimpleShare: 'CANCEL' | 'CHECK_FLOW_TYPE' | 'DISMISS' | 'RETRY';
isIOS: 'BLUETOOTH_STATE_DISABLED' | 'START_PERMISSION_CHECK';
isMinimumStorageRequiredForAuditEntryReached: 'done.invoke.scan.checkStorage:invocation[0]';
isOnlineSharing: 'SCAN';
isOpenIdQr: 'SCAN';
isQrLogin: 'SCAN';
isQrLoginViaDeepLinking: '' | 'STORE_RESPONSE';
isQuickShare: 'SCAN';
showFaceAuthConsentScreen: '' | 'VERIFY_AND_ACCEPT_REQUEST';
uptoAndroid11: '' | 'START_PERMISSION_CHECK';
};
eventsCausingServices: {
OpenId4VP: 'SCAN';
QrLogin: '' | 'SCAN';
checkBluetoothPermission:
| ''
| 'BLUETOOTH_STATE_DISABLED'
| 'NEARBY_ENABLED'
| 'START_PERMISSION_CHECK';
checkBluetoothState: '' | 'APP_ACTIVE';
checkLocationPermission: 'LOCATION_ENABLED';
checkLocationStatus: '' | 'APP_ACTIVE' | 'LOCATION_REQUEST';
checkNearByDevicesPermission: 'APP_ACTIVE' | 'START_PERMISSION_CHECK';
checkStorageAvailability:
| 'CANCEL'
| 'DISMISS'
| 'QRLOGIN_VIA_DEEP_LINK'
| 'RESET'
| 'RETRY'
| 'SCREEN_FOCUS'
| 'SELECT_VC';
disconnect: '' | 'DISMISS' | 'LOCATION_ENABLED' | 'RETRY' | 'SCREEN_BLUR';
monitorConnection:
| 'DISMISS'
| 'QRLOGIN_VIA_DEEP_LINK'
| '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'
| 'checkQrLoginViaDeepLink'
| '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.navigatingToHome'
| 'showQrLogin.storing'
| 'startPermissionCheck'
| 'startVPSharing'
| 'startVPSharing.inProgress'
| 'startVPSharing.showError'
| 'startVPSharing.success'
| 'startVPSharing.timeout'
| {
checkBluetoothPermission?: 'checking' | 'enabled';
checkBluetoothState?: 'checking' | 'enabled' | 'requesting';
checkNearbyDevicesPermission?: 'checking' | 'enabled' | 'requesting';
checkingLocationState?:
| 'LocationPermissionRationale'
| 'checkLocationService'
| 'checkingPermissionStatus'
| 'denied'
| 'disabled'
| 'requestToEnableLocation';
connecting?: 'inProgress' | 'timeout';
loadVCS?: 'idle' | 'navigatingToHome';
recheckBluetoothState?: 'checking' | 'enabled';
reviewing?:
| 'accepted'
| 'cancelling'
| 'checkFaceAuthConsentForMiniView'
| 'disconnect'
| 'faceVerificationConsent'
| 'idle'
| 'invalidIdentity'
| 'navigateToHistory'
| 'rejected'
| 'selectingVc'
| 'sendingVc'
| 'verifyingIdentity'
| {sendingVc?: 'inProgress' | 'sent' | 'timeout'};
showQrLogin?:
| 'idle'
| 'navigatingToHistory'
| 'navigatingToHome'
| 'storing';
startVPSharing?: 'inProgress' | 'showError' | 'success' | 'timeout';
};
tags: never;
}
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
"": { type: "" };
"done.invoke.QrLogin": { type: "done.invoke.QrLogin"; data: unknown; __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" };
"xstate.init": { type: "xstate.init" };
"xstate.stop": { type: "xstate.stop" };
};
invokeSrcNameMap: {
"checkBluetoothPermission": "done.invoke.scan.checkBluetoothPermission.checking:invocation[0]";
"checkBluetoothState": "done.invoke.scan.checkBluetoothState.checking:invocation[0]" | "done.invoke.scan.recheckBluetoothState.checking:invocation[0]";
"checkLocationPermission": "done.invoke.scan.checkingLocationState.checkingPermissionStatus:invocation[0]";
"checkLocationStatus": "done.invoke.scan.checkingLocationState.checkLocationService:invocation[0]";
"checkNearByDevicesPermission": "done.invoke.scan.checkNearbyDevicesPermission.checking:invocation[0]";
"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]";
"monitorConnection": "done.invoke.scan:invocation[0]";
"requestBluetooth": "done.invoke.scan.checkBluetoothState.requesting:invocation[0]";
"requestNearByDevicesPermission": "done.invoke.scan.checkNearbyDevicesPermission.requesting:invocation[0]";
"requestToEnableLocationPermission": "done.invoke.scan.checkingLocationState.requestToEnableLocation:invocation[0]";
"sendVc": "done.invoke.scan.reviewing.sendingVc:invocation[0]";
"startConnection": "done.invoke.scan.connecting:invocation[0]";
};
missingImplementations: {
actions: "clearUri" | "enableLocation" | "getFaceAuthConsent" | "loadMetaDataToMemory" | "loadVCDataToMemory" | "logFailedVerification" | "logShared" | "openAppPermission" | "openBluetoothSettings" | "refreshVCs" | "registerLoggers" | "removeLoggers" | "resetFaceCaptureBannerStatus" | "resetFlowType" | "resetIsQrLoginViaDeepLink" | "resetLinkCode" | "resetOpenID4VPFlowType" | "resetSelectedVc" | "resetShowQuickShareSuccessBanner" | "sendBLEConnectionErrorEvent" | "sendScanData" | "sendVCShareFlowCancelEndEvent" | "sendVCShareFlowTimeoutEndEvent" | "sendVPScanData" | "sendVcShareSuccessEvent" | "sendVcSharingStartEvent" | "setBleError" | "setFlowType" | "setIsQrLoginViaDeepLink" | "setLinkCode" | "setLinkCodeFromDeepLink" | "setOpenId4VPFlowType" | "setOpenId4VPRef" | "setQrLoginRef" | "setQuickShareData" | "setReadyForBluetoothStateCheck" | "setReceiverInfo" | "setSelectedVc" | "setSenderInfo" | "setShareLogTypeUnverified" | "setShareLogTypeVerified" | "setShowFaceAuthConsent" | "setShowQuickShareSuccessBanner" | "setUri" | "storeLoginItem" | "storeShowFaceAuthConsent" | "storingActivityLog" | "updateFaceCaptureBannerStatus" | "updateShowFaceAuthConsent";
delays: never;
guards: "isFlowTypeMiniViewShare" | "isFlowTypeMiniViewShareWithSelfie" | "isFlowTypeSimpleShare" | "isIOS" | "isMinimumStorageRequiredForAuditEntryReached" | "isOnlineSharing" | "isOpenIdQr" | "isQrLogin" | "isQrLoginViaDeepLinking" | "isQuickShare" | "showFaceAuthConsentScreen" | "uptoAndroid11";
services: "checkBluetoothPermission" | "checkBluetoothState" | "checkLocationPermission" | "checkLocationStatus" | "checkNearByDevicesPermission" | "checkStorageAvailability" | "disconnect" | "monitorConnection" | "requestBluetooth" | "requestNearByDevicesPermission" | "requestToEnableLocationPermission" | "sendVc" | "startConnection";
};
eventsCausingActions: {
"clearUri": "";
"enableLocation": "ALLOWED" | "LOCATION_REQUEST";
"getFaceAuthConsent": "DISCONNECT" | "DISMISS" | "xstate.after(DESTROY_TIMEOUT)#scan.clearingConnection";
"loadMetaDataToMemory": "SCAN";
"loadVCDataToMemory": "STORE_RESPONSE";
"logFailedVerification": "FACE_INVALID";
"logShared": "VC_ACCEPTED";
"openAppPermission": "GOTO_SETTINGS" | "LOCATION_REQUEST";
"openBluetoothSettings": "GOTO_SETTINGS";
"refreshVCs": "STORE_RESPONSE";
"registerLoggers": "";
"removeLoggers": "" | "DISCONNECT" | "DISMISS" | "DISMISS_QUICK_SHARE_BANNER" | "QRLOGIN_VIA_DEEP_LINK" | "RESET" | "SCREEN_BLUR" | "xstate.init";
"resetFaceCaptureBannerStatus": "" | "ACCEPT_REQUEST" | "CLOSE_BANNER";
"resetFlowType": "DISCONNECT" | "DISMISS" | "DISMISS_QUICK_SHARE_BANNER" | "GOTO_HISTORY" | "QRLOGIN_VIA_DEEP_LINK" | "RESET" | "SCREEN_BLUR" | "xstate.init";
"resetIsQrLoginViaDeepLink": "DISMISS" | "RESET";
"resetLinkCode": "BLE_ERROR" | "DISMISS" | "DISMISS_QUICK_SHARE_BANNER" | "QRLOGIN_VIA_DEEP_LINK" | "RESET" | "SCREEN_BLUR" | "SCREEN_FOCUS" | "SELECT_VC" | "xstate.stop";
"resetOpenID4VPFlowType": "CANCEL" | "DISMISS" | "RETRY" | "SCREEN_BLUR";
"resetSelectedVc": "DISCONNECT" | "DISMISS" | "DISMISS_QUICK_SHARE_BANNER" | "GOTO_HISTORY" | "QRLOGIN_VIA_DEEP_LINK" | "RESET" | "SCREEN_BLUR" | "xstate.init";
"resetShowQuickShareSuccessBanner": "DISMISS" | "DISMISS_QUICK_SHARE_BANNER";
"sendBLEConnectionErrorEvent": "BLE_ERROR";
"sendScanData": "" | "SCAN";
"sendVCShareFlowCancelEndEvent": "CANCEL";
"sendVCShareFlowTimeoutEndEvent": "CANCEL" | "RETRY";
"sendVPScanData": "SCAN";
"sendVcShareSuccessEvent": "VC_ACCEPTED";
"sendVcSharingStartEvent": "SCAN";
"setBleError": "BLE_ERROR";
"setFlowType": "SELECT_VC";
"setIsQrLoginViaDeepLink": "QRLOGIN_VIA_DEEP_LINK";
"setLinkCode": "SCAN";
"setLinkCodeFromDeepLink": "QRLOGIN_VIA_DEEP_LINK";
"setOpenId4VPFlowType": "SCAN";
"setOpenId4VPRef": "CANCEL" | "DISCONNECT" | "DISMISS" | "DISMISS_QUICK_SHARE_BANNER" | "QRLOGIN_VIA_DEEP_LINK" | "RESET" | "RETRY" | "SCREEN_BLUR" | "SCREEN_FOCUS" | "SELECT_VC" | "xstate.init";
"setQrLoginRef": "QRLOGIN_VIA_DEEP_LINK" | "SCAN";
"setQuickShareData": "SCAN";
"setReadyForBluetoothStateCheck": "BLUETOOTH_PERMISSION_ENABLED";
"setReceiverInfo": "CONNECTED";
"setSelectedVc": "SELECT_VC";
"setSenderInfo": "CONNECTED";
"setShareLogTypeUnverified": "ACCEPT_REQUEST" | "CHECK_FLOW_TYPE";
"setShareLogTypeVerified": "FACE_VALID";
"setShowFaceAuthConsent": "FACE_VERIFICATION_CONSENT";
"setShowQuickShareSuccessBanner": "STORE_RESPONSE";
"setUri": "SCAN";
"storeLoginItem": "done.invoke.QrLogin";
"storeShowFaceAuthConsent": "FACE_VERIFICATION_CONSENT";
"storingActivityLog": "STORE_RESPONSE";
"updateFaceCaptureBannerStatus": "FACE_VALID";
"updateShowFaceAuthConsent": "STORE_RESPONSE";
};
eventsCausingDelays: {
"CONNECTION_TIMEOUT": "SCAN";
"DESTROY_TIMEOUT": "" | "DISMISS" | "LOCATION_ENABLED" | "RETRY";
"SHARING_TIMEOUT": "ACCEPT_REQUEST" | "CHECK_FLOW_TYPE" | "FACE_VALID";
};
eventsCausingGuards: {
"isFlowTypeMiniViewShare": "CHECK_FLOW_TYPE";
"isFlowTypeMiniViewShareWithSelfie": "CHECK_FLOW_TYPE" | "DISMISS";
"isFlowTypeSimpleShare": "CANCEL" | "CHECK_FLOW_TYPE" | "DISMISS" | "RETRY";
"isIOS": "BLUETOOTH_STATE_DISABLED" | "START_PERMISSION_CHECK";
"isMinimumStorageRequiredForAuditEntryReached": "done.invoke.scan.checkStorage:invocation[0]";
"isOnlineSharing": "SCAN";
"isOpenIdQr": "SCAN";
"isQrLogin": "SCAN";
"isQrLoginViaDeepLinking": "" | "STORE_RESPONSE";
"isQuickShare": "SCAN";
"showFaceAuthConsentScreen": "" | "VERIFY_AND_ACCEPT_REQUEST";
"uptoAndroid11": "" | "START_PERMISSION_CHECK";
};
eventsCausingServices: {
"OpenId4VP": "SCAN";
"QrLogin": "" | "SCAN";
"checkBluetoothPermission": "" | "BLUETOOTH_STATE_DISABLED" | "NEARBY_ENABLED" | "START_PERMISSION_CHECK";
"checkBluetoothState": "" | "APP_ACTIVE";
"checkLocationPermission": "LOCATION_ENABLED";
"checkLocationStatus": "" | "APP_ACTIVE" | "LOCATION_REQUEST";
"checkNearByDevicesPermission": "APP_ACTIVE" | "START_PERMISSION_CHECK";
"checkStorageAvailability": "CANCEL" | "DISMISS" | "QRLOGIN_VIA_DEEP_LINK" | "RESET" | "RETRY" | "SCREEN_FOCUS" | "SELECT_VC";
"disconnect": "" | "DISMISS" | "LOCATION_ENABLED" | "RETRY" | "SCREEN_BLUR";
"monitorConnection": "DISMISS" | "QRLOGIN_VIA_DEEP_LINK" | "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" | "checkQrLoginViaDeepLink" | "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.navigatingToHome" | "showQrLogin.storing" | "startPermissionCheck" | "startVPSharing" | "startVPSharing.inProgress" | "startVPSharing.showError" | "startVPSharing.success" | "startVPSharing.timeout" | { "checkBluetoothPermission"?: "checking" | "enabled";
"checkBluetoothState"?: "checking" | "enabled" | "requesting";
"checkNearbyDevicesPermission"?: "checking" | "enabled" | "requesting";
"checkingLocationState"?: "LocationPermissionRationale" | "checkLocationService" | "checkingPermissionStatus" | "denied" | "disabled" | "requestToEnableLocation";
"connecting"?: "inProgress" | "timeout";
"loadVCS"?: "idle" | "navigatingToHome";
"recheckBluetoothState"?: "checking" | "enabled";
"reviewing"?: "accepted" | "cancelling" | "checkFaceAuthConsentForMiniView" | "disconnect" | "faceVerificationConsent" | "idle" | "invalidIdentity" | "navigateToHistory" | "rejected" | "selectingVc" | "sendingVc" | "verifyingIdentity" | { "sendingVc"?: "inProgress" | "sent" | "timeout"; };
"showQrLogin"?: "idle" | "navigatingToHistory" | "navigatingToHome" | "storing";
"startVPSharing"?: "inProgress" | "showError" | "success" | "timeout"; };
tags: never;
}

View File

@@ -1,70 +1,46 @@
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
'done.invoke.faceScanner.capturing:invocation[0]': {
type: 'done.invoke.faceScanner.capturing:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.faceScanner.verifying:invocation[0]': {
type: 'done.invoke.faceScanner.verifying:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'error.platform.faceScanner.capturing:invocation[0]': {
type: 'error.platform.faceScanner.capturing:invocation[0]';
data: unknown;
};
'xstate.init': {type: 'xstate.init'};
};
invokeSrcNameMap: {
captureImage: 'done.invoke.faceScanner.capturing:invocation[0]';
checkPermission: 'done.invoke.faceScanner.init.checkingPermission:invocation[0]';
requestPermission: 'done.invoke.faceScanner.init.requestingPermission:invocation[0]';
verifyImage: 'done.invoke.faceScanner.verifying:invocation[0]';
};
missingImplementations: {
actions: never;
delays: never;
guards: never;
services: never;
};
eventsCausingActions: {
openSettings: 'OPEN_SETTINGS';
setCameraRef: 'READY';
setCaptureError: 'error.platform.faceScanner.capturing:invocation[0]';
setCapturedImage: 'done.invoke.faceScanner.capturing:invocation[0]';
};
eventsCausingDelays: {};
eventsCausingGuards: {
canRequestPermission: 'DENIED';
doesFaceMatch: 'done.invoke.faceScanner.verifying:invocation[0]';
};
eventsCausingServices: {
captureImage: 'CAPTURE';
checkPermission: 'APP_FOCUSED' | 'xstate.init';
requestPermission: 'DENIED';
verifyImage: 'done.invoke.faceScanner.capturing:invocation[0]';
};
matchesStates:
| 'capturing'
| 'init'
| 'init.checkingPermission'
| 'init.permissionDenied'
| 'init.permissionGranted'
| 'init.requestingPermission'
| 'invalid'
| 'scanning'
| 'valid'
| 'verifying'
| {
init?:
| 'checkingPermission'
| 'permissionDenied'
| 'permissionGranted'
| 'requestingPermission';
};
tags: never;
}
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
"done.invoke.faceScanner.capturing:invocation[0]": { type: "done.invoke.faceScanner.capturing:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
"done.invoke.faceScanner.verifying:invocation[0]": { type: "done.invoke.faceScanner.verifying:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
"error.platform.faceScanner.capturing:invocation[0]": { type: "error.platform.faceScanner.capturing:invocation[0]"; data: unknown };
"xstate.init": { type: "xstate.init" };
};
invokeSrcNameMap: {
"captureImage": "done.invoke.faceScanner.capturing:invocation[0]";
"checkPermission": "done.invoke.faceScanner.init.checkingPermission:invocation[0]";
"requestPermission": "done.invoke.faceScanner.init.requestingPermission:invocation[0]";
"verifyImage": "done.invoke.faceScanner.verifying:invocation[0]";
};
missingImplementations: {
actions: never;
delays: never;
guards: never;
services: never;
};
eventsCausingActions: {
"openSettings": "OPEN_SETTINGS";
"setCameraRef": "READY";
"setCaptureError": "error.platform.faceScanner.capturing:invocation[0]";
"setCapturedImage": "done.invoke.faceScanner.capturing:invocation[0]";
};
eventsCausingDelays: {
};
eventsCausingGuards: {
"canRequestPermission": "DENIED";
"doesFaceMatch": "done.invoke.faceScanner.verifying:invocation[0]";
};
eventsCausingServices: {
"captureImage": "CAPTURE";
"checkPermission": "APP_FOCUSED" | "xstate.init";
"requestPermission": "DENIED";
"verifyImage": "done.invoke.faceScanner.capturing:invocation[0]";
};
matchesStates: "capturing" | "init" | "init.checkingPermission" | "init.permissionDenied" | "init.permissionGranted" | "init.requestingPermission" | "invalid" | "scanning" | "valid" | "verifying" | { "init"?: "checkingPermission" | "permissionDenied" | "permissionGranted" | "requestingPermission"; };
tags: never;
}

View File

@@ -1,41 +1,83 @@
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
'': {type: ''};
'xstate.after(INITIAL_FOCUS_DELAY)#pinInput.idle': {
type: 'xstate.after(INITIAL_FOCUS_DELAY)#pinInput.idle';
};
'xstate.init': {type: 'xstate.init'};
};
invokeSrcNameMap: {};
missingImplementations: {
actions: never;
delays: never;
guards: never;
services: never;
};
eventsCausingActions: {
clearInput: 'KEY_PRESS';
focusSelected:
| 'KEY_PRESS'
| 'UPDATE_INPUT'
| 'xstate.after(INITIAL_FOCUS_DELAY)#pinInput.idle';
selectInput: 'FOCUS_INPUT';
selectNextInput: 'UPDATE_INPUT';
selectPrevInput: 'KEY_PRESS';
updateInput: 'UPDATE_INPUT';
};
eventsCausingDelays: {
INITIAL_FOCUS_DELAY: '' | 'xstate.init';
};
eventsCausingGuards: {
canGoBack: 'KEY_PRESS';
hasNextInput: 'UPDATE_INPUT';
isBlank: 'UPDATE_INPUT';
};
eventsCausingServices: {};
matchesStates: 'idle' | 'selectingNext' | 'selectingPrev';
tags: never;
}
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
"": { type: "" };
"xstate.after(INITIAL_FOCUS_DELAY)#pinInput.idle": { type: "xstate.after(INITIAL_FOCUS_DELAY)#pinInput.idle" };
"xstate.init": { type: "xstate.init" };
};
invokeSrcNameMap: {
};
missingImplementations: {
actions: never;
delays: never;
guards: never;
services: never;
};
eventsCausingActions: {
"clearInput": "KEY_PRESS";
"focusSelected": "KEY_PRESS" | "UPDATE_INPUT" | "xstate.after(INITIAL_FOCUS_DELAY)#pinInput.idle";
"selectInput": "FOCUS_INPUT";
"selectNextInput": "UPDATE_INPUT";
"selectPrevInput": "KEY_PRESS";
"updateInput": "UPDATE_INPUT";
};
eventsCausingDelays: {
"INITIAL_FOCUS_DELAY": "" | "xstate.init";
};
eventsCausingGuards: {
"canGoBack": "KEY_PRESS";
"hasNextInput": "UPDATE_INPUT";
"isBlank": "UPDATE_INPUT";
};
eventsCausingServices: {
};
matchesStates: "idle" | "selectingNext" | "selectingPrev";
tags: never;
}
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
"": { type: "" };
"xstate.after(INITIAL_FOCUS_DELAY)#pinInput.idle": { type: "xstate.after(INITIAL_FOCUS_DELAY)#pinInput.idle" };
"xstate.init": { type: "xstate.init" };
};
invokeSrcNameMap: {
};
missingImplementations: {
actions: never;
delays: never;
guards: never;
services: never;
};
eventsCausingActions: {
"clearInput": "KEY_PRESS";
"focusSelected": "KEY_PRESS" | "UPDATE_INPUT" | "xstate.after(INITIAL_FOCUS_DELAY)#pinInput.idle";
"selectInput": "FOCUS_INPUT";
"selectNextInput": "UPDATE_INPUT";
"selectPrevInput": "KEY_PRESS";
"updateInput": "UPDATE_INPUT";
};
eventsCausingDelays: {
"INITIAL_FOCUS_DELAY": "" | "xstate.init";
};
eventsCausingGuards: {
"canGoBack": "KEY_PRESS";
"hasNextInput": "UPDATE_INPUT";
"isBlank": "UPDATE_INPUT";
};
eventsCausingServices: {
};
matchesStates: "idle" | "selectingNext" | "selectingPrev";
tags: never;
}

View File

@@ -46,6 +46,59 @@
"generateEncryptionKey": "ERROR" | "IGNORE" | "READY";
"getEncryptionKey": "TRY_AGAIN";
"hasEncryptionKey": never;
"store": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]";
};
matchesStates: "checkEncryptionKey" | "checkFreshInstall" | "checkStorageInitialisation" | "clearIosKeys" | "failedReadingKey" | "generatingEncryptionKey" | "gettingEncryptionKey" | "ready" | "resettingStorage";
tags: never;
}
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
"done.invoke._store": { type: "done.invoke._store"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
"done.invoke.store.checkFreshInstall:invocation[0]": { type: "done.invoke.store.checkFreshInstall:invocation[0]"; data: unknown; __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 };
"xstate.init": { type: "xstate.init" };
};
invokeSrcNameMap: {
"checkFreshInstall": "done.invoke.store.checkFreshInstall:invocation[0]";
"checkStorageInitialisedOrNot": "done.invoke.store.checkStorageInitialisation:invocation[0]";
"clear": "done.invoke.store.resettingStorage:invocation[0]";
"clearKeys": "done.invoke.store.clearIosKeys:invocation[0]";
"generateEncryptionKey": "done.invoke.store.generatingEncryptionKey:invocation[0]";
"getEncryptionKey": "done.invoke.store.gettingEncryptionKey:invocation[0]";
"hasEncryptionKey": "done.invoke.store.checkEncryptionKey:invocation[0]";
"store": "done.invoke._store";
};
missingImplementations: {
actions: never;
delays: never;
guards: never;
services: never;
};
eventsCausingActions: {
"forwardStoreRequest": "APPEND" | "CLEAR" | "EXPORT" | "FETCH_ALL_WELLKNOWN_CONFIG" | "GET" | "GET_VCS_DATA" | "PREPEND" | "REMOVE" | "REMOVE_ITEMS" | "REMOVE_VC_METADATA" | "RESTORE_BACKUP" | "SET" | "UPDATE";
"notifyParent": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]";
"setEncryptionKey": "KEY_RECEIVED";
};
eventsCausingDelays: {
};
eventsCausingGuards: {
"hasData": "done.invoke.store.checkFreshInstall:invocation[0]";
"isCustomSecureKeystore": "KEY_RECEIVED";
};
eventsCausingServices: {
"checkFreshInstall": "BIOMETRIC_CANCELLED" | "xstate.init";
"checkStorageInitialisedOrNot": "ERROR";
"clear": "KEY_RECEIVED";
"clearKeys": "done.invoke.store.checkFreshInstall:invocation[0]";
"generateEncryptionKey": "ERROR" | "IGNORE" | "READY";
"getEncryptionKey": "TRY_AGAIN";
"hasEncryptionKey": never;
"store": "KEY_RECEIVED" | "READY" | "done.invoke.store.resettingStorage:invocation[0]";
};
matchesStates: "checkEncryptionKey" | "checkFreshInstall" | "checkStorageInitialisation" | "clearIosKeys" | "failedReadingKey" | "generatingEncryptionKey" | "gettingEncryptionKey" | "ready" | "resettingStorage";

74
package-lock.json generated
View File

@@ -94,7 +94,8 @@
"react-native-shimmer-placeholder": "^2.0.9",
"react-native-spinkit": "^1.5.1",
"react-native-svg": "15.2.0",
"react-native-vector-icons": "^10.1.0",
"react-native-vector-icons": "^10.0.0",
"react-native-webview": "^13.13.5",
"react-native-zip-archive": "^6.1.0",
"react-test-renderer": "^18.2.0",
"short-unique-id": "^4.4.4",
@@ -13355,7 +13356,8 @@
"node_modules/dijkstrajs": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
"license": "MIT"
},
"node_modules/dir-glob": {
"version": "3.0.1",
@@ -13583,11 +13585,6 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/encode-utf8": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz",
"integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="
},
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
@@ -24695,12 +24692,12 @@
}
},
"node_modules/qrcode": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz",
"integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==",
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
"integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
"license": "MIT",
"dependencies": {
"dijkstrajs": "^1.0.1",
"encode-utf8": "^1.0.3",
"pngjs": "^5.0.0",
"yargs": "^15.3.1"
},
@@ -24723,6 +24720,7 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
"integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
"license": "MIT",
"engines": {
"node": ">=10.13.0"
}
@@ -25388,19 +25386,19 @@
}
},
"node_modules/react-native-qrcode-svg": {
"version": "6.3.12",
"resolved": "https://registry.npmjs.org/react-native-qrcode-svg/-/react-native-qrcode-svg-6.3.12.tgz",
"integrity": "sha512-7Bx23ZdFNJJdVXyW9BJmFWdI5kccjnpotzmL3exkV0irUKTmj51jesxpn5sqtgVdYFE4IUVoGzdS+8qg6Ua9BA==",
"version": "6.3.15",
"resolved": "https://registry.npmjs.org/react-native-qrcode-svg/-/react-native-qrcode-svg-6.3.15.tgz",
"integrity": "sha512-vLuNImGfstE8u+rlF4JfFpq65nPhmByuDG6XUPWh8yp8MgLQX11rN5eQ8nb/bf4OB+V8XoLTJB/AZF2g7jQSSQ==",
"license": "MIT",
"dependencies": {
"prop-types": "^15.8.0",
"qrcode": "^1.5.1",
"qrcode": "^1.5.4",
"text-encoding": "^0.7.0"
},
"peerDependencies": {
"react": "*",
"react-native": ">=0.63.4",
"react-native-svg": ">=13.2.0"
"react-native-svg": ">=14.0.0"
}
},
"node_modules/react-native-ratings": {
@@ -25500,6 +25498,7 @@
"version": "15.2.0",
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.2.0.tgz",
"integrity": "sha512-R0E6IhcJfVLsL0lRmnUSm72QO+mTqcAOM5Jb8FVGxJqX3NfJMlMP0YyvcajZiaRR8CqQUpEoqrY25eyZb006kw==",
"license": "MIT",
"dependencies": {
"css-select": "^5.1.0",
"css-tree": "^1.1.3"
@@ -25596,6 +25595,20 @@
"node": ">=10"
}
},
"node_modules/react-native-webview": {
"version": "13.13.5",
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.13.5.tgz",
"integrity": "sha512-MfC2B+woL4Hlj2WCzcb1USySKk+SteXnUKmKktOk/H/AQy5+LuVdkPKm8SknJ0/RxaxhZ48WBoTRGaqgR137hw==",
"license": "MIT",
"dependencies": {
"escape-string-regexp": "^4.0.0",
"invariant": "2.2.4"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-zip-archive": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/react-native-zip-archive/-/react-native-zip-archive-6.1.0.tgz",
@@ -40537,11 +40550,6 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"encode-utf8": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz",
"integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
@@ -48579,12 +48587,11 @@
"integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg=="
},
"qrcode": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz",
"integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==",
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
"integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
"requires": {
"dijkstrajs": "^1.0.1",
"encode-utf8": "^1.0.3",
"pngjs": "^5.0.0",
"yargs": "^15.3.1"
},
@@ -49235,12 +49242,12 @@
"requires": {}
},
"react-native-qrcode-svg": {
"version": "6.3.12",
"resolved": "https://registry.npmjs.org/react-native-qrcode-svg/-/react-native-qrcode-svg-6.3.12.tgz",
"integrity": "sha512-7Bx23ZdFNJJdVXyW9BJmFWdI5kccjnpotzmL3exkV0irUKTmj51jesxpn5sqtgVdYFE4IUVoGzdS+8qg6Ua9BA==",
"version": "6.3.15",
"resolved": "https://registry.npmjs.org/react-native-qrcode-svg/-/react-native-qrcode-svg-6.3.15.tgz",
"integrity": "sha512-vLuNImGfstE8u+rlF4JfFpq65nPhmByuDG6XUPWh8yp8MgLQX11rN5eQ8nb/bf4OB+V8XoLTJB/AZF2g7jQSSQ==",
"requires": {
"prop-types": "^15.8.0",
"qrcode": "^1.5.1",
"qrcode": "^1.5.4",
"text-encoding": "^0.7.0"
}
},
@@ -49387,6 +49394,15 @@
}
}
},
"react-native-webview": {
"version": "13.13.5",
"resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.13.5.tgz",
"integrity": "sha512-MfC2B+woL4Hlj2WCzcb1USySKk+SteXnUKmKktOk/H/AQy5+LuVdkPKm8SknJ0/RxaxhZ48WBoTRGaqgR137hw==",
"requires": {
"escape-string-regexp": "^4.0.0",
"invariant": "2.2.4"
}
},
"react-native-zip-archive": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/react-native-zip-archive/-/react-native-zip-archive-6.1.0.tgz",

View File

@@ -99,7 +99,8 @@
"react-native-shimmer-placeholder": "^2.0.9",
"react-native-spinkit": "^1.5.1",
"react-native-svg": "15.2.0",
"react-native-vector-icons": "^10.1.0",
"react-native-vector-icons": "^10.0.0",
"react-native-webview": "^13.13.5",
"react-native-zip-archive": "^6.1.0",
"react-test-renderer": "^18.2.0",
"short-unique-id": "^4.4.4",

View File

@@ -15,6 +15,7 @@ import {RequestLayout} from '../screens/Request/RequestLayout';
import {SplashScreen} from '../screens/SplashScreen';
import {RequestStackParamList} from './routesConstants';
import {KeyManagementScreen} from '../screens/Settings/KeyManagementScreen';
import AuthWebViewScreen from '../screens/AuthWebViewScreen';
export const baseRoutes: Screen[] = [
{
@@ -28,6 +29,10 @@ export const baseRoutes: Screen[] = [
name: 'KeyManagement',
component: KeyManagementScreen,
},
{
name:'AuthView',
component:AuthWebViewScreen
},
{
name: 'Language',
component: SetupLanguageScreen,

View File

@@ -1,3 +1,4 @@
import {t} from 'xstate';
import {MainBottomTabParamList} from './routeTypes';
export const BOTTOM_TAB_ROUTES = {
@@ -23,6 +24,10 @@ export const SETTINGS_ROUTES = {
KeyManagement: 'KeyManagement' as keyof SettingsStackParamList,
};
export const AUTH_ROUTES = {
AuthView: 'AuthView' as keyof AuthStackParamList,
};
export type ScanStackParamList = {
ScanScreen: undefined;
SendVcScreen: undefined;
@@ -38,3 +43,9 @@ export type RequestStackParamList = {
export type SettingsStackParamList = {
Keymanagement: undefined;
};
export type AuthStackParamList = {
authorizationEndpoint: string;
clientId: string;
redirectUri: string;
};

View File

@@ -0,0 +1,133 @@
import React, { useEffect, useRef, useState, useCallback } from 'react';
import psl from 'psl';
import {
View,
ActivityIndicator,
Alert,
TouchableOpacity,
Text, BackHandler
} from 'react-native';
import { WebView } from 'react-native-webview';
import { Ionicons } from '@expo/vector-icons';
import { VciClient } from '../shared/vciClient/VciClient';
import { Theme } from '../components/ui/styleUtils';
import { useTranslation } from 'react-i18next';
const AuthWebViewScreen: React.FC<any> = ({ route, navigation }) => {
const { authorizationURL, clientId, redirectUri, controller } = route.params;
const webViewRef = useRef<WebView>(null);
const [showWebView, setShowWebView] = useState(false);
const { t } = useTranslation('authWebView');
const hostName = new URL(authorizationURL).hostname; // example.mosip.net
const parsed = psl.parse(hostName);
const rootDomain = parsed.domain || hostName;
const ALERT_TITLE = t('title', {
wallet: "Inji Wallet",
domain: rootDomain || 'mosip.net'
});
const ALERT_MESSAGE = t('message');
const handleBackPress = useCallback(() => {
return true;
}, []);
useEffect(() => {
if (!authorizationURL || !clientId || !redirectUri) {
console.error('Missing required parameters for authentication');
navigation.goBack();
return;
}
navigation.setOptions({ gestureEnabled: false });
const backHandler = BackHandler.addEventListener('hardwareBackPress', handleBackPress);
Alert.alert(ALERT_TITLE, ALERT_MESSAGE, [
{
text: t('cancel'),
style: 'cancel',
onPress: () => {
controller.CANCEL();
navigation.goBack();
},
},
{
text: t('continue'),
style: 'default',
onPress: () => setShowWebView(true),
},
]);
return () => backHandler.remove();
}, [authorizationURL, clientId, redirectUri, navigation, controller, handleBackPress]);
const handleNavigationRequest = (request: any) => {
const { url } = request;
if (url.startsWith(redirectUri)) {
try {
const uri = new URL(url);
const code = uri.searchParams.get('code');
if (!code) {
controller.CANCEL();
navigation.goBack();
return false;
}
VciClient.client.sendAuthCodeFromJS(code);
navigation.goBack();
return false;
} catch (err: any) {
console.error('Error parsing redirect URL:', err);
controller.CANCEL();
navigation.goBack();
return false;
}
}
return true;
};
const Header = () => (
<View style={Theme.AuthWebViewScreenStyle.header}>
<TouchableOpacity onPress={() => {
controller.CANCEL();
navigation.goBack();
}}>
<Ionicons name="arrow-back" size={24} color="black" />
</TouchableOpacity>
<Text style={Theme.AuthWebViewScreenStyle.headerText}>Authenticate</Text>
<View style={{ width: 24 }} />
</View>
);
return (
<View style={{ flex: 1 }}>
<Header />
{showWebView && (
<WebView
ref={webViewRef}
originWhitelist={['*']}
source={{ uri: authorizationURL }}
onShouldStartLoadWithRequest={handleNavigationRequest}
startInLoadingState
renderLoading={() => (
<View style={Theme.AuthWebViewScreenStyle.loader}>
<ActivityIndicator size="large" />
</View>
)}
javaScriptEnabled
incognito
sharedCookiesEnabled={false}
thirdPartyCookiesEnabled={false}
/>
)}
</View>
);
};
export default AuthWebViewScreen;

View File

@@ -1,136 +1,62 @@
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]': {
type: 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]': {
type: 'done.invoke.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.AddVcModal.requestingCredential:invocation[0]': {
type: 'done.invoke.AddVcModal.requestingCredential:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]': {
type: 'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]';
data: unknown;
};
'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]': {
type: 'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]';
data: unknown;
};
'error.platform.AddVcModal.requestingCredential:invocation[0]': {
type: 'error.platform.AddVcModal.requestingCredential:invocation[0]';
data: unknown;
};
'xstate.after(100)#AddVcModal.acceptingIdInput.focusing': {
type: 'xstate.after(100)#AddVcModal.acceptingIdInput.focusing';
};
'xstate.init': {type: 'xstate.init'};
};
invokeSrcNameMap: {
requestCredential: 'done.invoke.AddVcModal.requestingCredential:invocation[0]';
requestOtp:
| 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'done.invoke.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]';
};
missingImplementations: {
actions: never;
delays: never;
guards: never;
services: never;
};
eventsCausingActions: {
clearDisplayId: 'CANCEL' | 'SELECT_ID_TYPE' | 'SET_INDIVIDUAL_ID';
clearIdError:
| 'INPUT_ID'
| 'SELECT_ID_TYPE'
| 'SET_INDIVIDUAL_ID'
| 'VALIDATE_INPUT';
clearOtp:
| 'SET_INDIVIDUAL_ID'
| 'WAIT'
| 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]'
| 'xstate.init';
focusInput:
| 'INPUT_ID'
| 'SELECT_ID_TYPE'
| 'SET_INDIVIDUAL_ID'
| 'VALIDATE_INPUT'
| 'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]'
| 'xstate.after(100)#AddVcModal.acceptingIdInput.focusing';
forwardToParent: 'CANCEL' | 'DISMISS';
resetIdInputRef: 'CANCEL';
setDisplayId: 'INPUT_ID' | 'SET_INDIVIDUAL_ID';
setEmail:
| 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'done.invoke.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]';
setIdBackendError:
| 'error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]';
setIdErrorEmpty: 'VALIDATE_INPUT';
setIdErrorWrongFormat: 'VALIDATE_INPUT';
setIdInputRef: 'READY';
setIdType: 'SELECT_ID_TYPE' | 'SET_INDIVIDUAL_ID';
setOtp: 'INPUT_OTP';
setOtpError: 'error.platform.AddVcModal.requestingCredential:invocation[0]';
setPhoneNumber:
| 'done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'done.invoke.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]';
setRequestId: 'done.invoke.AddVcModal.requestingCredential:invocation[0]';
setTransactionId:
| 'SET_INDIVIDUAL_ID'
| 'error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.AddVcModal.requestingCredential:invocation[0]'
| 'xstate.init';
};
eventsCausingDelays: {};
eventsCausingGuards: {
isEmptyId: 'VALIDATE_INPUT';
isIdInvalid: 'error.platform.AddVcModal.requestingCredential:invocation[0]';
isWrongIdFormat: 'VALIDATE_INPUT';
};
eventsCausingServices: {
requestCredential: 'INPUT_OTP';
requestOtp: 'RESEND_OTP' | 'VALIDATE_INPUT';
};
matchesStates:
| 'acceptingIdInput'
| 'acceptingIdInput.focusing'
| 'acceptingIdInput.idle'
| 'acceptingIdInput.invalid'
| 'acceptingIdInput.invalid.backend'
| 'acceptingIdInput.invalid.empty'
| 'acceptingIdInput.invalid.format'
| 'acceptingIdInput.rendering'
| 'acceptingIdInput.requestingOtp'
| 'acceptingOtpInput'
| 'acceptingOtpInput.idle'
| 'acceptingOtpInput.resendOTP'
| 'cancelDownload'
| 'done'
| 'requestingCredential'
| {
acceptingIdInput?:
| 'focusing'
| 'idle'
| 'invalid'
| 'rendering'
| 'requestingOtp'
| {invalid?: 'backend' | 'empty' | 'format'};
acceptingOtpInput?: 'idle' | 'resendOTP';
};
tags: never;
}
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
"done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]": { type: "done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
"done.invoke.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]": { type: "done.invoke.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
"done.invoke.AddVcModal.requestingCredential:invocation[0]": { type: "done.invoke.AddVcModal.requestingCredential:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
"error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]": { type: "error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]"; data: unknown };
"error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]": { type: "error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]"; data: unknown };
"error.platform.AddVcModal.requestingCredential:invocation[0]": { type: "error.platform.AddVcModal.requestingCredential:invocation[0]"; data: unknown };
"xstate.after(100)#AddVcModal.acceptingIdInput.focusing": { type: "xstate.after(100)#AddVcModal.acceptingIdInput.focusing" };
"xstate.init": { type: "xstate.init" };
};
invokeSrcNameMap: {
"requestCredential": "done.invoke.AddVcModal.requestingCredential:invocation[0]";
"requestOtp": "done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "done.invoke.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]";
};
missingImplementations: {
actions: never;
delays: never;
guards: never;
services: never;
};
eventsCausingActions: {
"clearDisplayId": "CANCEL" | "SELECT_ID_TYPE" | "SET_INDIVIDUAL_ID";
"clearIdError": "INPUT_ID" | "SELECT_ID_TYPE" | "SET_INDIVIDUAL_ID" | "VALIDATE_INPUT";
"clearOtp": "SET_INDIVIDUAL_ID" | "WAIT" | "done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]" | "error.platform.AddVcModal.requestingCredential:invocation[0]" | "xstate.init";
"focusInput": "INPUT_ID" | "SELECT_ID_TYPE" | "SET_INDIVIDUAL_ID" | "VALIDATE_INPUT" | "error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]" | "error.platform.AddVcModal.requestingCredential:invocation[0]" | "xstate.after(100)#AddVcModal.acceptingIdInput.focusing";
"forwardToParent": "CANCEL" | "DISMISS";
"resetIdInputRef": "CANCEL";
"setDisplayId": "INPUT_ID" | "SET_INDIVIDUAL_ID";
"setEmail": "done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "done.invoke.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]";
"setIdBackendError": "error.platform.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]" | "error.platform.AddVcModal.requestingCredential:invocation[0]";
"setIdErrorEmpty": "VALIDATE_INPUT";
"setIdErrorWrongFormat": "VALIDATE_INPUT";
"setIdInputRef": "READY";
"setIdType": "SELECT_ID_TYPE" | "SET_INDIVIDUAL_ID";
"setOtp": "INPUT_OTP";
"setOtpError": "error.platform.AddVcModal.requestingCredential:invocation[0]";
"setPhoneNumber": "done.invoke.AddVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "done.invoke.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]";
"setRequestId": "done.invoke.AddVcModal.requestingCredential:invocation[0]";
"setTransactionId": "SET_INDIVIDUAL_ID" | "error.platform.AddVcModal.acceptingOtpInput.resendOTP:invocation[0]" | "error.platform.AddVcModal.requestingCredential:invocation[0]" | "xstate.init";
};
eventsCausingDelays: {
};
eventsCausingGuards: {
"isEmptyId": "VALIDATE_INPUT";
"isIdInvalid": "error.platform.AddVcModal.requestingCredential:invocation[0]";
"isWrongIdFormat": "VALIDATE_INPUT";
};
eventsCausingServices: {
"requestCredential": "INPUT_OTP";
"requestOtp": "RESEND_OTP" | "VALIDATE_INPUT";
};
matchesStates: "acceptingIdInput" | "acceptingIdInput.focusing" | "acceptingIdInput.idle" | "acceptingIdInput.invalid" | "acceptingIdInput.invalid.backend" | "acceptingIdInput.invalid.empty" | "acceptingIdInput.invalid.format" | "acceptingIdInput.rendering" | "acceptingIdInput.requestingOtp" | "acceptingOtpInput" | "acceptingOtpInput.idle" | "acceptingOtpInput.resendOTP" | "cancelDownload" | "done" | "requestingCredential" | { "acceptingIdInput"?: "focusing" | "idle" | "invalid" | "rendering" | "requestingOtp" | { "invalid"?: "backend" | "empty" | "format"; };
"acceptingOtpInput"?: "idle" | "resendOTP"; };
tags: never;
}

View File

@@ -1,131 +1,63 @@
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
'done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]': {
type: 'done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]': {
type: 'done.invoke.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'done.invoke.GetVcModal.requestingUinVid:invocation[0]': {
type: 'done.invoke.GetVcModal.requestingUinVid:invocation[0]';
data: unknown;
__tip: 'See the XState TS docs to learn how to strongly type this.';
};
'error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]': {
type: 'error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]';
data: unknown;
};
'error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]': {
type: 'error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]';
data: unknown;
};
'error.platform.GetVcModal.requestingUinVid:invocation[0]': {
type: 'error.platform.GetVcModal.requestingUinVid:invocation[0]';
data: unknown;
};
'xstate.after(100)#GetVcModal.acceptingIdInput.focusing': {
type: 'xstate.after(100)#GetVcModal.acceptingIdInput.focusing';
};
'xstate.init': {type: 'xstate.init'};
};
invokeSrcNameMap: {
requestOtp:
| 'done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'done.invoke.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]';
requestingUinVid: 'done.invoke.GetVcModal.requestingUinVid:invocation[0]';
};
missingImplementations: {
actions: never;
delays: never;
guards: never;
services: never;
};
eventsCausingActions: {
clearIdError: 'INPUT_ID';
clearOtp:
| 'DISMISS'
| 'done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.GetVcModal.requestingUinVid:invocation[0]'
| 'xstate.init';
focusInput:
| 'INPUT_ID'
| 'VALIDATE_INPUT'
| 'error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.GetVcModal.requestingUinVid:invocation[0]'
| 'xstate.after(100)#GetVcModal.acceptingIdInput.focusing';
forwardToParent: 'DISMISS';
resetIdInputRef: 'DISMISS';
setEmail:
| 'done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'done.invoke.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]';
setIconColorActivate: 'ACTIVATE_ICON_COLOR';
setIconColorDeactivate: 'DEACTIVATE_ICON_COLOR';
setId: 'INPUT_ID';
setIdBackendError:
| 'error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.GetVcModal.requestingUinVid:invocation[0]';
setIdErrorEmpty: 'VALIDATE_INPUT';
setIdErrorWrongFormat: 'VALIDATE_INPUT';
setIdInputRef: 'READY';
setIndividualId: 'done.invoke.GetVcModal.requestingUinVid:invocation[0]';
setOtp: 'INPUT_OTP';
setOtpError: 'error.platform.GetVcModal.requestingUinVid:invocation[0]';
setPhoneNumber:
| 'done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]'
| 'done.invoke.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]';
setTransactionId:
| 'DISMISS'
| 'error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]'
| 'error.platform.GetVcModal.requestingUinVid:invocation[0]'
| 'xstate.init';
};
eventsCausingDelays: {};
eventsCausingGuards: {
isEmptyId: 'VALIDATE_INPUT';
isIdInvalid: 'error.platform.GetVcModal.requestingUinVid:invocation[0]';
isWrongIdFormat: 'VALIDATE_INPUT';
};
eventsCausingServices: {
AddVcModal:
| 'INPUT_ID'
| 'xstate.after(100)#GetVcModal.acceptingIdInput.focusing';
requestOtp: 'RESEND_OTP' | 'VALIDATE_INPUT';
requestingUinVid: 'INPUT_OTP';
};
matchesStates:
| 'acceptingIdInput'
| 'acceptingIdInput.focusing'
| 'acceptingIdInput.idle'
| 'acceptingIdInput.invalid'
| 'acceptingIdInput.invalid.backend'
| 'acceptingIdInput.invalid.empty'
| 'acceptingIdInput.invalid.format'
| 'acceptingIdInput.rendering'
| 'acceptingIdInput.requestingOtp'
| 'acceptingOtpInput'
| 'acceptingOtpInput.idle'
| 'acceptingOtpInput.resendOTP'
| 'done'
| 'requestingUinVid'
| {
acceptingIdInput?:
| 'focusing'
| 'idle'
| 'invalid'
| 'rendering'
| 'requestingOtp'
| {invalid?: 'backend' | 'empty' | 'format'};
acceptingOtpInput?: 'idle' | 'resendOTP';
};
tags: never;
}
// This file was automatically generated. Edits will be overwritten
export interface Typegen0 {
'@@xstate/typegen': true;
internalEvents: {
"done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]": { type: "done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
"done.invoke.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]": { type: "done.invoke.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
"done.invoke.GetVcModal.requestingUinVid:invocation[0]": { type: "done.invoke.GetVcModal.requestingUinVid:invocation[0]"; data: unknown; __tip: "See the XState TS docs to learn how to strongly type this." };
"error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]": { type: "error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]"; data: unknown };
"error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]": { type: "error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]"; data: unknown };
"error.platform.GetVcModal.requestingUinVid:invocation[0]": { type: "error.platform.GetVcModal.requestingUinVid:invocation[0]"; data: unknown };
"xstate.after(100)#GetVcModal.acceptingIdInput.focusing": { type: "xstate.after(100)#GetVcModal.acceptingIdInput.focusing" };
"xstate.init": { type: "xstate.init" };
};
invokeSrcNameMap: {
"requestOtp": "done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "done.invoke.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]";
"requestingUinVid": "done.invoke.GetVcModal.requestingUinVid:invocation[0]";
};
missingImplementations: {
actions: never;
delays: never;
guards: never;
services: never;
};
eventsCausingActions: {
"clearIdError": "INPUT_ID";
"clearOtp": "DISMISS" | "done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]" | "error.platform.GetVcModal.requestingUinVid:invocation[0]" | "xstate.init";
"focusInput": "INPUT_ID" | "VALIDATE_INPUT" | "error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]" | "error.platform.GetVcModal.requestingUinVid:invocation[0]" | "xstate.after(100)#GetVcModal.acceptingIdInput.focusing";
"forwardToParent": "DISMISS";
"resetIdInputRef": "DISMISS";
"setEmail": "done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "done.invoke.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]";
"setIconColorActivate": "ACTIVATE_ICON_COLOR";
"setIconColorDeactivate": "DEACTIVATE_ICON_COLOR";
"setId": "INPUT_ID";
"setIdBackendError": "error.platform.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]" | "error.platform.GetVcModal.requestingUinVid:invocation[0]";
"setIdErrorEmpty": "VALIDATE_INPUT";
"setIdErrorWrongFormat": "VALIDATE_INPUT";
"setIdInputRef": "READY";
"setIndividualId": "done.invoke.GetVcModal.requestingUinVid:invocation[0]";
"setOtp": "INPUT_OTP";
"setOtpError": "error.platform.GetVcModal.requestingUinVid:invocation[0]";
"setPhoneNumber": "done.invoke.GetVcModal.acceptingIdInput.requestingOtp:invocation[0]" | "done.invoke.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]";
"setTransactionId": "DISMISS" | "error.platform.GetVcModal.acceptingOtpInput.resendOTP:invocation[0]" | "error.platform.GetVcModal.requestingUinVid:invocation[0]" | "xstate.init";
};
eventsCausingDelays: {
};
eventsCausingGuards: {
"isEmptyId": "VALIDATE_INPUT";
"isIdInvalid": "error.platform.GetVcModal.requestingUinVid:invocation[0]";
"isWrongIdFormat": "VALIDATE_INPUT";
};
eventsCausingServices: {
"AddVcModal": "INPUT_ID" | "xstate.after(100)#GetVcModal.acceptingIdInput.focusing";
"requestOtp": "RESEND_OTP" | "VALIDATE_INPUT";
"requestingUinVid": "INPUT_OTP";
};
matchesStates: "acceptingIdInput" | "acceptingIdInput.focusing" | "acceptingIdInput.idle" | "acceptingIdInput.invalid" | "acceptingIdInput.invalid.backend" | "acceptingIdInput.invalid.empty" | "acceptingIdInput.invalid.format" | "acceptingIdInput.rendering" | "acceptingIdInput.requestingOtp" | "acceptingOtpInput" | "acceptingOtpInput.idle" | "acceptingOtpInput.resendOTP" | "done" | "requestingUinVid" | { "acceptingIdInput"?: "focusing" | "idle" | "invalid" | "rendering" | "requestingOtp" | { "invalid"?: "backend" | "empty" | "format"; };
"acceptingOtpInput"?: "idle" | "resendOTP"; };
tags: never;
}

View File

@@ -126,6 +126,7 @@ export const OtpVerificationModal: React.FC<
testID="otpVerificationPinInput"
length={6}
onDone={handleEnteredOtp}
autosubmit={true}
/>
<Column crossAlign="center">
<Text

View File

@@ -69,7 +69,7 @@ export const ViewVcModal: React.FC<ViewVcModalProps> = props => {
let [fields, setFields] = useState([]);
const [wellknown, setWellknown] = useState(null);
const [wellknownFieldsFlag, setWellknownFieldsFlag] = useState(false);
const verifiableCredentialData = controller.verifiableCredentialData;
useEffect(() => {
@@ -82,6 +82,7 @@ export const ViewVcModal: React.FC<ViewVcModalProps> = props => {
).then(response => {
setWellknown(response.matchingCredentialIssuerMetadata);
setFields(response.fields);
setWellknownFieldsFlag(response.wellknownFieldsFlag);
});
}, [verifiableCredentialData?.wellKnown]);
@@ -152,6 +153,7 @@ export const ViewVcModal: React.FC<ViewVcModalProps> = props => {
) : (
<VcDetailsContainer
fields={fields}
wellknownFieldsFlag={wellknownFieldsFlag}
wellknown={wellknown}
credential={verifiableCredential}
credentialWrapper={controller.credential}

View File

@@ -0,0 +1,56 @@
import React from 'react';
import { Modal, View, Text, TouchableWithoutFeedback } from 'react-native';
import { Button } from '../../components/ui';
import { Theme } from '../../components/ui/styleUtils';
import { useTranslation } from 'react-i18next';
interface CancelDownloadModalProps {
visible: boolean;
onCancel: () => void;
onConfirm: () => void;
}
export const CancelDownloadModal: React.FC<CancelDownloadModalProps> = ({
visible,
onCancel,
onConfirm,
}) => {
const {t} = useTranslation('cancelDownloadModal');
return (
<Modal visible={visible} transparent={true} onRequestClose={onCancel}>
<TouchableWithoutFeedback onPress={null}>
<View
style={Theme.TransactionCodeScreenStyle.confirmationModalView}>
<TouchableWithoutFeedback>
<View
style={Theme.TransactionCodeScreenStyle.confirmationModalInnerView}>
<Text testID="cancelDownoadModalHeading" style={Theme.TransactionCodeScreenStyle.confirmationModalContentHeading}>
{t('heading')}
</Text>
<Text
testID='cancelDownoadModalSubHeading'
style={Theme.TransactionCodeScreenStyle.confirmationModalContentSubHeading}>
{t('subHeading')}
</Text>
<Button
testID="cancelDownloadModalNoButton"
styles={{ marginTop: 24 }}
type="gradient"
title={t('cancel')}
onPress={onCancel}
/>
<Button
testID='cancelDownloadModalYesButton'
styles={{ marginTop: 12, marginBottom: -20 }}
type="clear"
title={t('confirm')}
onPress={onConfirm}
/>
</View>
</TouchableWithoutFeedback>
</View>
</TouchableWithoutFeedback>
</Modal>
);
};

View File

@@ -16,16 +16,16 @@ export const CredentialTypeSelectionScreen: React.FC<
> = props => {
const controller = useIssuerScreenController(props);
const {t} = useTranslation('IssuersScreen');
const selectedIssuerDisplayObject = getDisplayObjectForCurrentLanguage(
controller.selectedIssuer.display,
);
const selectedIssuerDisplayObject = controller.selectedIssuer.display
? getDisplayObjectForCurrentLanguage(controller.selectedIssuer.display)
: {};
return (
<Modal
testID="credentialTypeSelectionScreen"
isVisible={controller.isSelectingCredentialType}
arrowLeft={true}
headerTitle={selectedIssuerDisplayObject.name}
headerTitle={selectedIssuerDisplayObject?.name}
headerElevation={2}
onDismiss={() => controller.CANCEL()}>
<Column style={Theme.IssuersScreenStyles.issuerListOuterContainer}>

View File

@@ -1,4 +1,4 @@
import {useSelector} from '@xstate/react';
import { useSelector } from '@xstate/react';
import {
selectSupportedCredentialTypes,
selectErrorMessageType,
@@ -14,23 +14,37 @@ import {
selectStoring,
selectVerificationErrorMessage,
selectIsNonGenericError,
selectIsQrScanning,
selectCredentialOfferData,
selectAuthWebViewStatus,
selectAuthEndPoint,
selectIsTxCodeRequested,
selectIsConsentRequested,
selectIssuerLogo,
selectIssuerName,
selectTxCodeDisplayDetails,
} from '../../machines/Issuers/IssuersSelectors';
import {ActorRefFrom} from 'xstate';
import {BOTTOM_TAB_ROUTES} from '../../routes/routesConstants';
import {logState} from '../../shared/commonUtil';
import {isAndroid} from '../../shared/constants';
import { ActorRefFrom } from 'xstate';
import { BOTTOM_TAB_ROUTES } from '../../routes/routesConstants';
import { logState } from '../../shared/commonUtil';
import { isAndroid } from '../../shared/constants';
import {
IssuerScreenTabEvents,
IssuersMachine,
} from '../../machines/Issuers/IssuersMachine';
import {CredentialTypes} from '../../machines/VerifiableCredential/VCMetaMachine/vc';
import { CredentialTypes } from '../../machines/VerifiableCredential/VCMetaMachine/vc';
export function useIssuerScreenController({route, navigation}) {
export function useIssuerScreenController({ route, navigation }) {
const service = route.params.service;
service.subscribe(logState);
return {
issuers: useSelector(service, selectIssuers),
issuerLogo: useSelector(service,selectIssuerLogo),
issuerName: useSelector(service,selectIssuerName),
isTxCodeRequested: useSelector(service,selectIsTxCodeRequested),
txCodeDisplayDetails: useSelector(service,selectTxCodeDisplayDetails),
authEndpount: useSelector(service, selectAuthEndPoint),
selectedIssuer: useSelector(service, selectSelectedIssuer),
errorMessageType: useSelector(service, selectErrorMessageType),
isDownloadingCredentials: useSelector(service, selectIsDownloadCredentials),
@@ -40,10 +54,16 @@ export function useIssuerScreenController({route, navigation}) {
isNonGenericError: useSelector(service, selectIsNonGenericError),
loadingReason: useSelector(service, selectLoadingReason),
isStoring: useSelector(service, selectStoring),
isQrScanning: useSelector(service, selectIsQrScanning),
isAuthEndpointToOpen: useSelector(service, selectAuthWebViewStatus),
isSelectingCredentialType: useSelector(
service,
selectSelectingCredentialType,
),
isConsentRequested: useSelector(
service,selectIsConsentRequested
),
credentialOfferData: useSelector(service, selectCredentialOfferData),
supportedCredentialTypes: useSelector(
service,
selectSupportedCredentialTypes,
@@ -61,22 +81,34 @@ export function useIssuerScreenController({route, navigation}) {
RESET_ERROR: () => service.send(IssuerScreenTabEvents.RESET_ERROR()),
DOWNLOAD_ID: () => {
service.send(IssuerScreenTabEvents.DOWNLOAD_ID());
navigation.navigate(BOTTOM_TAB_ROUTES.home, {screen: 'HomeScreen'});
navigation.navigate(BOTTOM_TAB_ROUTES.home, { screen: 'HomeScreen' });
},
SELECTED_CREDENTIAL_TYPE: (credType: CredentialTypes) =>
service.send(IssuerScreenTabEvents.SELECTED_CREDENTIAL_TYPE(credType)),
RESET_VERIFY_ERROR: () => {
service.send(IssuerScreenTabEvents.RESET_VERIFY_ERROR());
if (isAndroid()) {
navigation.navigate(BOTTOM_TAB_ROUTES.home, {screen: 'HomeScreen'});
navigation.navigate(BOTTOM_TAB_ROUTES.home, { screen: 'HomeScreen' });
} else {
setTimeout(
() =>
navigation.navigate(BOTTOM_TAB_ROUTES.home, {screen: 'HomeScreen'}),
navigation.navigate(BOTTOM_TAB_ROUTES.home, { screen: 'HomeScreen' }),
0,
);
}
},
QR_CODE_SCANNED: (qrData: string) => {
service.send(IssuerScreenTabEvents.QR_CODE_SCANNED(qrData));
},
SCAN_CREDENTIAL_OFFER_QR_CODE: () => {
service.send(IssuerScreenTabEvents.SCAN_CREDENTIAL_OFFER_QR_CODE());
},
TX_CODE_RECEIVED: (txCode: string) => {
service.send(IssuerScreenTabEvents.TX_CODE_RECEIVED(txCode));
},
ON_CONSENT_GIVEN: () => {
service.send(IssuerScreenTabEvents.ON_CONSENT_GIVEN());
}
};
}

View File

@@ -1,16 +1,20 @@
import React, {useLayoutEffect, useState} from 'react';
import {useTranslation} from 'react-i18next';
import {FlatList, Pressable} from 'react-native';
import {Issuer} from '../../components/openId4VCI/Issuer';
import {Error} from '../../components/ui/Error';
import {Header} from '../../components/ui/Header';
import {Button, Column, Row, Text} from '../../components/ui';
import {Theme} from '../../components/ui/styleUtils';
import {RootRouteProps} from '../../routes';
import {HomeRouteProps} from '../../routes/routeTypes';
import {useIssuerScreenController} from './IssuerScreenController';
import {Loader} from '../../components/ui/Loader';
import {isTranslationKeyFound, removeWhiteSpace} from '../../shared/commonUtil';
import React, { useEffect, useLayoutEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { FlatList, Pressable, View } from 'react-native';
import { Issuer } from '../../components/openId4VCI/Issuer';
import { Error } from '../../components/ui/Error';
import { Header } from '../../components/ui/Header';
import { Button, Column, Row, Text } from '../../components/ui';
import { Theme } from '../../components/ui/styleUtils';
import { RootRouteProps } from '../../routes';
import { HomeRouteProps } from '../../routes/routeTypes';
import { useIssuerScreenController } from './IssuerScreenController';
import { Loader } from '../../components/ui/Loader';
import ScanIcon from '../../assets/scanIcon.svg';
import {
isTranslationKeyFound,
removeWhiteSpace,
} from '../../shared/commonUtil';
import {
ErrorMessage,
getDisplayObjectForCurrentLanguage,
@@ -22,20 +26,24 @@ import {
sendInteractEvent,
sendStartEvent,
} from '../../shared/telemetry/TelemetryUtils';
import {TelemetryConstants} from '../../shared/telemetry/TelemetryConstants';
import {MessageOverlay} from '../../components/MessageOverlay';
import {SearchBar} from '../../components/ui/SearchBar';
import {SvgImage} from '../../components/ui/svg';
import {Icon} from 'react-native-elements';
import {BannerNotificationContainer} from '../../components/BannerNotificationContainer';
import {CredentialTypeSelectionScreen} from './CredentialTypeSelectionScreen';
import { TelemetryConstants } from '../../shared/telemetry/TelemetryConstants';
import { MessageOverlay } from '../../components/MessageOverlay';
import { SearchBar } from '../../components/ui/SearchBar';
import { SvgImage } from '../../components/ui/svg';
import { Icon } from 'react-native-elements';
import { BannerNotificationContainer } from '../../components/BannerNotificationContainer';
import { CredentialTypeSelectionScreen } from './CredentialTypeSelectionScreen';
import { QrScanner } from '../../components/QrScanner';
import { IssuersModel } from '../../machines/Issuers/IssuersModel';
import { AUTH_ROUTES } from '../../routes/routesConstants';
import { TransactionCodeModal } from './TransactionCodeScreen';
import { TrustIssuerModal } from './TrustIssuerModal';
export const IssuersScreen: React.FC<
HomeRouteProps | RootRouteProps
> = props => {
const model = IssuersModel;
const controller = useIssuerScreenController(props);
const {t} = useTranslation('IssuersScreen');
const { i18n, t } = useTranslation('IssuersScreen');
const issuers = controller.issuers;
let [filteredSearchData, setFilteredSearchData] = useState(issuers);
const [search, setSearch] = useState('');
@@ -62,25 +70,37 @@ export const IssuersScreen: React.FC<
header: props => (
<Header
goBack={props.navigation.goBack}
title={t('title')}
title={ controller.isQrScanning?t('download'):t('title')}
testID="issuersScreenHeader"
/>
),
});
}
if (controller.isStoring) {
props.navigation.goBack();
}
}, [
controller.loadingReason,
controller.errorMessageType,
controller.isStoring,
controller.isQrScanning,
]);
if (controller.isStoring) {
props.navigation.goBack();
}
useEffect(() => {
if (controller.isAuthEndpointToOpen) {
(props.navigation as any).navigate(AUTH_ROUTES.AuthView, {
authorizationURL: controller.authEndpount,
clientId: controller.selectedIssuer.client_id ?? "wallet",
redirectUri: controller.selectedIssuer.redirect_uri ?? "io.mosip.residentapp.inji://oauthredirect",
controller: controller,
});
}
}, [controller.isAuthEndpointToOpen]);
const onPressHandler = (id: string, protocol: string) => {
sendStartEvent(
getStartEventData(TelemetryConstants.FlowType.vcDownload, {id: id}),
getStartEventData(TelemetryConstants.FlowType.vcDownload, { id: id }),
);
sendInteractEvent(
getInteractEventData(
@@ -102,9 +122,9 @@ export const IssuersScreen: React.FC<
return (
controller.errorMessageType === ErrorMessage.TECHNICAL_DIFFICULTIES ||
controller.errorMessageType ===
ErrorMessage.CREDENTIAL_TYPE_DOWNLOAD_FAILURE ||
ErrorMessage.CREDENTIAL_TYPE_DOWNLOAD_FAILURE ||
controller.errorMessageType ===
ErrorMessage.AUTHORIZATION_GRANT_TYPE_NOT_SUPPORTED
ErrorMessage.AUTHORIZATION_GRANT_TYPE_NOT_SUPPORTED
);
}
@@ -140,7 +160,7 @@ export const IssuersScreen: React.FC<
const filteredData = issuers.filter(item => {
if (
getDisplayObjectForCurrentLanguage(item.display)
?.title.toLowerCase()
?.name.toLowerCase()
.includes(searchText.toLowerCase())
) {
return getDisplayObjectForCurrentLanguage(item.display);
@@ -172,10 +192,23 @@ export const IssuersScreen: React.FC<
primaryButtonText="goBack"
primaryButtonEvent={controller.RESET_VERIFY_ERROR}
primaryButtonTestID="goBack"
customStyles={{marginTop: '30%'}}
customStyles={{ marginTop: '30%' }}
/>
);
}
if (controller.isConsentRequested) {
return issuerTrustConsentComponent();
}
if (controller.isTxCodeRequested) {
return <TransactionCodeModal
visible={controller.isTxCodeRequested}
onDismiss={controller.CANCEL}
onVerify={controller.TX_CODE_RECEIVED}
inputMode= {controller.txCodeDisplayDetails.inputMode}
description={controller.txCodeDisplayDetails.description}
length={controller.txCodeDisplayDetails.length}
/>
}
if (controller.isBiometricsCancelled) {
return (
@@ -217,7 +250,7 @@ export const IssuersScreen: React.FC<
primaryButtonTestID="tryAgain"
primaryButtonText={
controller.errorMessageType != ErrorMessage.TECHNICAL_DIFFICULTIES &&
controller.errorMessageType !=
controller.errorMessageType !=
ErrorMessage.AUTHORIZATION_GRANT_TYPE_NOT_SUPPORTED
? 'tryAgain'
: undefined
@@ -236,6 +269,24 @@ export const IssuersScreen: React.FC<
/>
);
}
if (controller.isQrScanning) {
return qrScannerComponent();
}
function qrScannerComponent() {
return (
<Column crossAlign="center">
<QrScanner
onQrFound={controller.QR_CODE_SCANNED}
/>
</Column>
);
}
function issuerTrustConsentComponent() {
return <TrustIssuerModal isVisible={true} issuerLogo={controller.issuerLogo} issuerName={controller.issuerName} onConfirm={controller.ON_CONSENT_GIVEN} onCancel={controller.CANCEL} />
}
return (
<React.Fragment>
@@ -279,11 +330,19 @@ export const IssuersScreen: React.FC<
}}>
{t('description')}
</Text>
{search === '' && <View style={{ height: 85 }}><Issuer defaultLogo={ScanIcon} displayDetails={{
title: t('offerTitle'),
locale: i18n.language,
description: t('offerDescription'),
}} onPress={
controller.SCAN_CREDENTIAL_OFFER_QR_CODE
} testID={'credentalOfferButton'} /></View>}
<Column scroll style={Theme.IssuersScreenStyles.issuersContainer}>
{controller.issuers.length > 0 && (
<FlatList
data={filteredSearchData}
renderItem={({item}) => (
renderItem={({ item }) => (
<Issuer
testID={removeWhiteSpace(item.issuer_id)}
key={item.issuer_id}
@@ -306,3 +365,5 @@ export const IssuersScreen: React.FC<
</React.Fragment>
);
};

View File

@@ -0,0 +1,214 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Button, Column, Text } from '../../components/ui';
import { Theme } from '../../components/ui/styleUtils';
import {
Dimensions,
Keyboard,
KeyboardAvoidingView, TouchableWithoutFeedback,
View,
ModalProps
} from 'react-native';
import { isIOS } from '../../shared/constants';
import { SvgImage } from '../../components/ui/svg';
import { getScreenHeight } from '../../shared/commonUtil';
import { PinInput } from '../../components/PinInput';
import { Modal } from '../../components/ui/Modal';
import { CancelDownloadModal } from './ConfirmationModal';
import { Icon, Input } from 'react-native-elements';
export const TransactionCodeModal: React.FC<ExtendedModalProps> = props => {
const { t } = useTranslation('transactionCodeScreen');
const { isSmallScreen, screenHeight } = getScreenHeight();
const [transactionCode, setTransactionCode] = useState('');
const [errorMessage, setErrorMessage] = useState('');
const [showCancelConfirm, setShowCancelConfirm] = useState(false);
const [showCode, setShowCode] = useState(false);
const [touched, setTouched] = useState(false);
const [showFullDescription, setShowFullDescription] = useState(false);
const [textLineCount, setTextLineCount] = useState(0);
const maxLines = 2;
const validateCode = (code: string): string => {
if (!code.trim()) return t('emptyCodeError');
if (!/^[a-zA-Z0-9]+$/.test(code)) return t('invalidCharacters');
return '';
};
const handleVerify = () => {
const error = validateCode(transactionCode);
if (error) {
setErrorMessage(error);
return;
}
setErrorMessage('');
props.onVerify?.(transactionCode);
};
const handleChange = (text: string) => {
if (!touched)
setTouched(true);
setTransactionCode(text);
let error;
if (touched)
error = validateCode(text);
setErrorMessage(error);
};
return (
<>
{showCancelConfirm ? (
<CancelDownloadModal onCancel={() => setShowCancelConfirm(false)} onConfirm={props.onDismiss ?? (() => { })} visible={showCancelConfirm} />
) : (
<Modal isVisible={props.visible ?? false} onDismiss={() => setShowCancelConfirm(true)}>
<KeyboardAvoidingView
style={
isSmallScreen
? { flex: 1, paddingHorizontal: 10 }
: Theme.Styles.keyboardAvoidStyle
}
behavior={isIOS() ? 'padding' : 'height'}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={{ height: 700 }}>
<Column
crossAlign="center"
style={
isSmallScreen
? null
: {
maxHeight: screenHeight,
flex: 1,
justifyContent: 'space-around',
marginBottom: 20,
}
}>
{SvgImage.OtpVerificationIcon()}
<View>
<Column crossAlign="center">
<Text
testID="otpVerificationHeader"
weight="bold"
style={Theme.TextStyles.header}>
{t('TransactionCode')}
</Text>
<Text
style={{ marginTop: 15 }}
testID="otpVerificationDescription"
color={Theme.Colors.RetrieveIdLabel}
numLines={showFullDescription ? undefined : 2}
ellipsizeMode='tail'
weight="semibold"
size="small"
align="center"
onTextLayout={(e) => {
if (textLineCount !== e.nativeEvent.lines.length) {
setTextLineCount(e.nativeEvent.lines.length);
}
}}
>
{t(
`${props.description ||
t('description')
}`,
)}
</Text>
{textLineCount >= maxLines && <Text
onPress={() => setShowFullDescription(prev => !prev)}
style={Theme.TransactionCodeScreenStyle.showMoreButton}
>
{showFullDescription ? t('Show less ↑') : t('Show more ↓')}
</Text>}
</Column>
</View>
{(props.error || errorMessage) && (
<View
style={Theme.TransactionCodeScreenStyle.errorView}
>
<Text
testID="otpVerificationError"
align="center"
color={Theme.Colors.errorMessage}>
{errorMessage || props.error}
</Text>
</View>
)}
<View style={{ alignItems: 'center' }}>
{((!props.inputMode ||
(props.inputMode && props.inputMode === 'numeric')) &&
props.length &&
props.length <= 6) ? (
<>
<PinInput
testID="pinInput"
length={props.length}
autosubmit={false}
onChange={handleChange}
onDone={(code: string) => {
const error = validateCode(code);
if (error) {
setErrorMessage(error);
return;
}
setErrorMessage('');
props.onVerify?.(code);
props.onDismiss?.();
}}
/>
<Button styles={{ marginTop: 30 }} disabled={transactionCode.length == 0} title={t('verify')} type="gradient" onPress={handleVerify} />
</>
) : (
<>
<Input
containerStyle={{
width: Dimensions.get('window').width - 80,
alignSelf: 'center',
}}
placeholder={t('placeholder')}
placeholderTextColor="#ACACAC"
inputContainerStyle={{
borderBottomColor: '#C1C1C1',
borderBottomWidth: 1,
marginBottom: 16,
}}
inputStyle={Theme.TransactionCodeScreenStyle.inputStyle}
maxLength={props.length ?? 30}
autoFocus
secureTextEntry={!showCode}
value={transactionCode}
keyboardType={props.inputMode === 'numeric' ? 'numeric' : 'default'}
onChangeText={handleChange}
rightIcon={
<Icon
name={showCode ? 'eye-off' : 'eye'}
type="feather"
size={20}
color="#888"
onPress={() => setShowCode(prev => !prev)}
/>
}
/>
<Button disabled={transactionCode.length == 0} title="Verify" type="gradient" onPress={handleVerify} />
</>
)}
</View>
</Column>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
</Modal>
)}
</>
);
};
interface ExtendedModalProps extends ModalProps {
onVerify?: (transactionCode: string) => void;
error?: string;
description?: string;
inputMode?: 'text' | 'numeric';
length?: number;
}

View File

@@ -0,0 +1,50 @@
import React from 'react';
import { Modal, View, Text, Image } from 'react-native';
import { Button } from '../../components/ui';
import { Theme } from '../../components/ui/styleUtils';
import { useTranslation } from 'react-i18next';
export const TrustIssuerModal = ({
isVisible,
issuerLogo,
issuerName,
onConfirm,
onCancel
}: {
isVisible: boolean;
issuerLogo: any;
issuerName: string;
onConfirm: () => void;
onCancel: () => void;
}) => {
const { t } = useTranslation('trustScreen');
return (
<Modal transparent={true} visible={isVisible} animationType="fade">
<View
style={Theme.TrustIssuerScreenStyle.modalOverlay}>
<View
style={Theme.TrustIssuerScreenStyle.modalContainer}>
{(issuerLogo || issuerName) && <View
style={Theme.TrustIssuerScreenStyle.issuerHeader}>
{issuerLogo && <Image
source={{ uri: issuerLogo }}
style={Theme.TrustIssuerScreenStyle.issuerLogo}
/>}
{issuerName && <Text
style={Theme.TrustIssuerScreenStyle.issuerName}>
{issuerName}
</Text>}
</View>}
<Text
style={Theme.TrustIssuerScreenStyle.description}>
{t('description')}
</Text>
<Button styles={{ marginBottom: 6 }} type='gradient' title={t('confirm')} onPress={onConfirm} />
<Button styles={{ marginBottom: -10 }} type='clear' title={t('cancel')} onPress={onCancel} />
</View>
</View>
</Modal>
);
};

View File

@@ -41,6 +41,7 @@ export const API_URLS: ApiUrls = {
buildURL: (authorizationServerUrl: string): string =>
`${authorizationServerUrl}/.well-known/oauth-authorization-server`,
},
allProperties: {
method: 'GET',
buildURL: (): `/${string}` => '/v1/mimoto/allProperties',
@@ -115,6 +116,14 @@ export const API = {
);
return response.response.issuers || [];
},
fetchIssuerConfig: async (issuerId: string) => {
const response = await request(
API_URLS.issuerConfig.method,
API_URLS.issuerConfig.buildURL(issuerId),
);
return response.response;
},
fetchIssuerWellknownConfig: async (credentialIssuer: string) => {
const response = await request(
API_URLS.issuerWellknownConfig.method,
@@ -122,17 +131,7 @@ export const API = {
);
return response;
},
fetchAuthorizationServerMetadata: async (authorizationServerUrl: string) => {
const response = await request(
API_URLS.authorizationServerMetadataConfig.method,
API_URLS.authorizationServerMetadataConfig.buildURL(
authorizationServerUrl,
),
undefined,
'',
);
return response;
},
fetchAllProperties: async () => {
const response = await request(
API_URLS.allProperties.method,

View File

@@ -81,6 +81,12 @@ export const SUPPORTED_KEY_TYPES = {
'ECC R1': KeyTypes.ES256,
RSA: KeyTypes.RS256,
};
export const KEY_TYPE_TO_JWT_ALG = {
[KeyTypes.ED25519]: 'EdDSA',
[KeyTypes.ES256K]: 'ES256K',
[KeyTypes.ES256]: 'ES256',
[KeyTypes.RS256]: 'RS256',
};
export function isAndroid(): boolean {
return Platform.OS === 'android';

View File

@@ -19,7 +19,7 @@ import {
VerifiableCredential,
} from '../../machines/VerifiableCredential/VCMetaMachine/vc';
import getAllConfigurations, {CACHED_API} from '../api';
import {isAndroid, isIOS} from '../constants';
import {isAndroid, isIOS, KEY_TYPE_TO_JWT_ALG} from '../constants';
import {getJWT} from '../cryptoutil/cryptoUtil';
import {isMockVC} from '../Utils';
import {
@@ -34,7 +34,6 @@ import {KeyTypes} from '../cryptoutil/KeyTypes';
import {VCFormat} from '../VCFormat';
import {UnsupportedVcFormat} from '../error/UnsupportedVCFormat';
import {VCMetadata} from '../VCMetadata';
import {UUID} from '../Utils';
export const Protocols = {
OpenId4VCI: 'OpenId4VCI',
@@ -71,7 +70,7 @@ export const isActivationNeeded = (issuer: string) => {
export const Issuers_Key_Ref = 'OpenId4VCI_KeyPair';
export const updateCredentialInformation = async (
context,
context: any,
credential: VerifiableCredential,
): Promise<CredentialWrapper> => {
let processedCredential;
@@ -81,14 +80,23 @@ export const updateCredentialInformation = async (
context.selectedCredentialType.format,
);
}
const verifiableCredential = {
...credential,
credentialConfigurationId: context.selectedCredentialType.id,
issuerLogo: getDisplayObjectForCurrentLanguage(
context.selectedIssuer.display,
)?.logo,
processedCredential,
};
let verifiableCredential;
try {
verifiableCredential = {
...credential,
credentialConfigurationId: context.selectedCredentialType.id,
issuerLogo: getDisplayObjectForCurrentLanguage(
context.selectedIssuer.display,
)?.logo,
processedCredential,
};
} catch (e) {
console.error(
'Error occurred while processing credential for rendering',
e,
);
}
return {
verifiableCredential,
format: context.selectedCredentialType.format,
@@ -111,28 +119,14 @@ export const getDisplayObjectForCurrentLanguage = (
obj => obj[languageKey] == currentLanguage,
)[0];
if (!displayType) {
displayType = display.filter(obj => obj[languageKey] === 'en')[0];
displayType =
display.filter(obj => obj[languageKey] === 'en')[0] ||
display.filter(obj => obj[languageKey] === 'en-US')[0] ||
display[0];
}
return displayType;
};
export const constructAuthorizationConfiguration = (
selectedIssuer: issuerType,
supportedScope: string,
) => {
return {
issuer: selectedIssuer.issuer_id,
clientId: selectedIssuer.client_id,
scopes: [supportedScope],
redirectUrl: selectedIssuer.redirect_uri,
additionalParameters: {ui_locales: i18n.language},
serviceConfiguration: {
authorizationEndpoint: selectedIssuer.authorizationEndpoint,
tokenEndpoint: selectedIssuer.token_endpoint,
},
};
};
export const getCredentialIssuersWellKnownConfig = async (
issuer: string | undefined,
defaultFields: string[],
@@ -141,6 +135,7 @@ export const getCredentialIssuersWellKnownConfig = async (
issuerHost: string,
) => {
let fields: string[] = defaultFields;
let wellknownFieldsFlag = false;
let matchingWellknownDetails: any;
const wellknownResponse = await CACHED_API.fetchIssuerWellknownConfig(
issuer!,
@@ -169,9 +164,13 @@ export const getCredentialIssuersWellKnownConfig = async (
);
});
} else if (format === VCFormat.ldp_vc) {
fields = Object.keys(
const ldpFields = Object.keys(
matchingWellknownDetails.credential_definition.credentialSubject,
);
if (ldpFields.length > 0) {
fields = ldpFields;
wellknownFieldsFlag = true;
}
} else {
console.error(`Unsupported credential format - ${format} found`);
throw new UnsupportedVcFormat(format);
@@ -186,12 +185,15 @@ export const getCredentialIssuersWellKnownConfig = async (
return {
matchingCredentialIssuerMetadata: matchingWellknownDetails,
fields: fields,
wellknownFieldsFlag: false,
};
}
return {
matchingCredentialIssuerMetadata: matchingWellknownDetails,
wellknownResponse,
fields: fields,
wellknownFieldsFlag:
wellknownFieldsFlag || matchingWellknownDetails?.order?.length > 0,
};
};
@@ -217,6 +219,7 @@ export const getDetailedViewFields = async (
return {
matchingCredentialIssuerMetadata: response.matchingCredentialIssuerMetadata,
fields: updatedFieldsList,
wellknownFieldsFlag: response.wellknownFieldsFlag,
wellknownResponse: response.wellknownResponse,
};
};
@@ -245,7 +248,8 @@ export const OIDCErrors = {
AUTHORIZATION_ENDPOINT_DISCOVERY: {
GRANT_TYPE_NOT_SUPPORTED: 'Grant type not supported by Wallet',
FAILED_TO_FETCH_AUTHORIZATION_ENDPOINT: 'Failed to fetch authorization endpoint or grant type not supported by wallet',
FAILED_TO_FETCH_AUTHORIZATION_ENDPOINT:
'Failed to fetch authorization endpoint or grant type not supported by wallet',
},
};
@@ -267,17 +271,24 @@ export async function constructProofJWT(
accessToken: string,
selectedIssuer: issuerType,
keyType: string,
isCredentialOfferFlow: boolean,
cNonce?: string,
): Promise<string> {
const jwk = await getJWK(publicKey, keyType);
const jwtHeader = {
alg: keyType,
jwk: await getJWK(publicKey, keyType),
alg: KEY_TYPE_TO_JWT_ALG[keyType],
typ: 'openid4vci-proof+jwt',
};
if (isCredentialOfferFlow) {
jwtHeader['kid'] = `did:jwk:${base64url(JSON.stringify(jwk))}#0`;
} else {
jwtHeader['jwk'] = jwk;
}
const decodedToken = jwtDecode(accessToken);
const jwtPayload = {
iss: selectedIssuer.client_id,
nonce: decodedToken.c_nonce,
aud: selectedIssuer.credential_audience,
nonce: cNonce ?? decodedToken.c_nonce,
aud: selectedIssuer.credential_audience ?? selectedIssuer.credential_issuer,
iat: Math.floor(new Date().getTime() / 1000),
exp: Math.floor(new Date().getTime() / 1000) + 18000,
};
@@ -312,7 +323,7 @@ export const getJWK = async (publicKey, keyType) => {
}
return {
...publicKeyJWK,
alg: keyType,
alg: KEY_TYPE_TO_JWT_ALG[keyType],
use: 'sig',
};
} catch (e) {
@@ -387,23 +398,30 @@ export function selectCredentialRequestKey(
return keyOrder[index];
}
}
return '';
return KeyTypes.ED25519;
}
export const constructIssuerMetaData = (
selectedIssuer: issuerType,
selectedCredentialType: CredentialTypes,
downloadTimeout: Number,
scope: string,
): Object => {
const issuerMeta: Object = {
credentialAudience: selectedIssuer.credential_audience,
credentialEndpoint: selectedIssuer.credential_endpoint,
downloadTimeoutInMilliSeconds: downloadTimeout,
credentialFormat: selectedCredentialType.format,
credentialFormat: isIOS()
? selectedCredentialType.format
: selectedCredentialType.format.toUpperCase(),
authorizationServers: selectedIssuer['authorization_servers'],
tokenEndpoint: selectedIssuer.token_endpoint,
scope: scope,
};
if (selectedCredentialType.format === VCFormat.ldp_vc) {
issuerMeta['credentialType'] = selectedCredentialType?.credential_definition
?.type ?? ['VerifiableCredential'];
if (selectedCredentialType?.credential_definition['@context'])
issuerMeta['context'] =
selectedCredentialType?.credential_definition['@context'];
} else if (selectedCredentialType.format === VCFormat.mso_mdoc) {
issuerMeta['doctype'] = selectedCredentialType.doctype;
issuerMeta['claims'] = selectedCredentialType.claims;

View File

@@ -1,19 +1,126 @@
import {NativeModules} from 'react-native';
import {NativeModules, NativeEventEmitter} from 'react-native';
import {__AppId} from '../GlobalVariables';
import {constructProofJWT} from '../openId4VCI/Utils';
import {issuerType} from '../../machines/Issuers/IssuersMachine';
import {VerifiableCredential} from '../../machines/VerifiableCredential/VCMetaMachine/vc';
const emitter = new NativeEventEmitter(NativeModules.InjiVciClient);
export class VciClient {
static async downloadCredential(
issuerMetaData: Object,
jwtProof: string,
accessToken: string,
static get client() {
const nativeClient = NativeModules.InjiVciClient;
nativeClient.init(__AppId.getValue());
return nativeClient;
}
static async requestCredentialByOffer(
credentialOffer: string,
getTxCode: (
inputMode: string | undefined,
description: string | undefined,
length: number | undefined,
) => void,
getProofJwt: (
accesToken: string,
cNonce: string | null,
issuerMetadata: object,
credentialConfigurationId: string,
) => void,
navigateToAuthView: (authorizationEndpoint: string) => void,
requestTrustIssuerConsent: (issuerMetadata: object) => void,
) {
const InjiVciClient = NativeModules.InjiVciClient;
InjiVciClient.init(__AppId.getValue());
const credentialResponse = await InjiVciClient.requestCredential(
issuerMetaData,
jwtProof,
accessToken,
const proofListener = emitter.addListener(
'onRequestProof',
async ({
accessToken,
cNonce,
issuerMetadata,
credentialConfigurationId,
}) => {
getProofJwt(
accessToken,
cNonce,
JSON.parse(issuerMetadata),
credentialConfigurationId,
);
},
);
return JSON.parse(credentialResponse);
const authListener = emitter.addListener(
'onRequestAuthCode',
async ({authorizationEndpoint}) => {
navigateToAuthView(authorizationEndpoint);
},
);
const txCodeListener = emitter.addListener(
'onRequestTxCode',
async ({inputMode, description, length}) => {
getTxCode(inputMode, description, length);
},
);
const trustIssuerListener = emitter.addListener(
'onCheckIssuerTrust',
async ({issuerMetadata}) => {
const issuerMetadataObject = JSON.parse(issuerMetadata);
requestTrustIssuerConsent(issuerMetadataObject);
},
);
let response = '';
try {
response = await VciClient.client.requestCredentialByOffer(
credentialOffer,
JSON.stringify({
clientId: 'wallet',
redirectUri: 'io.mosip.residentapp.inji://oauthredirect',
}),
);
} catch (error) {
console.error('Error requesting credential by offer:', error);
throw error;
}
proofListener.remove();
authListener.remove();
txCodeListener.remove();
trustIssuerListener.remove();
return JSON.parse(response) as VerifiableCredential;
}
static async requestCredentialFromTrustedIssuer(
resolvedIssuerMetaData: Object,
clientMetadata: Object,
getProofJwt: (accessToken: string, cNonce: string) => Promise<void>,
navigateToAuthView: (authorizationEndpoint: string) => void,
) {
const proofListener = emitter.addListener(
'onRequestProof',
async ({accessToken, cNonce}) => {
getProofJwt(accessToken, cNonce);
proofListener.remove();
},
);
const authListener = emitter.addListener(
'onRequestAuthCode',
({authorizationEndpoint}) => {
navigateToAuthView(authorizationEndpoint);
},
);
let response = '';
try {
response = await VciClient.client.requestCredentialFromTrustedIssuer(
JSON.stringify(resolvedIssuerMetaData),
JSON.stringify(clientMetadata),
);
} catch (error) {
console.error('Error requesting credential from trusted issuer:', error);
throw error;
}
proofListener.remove();
authListener.remove();
return JSON.parse(response);
}
}