From 3732b06b72e54baf78163ed50911a34cd6c9db4e Mon Sep 17 00:00:00 2001
From: Chris <34682781+monkins1010@users.noreply.github.com>
Date: Thu, 15 Feb 2024 16:10:11 +0000
Subject: [PATCH 01/10] Add attestation
---
package.json | 5 +-
src/components/Attestation.js | 94 +++++++++++++
.../LoginRequestComplete.js | 54 ++++++--
.../LoginRequestIdentity.js | 43 +++++-
.../LoginRequestInfo/LoginRequestInfo.js | 123 +++++++++++++++++-
src/utils/deeplink/handleRedirect.js | 6 +
6 files changed, 312 insertions(+), 13 deletions(-)
create mode 100644 src/components/Attestation.js
diff --git a/package.json b/package.json
index 99b2bbd6..c8178fc9 100755
--- a/package.json
+++ b/package.json
@@ -223,7 +223,10 @@
"@babel/core": "7.21.3",
"blake2b-wasm": "https://github.com/michaeltout/blake2b-wasm/",
"@bitgo/blake2b-wasm": "https://github.com/michaeltout/blake2b-wasm/",
- "browserify-sign": "4.2.2"
+ "browserify-sign": "4.2.2",
+ "verus-typescript-primitives": "file:d:/dev/verus-typescript-primitives",
+ "verusid-ts-client": "file:d:/dev/verusid-ts-client",
+ "verusd-rpc-ts-client": "file:d:/dev/verusd-rpc-ts-client"
},
"jest": {
"preset": "react-native",
diff --git a/src/components/Attestation.js b/src/components/Attestation.js
new file mode 100644
index 00000000..05226877
--- /dev/null
+++ b/src/components/Attestation.js
@@ -0,0 +1,94 @@
+import React, {useEffect, useState} from 'react';
+import { SafeAreaView, ScrollView, View, Dimensions } from 'react-native';
+import { Button, Dialog, Portal, Text, List} from 'react-native-paper';
+import { connect } from 'react-redux';
+import Colors from '../globals/colors';
+import { getIdentity } from '../utils/api/channels/verusid/callCreators';
+import { primitives } from 'verusid-ts-client';
+import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
+
+const getIdentities = async (identities) => {
+
+ const identity = await Promise.all(identities.map(async (iaddress) => {return await getIdentity(null , iaddress)}));
+ console.log(identity);
+ return identity;
+
+}
+
+const AttestationModal = (props) => {
+
+ const {visible, loginConsentResponse, attestation, viewOnly, buttons = [], mainTitle } = props;
+ const [signers, setSigners] = useState([]);
+ const signatures = Object.keys(attestation.signatures);
+ let attestationValues = {};
+
+ for (let [key, value] of attestation.components) {
+ if (primitives.ATTESTATION_IDENTITY_DATA[value.attestationKey]) {
+ attestationValues[primitives.ATTESTATION_IDENTITY_DATA[value.attestationKey].detail] = value.value;
+ }
+ }
+
+ useEffect(() => {
+ getIdentities(signatures).then((identities) => setSigners(identities));
+
+ }, []);
+
+ const title = attestationValues["Document Type"] || '' ;
+
+ const { height } = Dimensions.get('window');
+ const dialogContentMaxHeight = height * 0.6; // Adjust this value as needed
+
+ return (
+
+
+
+
+
+ );
+
+};
+
+const mapStateToProps = (state) => {
+ return {
+ activeAlert: state.alert.active,
+ };
+};
+
+export default connect(mapStateToProps)(AttestationModal);
\ No newline at end of file
diff --git a/src/containers/DeepLink/LoginRequestComplete/LoginRequestComplete.js b/src/containers/DeepLink/LoginRequestComplete/LoginRequestComplete.js
index fe5a2feb..24b47acd 100644
--- a/src/containers/DeepLink/LoginRequestComplete/LoginRequestComplete.js
+++ b/src/containers/DeepLink/LoginRequestComplete/LoginRequestComplete.js
@@ -1,4 +1,4 @@
-import React, {useState} from 'react';
+import React, {useState, useEffect} from 'react';
import {ScrollView, View, TouchableOpacity} from 'react-native';
import Styles from '../../../styles/index';
import {primitives} from 'verusid-ts-client';
@@ -14,6 +14,8 @@ import AnimatedActivityIndicator from '../../../components/AnimatedActivityIndic
import { useDispatch, useSelector } from 'react-redux';
import { resetDeeplinkData } from '../../../actions/actionCreators';
+import { useSelector } from 'react-redux';
+import Attestation from '../../../components/Attestation';
const LoginRequestComplete = props => {
const {signedResponse} = props.route.params;
@@ -28,6 +30,8 @@ const LoginRequestComplete = props => {
let redirectinfo = null;
const [loading, setLoading] = useState(false);
const dispatch = useDispatch();
+ const [showAttestation, setShowAttestation] = useState(false);
+ const [attestationObj, setAttestationObj] = useState(null);
const cancel = () => {
dispatch(resetDeeplinkData());
@@ -39,9 +43,36 @@ const LoginRequestComplete = props => {
);
};
+ const storeAttestation = () => {
+
+ }
+
let redirectsObj = {};
redirects.forEach(a => {redirectsObj[a.vdxfkey] = a;});
+ const attestationPresent = !!redirectsObj[primitives.LOGIN_CONSENT_ATTESTATION_WEBHOOK_VDXF_KEY.vdxfid];
+
+ useEffect(() => {
+ if (attestationPresent) {
+ try {
+ setLoading(true);
+ handleRedirect(signedResponse,
+ redirectsObj[primitives.LOGIN_CONSENT_ATTESTATION_WEBHOOK_VDXF_KEY.vdxfid]).then((attestation) => {
+ if (attestation && attestation.data) {
+ const localAttestaionObj = new primitives.Attestation();
+ localAttestaionObj.fromBuffer(Buffer.from(attestation.data, 'hex'));
+ setAttestationObj(localAttestaionObj);
+ setShowAttestation(true);
+ }
+ setLoading(false);
+ });
+ } catch(e) {
+ createAlert('Error', e.message);
+ setLoading(false);
+ cancel();
+ }
+ }
+ }, []);
if (redirectsObj[primitives.LOGIN_CONSENT_REDIRECT_VDXF_KEY.vdxfid]) {
try {
@@ -57,7 +88,6 @@ const LoginRequestComplete = props => {
redirectinfo = redirectsObj[primitives.LOGIN_CONSENT_WEBHOOK_VDXF_KEY.vdxfid];
}
-
const tryRedirect = async () => {
try {
setLoading(true);
@@ -85,11 +115,19 @@ const LoginRequestComplete = props => {
return (
+ style={{...Styles.fullWidth, ...Styles.backgroundColorWhite}}
+ contentContainerStyle={{
+ ...Styles.focalCenter,
+ justifyContent: 'space-between',
+ }}>
+ {attestationObj && setShowAttestation(false)},
+ {disabled: false, onPress: () => {storeAttestation(); setShowAttestation(false);}, text: "save"},]}
+ mainTitle={"Attestation Received"}
+ />}
{
fontSize: 20,
color: Colors.verusDarkGray,
}}>
- {loading ? "Loading..." : 'Success!'}
+ {loading ? attestationPresent ? "Retrieving Attestation" : "Loading..." : 'Success!'}
{loading ? (
diff --git a/src/containers/DeepLink/LoginRequestIdentity/LoginRequestIdentity.js b/src/containers/DeepLink/LoginRequestIdentity/LoginRequestIdentity.js
index 1ba32c0a..20a2e7cd 100644
--- a/src/containers/DeepLink/LoginRequestIdentity/LoginRequestIdentity.js
+++ b/src/containers/DeepLink/LoginRequestIdentity/LoginRequestIdentity.js
@@ -27,6 +27,7 @@ const LoginRequestIdentity = props => {
const [sortedIds, setSortedIds] = useState({});
const [idProvisionSuccess, setIdProvisionSuccess] = useState(false)
const [canProvision, setCanProvision] = useState(false)
+ const [attestationID, setattestationID] = useState('')
const req = new primitives.LoginConsentRequest(deeplinkData)
const encryptedIds = useSelector(state => state.services.stored[VERUSID_SERVICE_ID])
const sendModal = useSelector((state) => state.sendModal);
@@ -97,9 +98,44 @@ const LoginRequestIdentity = props => {
const data = {[SEND_MODAL_IDENTITY_TO_LINK_FIELD]: passthrough.fqnToAutoLink, noLogin: noLogin};
openLinkIdentityModal(CoinDirectory.findCoinObj(system_id, null, true), data);
}
- }, [passthrough])
+ }, [extraParams])
- //TODO: add a check that checks to see if the ID is ready, and relates to the provider.
+ useEffect(() => {
+
+ if (idsloaded && req.challenge.subject && req.challenge.subject.length > 0 &&
+ req.challenge.subject.some(item => item.vdxfkey === primitives.ID_ADDRESS_VDXF_KEY.vdxfid)) {
+
+ const providionedId = req.challenge.subject.find(item => item.vdxfkey === primitives.ID_ADDRESS_VDXF_KEY.vdxfid).data;
+ if(req.challenge.redirect_uris && req.challenge.redirect_uris
+ .some((uriKey) => uriKey.vdxfkey === primitives.LOGIN_CONSENT_ATTESTATION_WEBHOOK_VDXF_KEY.vdxfid)){
+ // if an attestation is provided, set the attestationID so it only shows the attestation the ID is for.
+ setattestationID(providionedId)
+ }
+
+ for (const chainId of activeCoinIds) {
+ if (linkedIds[chainId] && Object.keys(linkedIds[chainId]).includes(providionedId)) {
+ return;
+ }
+ }
+ getIdentity(system_id, providionedId).then((provisionedID) => {
+ getPotentialPrimaryAddresses().then((addresses) => {
+ if (provisionedID.result) {
+ for (const address of provisionedID.result.identity.primaryaddresses) {
+ if (addresses.includes(address)) {
+ dispatch({
+ type: SET_DEEPLINK_DATA_EXTRAPARAMS,
+ payload: {
+ extraParams: { fqn: provisionedID.result.fullyqualifiedname }
+ },
+ });
+ return;
+ }
+ }
+ }
+ })
+ })
+ }
+ }, [idsloaded])
useEffect(() => {
onEncryptedIdsUpdate()
@@ -185,6 +221,9 @@ const LoginRequestIdentity = props => {
{`Linked ${chainId} VerusIDs`}
)}
{sortedIds[chainId].map(iAddr => {
+ if(attestationID && attestationID !== iAddr) {
+ return null
+ }
return (
diff --git a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
index 1c808c4e..407cf4f1 100644
--- a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
+++ b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
@@ -1,5 +1,5 @@
-import React, {useState, useEffect} from 'react';
-import {SafeAreaView, ScrollView, TouchableOpacity, View} from 'react-native';
+import React, { useState, useEffect } from 'react';
+import { Alert, SafeAreaView, ScrollView, TouchableOpacity, View } from 'react-native';
import Styles from '../../../styles/index';
import { primitives } from "verusid-ts-client"
import { Button, Divider, List, Portal, Text } from 'react-native-paper';
@@ -17,6 +17,9 @@ import { createAlert, resolveAlert } from '../../../actions/actions/alert/dispat
import { CoinDirectory } from '../../../utils/CoinData/CoinDirectory';
import { addCoin, addKeypairs, setUserCoins } from '../../../actions/actionCreators';
import { refreshActiveChainLifecycles } from '../../../actions/actions/intervals/dispatchers/lifecycleManager';
+import { requestServiceStoredData } from '../../../utils/auth/authBox';
+import { VERUSID_SERVICE_ID } from '../../../utils/constants/services';
+import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
const LoginRequestInfo = props => {
const { deeplinkData, sigtime, cancel, signerFqn } = props
@@ -112,6 +115,103 @@ const LoginRequestInfo = props => {
setReq(new primitives.LoginConsentRequest(deeplinkData))
}, [deeplinkData]);
+ const buildAlert = (request) => {
+ return createAlert(
+ request.title,
+ request.data,
+ [
+ {
+ text: 'DECLINE',
+ onPress: () => resolveAlert(false),
+ style: 'cancel',
+ },
+ {
+ text: 'ACCEPT', onPress: () => {
+
+ var _permissions = [];
+ for (let i = 0; i < permissions.length; i++) {
+ _permissions.push(permissions[i]);
+ if (_permissions[i].vdxfkey == request.vdxfkey) {
+ _permissions[i].agreed = true;
+ }
+ }
+ setExtraPermissions(_permissions);
+
+ resolveAlert(true)
+ }
+ },
+ ],
+ {
+ cancelable: true,
+ },
+ )
+ }
+
+
+ useEffect(() => {
+
+ if (req && req.challenge && req.challenge.requested_access) {
+ var tempMethod = 0;
+ var attestationProvided = -1;
+
+ if (req.challenge.redirect_uris.length > 0) {
+ attestationProvided = req.challenge.redirect_uris.map((data) => data.vdxfkey).indexOf(primitives.LOGIN_CONSENT_ATTESTATION_WEBHOOK_VDXF_KEY.vdxfid)
+ }
+
+ var tempdata = {};
+ if ((req.challenge.requested_access.length > 1) || (attestationProvided > -1) && !permissions) {
+ var loginTemp = [];
+ for (let i = 1; i < req.challenge.requested_access.length; i++) {
+ if (req.challenge.requested_access[i].vdxfkey === primitives.IDENTITY_AGREEMENT.vdxfid) {
+ tempMethod = tempMethod | 1;
+ tempdata = { data: req.challenge.requested_access[i].toJson().data, title: "Agreement to accept" }
+ }
+ // TODO: Add support for viewing identity data
+ loginTemp.push({ vdxfkey: req.challenge.requested_access[i].vdxfkey, ...tempdata, agreed: false })
+ }
+ if (attestationProvided > -1) {
+ tempMethod = tempMethod | 4;
+ if (!req.challenge.subject.some((subject) => subject.vdxfkey === primitives.ID_ADDRESS_VDXF_KEY.vdxfid)) {
+ throw new Error("Attestation requested without ID Specified");
+ }
+ const attestationId = req.challenge.subject.find((subject) => subject.vdxfkey === primitives.ID_ADDRESS_VDXF_KEY.vdxfid).data;
+
+ requestServiceStoredData(VERUSID_SERVICE_ID).then((verusIdServiceData) => {
+
+ if (verusIdServiceData.linked_ids)
+
+ for (const chainId of Object.keys(verusIdServiceData.linked_ids)) {
+ if (verusIdServiceData.linked_ids[chainId] &&
+ Object.keys(verusIdServiceData.linked_ids[chainId])
+ .includes(attestationId)) {
+ loginTemp.push({ vdxfkey: primitives.LOGIN_CONSENT_ATTESTATION_WEBHOOK_VDXF_KEY.vdxfid,
+ title: verusIdServiceData.linked_ids[chainId][attestationId],
+ data: "Contains an Attestation for",
+ agreed: true,
+ nonChecked: true })
+ }
+ }
+ setExtraPermissions(loginTemp);
+ })
+ }
+ if (tempMethod > 5) Alert.alert("Error", "Invalid login method");
+ } else if (req.challenge.requested_access.length === 1) {
+ setReady(true);
+ }
+ setLoginMethod(tempMethod);
+ }
+ }, []);
+
+ useEffect(() => {
+ if (permissions) {
+ for (let i = 0; i < permissions.length; i++) {
+ if (!permissions[i].agreed)
+ return;
+ }
+ setReady(true);
+ }
+ }, [permissions]);
+
useEffect(() => {
setSigDateString(unixToDate(sigtime))
}, [sigtime]);
@@ -294,6 +394,25 @@ const LoginRequestInfo = props => {
+ {permissions && permissions.map((request, index) => {
+ return (
+ !!request.nonChecked ? null : buildAlert(request) }>
+ (
+ !!!request.nonChecked &&
+ )}
+ left= {() => }
+ />
+
+
+ );
+ })}
{
+ return await axios.post(
+ uri,
+ response
+ );
+ },
[primitives.LOGIN_CONSENT_REDIRECT_VDXF_KEY.vdxfid]: (uri, response) => {
const url = new URL(uri)
const res = new primitives.LoginConsentResponse(response)
From 010e91f725d50b53865962b4d6f82f592404410d Mon Sep 17 00:00:00 2001
From: Chris <34682781+monkins1010@users.noreply.github.com>
Date: Thu, 15 Feb 2024 16:10:18 +0000
Subject: [PATCH 02/10] Add more data
---
package.json | 5 +-
shim.js | 26 ++++
src/components/Attestation.js | 94 -------------
.../LoginRequestComplete.js | 54 ++------
.../LoginRequestIdentity.js | 43 +-----
.../LoginRequestInfo/LoginRequestInfo.js | 123 +-----------------
src/utils/deeplink/handleRedirect.js | 6 -
7 files changed, 39 insertions(+), 312 deletions(-)
create mode 100644 shim.js
delete mode 100644 src/components/Attestation.js
diff --git a/package.json b/package.json
index c8178fc9..99b2bbd6 100755
--- a/package.json
+++ b/package.json
@@ -223,10 +223,7 @@
"@babel/core": "7.21.3",
"blake2b-wasm": "https://github.com/michaeltout/blake2b-wasm/",
"@bitgo/blake2b-wasm": "https://github.com/michaeltout/blake2b-wasm/",
- "browserify-sign": "4.2.2",
- "verus-typescript-primitives": "file:d:/dev/verus-typescript-primitives",
- "verusid-ts-client": "file:d:/dev/verusid-ts-client",
- "verusd-rpc-ts-client": "file:d:/dev/verusd-rpc-ts-client"
+ "browserify-sign": "4.2.2"
},
"jest": {
"preset": "react-native",
diff --git a/shim.js b/shim.js
new file mode 100644
index 00000000..812d6b45
--- /dev/null
+++ b/shim.js
@@ -0,0 +1,26 @@
+if (typeof __dirname === 'undefined') global.__dirname = '/'
+if (typeof __filename === 'undefined') global.__filename = ''
+if (typeof process === 'undefined') {
+ global.process = require('process')
+} else {
+ const bProcess = require('process')
+ for (var p in bProcess) {
+ if (!(p in process)) {
+ process[p] = bProcess[p]
+ }
+ }
+}
+
+process.browser = false
+if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer
+
+// global.location = global.location || { port: 80 }
+const isDev = typeof __DEV__ === 'boolean' && __DEV__
+process.env['NODE_ENV'] = isDev ? 'development' : 'production'
+if (typeof localStorage !== 'undefined') {
+ localStorage.debug = isDev ? '*' : ''
+}
+
+// If using the crypto shim, uncomment the following line to ensure
+// crypto is loaded first, so it can populate global.crypto
+// require('crypto')
diff --git a/src/components/Attestation.js b/src/components/Attestation.js
deleted file mode 100644
index 05226877..00000000
--- a/src/components/Attestation.js
+++ /dev/null
@@ -1,94 +0,0 @@
-import React, {useEffect, useState} from 'react';
-import { SafeAreaView, ScrollView, View, Dimensions } from 'react-native';
-import { Button, Dialog, Portal, Text, List} from 'react-native-paper';
-import { connect } from 'react-redux';
-import Colors from '../globals/colors';
-import { getIdentity } from '../utils/api/channels/verusid/callCreators';
-import { primitives } from 'verusid-ts-client';
-import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
-
-const getIdentities = async (identities) => {
-
- const identity = await Promise.all(identities.map(async (iaddress) => {return await getIdentity(null , iaddress)}));
- console.log(identity);
- return identity;
-
-}
-
-const AttestationModal = (props) => {
-
- const {visible, loginConsentResponse, attestation, viewOnly, buttons = [], mainTitle } = props;
- const [signers, setSigners] = useState([]);
- const signatures = Object.keys(attestation.signatures);
- let attestationValues = {};
-
- for (let [key, value] of attestation.components) {
- if (primitives.ATTESTATION_IDENTITY_DATA[value.attestationKey]) {
- attestationValues[primitives.ATTESTATION_IDENTITY_DATA[value.attestationKey].detail] = value.value;
- }
- }
-
- useEffect(() => {
- getIdentities(signatures).then((identities) => setSigners(identities));
-
- }, []);
-
- const title = attestationValues["Document Type"] || '' ;
-
- const { height } = Dimensions.get('window');
- const dialogContentMaxHeight = height * 0.6; // Adjust this value as needed
-
- return (
-
-
-
-
-
- );
-
-};
-
-const mapStateToProps = (state) => {
- return {
- activeAlert: state.alert.active,
- };
-};
-
-export default connect(mapStateToProps)(AttestationModal);
\ No newline at end of file
diff --git a/src/containers/DeepLink/LoginRequestComplete/LoginRequestComplete.js b/src/containers/DeepLink/LoginRequestComplete/LoginRequestComplete.js
index 24b47acd..fe5a2feb 100644
--- a/src/containers/DeepLink/LoginRequestComplete/LoginRequestComplete.js
+++ b/src/containers/DeepLink/LoginRequestComplete/LoginRequestComplete.js
@@ -1,4 +1,4 @@
-import React, {useState, useEffect} from 'react';
+import React, {useState} from 'react';
import {ScrollView, View, TouchableOpacity} from 'react-native';
import Styles from '../../../styles/index';
import {primitives} from 'verusid-ts-client';
@@ -14,8 +14,6 @@ import AnimatedActivityIndicator from '../../../components/AnimatedActivityIndic
import { useDispatch, useSelector } from 'react-redux';
import { resetDeeplinkData } from '../../../actions/actionCreators';
-import { useSelector } from 'react-redux';
-import Attestation from '../../../components/Attestation';
const LoginRequestComplete = props => {
const {signedResponse} = props.route.params;
@@ -30,8 +28,6 @@ const LoginRequestComplete = props => {
let redirectinfo = null;
const [loading, setLoading] = useState(false);
const dispatch = useDispatch();
- const [showAttestation, setShowAttestation] = useState(false);
- const [attestationObj, setAttestationObj] = useState(null);
const cancel = () => {
dispatch(resetDeeplinkData());
@@ -43,36 +39,9 @@ const LoginRequestComplete = props => {
);
};
- const storeAttestation = () => {
-
- }
-
let redirectsObj = {};
redirects.forEach(a => {redirectsObj[a.vdxfkey] = a;});
- const attestationPresent = !!redirectsObj[primitives.LOGIN_CONSENT_ATTESTATION_WEBHOOK_VDXF_KEY.vdxfid];
-
- useEffect(() => {
- if (attestationPresent) {
- try {
- setLoading(true);
- handleRedirect(signedResponse,
- redirectsObj[primitives.LOGIN_CONSENT_ATTESTATION_WEBHOOK_VDXF_KEY.vdxfid]).then((attestation) => {
- if (attestation && attestation.data) {
- const localAttestaionObj = new primitives.Attestation();
- localAttestaionObj.fromBuffer(Buffer.from(attestation.data, 'hex'));
- setAttestationObj(localAttestaionObj);
- setShowAttestation(true);
- }
- setLoading(false);
- });
- } catch(e) {
- createAlert('Error', e.message);
- setLoading(false);
- cancel();
- }
- }
- }, []);
if (redirectsObj[primitives.LOGIN_CONSENT_REDIRECT_VDXF_KEY.vdxfid]) {
try {
@@ -88,6 +57,7 @@ const LoginRequestComplete = props => {
redirectinfo = redirectsObj[primitives.LOGIN_CONSENT_WEBHOOK_VDXF_KEY.vdxfid];
}
+
const tryRedirect = async () => {
try {
setLoading(true);
@@ -115,19 +85,11 @@ const LoginRequestComplete = props => {
return (
- {attestationObj && setShowAttestation(false)},
- {disabled: false, onPress: () => {storeAttestation(); setShowAttestation(false);}, text: "save"},]}
- mainTitle={"Attestation Received"}
- />}
+ style={{...Styles.fullWidth, ...Styles.backgroundColorWhite}}
+ contentContainerStyle={{
+ ...Styles.focalCenter,
+ justifyContent: 'space-between',
+ }}>
{
fontSize: 20,
color: Colors.verusDarkGray,
}}>
- {loading ? attestationPresent ? "Retrieving Attestation" : "Loading..." : 'Success!'}
+ {loading ? "Loading..." : 'Success!'}
{loading ? (
diff --git a/src/containers/DeepLink/LoginRequestIdentity/LoginRequestIdentity.js b/src/containers/DeepLink/LoginRequestIdentity/LoginRequestIdentity.js
index 20a2e7cd..1ba32c0a 100644
--- a/src/containers/DeepLink/LoginRequestIdentity/LoginRequestIdentity.js
+++ b/src/containers/DeepLink/LoginRequestIdentity/LoginRequestIdentity.js
@@ -27,7 +27,6 @@ const LoginRequestIdentity = props => {
const [sortedIds, setSortedIds] = useState({});
const [idProvisionSuccess, setIdProvisionSuccess] = useState(false)
const [canProvision, setCanProvision] = useState(false)
- const [attestationID, setattestationID] = useState('')
const req = new primitives.LoginConsentRequest(deeplinkData)
const encryptedIds = useSelector(state => state.services.stored[VERUSID_SERVICE_ID])
const sendModal = useSelector((state) => state.sendModal);
@@ -98,44 +97,9 @@ const LoginRequestIdentity = props => {
const data = {[SEND_MODAL_IDENTITY_TO_LINK_FIELD]: passthrough.fqnToAutoLink, noLogin: noLogin};
openLinkIdentityModal(CoinDirectory.findCoinObj(system_id, null, true), data);
}
- }, [extraParams])
+ }, [passthrough])
- useEffect(() => {
-
- if (idsloaded && req.challenge.subject && req.challenge.subject.length > 0 &&
- req.challenge.subject.some(item => item.vdxfkey === primitives.ID_ADDRESS_VDXF_KEY.vdxfid)) {
-
- const providionedId = req.challenge.subject.find(item => item.vdxfkey === primitives.ID_ADDRESS_VDXF_KEY.vdxfid).data;
- if(req.challenge.redirect_uris && req.challenge.redirect_uris
- .some((uriKey) => uriKey.vdxfkey === primitives.LOGIN_CONSENT_ATTESTATION_WEBHOOK_VDXF_KEY.vdxfid)){
- // if an attestation is provided, set the attestationID so it only shows the attestation the ID is for.
- setattestationID(providionedId)
- }
-
- for (const chainId of activeCoinIds) {
- if (linkedIds[chainId] && Object.keys(linkedIds[chainId]).includes(providionedId)) {
- return;
- }
- }
- getIdentity(system_id, providionedId).then((provisionedID) => {
- getPotentialPrimaryAddresses().then((addresses) => {
- if (provisionedID.result) {
- for (const address of provisionedID.result.identity.primaryaddresses) {
- if (addresses.includes(address)) {
- dispatch({
- type: SET_DEEPLINK_DATA_EXTRAPARAMS,
- payload: {
- extraParams: { fqn: provisionedID.result.fullyqualifiedname }
- },
- });
- return;
- }
- }
- }
- })
- })
- }
- }, [idsloaded])
+ //TODO: add a check that checks to see if the ID is ready, and relates to the provider.
useEffect(() => {
onEncryptedIdsUpdate()
@@ -221,9 +185,6 @@ const LoginRequestIdentity = props => {
{`Linked ${chainId} VerusIDs`}
)}
{sortedIds[chainId].map(iAddr => {
- if(attestationID && attestationID !== iAddr) {
- return null
- }
return (
diff --git a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
index 407cf4f1..1c808c4e 100644
--- a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
+++ b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
@@ -1,5 +1,5 @@
-import React, { useState, useEffect } from 'react';
-import { Alert, SafeAreaView, ScrollView, TouchableOpacity, View } from 'react-native';
+import React, {useState, useEffect} from 'react';
+import {SafeAreaView, ScrollView, TouchableOpacity, View} from 'react-native';
import Styles from '../../../styles/index';
import { primitives } from "verusid-ts-client"
import { Button, Divider, List, Portal, Text } from 'react-native-paper';
@@ -17,9 +17,6 @@ import { createAlert, resolveAlert } from '../../../actions/actions/alert/dispat
import { CoinDirectory } from '../../../utils/CoinData/CoinDirectory';
import { addCoin, addKeypairs, setUserCoins } from '../../../actions/actionCreators';
import { refreshActiveChainLifecycles } from '../../../actions/actions/intervals/dispatchers/lifecycleManager';
-import { requestServiceStoredData } from '../../../utils/auth/authBox';
-import { VERUSID_SERVICE_ID } from '../../../utils/constants/services';
-import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
const LoginRequestInfo = props => {
const { deeplinkData, sigtime, cancel, signerFqn } = props
@@ -115,103 +112,6 @@ const LoginRequestInfo = props => {
setReq(new primitives.LoginConsentRequest(deeplinkData))
}, [deeplinkData]);
- const buildAlert = (request) => {
- return createAlert(
- request.title,
- request.data,
- [
- {
- text: 'DECLINE',
- onPress: () => resolveAlert(false),
- style: 'cancel',
- },
- {
- text: 'ACCEPT', onPress: () => {
-
- var _permissions = [];
- for (let i = 0; i < permissions.length; i++) {
- _permissions.push(permissions[i]);
- if (_permissions[i].vdxfkey == request.vdxfkey) {
- _permissions[i].agreed = true;
- }
- }
- setExtraPermissions(_permissions);
-
- resolveAlert(true)
- }
- },
- ],
- {
- cancelable: true,
- },
- )
- }
-
-
- useEffect(() => {
-
- if (req && req.challenge && req.challenge.requested_access) {
- var tempMethod = 0;
- var attestationProvided = -1;
-
- if (req.challenge.redirect_uris.length > 0) {
- attestationProvided = req.challenge.redirect_uris.map((data) => data.vdxfkey).indexOf(primitives.LOGIN_CONSENT_ATTESTATION_WEBHOOK_VDXF_KEY.vdxfid)
- }
-
- var tempdata = {};
- if ((req.challenge.requested_access.length > 1) || (attestationProvided > -1) && !permissions) {
- var loginTemp = [];
- for (let i = 1; i < req.challenge.requested_access.length; i++) {
- if (req.challenge.requested_access[i].vdxfkey === primitives.IDENTITY_AGREEMENT.vdxfid) {
- tempMethod = tempMethod | 1;
- tempdata = { data: req.challenge.requested_access[i].toJson().data, title: "Agreement to accept" }
- }
- // TODO: Add support for viewing identity data
- loginTemp.push({ vdxfkey: req.challenge.requested_access[i].vdxfkey, ...tempdata, agreed: false })
- }
- if (attestationProvided > -1) {
- tempMethod = tempMethod | 4;
- if (!req.challenge.subject.some((subject) => subject.vdxfkey === primitives.ID_ADDRESS_VDXF_KEY.vdxfid)) {
- throw new Error("Attestation requested without ID Specified");
- }
- const attestationId = req.challenge.subject.find((subject) => subject.vdxfkey === primitives.ID_ADDRESS_VDXF_KEY.vdxfid).data;
-
- requestServiceStoredData(VERUSID_SERVICE_ID).then((verusIdServiceData) => {
-
- if (verusIdServiceData.linked_ids)
-
- for (const chainId of Object.keys(verusIdServiceData.linked_ids)) {
- if (verusIdServiceData.linked_ids[chainId] &&
- Object.keys(verusIdServiceData.linked_ids[chainId])
- .includes(attestationId)) {
- loginTemp.push({ vdxfkey: primitives.LOGIN_CONSENT_ATTESTATION_WEBHOOK_VDXF_KEY.vdxfid,
- title: verusIdServiceData.linked_ids[chainId][attestationId],
- data: "Contains an Attestation for",
- agreed: true,
- nonChecked: true })
- }
- }
- setExtraPermissions(loginTemp);
- })
- }
- if (tempMethod > 5) Alert.alert("Error", "Invalid login method");
- } else if (req.challenge.requested_access.length === 1) {
- setReady(true);
- }
- setLoginMethod(tempMethod);
- }
- }, []);
-
- useEffect(() => {
- if (permissions) {
- for (let i = 0; i < permissions.length; i++) {
- if (!permissions[i].agreed)
- return;
- }
- setReady(true);
- }
- }, [permissions]);
-
useEffect(() => {
setSigDateString(unixToDate(sigtime))
}, [sigtime]);
@@ -394,25 +294,6 @@ const LoginRequestInfo = props => {
- {permissions && permissions.map((request, index) => {
- return (
- !!request.nonChecked ? null : buildAlert(request) }>
- (
- !!!request.nonChecked &&
- )}
- left= {() => }
- />
-
-
- );
- })}
{
- return await axios.post(
- uri,
- response
- );
- },
[primitives.LOGIN_CONSENT_REDIRECT_VDXF_KEY.vdxfid]: (uri, response) => {
const url = new URL(uri)
const res = new primitives.LoginConsentResponse(response)
From fcb15f13d1f843070c4483915cd99ef343fb4509 Mon Sep 17 00:00:00 2001
From: Chris <34682781+monkins1010@users.noreply.github.com>
Date: Thu, 7 Mar 2024 07:40:05 +0000
Subject: [PATCH 03/10] Updates for attestations
---
.gitignore | 18 ++++
package.json | 3 +-
src/containers/DeepLink/DeepLink.js | 2 +-
.../LoginRequestInfo/LoginRequestInfo.js | 97 ++++++++++++++++++-
.../PersonalSelectData/PersonalSelectData.js | 88 +++++++++++++++++
.../PersonalSelectData.render.js | 19 ++++
.../DeepLinkStackScreens.js | 10 +-
src/utils/nativeStore/personalDataStorage.js | 67 +++++++++++++
yarn.lock | 32 +++++-
9 files changed, 327 insertions(+), 9 deletions(-)
create mode 100644 src/containers/DeepLink/PersonalSelectData/PersonalSelectData.js
create mode 100644 src/containers/DeepLink/PersonalSelectData/PersonalSelectData.render.js
create mode 100644 src/utils/nativeStore/personalDataStorage.js
diff --git a/.gitignore b/.gitignore
index 89f70fad..758474b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -112,3 +112,21 @@ android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png
+package.json
+yarn.lock
+android/app/src/main/assets/index.android.bundle
+android/app/src/main/res/drawable-hdpi/node_modules_reactnavigation_drawer_src_views_assets_toggledrawericon.png
+android/app/src/main/res/drawable-hdpi/node_modules_reactnavigation_elements_src_assets_backicon.png
+android/app/src/main/res/drawable-mdpi/node_modules_reactnative_libraries_newappscreen_components_logo.png
+android/app/src/main/res/drawable-mdpi/node_modules_reactnavigation_drawer_src_views_assets_toggledrawericon.png
+android/app/src/main/res/drawable-mdpi/node_modules_reactnavigation_elements_src_assets_backicon.png
+android/app/src/main/res/drawable-mdpi/node_modules_reactnavigation_elements_src_assets_backiconmask.png
+android/app/src/main/res/drawable-mdpi/src_images_customicons_coinsicon.png
+android/app/src/main/res/drawable-mdpi/src_images_customicons_recovericon.png
+android/app/src/main/res/drawable-mdpi/src_images_customicons_revokeicon.png
+android/app/src/main/res/drawable-xhdpi/node_modules_reactnavigation_drawer_src_views_assets_toggledrawericon.png
+android/app/src/main/res/drawable-xhdpi/node_modules_reactnavigation_elements_src_assets_backicon.png
+android/app/src/main/res/drawable-xxhdpi/node_modules_reactnavigation_drawer_src_views_assets_toggledrawericon.png
+android/app/src/main/res/drawable-xxhdpi/node_modules_reactnavigation_elements_src_assets_backicon.png
+android/app/src/main/res/drawable-xxxhdpi/node_modules_reactnavigation_drawer_src_views_assets_toggledrawericon.png
+android/app/src/main/res/drawable-xxxhdpi/node_modules_reactnavigation_elements_src_assets_backicon.png
diff --git a/package.json b/package.json
index 99b2bbd6..376693c6 100755
--- a/package.json
+++ b/package.json
@@ -118,7 +118,7 @@
"uuid": "8.0.0",
"version_compare": "0.0.3",
"verus-pay-utils": "git+https://github.com/michaeltout/verus-pay-utils.git",
- "verus-typescript-primitives": "https://github.com/VerusCoin/verus-typescript-primitives.git",
+ "verus-typescript-primitives": "file:d:/dev/verus-typescript-primitives",
"verus-zkedid-utils": "git+https://github.com/michaeltout/verus-zkedid-utils.git",
"verusd-rpc-ts-client": "git+https://github.com/VerusCoin/verusd-rpc-ts-client.git",
"verusid-ts-client": "git+https://github.com/VerusCoin/verusid-ts-client.git",
@@ -223,6 +223,7 @@
"@babel/core": "7.21.3",
"blake2b-wasm": "https://github.com/michaeltout/blake2b-wasm/",
"@bitgo/blake2b-wasm": "https://github.com/michaeltout/blake2b-wasm/",
+ "verus-typescript-primitives": "file:d:/dev/verus-typescript-primitives",
"browserify-sign": "4.2.2"
},
"jest": {
diff --git a/src/containers/DeepLink/DeepLink.js b/src/containers/DeepLink/DeepLink.js
index d6f310c1..c6dca947 100644
--- a/src/containers/DeepLink/DeepLink.js
+++ b/src/containers/DeepLink/DeepLink.js
@@ -21,7 +21,7 @@ import { getCurrency, getIdentity } from '../../utils/api/channels/verusid/callC
import { convertFqnToDisplayFormat } from '../../utils/fullyqualifiedname';
import { resetDeeplinkData } from '../../actions/actionCreators';
-const authorizedPermissions = [primitives.IDENTITY_VIEW.vdxfid,/*TODO: primitives.IDENTITY_AGREEMENT.vdxfid, primitives.ATTESTATION_READ_REQUEST.vdxfid */]
+const authorizedPermissions = [primitives.IDENTITY_VIEW.vdxfid, primitives.IDENTITY_AGREEMENT.vdxfid, primitives.ATTESTATION_READ_REQUEST.vdxfid, primitives.PROFILE_DATA_VIEW_REQUEST.vdxfid]
import { CoinDirectory } from '../../utils/CoinData/CoinDirectory';
import BigNumber from 'bignumber.js';
import { blocksToTime, satsToCoins } from '../../utils/math';
diff --git a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
index 1c808c4e..ac5ab14f 100644
--- a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
+++ b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
@@ -29,6 +29,8 @@ const LoginRequestInfo = props => {
const signedIn = useSelector(state => state.authentication.signedIn)
const passthrough = useSelector((state) => state.deeplink.passthrough);
const sendModalType = useSelector(state => state.sendModal.type)
+ const [permissions, setExtraPermissions] = useState(null);
+ const [ready, setReady] = useState(false);
const dispatch = useDispatch()
@@ -121,6 +123,74 @@ const LoginRequestInfo = props => {
setLoading(false)
} else setLoading(true)
}, [sendModalType]);
+
+ const buildAlert = (request) => {
+ return createAlert(
+ request.title,
+ request.data,
+ [
+ {
+ text: 'DECLINE',
+ onPress: () => resolveAlert(false),
+ style: 'cancel',
+ },
+ {
+ text: 'ACCEPT', onPress: () => {
+ const _permissions = permissions.map(permission => {
+ if (permission.vdxfkey === request.vdxfkey) {
+ return { ...permission, agreed: true };
+ }
+ return permission;
+ });
+ setExtraPermissions(_permissions);
+ resolveAlert(true)
+ props.navigation.navigate("PersonalSelectData");
+
+ }
+ },
+ ],
+ {cancelable: true});
+ }
+
+
+ useEffect(() => {
+
+ if (req && req.challenge && req.challenge.requested_access) {
+ if (req.challenge.requested_access.length === 1 && req.challenge.requested_access.some(primitives.IDENTITY_VIEW.vdxfid)) {
+ setReady(true);
+ } else {
+ var loginTemp = [];
+ for (let i = 0; i < req.challenge.requested_access.length; i++) {
+ var tempdata = {};
+
+ if (req.challenge.requested_access[i].vdxfkey === primitives.IDENTITY_VIEW.vdxfid) {
+ continue;
+ } else if (req.challenge.requested_access[i].vdxfkey === primitives.IDENTITY_AGREEMENT.vdxfid) {
+ tempdata = { data: req.challenge.requested_access[i].toJson().data, title: "Agreement to accept" }
+ } else if (req.challenge.requested_access[i].vdxfkey === primitives.ATTESTATION_READ_REQUEST.vdxfid) {
+ tempdata = { data: "Agree to share attestation data", title: "Attestation View Request" }
+ } else if (req.challenge.requested_access[i].vdxfkey === primitives.PROFILE_DATA_VIEW_REQUEST.vdxfid) {
+ tempdata = { data: "Agree to share profile data", title: "Personal Data Input Request" }
+
+ }
+ loginTemp.push({ vdxfkey: req.challenge.requested_access[i].vdxfkey, ...tempdata, agreed: false })
+ }
+ setExtraPermissions(loginTemp);
+ }
+ }
+ }, [req]);
+
+ useEffect(() => {
+ if (permissions) {
+ for (let i = 0; i < permissions.length; i++) {
+ if (!permissions[i].agreed)
+ return;
+ }
+ setReady(true);
+ }
+ }, [permissions]);
+
+
const addRootSystem = async () => {
setLoading(true)
@@ -189,8 +259,14 @@ const LoginRequestInfo = props => {
}
}
- const handleContinue = () => {
+ const handleContinue = async () => {
if (signedIn) {
+ if (!ready) {
+ for (let i = 0; i < permissions.length; i++) {
+ const result = await buildAlert(permissions[i], i);
+ if (!result) return;
+ }
+ }
const coinObj = CoinDirectory.findCoinObj(chain_id);
if (!!coinObj.testnet != isTestnet) {
createAlert(
@@ -294,6 +370,23 @@ const LoginRequestInfo = props => {
+ {permissions && permissions.map((request, index) => {
+ return (
+ buildAlert(request)}>
+ (
+
+ )} />
+
+
+ );
+ })}
{
Cancel
@@ -63,11 +47,11 @@ export const PersonalSelectDataRender = function () {
cancel()}>
+ onPress={() => this.cancel()}>
Cancel
this.handleContinue()}>
Accept
diff --git a/src/containers/Personal/PersonalLocations/PersonalLocationsEditAddress/PersonalLocationsEditAddress.js b/src/containers/Personal/PersonalLocations/PersonalLocationsEditAddress/PersonalLocationsEditAddress.js
index e8166f87..a0627ec5 100644
--- a/src/containers/Personal/PersonalLocations/PersonalLocationsEditAddress/PersonalLocationsEditAddress.js
+++ b/src/containers/Personal/PersonalLocations/PersonalLocationsEditAddress/PersonalLocationsEditAddress.js
@@ -57,7 +57,7 @@ class PersonalLocationsEditAddress extends Component {
title: "State/Province/Region",
placeholder: "optional"
},
- [IDENTITYDATA_HOMEADDRESS_COUNTRY.vdxfid]: {
+ [IDENTITYDATA_HOMEADDRESS_POSTCODE.vdxfid]: {
title: "ZIP/Postal Code",
placeholder: "required"
}
diff --git a/src/containers/Personal/PersonalPaymentMethods/PersonalPaymentMethodsEditBankAccount/PersonalPaymentMethodsEditBankAccount.js b/src/containers/Personal/PersonalPaymentMethods/PersonalPaymentMethodsEditBankAccount/PersonalPaymentMethodsEditBankAccount.js
index 946c9eb0..67eca566 100644
--- a/src/containers/Personal/PersonalPaymentMethods/PersonalPaymentMethodsEditBankAccount/PersonalPaymentMethodsEditBankAccount.js
+++ b/src/containers/Personal/PersonalPaymentMethods/PersonalPaymentMethodsEditBankAccount/PersonalPaymentMethodsEditBankAccount.js
@@ -38,6 +38,8 @@ import {
PERSONAL_BANK_CLABE
} from "../../../../utils/constants/personal";
import { PersonalPaymentMethodsEditBankAccountRender } from "./PersonalPaymentMethodsEditBankAccount.render"
+import { primitives } from "verus-typescript-primitives"
+const { IDENTITYDATA_HOMEADDRESS_STREET1, IDENTITYDATA_HOMEADDRESS_STREET2, IDENTITYDATA_HOMEADDRESS_CITY, IDENTITYDATA_HOMEADDRESS_REGION, IDENTITYDATA_HOMEADDRESS_POSTCODE, IDENTITYDATA_HOMEADDRESS_COUNTRY } = primitives;
class PersonalPaymentMethodsEditBankAccount extends Component {
constructor(props) {
@@ -56,12 +58,12 @@ class PersonalPaymentMethodsEditBankAccount extends Component {
[PERSONAL_BANK_BENEFICIARY_TYPE]:
PERSONAL_BENEFICIARY_TYPE_INDIVIDUAL,
[PERSONAL_BANK_BENEFICIARY_PHYSICAL_ADDRESS]: {
- street1: "",
- street2: "",
- city: "",
- state_province_region: "",
- postal_code: "",
- country: "",
+ [IDENTITYDATA_HOMEADDRESS_STREET1.vdxfid]: "",
+ [IDENTITYDATA_HOMEADDRESS_STREET2.vdxfid]: "",
+ [IDENTITYDATA_HOMEADDRESS_CITY.vdxfid]: "",
+ [IDENTITYDATA_HOMEADDRESS_REGION.vdxfid]: "",
+ [IDENTITYDATA_HOMEADDRESS_POSTCODE.vdxfid]: "",
+ [IDENTITYDATA_HOMEADDRESS_COUNTRY.vdxfid]: "",
},
[PERSONAL_BANK_BENEFICIARY_NAME_FIRST]: "",
[PERSONAL_BANK_BENEFICIARY_NAME_LAST]: "",
diff --git a/src/utils/deeplink/handlePersonalDataSend.js b/src/utils/deeplink/handlePersonalDataSend.js
new file mode 100644
index 00000000..8dfb8118
--- /dev/null
+++ b/src/utils/deeplink/handlePersonalDataSend.js
@@ -0,0 +1,18 @@
+import axios from "axios";
+import { primitives } from "verus-typescript-primitives"
+
+
+const handlers = {
+ [primitives.LOGIN_CONSENT_PERSONALINFO_WEBHOOK_VDXF_KEY.vdxfid]: async (uri, response) => {
+ return await axios.post(
+ uri,
+ response
+ );
+ }
+}
+
+export const handlePersonalDataSend = (response, redirectinfo) => {
+ const { vdxfkey, uri } = redirectinfo
+
+ return handlers[vdxfkey] == null ? null : handlers[vdxfkey](uri, response);
+}
\ No newline at end of file
diff --git a/src/utils/personal/displayUtils.js b/src/utils/personal/displayUtils.js
index bd269db5..6c0b313d 100644
--- a/src/utils/personal/displayUtils.js
+++ b/src/utils/personal/displayUtils.js
@@ -9,30 +9,41 @@ import {
import { Platform } from 'react-native';
var RNFS = require('react-native-fs');
import { primitives } from "verusid-ts-client"
+import { requestPersonalData } from "../auth/authBox";
+import {
+ PERSONAL_ATTRIBUTES,
+ PERSONAL_CONTACT,
+ PERSONAL_LOCATIONS,
+ PERSONAL_PAYMENT_METHODS,
+ PERSONAL_IMAGES,
+} from "../constants/personal";
+
+import { AttestationVdxfidMap } from 'verus-typescript-primitives/dist/vdxf/classes/attestationData.js';
+import Colors from '../../globals/colors';
+
const { IDENTITYDATA_FIRSTNAME, IDENTITYDATA_LASTNAME, IDENTITYDATA_MIDDLENAME,
- BANK_ACCOUNT_COUNTRY, BANK_ACCOUNT_CURRENCY, BANK_ACCOUNT_NUMBER, BANK_ACCOUNT_TYPE} = primitives;
- const { IDENTITYDATA_HOMEADDRESS_STREET1, IDENTITYDATA_HOMEADDRESS_STREET2, IDENTITYDATA_HOMEADDRESS_CITY, IDENTITYDATA_HOMEADDRESS_REGION, IDENTITYDATA_HOMEADDRESS_POSTCODE, IDENTITYDATA_HOMEADDRESS_COUNTRY } = primitives;
+ BANK_ACCOUNT_COUNTRY, BANK_ACCOUNT_CURRENCY, BANK_ACCOUNT_NUMBER, BANK_ACCOUNT_TYPE } = primitives;
+const { IDENTITYDATA_HOMEADDRESS_STREET1, IDENTITYDATA_HOMEADDRESS_STREET2, IDENTITYDATA_HOMEADDRESS_CITY, IDENTITYDATA_HOMEADDRESS_REGION, IDENTITYDATA_HOMEADDRESS_POSTCODE, IDENTITYDATA_HOMEADDRESS_COUNTRY } = primitives;
+const { IDENTITYDATA_CONTACT, IDENTITYDATA_PERSONAL_DETAILS, IDENTITYDATA_LOCATIONS, IDENTITYDATA_DOCUMENTS_AND_IMAGES, IDENTITYDATA_BANKING_INFORMATION } = primitives;
+
export const renderPersonalFullName = (state) => {
return {
- title: `${state[IDENTITYDATA_FIRSTNAME.vdxfid]} ${
- state[IDENTITYDATA_MIDDLENAME.vdxfid] != null && state[IDENTITYDATA_MIDDLENAME.vdxfid] > 0 ? state[IDENTITYDATA_MIDDLENAME.vdxfid] + " " : ""
- }${state[IDENTITYDATA_LASTNAME.vdxfid]}`
+ title: `${state[IDENTITYDATA_FIRSTNAME.vdxfid]} ${state[IDENTITYDATA_MIDDLENAME.vdxfid] != null && state[IDENTITYDATA_MIDDLENAME.vdxfid] > 0 ? state[IDENTITYDATA_MIDDLENAME.vdxfid] + " " : ""
+ }${state[IDENTITYDATA_LASTNAME.vdxfid]}`
};
};
export const renderPersonalPhoneNumber = (phone, includeEmoji = true) => {
return {
- title: `${
- includeEmoji &&
+ title: `${includeEmoji &&
CALLING_CODES_TO_ISO_3166[phone.calling_code] != null &&
ISO_3166_COUNTRIES[CALLING_CODES_TO_ISO_3166[phone.calling_code]] != null
- ? ISO_3166_COUNTRIES[CALLING_CODES_TO_ISO_3166[phone.calling_code]]
- .emoji + " "
- : ""
- }${phone.calling_code.length > 0 ? phone.calling_code : "+0"} ${
- phone.number.length > 0 ? phone.number : "000000000"
- }`,
+ ? ISO_3166_COUNTRIES[CALLING_CODES_TO_ISO_3166[phone.calling_code]]
+ .emoji + " "
+ : ""
+ }${phone.calling_code.length > 0 ? phone.calling_code : "+0"} ${phone.number.length > 0 ? phone.number : "000000000"
+ }`,
};
};
@@ -78,14 +89,13 @@ export const renderPersonalDocument = (document) => {
document.image_type == null
? 'Document'
: PERSONAL_IMAGE_TYPE_SCHEMA[document.image_type] == null
- ? "??"
- : `${PERSONAL_IMAGE_TYPE_SCHEMA[document.image_type].title}${
- document.image_subtype == null ||
+ ? "??"
+ : `${PERSONAL_IMAGE_TYPE_SCHEMA[document.image_type].title}${document.image_subtype == null ||
PERSONAL_IMAGE_SUBTYPE_SCHEMA[document.image_subtype] == null
- ? ""
- : ` (${PERSONAL_IMAGE_SUBTYPE_SCHEMA[
- document.image_subtype
- ].title.toLowerCase()})`
+ ? ""
+ : ` (${PERSONAL_IMAGE_SUBTYPE_SCHEMA[
+ document.image_subtype
+ ].title.toLowerCase()})`
}`,
};
};
@@ -107,17 +117,14 @@ export const renderPersonalAddress = (address) => {
return {
title:
address[IDENTITYDATA_HOMEADDRESS_COUNTRY.vdxfid].length > 0
- ? `${address[IDENTITYDATA_HOMEADDRESS_STREET1.vdxfid]}${
- address[IDENTITYDATA_HOMEADDRESS_STREET2.vdxfid] != null && address[IDENTITYDATA_HOMEADDRESS_STREET2.vdxfid].length > 0 ? `, ${address[IDENTITYDATA_HOMEADDRESS_STREET2.vdxfid]}` : ""
- }`
+ ? `${address[IDENTITYDATA_HOMEADDRESS_STREET1.vdxfid]}${address[IDENTITYDATA_HOMEADDRESS_STREET2.vdxfid] != null && address[IDENTITYDATA_HOMEADDRESS_STREET2.vdxfid].length > 0 ? `, ${address[IDENTITYDATA_HOMEADDRESS_STREET2.vdxfid]}` : ""
+ }`
: "Empty address",
- description: `${address[IDENTITYDATA_HOMEADDRESS_POSTCODE.vdxfid].length > 0 ? `${address[IDENTITYDATA_HOMEADDRESS_POSTCODE.vdxfid]} ` : ""}${
- address[IDENTITYDATA_HOMEADDRESS_REGION.vdxfid]?.length > 0 ? `${address[IDENTITYDATA_HOMEADDRESS_REGION.vdxfid]}, ` : ""
- }${address[IDENTITYDATA_HOMEADDRESS_CITY.vdxfid]?.length > 0 ? `${address[IDENTITYDATA_HOMEADDRESS_CITY.vdxfid]}, ` : "Unknown City, "}${
- ISO_3166_COUNTRIES[address[IDENTITYDATA_HOMEADDRESS_COUNTRY.vdxfid]] != null
+ description: `${address[IDENTITYDATA_HOMEADDRESS_POSTCODE.vdxfid].length > 0 ? `${address[IDENTITYDATA_HOMEADDRESS_POSTCODE.vdxfid]} ` : ""}${address[IDENTITYDATA_HOMEADDRESS_REGION.vdxfid]?.length > 0 ? `${address[IDENTITYDATA_HOMEADDRESS_REGION.vdxfid]}, ` : ""
+ }${address[IDENTITYDATA_HOMEADDRESS_CITY.vdxfid]?.length > 0 ? `${address[IDENTITYDATA_HOMEADDRESS_CITY.vdxfid]}, ` : "Unknown City, "}${ISO_3166_COUNTRIES[address[IDENTITYDATA_HOMEADDRESS_COUNTRY.vdxfid]] != null
? `${ISO_3166_COUNTRIES[address[IDENTITYDATA_HOMEADDRESS_COUNTRY.vdxfid]].emoji} ${ISO_3166_COUNTRIES[address[IDENTITYDATA_HOMEADDRESS_COUNTRY.vdxfid]].name}`
: "Unknown Country"
- }`,
+ }`,
};
}
@@ -129,14 +136,100 @@ export const renderPersonalBankAccount = (account) => {
account[BANK_ACCOUNT_NUMBER.vdxfid] != null && account[BANK_ACCOUNT_NUMBER.vdxfid].length > 4
? ` ending in ${account[BANK_ACCOUNT_NUMBER.vdxfid].slice(-4)}`
: "";
- const accountDescription = `${
- account[BANK_ACCOUNT_CURRENCY.vdxfid] != null && account[BANK_ACCOUNT_CURRENCY.vdxfid].length > 0
- ? account[BANK_ACCOUNT_CURRENCY.vdxfid] + " "
- : ""
- }${account[BANK_ACCOUNT_TYPE.vdxfid]}`;
+ const accountDescription = `${account[BANK_ACCOUNT_CURRENCY.vdxfid] != null && account[BANK_ACCOUNT_CURRENCY.vdxfid].length > 0
+ ? account[BANK_ACCOUNT_CURRENCY.vdxfid] + " "
+ : ""
+ }${account[BANK_ACCOUNT_TYPE.vdxfid]}`;
return {
title: `${accountLocaleString}${accountNumberString}`,
description: accountDescription,
};
-};
\ No newline at end of file
+};
+
+/********************************/
+// template defaultPersonalProfileDataTemplate in the order:
+// new PersonalDataCategory(),
+// new ContactDataCategory(),
+// new LocationDataCategory(),
+// new BankingDataCategory(),
+// new DocumentsCategory()
+/********************************/
+
+export const checkPersonalDataCatagories = async (profileDataRequested = []) => {
+ let success = true;
+ await Promise.all(Object.keys(profileDataRequested).map(async (permission) => {
+ let errorDetails = "";
+ let profiletype;
+ let optionalKeys = {}
+
+ switch (permission) {
+
+ case IDENTITYDATA_PERSONAL_DETAILS.vdxfid:
+ attributes = await requestPersonalData(PERSONAL_ATTRIBUTES);
+ optionalKeys = { [primitives.IDENTITYDATA_MIDDLENAME.vdxfid]: true };
+ profiletype = primitives.defaultPersonalProfileDataTemplate[0].data;
+ break;
+ case IDENTITYDATA_CONTACT.vdxfid:
+ attributes = await requestPersonalData(PERSONAL_CONTACT);
+ profiletype = primitives.defaultPersonalProfileDataTemplate[1].data;
+ break;
+ case IDENTITYDATA_LOCATIONS.vdxfid:
+ const locationReply = await requestPersonalData(PERSONAL_LOCATIONS);
+ attributes = locationReply.physical_addresses && locationReply.physical_addresses.length > 0 ? locationReply.physical_addresses[0] : {};
+ optionalKeys = { [primitives.IDENTITYDATA_HOMEADDRESS_STREET2.vdxfid]: true };
+ profiletype = primitives.defaultPersonalProfileDataTemplate[2].data;
+ break;
+ case IDENTITYDATA_BANKING_INFORMATION.vdxfid:
+ const bankRetval = await checkBankAccountPresent();
+ attributes = bankRetval.attributes;
+ profiletype = bankRetval.profiletype;
+ break;
+ case IDENTITYDATA_DOCUMENTS_AND_IMAGES.vdxfid:
+ const retval = await checkDocumentsPresent();
+ attributes = retval.attributes;
+ profiletype = retval.profiletype;
+ break;
+ }
+
+ profiletype.forEach((templateCategory) => {
+ const one = attributes[templateCategory.vdxfkey];
+ if (!optionalKeys[templateCategory.vdxfkey] && ((typeof one === 'object' && Array.isArray(one) && one.length === 0) ||
+ (typeof one === 'object' && Object.keys(one).length === 0) ||
+ (typeof one === 'string' && one.length === 0))) {
+ errorDetails += `${AttestationVdxfidMap[templateCategory.vdxfkey]?.name || templateCategory.vdxfkey}, `;
+ }
+ })
+
+ if (errorDetails.length > 0) {
+ profileDataRequested[permission].details = "Missing: " + errorDetails + " please add.";
+ profileDataRequested[permission].color = Colors.warningButtonColor;
+ success = false;
+ }
+
+ }));
+ return success;
+}
+
+export const checkBankAccountPresent = async () => {
+
+ const paymentMethods = await requestPersonalData(PERSONAL_PAYMENT_METHODS);
+
+ if (!paymentMethods.bank_accounts || paymentMethods.bank_accounts.length === 0) {
+ return { profiletype: [{ vdxfkey: primitives.BANK_ACCOUNT.vdxfid }], attributes: { [primitives.BANK_ACCOUNT.vdxfid]: "" } };
+ }
+ return { profiletype: [{ vdxfkey: primitives.BANK_ACCOUNT.vdxfid }], attributes: { [primitives.BANK_ACCOUNT.vdxfid]: "OK" } };
+}
+
+export const checkDocumentsPresent = async () => {
+
+ const images = await requestPersonalData(PERSONAL_IMAGES);
+
+ if (!images.documents || images.documents.length === 0) {
+ return { profiletype: [{ vdxfkey: primitives.IDENTITYDATA_DOCUMENTS_AND_IMAGES.vdxfid }], attributes: { [primitives.IDENTITYDATA_DOCUMENTS_AND_IMAGES.vdxfid]: "" }};
+ }
+ return { profiletype: [{ vdxfkey: primitives.IDENTITYDATA_DOCUMENTS_AND_IMAGES.vdxfid }], attributes: { [primitives.IDENTITYDATA_DOCUMENTS_AND_IMAGES.vdxfid]: "OK" }};
+
+}
+
+export const checkPersonalDataKeys = () => { }
\ No newline at end of file
From 8b870c7606e39a029c0f1a2cdb9787a1fb67e651 Mon Sep 17 00:00:00 2001
From: Chris <34682781+monkins1010@users.noreply.github.com>
Date: Wed, 27 Mar 2024 09:08:41 +0000
Subject: [PATCH 08/10] Add personal info
---
index.js | 2 +-
metro.config.js | 4 +
package.json | 1 +
src/containers/DeepLink/DeepLink.js | 7 +-
.../LoginRequestInfo/LoginRequestInfo.js | 12 +--
.../PersonalSelectData/PersonalSelectData.js | 102 +++++++++++-------
.../PersonalSelectData.render.js | 5 +-
.../PersonalPaymentMethodsEditBankAccount.js | 2 +-
src/utils/deeplink/handlePersonalDataSend.js | 2 +-
src/utils/personal/displayUtils.js | 22 ++--
yarn.lock | 35 ++----
11 files changed, 108 insertions(+), 86 deletions(-)
diff --git a/index.js b/index.js
index 5a4eb85b..41d1a4ca 100644
--- a/index.js
+++ b/index.js
@@ -16,9 +16,9 @@ const IGNORED_LOGS = [
LogBox.ignoreLogs(IGNORED_LOGS);
+import './shims/crypto.js';
import App from './App';
import {name as appName} from './app.json';
-import './shims/crypto.js';
import './shims/stringify.js';
AppRegistry.registerComponent(appName, () => App);
diff --git a/metro.config.js b/metro.config.js
index ba3e67d0..d654bbc4 100644
--- a/metro.config.js
+++ b/metro.config.js
@@ -19,6 +19,10 @@ module.exports = (async () => {
resolver: {
assetExts: assetExts.filter(ext => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg'],
+ extraNodeModules: {
+ stream: require.resolve('readable-stream'),
+ crypto: require.resolve('react-native-crypto'),
+ }
},
};
})();
diff --git a/package.json b/package.json
index 376693c6..6acc793f 100755
--- a/package.json
+++ b/package.json
@@ -221,6 +221,7 @@
"@sideway/formula": "3.0.1",
"@babel/traverse": "7.23.2",
"@babel/core": "7.21.3",
+ "@bitgo/utxo-lib": "git+https://github.com/VerusCoin/BitGoJS.git#7c754d4a5920198d9fe6827d3e23bd5cf431f264",
"blake2b-wasm": "https://github.com/michaeltout/blake2b-wasm/",
"@bitgo/blake2b-wasm": "https://github.com/michaeltout/blake2b-wasm/",
"verus-typescript-primitives": "file:d:/dev/verus-typescript-primitives",
diff --git a/src/containers/DeepLink/DeepLink.js b/src/containers/DeepLink/DeepLink.js
index c6dca947..ea8f50bb 100644
--- a/src/containers/DeepLink/DeepLink.js
+++ b/src/containers/DeepLink/DeepLink.js
@@ -21,7 +21,12 @@ import { getCurrency, getIdentity } from '../../utils/api/channels/verusid/callC
import { convertFqnToDisplayFormat } from '../../utils/fullyqualifiedname';
import { resetDeeplinkData } from '../../actions/actionCreators';
-const authorizedPermissions = [primitives.IDENTITY_VIEW.vdxfid, primitives.IDENTITY_AGREEMENT.vdxfid, primitives.ATTESTATION_READ_REQUEST.vdxfid, primitives.PROFILE_DATA_VIEW_REQUEST.vdxfid]
+const authorizedPermissions = [primitives.IDENTITY_VIEW.vdxfid,
+ primitives.IDENTITY_AGREEMENT.vdxfid,
+ primitives.ATTESTATION_READ_REQUEST.vdxfid,
+ primitives.PROFILE_DATA_VIEW_REQUEST.vdxfid,
+ primitives.LOGIN_CONSENT_PERSONALINFO_WEBHOOK_VDXF_KEY.vdxfid,
+]
import { CoinDirectory } from '../../utils/CoinData/CoinDirectory';
import BigNumber from 'bignumber.js';
import { blocksToTime, satsToCoins } from '../../utils/math';
diff --git a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
index 7b9e85c2..25b73159 100644
--- a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
+++ b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
@@ -142,12 +142,14 @@ const LoginRequestInfo = props => {
return;
}
else if (request.openProfile) {
+ if(!signedIn) return;
props.navigation.navigate("PersonalSelectData",
{
deeplinkData,
fromService: false,
cancel: {cancel},
onGoBack: (data) => data ? setPermission(data) : () => {},
+ signerFqn
});
return;
}
@@ -164,16 +166,13 @@ const LoginRequestInfo = props => {
{
text: 'ACCEPT', onPress: () => {
setPermission();
- resolveAlert(true)
-
-
+ resolveAlert(true)
}
},
],
{cancelable: true});
}
-
useEffect(() => {
if (req && req.challenge && req.challenge.requested_access) {
@@ -192,7 +191,8 @@ const LoginRequestInfo = props => {
tempdata = { data: "Agree to share attestation data", title: "Attestation View Request", openAttestation: true }
} else if (req.challenge.requested_access[i].vdxfkey === primitives.PROFILE_DATA_VIEW_REQUEST.vdxfid) {
tempdata = { data: "Agree to share profile data", title: "Personal Data Input Request", openProfile: true }
-
+ } else if (req.challenge.requested_access[i].vdxfkey === primitives.LOGIN_CONSENT_PERSONALINFO_WEBHOOK_VDXF_KEY.vdxfid) {
+ continue;
}
loginTemp.push({ vdxfkey: req.challenge.requested_access[i].vdxfkey, ...tempdata, agreed: false })
}
@@ -400,7 +400,7 @@ const LoginRequestInfo = props => {
key={request}
{...props}
icon="check"
- style={{ borderRadius: 90, backgroundColor: request.agreed ? 'green' : 'grey' }}
+ style={{ borderRadius: 90, backgroundColor: request.agreed ? Colors.verusGreenColor : 'grey' }}
color={Colors.secondaryColor}
/>
)} />
diff --git a/src/containers/DeepLink/PersonalSelectData/PersonalSelectData.js b/src/containers/DeepLink/PersonalSelectData/PersonalSelectData.js
index 30e45274..b05274d4 100644
--- a/src/containers/DeepLink/PersonalSelectData/PersonalSelectData.js
+++ b/src/containers/DeepLink/PersonalSelectData/PersonalSelectData.js
@@ -1,14 +1,15 @@
import moment from "moment";
import { Component } from "react"
import { connect } from 'react-redux'
-import { createAlert } from "../../../actions/actions/alert/dispatchers/alert"
+import { createAlert, resolveAlert } from "../../../actions/actions/alert/dispatchers/alert"
import { modifyPersonalDataForUser } from "../../../actions/actionDispatchers";
import { requestPersonalData } from "../../../utils/auth/authBox";
-import { PERSONAL_ATTRIBUTES, PERSONAL_BIRTHDAY, PERSONAL_NATIONALITIES } from "../../../utils/constants/personal";
+import { PERSONAL_ATTRIBUTES, PERSONAL_CONTACT, PERSONAL_LOCATIONS, PERSONAL_PAYMENT_METHODS, PERSONAL_IMAGES } from "../../../utils/constants/personal";
import { provideCustomBackButton } from "../../../utils/navigation/customBack";
import { PersonalSelectDataRender } from "./PersonalSelectData.render"
-import { checkPersonalDataCatagories, checkPersonalDataKeys } from "../../../utils/personal/displayUtils";
-import { primitives } from "verus-typescript-primitives"
+import { checkPersonalDataCatagories } from "../../../utils/personal/displayUtils";
+import { handlePersonalDataSend } from "../../../utils/deeplink/handlePersonalDataSend";
+import { primitives } from "verusid-ts-client"
const { IDENTITYDATA_CONTACT, IDENTITYDATA_PERSONAL_DETAILS, IDENTITYDATA_LOCATIONS, IDENTITYDATA_DOCUMENTS_AND_IMAGES, IDENTITYDATA_BANKING_INFORMATION} = primitives;
@@ -47,7 +48,8 @@ class PersonalSelectData extends Component {
loading: false,
ready: false,
catagoriesRequested: null,
- personalDataURL: ""
+ personalDataURL: "",
+ signerFqn: this.props.route.params.signerFqn
};
}
@@ -92,53 +94,75 @@ class PersonalSelectData extends Component {
});
checkPersonalDataCatagories(catagoriesRequested).then((success) => {
- this.setState({ catagoriesRequested: catagoriesRequested, personalDataURL, ready: success});
+ this.setState({ catagoriesRequested: catagoriesRequested, personalDataURL: {vdxfkey: personalDataURL[0].vdxfkey ,uri: personalDataURL[0].data}, ready: success});
});
}
handleContinue() {
this.setState({loading: true});
- this.getPersonalDataFromCategories(personalData).then(() => {
- sendPersonalData(personalData, this.state.personalDataURL)
- .then(() => {
- this.setState({loading: false});
- this.props.route.params.onGoBack(true);
- this.props.navigation.goBack();
- })
- .catch((e) => {
- this.setState({loading: false});
- createAlert("Error", e.message);
- })
+ this.getPersonalDataFromCategories().then((personalData) => {
+
+ createAlert(
+ "Send Personal info",
+ "Are you sure you want to send your data to: \n" + `${this.state.signerFqn}`,
+ [
+ {
+ text: "No",
+ onPress: () => {
+ resolveAlert();
+ },
+ },
+ {
+ text: "Yes",
+ onPress: () => {
+ resolveAlert();
+ handlePersonalDataSend(personalData, this.state.personalDataURL)
+ .then(() => {
+ this.setState({loading: false});
+ this.props.route.params.onGoBack(true);
+ this.props.navigation.goBack();
+ })
+ },
+ },
+ ],
+ {
+ cancelable: false,
+ }
+ );
}
).catch((e) => {
this.setState({loading: false});
createAlert("Error", e.message);
- })};
+ });
+
+ };
async getPersonalDataFromCategories() {
let personalData = {};
- // await Promise.all(Object.keys(this.state.catagoriesRequested).forEach(async (categoryVdxfkey) => {
- // switch (categoryVdxfkey) {
- // case IDENTITYDATA_PERSONAL_DETAILS.vdxfid:
- // personalData[IDENTITYDATA_PERSONAL_DETAILS.vdxfid] = await requestPersonalData(PERSONAL_ATTRIBUTES);
- // break;
- // case IDENTITYDATA_CONTACT.vdxfid:
- // personalData[IDENTITYDATA_CONTACT.vdxfid] = await requestPersonalData(PERSONAL_CONTACT);
- // break;
- // case IDENTITYDATA_LOCATIONS.vdxfid:
- // personalData[IDENTITYDATA_LOCATIONS.vdxfid] = await requestPersonalData(PERSONAL_LOCATIONS);
- // break;
- // case IDENTITYDATA_BANKING_INFORMATION.vdxfid:
- // personalData[IDENTITYDATA_BANKING_INFORMATION.vdxfid] = await requestPersonalData(PERSONAL_PAYMENT_METHODS);
- // break;
- // case IDENTITYDATA_DOCUMENTS_AND_IMAGES.vdxfid:
- // personalData[IDENTITYDATA_DOCUMENTS_AND_IMAGES.vdxfid] = await requestPersonalData(PERSONAL_IMAGES);
- // break;
- // default:
- // break;
- // }
- // }));
+
+ await Promise.all(Object.keys(this.state.catagoriesRequested).map(async (categoryVdxfkey) => {
+ switch (categoryVdxfkey) {
+ case IDENTITYDATA_PERSONAL_DETAILS.vdxfid:
+ personalData[IDENTITYDATA_PERSONAL_DETAILS.vdxfid] = await requestPersonalData(PERSONAL_ATTRIBUTES);
+ break;
+ case IDENTITYDATA_CONTACT.vdxfid:
+ personalData[IDENTITYDATA_CONTACT.vdxfid] = await requestPersonalData(PERSONAL_CONTACT);
+ break;
+ case IDENTITYDATA_LOCATIONS.vdxfid:
+ personalData[IDENTITYDATA_LOCATIONS.vdxfid] = await requestPersonalData(PERSONAL_LOCATIONS);
+ break;
+ case IDENTITYDATA_BANKING_INFORMATION.vdxfid:
+ personalData[IDENTITYDATA_BANKING_INFORMATION.vdxfid] = await requestPersonalData(PERSONAL_PAYMENT_METHODS);
+ break;
+ case IDENTITYDATA_DOCUMENTS_AND_IMAGES.vdxfid:
+ personalData[IDENTITYDATA_DOCUMENTS_AND_IMAGES.vdxfid] = await requestPersonalData(PERSONAL_IMAGES);
+ break;
+ default:
+ break;
+ }
+ }));
+
return personalData;
}
diff --git a/src/containers/DeepLink/PersonalSelectData/PersonalSelectData.render.js b/src/containers/DeepLink/PersonalSelectData/PersonalSelectData.render.js
index b981ebbf..8e55b469 100644
--- a/src/containers/DeepLink/PersonalSelectData/PersonalSelectData.render.js
+++ b/src/containers/DeepLink/PersonalSelectData/PersonalSelectData.render.js
@@ -20,12 +20,13 @@ export const PersonalSelectDataRender = function (props) {
{this.state.catagoriesRequested && Object.values(this.state.catagoriesRequested).map(request => {
return (
-
+
{request.details}}
onPress={this.state.loading ? () => { } : () => this.openAttributes(request.navigateTo)}
- right={(props) => }
+ right={(props) => }
+ key={request.details}
/>
diff --git a/src/containers/Personal/PersonalPaymentMethods/PersonalPaymentMethodsEditBankAccount/PersonalPaymentMethodsEditBankAccount.js b/src/containers/Personal/PersonalPaymentMethods/PersonalPaymentMethodsEditBankAccount/PersonalPaymentMethodsEditBankAccount.js
index 67eca566..82027863 100644
--- a/src/containers/Personal/PersonalPaymentMethods/PersonalPaymentMethodsEditBankAccount/PersonalPaymentMethodsEditBankAccount.js
+++ b/src/containers/Personal/PersonalPaymentMethods/PersonalPaymentMethodsEditBankAccount/PersonalPaymentMethodsEditBankAccount.js
@@ -38,7 +38,7 @@ import {
PERSONAL_BANK_CLABE
} from "../../../../utils/constants/personal";
import { PersonalPaymentMethodsEditBankAccountRender } from "./PersonalPaymentMethodsEditBankAccount.render"
-import { primitives } from "verus-typescript-primitives"
+import { primitives } from "verusid-ts-client"
const { IDENTITYDATA_HOMEADDRESS_STREET1, IDENTITYDATA_HOMEADDRESS_STREET2, IDENTITYDATA_HOMEADDRESS_CITY, IDENTITYDATA_HOMEADDRESS_REGION, IDENTITYDATA_HOMEADDRESS_POSTCODE, IDENTITYDATA_HOMEADDRESS_COUNTRY } = primitives;
class PersonalPaymentMethodsEditBankAccount extends Component {
diff --git a/src/utils/deeplink/handlePersonalDataSend.js b/src/utils/deeplink/handlePersonalDataSend.js
index 8dfb8118..e67a76e6 100644
--- a/src/utils/deeplink/handlePersonalDataSend.js
+++ b/src/utils/deeplink/handlePersonalDataSend.js
@@ -1,5 +1,5 @@
import axios from "axios";
-import { primitives } from "verus-typescript-primitives"
+import * as primitives from "verus-typescript-primitives"
const handlers = {
diff --git a/src/utils/personal/displayUtils.js b/src/utils/personal/displayUtils.js
index 6c0b313d..d0606680 100644
--- a/src/utils/personal/displayUtils.js
+++ b/src/utils/personal/displayUtils.js
@@ -18,7 +18,7 @@ import {
PERSONAL_IMAGES,
} from "../constants/personal";
-import { AttestationVdxfidMap } from 'verus-typescript-primitives/dist/vdxf/classes/attestationData.js';
+import { IdentityVdxfidMap } from 'verus-typescript-primitives/dist/vdxf/classes/IdentityData';
import Colors from '../../globals/colors';
const { IDENTITYDATA_FIRSTNAME, IDENTITYDATA_LASTNAME, IDENTITYDATA_MIDDLENAME,
@@ -28,9 +28,14 @@ const { IDENTITYDATA_CONTACT, IDENTITYDATA_PERSONAL_DETAILS, IDENTITYDATA_LOCATI
export const renderPersonalFullName = (state) => {
+
+ if (!state[IDENTITYDATA_FIRSTNAME.vdxfid] && !state[IDENTITYDATA_LASTNAME.vdxfid]) {
+ return {title: "John Doe"}
+ }
+
return {
- title: `${state[IDENTITYDATA_FIRSTNAME.vdxfid]} ${state[IDENTITYDATA_MIDDLENAME.vdxfid] != null && state[IDENTITYDATA_MIDDLENAME.vdxfid] > 0 ? state[IDENTITYDATA_MIDDLENAME.vdxfid] + " " : ""
- }${state[IDENTITYDATA_LASTNAME.vdxfid]}`
+ title: `${state[IDENTITYDATA_FIRSTNAME.vdxfid] || ""} ${state[IDENTITYDATA_MIDDLENAME.vdxfid] != null && state[IDENTITYDATA_MIDDLENAME.vdxfid] > 0 ? state[IDENTITYDATA_MIDDLENAME.vdxfid] + " " : ""
+ }${state[IDENTITYDATA_LASTNAME.vdxfid] || ""}`
};
};
@@ -162,7 +167,7 @@ export const checkPersonalDataCatagories = async (profileDataRequested = []) =>
let errorDetails = "";
let profiletype;
let optionalKeys = {}
-
+ let attributes = {};
switch (permission) {
case IDENTITYDATA_PERSONAL_DETAILS.vdxfid:
@@ -196,16 +201,17 @@ export const checkPersonalDataCatagories = async (profileDataRequested = []) =>
const one = attributes[templateCategory.vdxfkey];
if (!optionalKeys[templateCategory.vdxfkey] && ((typeof one === 'object' && Array.isArray(one) && one.length === 0) ||
(typeof one === 'object' && Object.keys(one).length === 0) ||
- (typeof one === 'string' && one.length === 0))) {
- errorDetails += `${AttestationVdxfidMap[templateCategory.vdxfkey]?.name || templateCategory.vdxfkey}, `;
+ (typeof one === 'string' && one.length === 0)
+ || one == undefined)) {
+ errorDetails += (errorDetails ? ", " : "") +`${IdentityVdxfidMap[templateCategory.vdxfkey]?.name || templateCategory.vdxfkey}`;
}
})
if (errorDetails.length > 0) {
- profileDataRequested[permission].details = "Missing: " + errorDetails + " please add.";
+ profileDataRequested[permission].details = "Missing Information: " + errorDetails;
profileDataRequested[permission].color = Colors.warningButtonColor;
success = false;
- }
+ }
}));
return success;
diff --git a/yarn.lock b/yarn.lock
index 5a1769c5..2e136f0d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -946,7 +946,7 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
-"@bitgo/blake2b-wasm@^3.0.1", "@bitgo/blake2b-wasm@https://github.com/michaeltout/blake2b-wasm/", blake2b-wasm@^2.4.0, "blake2b-wasm@https://github.com/BitGo/blake2b-wasm#193cdb71656c1a6c7f89b05d0327bb9b758d071b", "blake2b-wasm@https://github.com/michaeltout/blake2b-wasm/":
+"@bitgo/blake2b-wasm@^3.0.1", "@bitgo/blake2b-wasm@https://github.com/michaeltout/blake2b-wasm/":
version "2.0.0"
resolved "https://github.com/michaeltout/blake2b-wasm/#a16070b30bb8d8aee670f0c69b642913eca79998"
dependencies:
@@ -960,7 +960,7 @@
"@bitgo/blake2b-wasm" "^3.0.1"
nanoassert "^2.0.0"
-"@bitgo/utxo-lib@git+https://github.com/VerusCoin/BitGoJS.git#7c754d4a5920198d9fe6827d3e23bd5cf431f264":
+"@bitgo/utxo-lib@git+https://github.com/VerusCoin/BitGoJS.git#7c754d4a5920198d9fe6827d3e23bd5cf431f264", "@bitgo/utxo-lib@https://github.com/VerusCoin/BitGoJS.git#f8723bcc2bf4052de171ca8654de23fc06a03337":
version "1.9.6"
resolved "git+https://github.com/VerusCoin/BitGoJS.git#7c754d4a5920198d9fe6827d3e23bd5cf431f264"
dependencies:
@@ -986,31 +986,6 @@
optionalDependencies:
secp256k1 "3.5.2"
-"@bitgo/utxo-lib@https://github.com/VerusCoin/BitGoJS.git#f8723bcc2bf4052de171ca8654de23fc06a03337":
- version "1.9.6"
- resolved "https://github.com/VerusCoin/BitGoJS.git#f8723bcc2bf4052de171ca8654de23fc06a03337"
- dependencies:
- "@bitgo/blake2b" "3.0.1"
- bech32 "0.0.3"
- bigi "1.4.0"
- bip32 "2.0.6"
- bip66 "1.1.0"
- bitcoin-ops "git+https://github.com/VerusCoin/bitcoin-ops"
- bs58check "2.0.0"
- create-hash "1.1.0"
- create-hmac "1.1.3"
- debug "~3.1.0"
- ecurve "1.0.0"
- merkle-lib "2.0.10"
- pushdata-bitcoin "1.0.1"
- randombytes "2.0.1"
- safe-buffer "5.0.1"
- typeforce "1.11.3"
- varuint-bitcoin "1.0.4"
- wif "2.0.1"
- optionalDependencies:
- secp256k1 "3.5.2"
-
"@callstack/react-theme-provider@^3.0.5":
version "3.0.8"
resolved "https://registry.yarnpkg.com/@callstack/react-theme-provider/-/react-theme-provider-3.0.8.tgz#d0d7ac71e422133c5f7b78f4c4aa1bc57f156f50"
@@ -3367,6 +3342,12 @@ bl@^4.1.0:
inherits "^2.0.4"
readable-stream "^3.4.0"
+blake2b-wasm@^2.4.0, "blake2b-wasm@https://github.com/BitGo/blake2b-wasm#193cdb71656c1a6c7f89b05d0327bb9b758d071b", "blake2b-wasm@https://github.com/michaeltout/blake2b-wasm/":
+ version "2.0.0"
+ resolved "https://github.com/michaeltout/blake2b-wasm/#a16070b30bb8d8aee670f0c69b642913eca79998"
+ dependencies:
+ nanoassert "1.0.0"
+
"blake2b@git+https://github.com/michaeltout/blake2b":
version "2.1.3"
resolved "git+https://github.com/michaeltout/blake2b#777f844b986173d08fc27fe9547c6f6320a82d62"
From 54a3b1b9050966af912198415999c769f83fadba Mon Sep 17 00:00:00 2001
From: Chris <34682781+monkins1010@users.noreply.github.com>
Date: Thu, 16 May 2024 09:13:22 +0100
Subject: [PATCH 09/10] Add Attestation receive and storage
---
env/main.android.json | 1 +
env/main.ios.json | 1 +
ios/assets/env/main.json | 1 +
.../actions/account/dispatchers/account.js | 2 +
.../attestations/creators/attestations.js | 10 +
.../attestations/dispatchers/attestations.js | 31 +++
.../LoginReceiveAttestation.js | 177 ++++++++++++++++++
.../LoginReceiveAttestation.render.js | 67 +++++++
.../LoginRequestInfo/LoginRequestInfo.js | 96 ++++++----
.../DeepLinkStackScreens.js | 9 +
src/reducers/attestations.js | 19 ++
src/reducers/index.js | 4 +-
.../api/channels/vrpc/requests/verifyHash.js | 15 ++
src/utils/constants/attestations.js | 1 +
src/utils/constants/storeType.js | 5 +-
.../nativeStore/attestationDataStorage.js | 69 +++++++
16 files changed, 466 insertions(+), 42 deletions(-)
create mode 100644 src/actions/actions/attestations/creators/attestations.js
create mode 100644 src/actions/actions/attestations/dispatchers/attestations.js
create mode 100644 src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.js
create mode 100644 src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.render.js
create mode 100644 src/reducers/attestations.js
create mode 100644 src/utils/api/channels/vrpc/requests/verifyHash.js
create mode 100644 src/utils/constants/attestations.js
create mode 100644 src/utils/nativeStore/attestationDataStorage.js
diff --git a/env/main.android.json b/env/main.android.json
index 89e8e700..098c8bd2 100644
--- a/env/main.android.json
+++ b/env/main.android.json
@@ -43,6 +43,7 @@
"SETTINGS_STORAGE_INTERNAL_KEY": "settings",
"BLOCK_HEIGHT_STORAGE_INTERNAL_KEY": "blockHeight",
"PERSONAL_DATA_STORAGE_INTERNAL_KEY": "personal",
+ "ATTESTATION_DATA_STORAGE_INTERNAL_KEY": "attestation",
"SERVICE_STORAGE_INTERNAL_KEY": "serviceStoredData",
"NOTIFICATIONS_STORAGE_INTERNAL_KEY": "notifications",
"WIDGET_STORAGE_INTERNAL_KEY": "widgets",
diff --git a/env/main.ios.json b/env/main.ios.json
index 2d5505ec..f6107af1 100644
--- a/env/main.ios.json
+++ b/env/main.ios.json
@@ -43,6 +43,7 @@
"SETTINGS_STORAGE_INTERNAL_KEY": "settings",
"BLOCK_HEIGHT_STORAGE_INTERNAL_KEY": "blockHeight",
"PERSONAL_DATA_STORAGE_INTERNAL_KEY": "personal",
+ "ATTESTATION_DATA_STORAGE_INTERNAL_KEY": "attestation",
"SERVICE_STORAGE_INTERNAL_KEY": "serviceStoredData",
"NOTIFICATIONS_STORAGE_INTERNAL_KEY": "notifications",
"WIDGET_STORAGE_INTERNAL_KEY": "widgets",
diff --git a/ios/assets/env/main.json b/ios/assets/env/main.json
index 2d5505ec..f6107af1 100644
--- a/ios/assets/env/main.json
+++ b/ios/assets/env/main.json
@@ -43,6 +43,7 @@
"SETTINGS_STORAGE_INTERNAL_KEY": "settings",
"BLOCK_HEIGHT_STORAGE_INTERNAL_KEY": "blockHeight",
"PERSONAL_DATA_STORAGE_INTERNAL_KEY": "personal",
+ "ATTESTATION_DATA_STORAGE_INTERNAL_KEY": "attestation",
"SERVICE_STORAGE_INTERNAL_KEY": "serviceStoredData",
"NOTIFICATIONS_STORAGE_INTERNAL_KEY": "notifications",
"WIDGET_STORAGE_INTERNAL_KEY": "widgets",
diff --git a/src/actions/actions/account/dispatchers/account.js b/src/actions/actions/account/dispatchers/account.js
index 22e2b6a1..16aac85e 100644
--- a/src/actions/actions/account/dispatchers/account.js
+++ b/src/actions/actions/account/dispatchers/account.js
@@ -8,6 +8,7 @@ import {
clearChainLifecycle,
} from "../../intervals/dispatchers/lifecycleManager";
import { initPersonalDataForUser } from "../../personal/dispatchers/personal";
+import { initAttestationDataForUser } from "../../attestations/dispatchers/attestations";
import { initServiceStoredDataForUser } from "../../services/dispatchers/services";
import { fetchUsers, validateLogin } from "../../UserData";
import { initSettings, saveGeneralSettings } from "../../WalletSettings";
@@ -100,6 +101,7 @@ export const initializeAccountData = async (
activateServiceLifecycle();
await initPersonalDataForUser(account.accountHash);
+ await initAttestationDataForUser(account.accountHash);
store.dispatch(signIntoAuthenticatedAccount());
} else {
throw new Error(
diff --git a/src/actions/actions/attestations/creators/attestations.js b/src/actions/actions/attestations/creators/attestations.js
new file mode 100644
index 00000000..5e4226f9
--- /dev/null
+++ b/src/actions/actions/attestations/creators/attestations.js
@@ -0,0 +1,10 @@
+import { SET_ATTESTATION_DATA } from "../../../../utils/constants/storeType"
+
+export const setAttestationData = (
+ data = {
+ attestations: null
+ }
+) => ({
+ type: SET_ATTESTATION_DATA,
+ data,
+});
\ No newline at end of file
diff --git a/src/actions/actions/attestations/dispatchers/attestations.js b/src/actions/actions/attestations/dispatchers/attestations.js
new file mode 100644
index 00000000..23167a19
--- /dev/null
+++ b/src/actions/actions/attestations/dispatchers/attestations.js
@@ -0,0 +1,31 @@
+import store from "../../../../store"
+import { deleteAttestationDataForUser, loadAttestationDataForUser, storeAttestationDataForUser } from "../../../../utils/nativeStore/attestationDataStorage"
+import { requestPassword } from "../../../../utils/auth/authBox"
+import { encryptkey } from "../../../../utils/seedCrypt"
+import { setAttestationData } from "../creators/attestations"
+
+export const saveEncryptedAttestationDataForUser = async (encryptedData = {}, accountHash) => {
+ const attestationData = await storeAttestationDataForUser(encryptedData, accountHash)
+ store.dispatch(setAttestationData(encryptedData))
+ return attestationData
+}
+
+export const clearEncryptedAttestationDataForUser = async (accountHash) => {
+ const attestationData = await deleteAttestationDataForUser(accountHash)
+ store.dispatch(setAttestationData({}))
+ return attestationData
+}
+
+export const modifyAttestationDataForUser = async (data = {}, dataType, accountHash) => {
+ let attestationData = {...(await loadAttestationDataForUser(accountHash))}
+ attestationData[dataType] = await encryptkey(await requestPassword(), JSON.stringify(data))
+ await saveEncryptedAttestationDataForUser(attestationData, accountHash)
+
+ return data
+}
+
+export const initAttestationDataForUser = async (accountHash) => {
+ const attestationData = await loadAttestationDataForUser(accountHash)
+ store.dispatch(setAttestationData(attestationData))
+ return attestationData
+}
\ No newline at end of file
diff --git a/src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.js b/src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.js
new file mode 100644
index 00000000..0718078c
--- /dev/null
+++ b/src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.js
@@ -0,0 +1,177 @@
+import { Component } from "react"
+import { connect } from 'react-redux'
+import { createAlert, resolveAlert } from "../../../actions/actions/alert/dispatchers/alert"
+import { LoginReceiveAttestationRender } from "./LoginReceiveAttestation.render"
+import { primitives } from "verusid-ts-client"
+import { VDXFDataToUniValueArray } from "verus-typescript-primitives/dist/vdxf/classes/DataDescriptor.js";
+import * as VDXF_Data from "verus-typescript-primitives/dist/vdxf/vdxfDataKeys";
+import { SignatureData } from "verus-typescript-primitives/dist/vdxf/classes/SignatureData";
+import { verifyHash } from "../../../utils/api/channels/vrpc/requests/verifyHash";
+import { getSignatureInfo } from "../../../utils/api/channels/vrpc/requests/getSignatureInfo";
+const { ATTESTATION_NAME } = primitives;
+import { IdentityVdxfidMap } from "verus-typescript-primitives/dist/vdxf/classes/IdentityData";
+import { ATTESTATIONS_PROVISIONED } from "../../../utils/constants/attestations";
+import { modifyAttestationDataForUser } from "../../../actions/actions/attestations/dispatchers/attestations";
+
+class LoginReceiveAttestation extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ loginConsent: null,
+ loading: false,
+ ready: false,
+ personalDataURL: "",
+ signerFqn: this.props.route.params.signerFqn,
+ attestationName: "",
+ attestationData: {},
+ completeAttestaton: {},
+ };
+ const dfg = 2111111
+ }
+
+ componentDidMount() {
+ this.updateDisplay();
+ }
+
+ cancel = () => {
+ if (this.props.route.params.cancel) {
+ this.props.route.params.cancel.cancel()
+ }
+ }
+
+ validateAttestation = async (signatureData) => {
+
+ const sigObject = SignatureData.fromJson(signatureData);
+
+ const sigInfo = await getSignatureInfo(
+ sigObject.systemID,
+ sigObject.identityID,
+ sigObject.signatureAsVch.toString('base64'),
+ );
+
+ return await verifyHash(sigObject.systemID, sigObject.identityID, sigObject.signatureAsVch.toString('base64'), sigObject.getIdentityHash(sigInfo));
+
+ }
+
+ getAttestationData = (dataDescriptors) => {
+
+ const data = {};
+ dataDescriptors.forEach((dataDescriptor) => {
+ const label = dataDescriptor.objectdata[Object.keys(dataDescriptor.objectdata)[0]].label;
+ let key = "";
+
+ if (label === ATTESTATION_NAME.vdxfid) {
+ key = `Attestation name`
+ } else {
+ key = IdentityVdxfidMap[label]?.name || label;
+ }
+
+ const mime = dataDescriptor.objectdata[Object.keys(dataDescriptor.objectdata)[0]].mimetype || "";
+ if (mime.startsWith("text/")) {
+ data[key] = { "message": dataDescriptor.objectdata[Object.keys(dataDescriptor.objectdata)[0]].objectdata.message };
+ } else if (mime.startsWith("image/")) {
+ if (mime === "image/jpeg" || mime === "image/png") {
+ data[key] = { "image": `data:${mime};base64,${Buffer.from(dataDescriptor.objectdata[Object.keys(dataDescriptor.objectdata)[0]].objectdata, "hex").toString("base64")}` };
+ }
+ }
+ });
+
+ return data;
+
+ }
+
+ updateDisplay() {
+ const { deeplinkData } = this.props.route.params
+ const loginConsent = new primitives.LoginConsentRequest(deeplinkData);
+
+ if (loginConsent.challenge.attestations && loginConsent.challenge.attestations.length > 1) {
+ createAlert("Error", "Only one attestation is allowed to be received at a time.");
+ this.cancel();
+ return;
+ }
+
+ const checkAttestation = loginConsent.challenge.attestations[0];
+
+ if (checkAttestation.vdxfkey === primitives.ATTESTATION_PROVISION_OBJECT.vdxfid) {
+
+ const dataDescriptorObject = VDXFDataToUniValueArray(Buffer.from(checkAttestation.data, "hex"));
+
+ if (!Array.isArray(dataDescriptorObject)) {
+ createAlert("Error", "Invalid data descriptor object in Attestation.");
+ this.cancel();
+ return;
+ }
+
+ if (dataDescriptorObject.some((dataDescriptor) => Object.keys(dataDescriptor)[0] === VDXF_Data.DataURLKey().vdxfid)) {
+
+ // TODO: Handle fetch data from URL
+ }
+ else if (dataDescriptorObject.some((dataDescriptor) => Object.keys(dataDescriptor)[0] === VDXF_Data.MMRDescriptorKey().vdxfid) &&
+ dataDescriptorObject.some((dataDescriptor) => Object.keys(dataDescriptor)[0] === VDXF_Data.SignatureDataKey().vdxfid)) {
+
+ const signatureData = dataDescriptorObject.find((dataDescriptor) => Object.keys(dataDescriptor)[0] === VDXF_Data.SignatureDataKey().vdxfid)[VDXF_Data.SignatureDataKey().vdxfid];
+ const mmrData = dataDescriptorObject.find((dataDescriptor) => Object.keys(dataDescriptor)[0] === VDXF_Data.MMRDescriptorKey().vdxfid)[VDXF_Data.MMRDescriptorKey().vdxfid];
+
+ if (!this.validateAttestation(signatureData) || mmrData.mmrroot.objectdata != signatureData.signaturehash) {
+ createAlert("Error", "Invalid attestation signature.");
+ this.cancel();
+ return;
+ }
+
+ const attestationName = mmrData.datadescriptors.find((dataDescriptor) => dataDescriptor.objectdata[Object.keys(dataDescriptor.objectdata)[0]].label === ATTESTATION_NAME.vdxfid)?.objectdata;
+
+ if (!attestationName || Object.values(attestationName)[0].label !== ATTESTATION_NAME.vdxfid) {
+ createAlert("Error", "Attestation has no name.");
+ this.cancel();
+ return;
+ } else {
+
+ this.setState({ attestationName: Object.values(attestationName)[0].objectdata.message });
+
+ }
+
+ const containingData = this.getAttestationData(mmrData.datadescriptors);
+ this.setState({ attestationData: containingData, completeAttestaton: {[loginConsent.getChallengeHash(1).toString('base64')]: dataDescriptorObject} });
+
+ } else {
+ createAlert("Error", "Invalid attestation type.");
+ this.cancel();
+ return;
+ }
+
+ }
+ }
+
+ handleContinue() {
+ this.setState(
+ { loading: true },
+ async () => {
+ // console.log(JSON.stringify(this.state.completeAttestaton, null, 2))
+ await modifyAttestationDataForUser(
+ this.state.completeAttestaton,
+ ATTESTATIONS_PROVISIONED,
+ this.props.activeAccount.accountHash
+ );
+
+ this.setState({ loading: false });
+ this.props.route.params.onGoBack(true);
+ this.props.navigation.goBack();
+ this.cancel();
+ }
+ );
+ };
+
+
+ render() {
+ return LoginReceiveAttestationRender.call(this);
+ }
+}
+
+const mapStateToProps = (state) => {
+ return {
+ activeAccount: state.authentication.activeAccount,
+ encryptedPersonalData: state.personal
+ }
+};
+
+export default connect(mapStateToProps)(LoginReceiveAttestation);
\ No newline at end of file
diff --git a/src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.render.js b/src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.render.js
new file mode 100644
index 00000000..7c08dd2b
--- /dev/null
+++ b/src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.render.js
@@ -0,0 +1,67 @@
+import React from "react";
+import { SafeAreaView, ScrollView, View, Image } from "react-native";
+import { Divider, List, Button, Text } from "react-native-paper";
+import Styles from "../../../styles";
+import Colors from '../../../globals/colors';
+import {convertFqnToDisplayFormat} from '../../../utils/fullyqualifiedname';
+
+export const LoginReceiveAttestationRender = function (props) {
+
+ return (
+
+
+
+
+
+ Agree to Receive the following attestation.
+
+
+ {`${convertFqnToDisplayFormat(this.state.attestationName)}`}
+
+
+ {`From: `}{`${this.state.signerFqn}`}
+
+ {this.state.attestationData && Object.keys(this.state.attestationData).map(request => {
+ return (
+
+ this.state.attestationData[request]?.image ? : null}
+ />
+
+
+
+ );
+ })}
+
+
+
+
+
+ this.cancel()}>
+ Cancel
+
+ this.handleContinue()}>
+ Accept
+
+
+
+ );
+};
diff --git a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
index 25b73159..08168497 100644
--- a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
+++ b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
@@ -1,5 +1,5 @@
-import React, {useState, useEffect} from 'react';
-import {SafeAreaView, ScrollView, TouchableOpacity, View} from 'react-native';
+import React, { useState, useEffect } from 'react';
+import { SafeAreaView, ScrollView, TouchableOpacity, View } from 'react-native';
import Styles from '../../../styles/index';
import { primitives } from "verusid-ts-client"
import { Button, Divider, List, Portal, Text } from 'react-native-paper';
@@ -58,6 +58,8 @@ const LoginRequestInfo = props => {
} else {
if (passthrough?.fqnToAutoLink) {
mainLoginMessage = `VerusID from ${signerFqn} now ready to link`
+ } else if (challenge.attestations && challenge.attestations.length > 0) {
+ mainLoginMessage = `Would you like to accept an attestation from ${signerFqn}?`
} else {
mainLoginMessage = `Would you like to request a VerusID from ${signerFqn}?`
}
@@ -79,7 +81,7 @@ const LoginRequestInfo = props => {
loadFriendlyNames: async () => {
try {
const identityObj = await getVerusId(chain, iAddress);
-
+
return getFriendlyNameMap(CoinDirectory.getBasicCoinObj(chain), identityObj);
} catch (e) {
return {
@@ -123,7 +125,7 @@ const LoginRequestInfo = props => {
setLoading(false)
} else setLoading(true)
}, [sendModalType]);
-
+
const buildAlert = (request) => {
const setPermission = () => {
@@ -138,19 +140,31 @@ const LoginRequestInfo = props => {
if (request.agreed) return;
- if (request.openAttestation) {
+ if (request.viewAttestation) {
return;
}
- else if (request.openProfile) {
- if(!signedIn) return;
+ else if (request.attestationToAccept) {
+ if (!signedIn) return;
+ props.navigation.navigate("LoginReceiveAttestation",
+ {
+ deeplinkData,
+ fromService: false,
+ cancel: { cancel },
+ onGoBack: (data) => data ? setPermission(data) : () => { },
+ signerFqn
+ });
+ return;
+ }
+ else if (request.openProfile) {
+ if (!signedIn) return;
props.navigation.navigate("PersonalSelectData",
- {
- deeplinkData,
- fromService: false,
- cancel: {cancel},
- onGoBack: (data) => data ? setPermission(data) : () => {},
- signerFqn
- });
+ {
+ deeplinkData,
+ fromService: false,
+ cancel: { cancel },
+ onGoBack: (data) => data ? setPermission(data) : () => { },
+ signerFqn
+ });
return;
}
@@ -166,29 +180,33 @@ const LoginRequestInfo = props => {
{
text: 'ACCEPT', onPress: () => {
setPermission();
- resolveAlert(true)
+ resolveAlert(true)
}
},
],
- {cancelable: true});
- }
+ { cancelable: true });
+ }
useEffect(() => {
if (req && req.challenge && req.challenge.requested_access) {
- if (req.challenge.requested_access.length === 1 && req.challenge.requested_access.some(primitives.IDENTITY_VIEW.vdxfid)) {
- setReady(true);
+ var loginTemp = [];
+ if (req.challenge.requested_access.length === 1 && req.challenge.requested_access.some(value => value.vdxfkey === primitives.IDENTITY_VIEW.vdxfid)) {
+ if (req.challenge.attestations && req.challenge.attestations.length > 0) {
+ loginTemp.push({ data: "Accept attestation", title: "Attestation Provisioning Request", attestationToAccept: true, agreed: false });
+ } else {
+ setReady(true);
+ }
} else {
- var loginTemp = [];
for (let i = 0; i < req.challenge.requested_access.length; i++) {
var tempdata = {};
- if (req.challenge.requested_access[i].vdxfkey === primitives.IDENTITY_VIEW.vdxfid) {
+ if (req.challenge.requested_access[i].vdxfkey === primitives.IDENTITY_VIEW.vdxfid) {
continue;
} else if (req.challenge.requested_access[i].vdxfkey === primitives.IDENTITY_AGREEMENT.vdxfid) {
tempdata = { data: req.challenge.requested_access[i].toJson().data, title: "Agreement to accept" }
} else if (req.challenge.requested_access[i].vdxfkey === primitives.ATTESTATION_READ_REQUEST.vdxfid) {
- tempdata = { data: "Agree to share attestation data", title: "Attestation View Request", openAttestation: true }
+ tempdata = { data: "Agree to share attestation data", title: "Attestation View Request", viewAttestation: true }
} else if (req.challenge.requested_access[i].vdxfkey === primitives.PROFILE_DATA_VIEW_REQUEST.vdxfid) {
tempdata = { data: "Agree to share profile data", title: "Personal Data Input Request", openProfile: true }
} else if (req.challenge.requested_access[i].vdxfkey === primitives.LOGIN_CONSENT_PERSONALINFO_WEBHOOK_VDXF_KEY.vdxfid) {
@@ -196,8 +214,9 @@ const LoginRequestInfo = props => {
}
loginTemp.push({ vdxfkey: req.challenge.requested_access[i].vdxfkey, ...tempdata, agreed: false })
}
- setExtraPermissions(loginTemp);
}
+
+ if (loginTemp.length > 0) setExtraPermissions(loginTemp);
}
}, [req]);
@@ -228,28 +247,28 @@ const LoginRequestInfo = props => {
: activeAccount.keyDerivationVersion,
),
);
-
+
const addCoinAction = await addCoin(
fullCoinData,
activeCoinList,
activeAccount.id,
fullCoinData.compatible_channels,
);
-
+
if (addCoinAction) {
dispatch(addCoinAction);
-
+
const setUserCoinsAction = setUserCoins(
activeCoinList,
activeAccount.id,
);
dispatch(setUserCoinsAction);
-
+
refreshActiveChainLifecycles(setUserCoinsAction.payload.activeCoinsForUser);
} else {
createAlert("Error", "Error adding coin")
}
- } catch(e) {
+ } catch (e) {
createAlert("Error", e.message)
}
@@ -266,7 +285,7 @@ const LoginRequestInfo = props => {
onPress: () => resolveAlert(false),
style: 'cancel',
},
- {text: 'Yes', onPress: () => resolveAlert(true)},
+ { text: 'Yes', onPress: () => resolveAlert(true) },
],
{
cancelable: true,
@@ -292,9 +311,8 @@ const LoginRequestInfo = props => {
if (!!coinObj.testnet != isTestnet) {
createAlert(
"Incorrect profile type",
- `Please login to a ${
- coinObj.testnet ? 'testnet' : 'mainnet'
- } profile to use this login request.`, );
+ `Please login to a ${coinObj.testnet ? 'testnet' : 'mainnet'
+ } profile to use this login request.`,);
return;
}
else if (!rootSystemAdded) {
@@ -331,15 +349,13 @@ const LoginRequestInfo = props => {
const data = {
[SEND_MODAL_USER_ALLOWLIST]: allowList
}
-
+
openAuthenticateUserModal(data);
} else {
createAlert(
"Cannot continue",
- `No ${
- coinObj.testnet ? 'testnet' : 'mainnet'
- } profiles found, cannot respond to ${
- coinObj.testnet ? 'testnet' : 'mainnet'
+ `No ${coinObj.testnet ? 'testnet' : 'mainnet'
+ } profiles found, cannot respond to ${coinObj.testnet ? 'testnet' : 'mainnet'
} login request.`,
);
}
@@ -360,7 +376,7 @@ const LoginRequestInfo = props => {
contentContainerStyle={Styles.focalCenter}>
-
+
{mainLoginMessage}
@@ -419,13 +435,13 @@ const LoginRequestInfo = props => {
}}>
cancel()}>
Cancel
handleContinue()}>
Continue
diff --git a/src/containers/RootStack/DeepLinkStackScreens/DeepLinkStackScreens.js b/src/containers/RootStack/DeepLinkStackScreens/DeepLinkStackScreens.js
index 623ee7da..ba899fa9 100644
--- a/src/containers/RootStack/DeepLinkStackScreens/DeepLinkStackScreens.js
+++ b/src/containers/RootStack/DeepLinkStackScreens/DeepLinkStackScreens.js
@@ -7,6 +7,7 @@ import LoginRequestComplete from '../../DeepLink/LoginRequestComplete/LoginReque
import InvoicePaymentConfiguration from '../../DeepLink/InvoicePaymentConfiguration/InvoicePaymentConfiguration';
import PersonalSelectData from '../../DeepLink/PersonalSelectData/PersonalSelectData';
import ProfileStackScreens from '../ProfileStackScreens/ProfileStackScreens';
+import LoginReceiveAttestation from '../../DeepLink/LoginReceiveAttestation/LoginReceiveAttestation';
const DeepLinkStack = createStackNavigator();
const DeepLinkStackScreens = props => {
@@ -57,6 +58,14 @@ const DeepLinkStackScreens = props => {
component={ProfileStackScreens}
options={{ headerShown: false }}
/>
+ null,
+ title: "Receive Attestation"
+ }}
+ />
);
};
diff --git a/src/reducers/attestations.js b/src/reducers/attestations.js
new file mode 100644
index 00000000..b505d6fc
--- /dev/null
+++ b/src/reducers/attestations.js
@@ -0,0 +1,19 @@
+import {SIGN_OUT, SET_ATTESTATION_DATA} from '../utils/constants/storeType';
+
+export const attestation = (
+ state = {
+ attestations: null
+ },
+ action,
+) => {
+ switch (action.type) {
+ case SET_ATTESTATION_DATA:
+ return action.data;
+ case SIGN_OUT:
+ return {
+ attestations: null
+ };
+ default:
+ return state;
+ }
+};
diff --git a/src/reducers/index.js b/src/reducers/index.js
index 250fa43d..bfd9704f 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -4,6 +4,7 @@ import { coins } from './coins';
import { ledger } from './ledger';
import { settings } from './settings';
import { personal } from './personal';
+import { attestation } from './attestations';
import { services } from './services';
import { electrum } from './cache/electrum';
import { headers } from './cache/headers';
@@ -71,5 +72,6 @@ export default combineReducers({
sendModal,
loadingModal,
secureLoading,
- deeplink
+ deeplink,
+ attestation
});
diff --git a/src/utils/api/channels/vrpc/requests/verifyHash.js b/src/utils/api/channels/vrpc/requests/verifyHash.js
new file mode 100644
index 00000000..376cdddf
--- /dev/null
+++ b/src/utils/api/channels/vrpc/requests/verifyHash.js
@@ -0,0 +1,15 @@
+import VrpcProvider from "../../../../vrpc/vrpcInterface"
+
+export const verifyHash = async (systemId, iAddrOrIdentity, base64Sig, hash) => {
+ const provider = VrpcProvider.getVerusIdInterface(systemId);
+
+ const identity = await provider.interface.getIdentity(iAddrOrIdentity);
+
+ return provider.verifyHash(
+ iAddrOrIdentity,
+ base64Sig,
+ hash,
+ identity.result,
+ systemId
+ );
+}
\ No newline at end of file
diff --git a/src/utils/constants/attestations.js b/src/utils/constants/attestations.js
new file mode 100644
index 00000000..337c15e5
--- /dev/null
+++ b/src/utils/constants/attestations.js
@@ -0,0 +1 @@
+export const ATTESTATIONS_PROVISIONED = "attestations_provisioned"
\ No newline at end of file
diff --git a/src/utils/constants/storeType.js b/src/utils/constants/storeType.js
index 1717a2db..445b53ff 100644
--- a/src/utils/constants/storeType.js
+++ b/src/utils/constants/storeType.js
@@ -309,4 +309,7 @@ export const SET_PERSONAL_DATA = "SET_PERSONAL_DATA"
// Services
export const SET_SERVICE_STORED_DATA = "SET_SERVICE_STORED_DATA"
-export const SET_SERVICE_DATA = "SET_SERVICE_DATA"
\ No newline at end of file
+export const SET_SERVICE_DATA = "SET_SERVICE_DATA"
+
+// Attestations
+export const SET_ATTESTATION_DATA = "SET_ATTESTATION_DATA"
\ No newline at end of file
diff --git a/src/utils/nativeStore/attestationDataStorage.js b/src/utils/nativeStore/attestationDataStorage.js
new file mode 100644
index 00000000..1296e5db
--- /dev/null
+++ b/src/utils/nativeStore/attestationDataStorage.js
@@ -0,0 +1,69 @@
+var RNFS = require('react-native-fs');
+import { ATTESTATION_DATA_STORAGE_INTERNAL_KEY } from '../../../env/index'
+
+export const storeAttestationData = (data) => {
+ if (typeof data !== 'object') throw new Error(`Attestation data store function expected object, received ${typeof data}`)
+
+ return new Promise((resolve, reject) => {
+ RNFS.writeFile(RNFS.DocumentDirectoryPath + `/${ATTESTATION_DATA_STORAGE_INTERNAL_KEY}.txt`, JSON.stringify(data), 'utf8')
+ .then((success) => {
+ resolve(data);
+ })
+ .catch(err => {
+ reject(err)
+ })
+ })
+};
+
+export const loadAttestationData = () => {
+ return new Promise((resolve, reject) => {
+ RNFS.readFile(RNFS.DocumentDirectoryPath + `/${ATTESTATION_DATA_STORAGE_INTERNAL_KEY}.txt`, "utf8")
+ .then(res => {
+ if (!res) {
+ resolve({});
+ } else {
+ _res = JSON.parse(res);
+ resolve(_res);
+ }
+ })
+ .catch(err => {
+ if (err.code === 'ENOENT') {
+ resolve({});
+ } else {
+ reject(err);
+ }
+ });
+ })
+};
+
+export const clearAllAttestationData = () => {
+ return new Promise((resolve, reject) => {
+ RNFS.unlink(RNFS.DocumentDirectoryPath + `/${ATTESTATION_DATA_STORAGE_INTERNAL_KEY}.txt`)
+ .then(() => {
+ resolve();
+ })
+ .catch(err => reject(err));
+ })
+};
+
+export const storeAttestationDataForUser = async (data, accountHash) => {
+ let allAttestationData = { ...(await loadAttestationData()) }
+ allAttestationData[accountHash] = data
+ return (await storeAttestationData(allAttestationData))[accountHash]
+}
+
+export const deleteAttestationDataForUser = async (accountHash) => {
+ let allAttestationData = { ...(await loadAttestationData()) }
+ delete allAttestationData[accountHash]
+ return (await storeAttestationData(allAttestationData))[accountHash]
+}
+
+export const loadAttestationDataForUser = async (accountHash) => {
+ const allAttestationData = await loadAttestationData()
+
+ if (allAttestationData[accountHash] == null)
+ return {
+ attestations: null
+ };
+ else return allAttestationData[accountHash];
+};
From c466359718a998ef8c36ebadf9a1d8a9ca619781 Mon Sep 17 00:00:00 2001
From: Chris <34682781+monkins1010@users.noreply.github.com>
Date: Wed, 22 May 2024 14:35:46 +0100
Subject: [PATCH 10/10] Add Attestations, send + recieve
---
.../attestations/creators/attestations.js | 2 +-
.../LoginReceiveAttestation.js | 7 +-
.../LoginRequestInfo/LoginRequestInfo.js | 9 +
.../LoginShareAttestation.js | 207 ++++++++++++++++++
.../LoginShareAttestation.render.js | 68 ++++++
.../DeepLinkStackScreens.js | 10 +
.../ServicesStackScreens.js | 9 +-
src/containers/Services/Service/Service.js | 7 +-
.../AttestationService/AttestationService.js | 66 ++++++
.../AttestationService.render.js | 54 +++++
.../ViewAttestation/ViewAttestation.js | 104 +++++++++
src/images/servicelogo/index.js | 5 +-
src/reducers/services.js | 8 +-
.../asyncStore/serviceStoredDataStorage.js | 2 +-
.../attestations/createAttestationResponse.js | 37 ++++
src/utils/auth/authBox.js | 27 ++-
src/utils/constants/services.js | 8 +-
src/utils/deeplink/handlePersonalDataSend.js | 12 +
.../nativeStore/attestationDataStorage.js | 2 +-
yarn.lock | 6 -
20 files changed, 628 insertions(+), 22 deletions(-)
create mode 100644 src/containers/DeepLink/LoginShareAttestation/LoginShareAttestation.js
create mode 100644 src/containers/DeepLink/LoginShareAttestation/LoginShareAttestation.render.js
create mode 100644 src/containers/Services/ServiceComponents/AttestationService/AttestationService.js
create mode 100644 src/containers/Services/ServiceComponents/AttestationService/AttestationService.render.js
create mode 100644 src/containers/Services/ServiceComponents/AttestationService/ViewAttestation/ViewAttestation.js
create mode 100644 src/utils/attestations/createAttestationResponse.js
diff --git a/src/actions/actions/attestations/creators/attestations.js b/src/actions/actions/attestations/creators/attestations.js
index 5e4226f9..bef5efda 100644
--- a/src/actions/actions/attestations/creators/attestations.js
+++ b/src/actions/actions/attestations/creators/attestations.js
@@ -2,7 +2,7 @@ import { SET_ATTESTATION_DATA } from "../../../../utils/constants/storeType"
export const setAttestationData = (
data = {
- attestations: null
+ attestations_provisioned: null
}
) => ({
type: SET_ATTESTATION_DATA,
diff --git a/src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.js b/src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.js
index 0718078c..35fd6b91 100644
--- a/src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.js
+++ b/src/containers/DeepLink/LoginReceiveAttestation/LoginReceiveAttestation.js
@@ -131,7 +131,11 @@ class LoginReceiveAttestation extends Component {
}
const containingData = this.getAttestationData(mmrData.datadescriptors);
- this.setState({ attestationData: containingData, completeAttestaton: {[loginConsent.getChallengeHash(1).toString('base64')]: dataDescriptorObject} });
+ this.setState({ attestationData: containingData,
+ completeAttestaton: {[loginConsent.getChallengeHash(1).toString('base64')]:{ name: Object.values(attestationName)[0].objectdata.message,
+ signer: this.state.signerFqn,
+ data: dataDescriptorObject}}
+ });
} else {
createAlert("Error", "Invalid attestation type.");
@@ -146,7 +150,6 @@ class LoginReceiveAttestation extends Component {
this.setState(
{ loading: true },
async () => {
- // console.log(JSON.stringify(this.state.completeAttestaton, null, 2))
await modifyAttestationDataForUser(
this.state.completeAttestaton,
ATTESTATIONS_PROVISIONED,
diff --git a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
index 08168497..27671d7a 100644
--- a/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
+++ b/src/containers/DeepLink/LoginRequestInfo/LoginRequestInfo.js
@@ -141,6 +141,15 @@ const LoginRequestInfo = props => {
if (request.agreed) return;
if (request.viewAttestation) {
+ if (!signedIn) return;
+ props.navigation.navigate("LoginShareAttestation",
+ {
+ deeplinkData,
+ fromService: false,
+ cancel: { cancel },
+ onGoBack: (data) => data ? setPermission(data) : () => { },
+ signerFqn
+ });
return;
}
else if (request.attestationToAccept) {
diff --git a/src/containers/DeepLink/LoginShareAttestation/LoginShareAttestation.js b/src/containers/DeepLink/LoginShareAttestation/LoginShareAttestation.js
new file mode 100644
index 00000000..6511545a
--- /dev/null
+++ b/src/containers/DeepLink/LoginShareAttestation/LoginShareAttestation.js
@@ -0,0 +1,207 @@
+import moment from "moment";
+import { Component } from "react"
+import { connect } from 'react-redux'
+import { createAlert, resolveAlert } from "../../../actions/actions/alert/dispatchers/alert"
+import { modifyPersonalDataForUser } from "../../../actions/actionDispatchers";
+import { requestPersonalData } from "../../../utils/auth/authBox";
+import { PERSONAL_ATTRIBUTES, PERSONAL_CONTACT, PERSONAL_LOCATIONS, PERSONAL_PAYMENT_METHODS, PERSONAL_IMAGES } from "../../../utils/constants/personal";
+import { provideCustomBackButton } from "../../../utils/navigation/customBack";
+import { LoginShareAttestationRender } from "./LoginShareAttestation.render"
+import { checkPersonalDataCatagories } from "../../../utils/personal/displayUtils";
+import { handleAttestationDataSend } from "../../../utils/deeplink/handlePersonalDataSend";
+import { primitives } from "verusid-ts-client"
+import { ATTESTATIONS_PROVISIONED } from "../../../utils/constants/attestations";
+import { requestAttestationData } from "../../../utils/auth/authBox";
+import { IdentityVdxfidMap } from 'verus-typescript-primitives/dist/vdxf/classes/IdentityData';
+import { getIdentity } from '../../../utils/api/channels/verusid/callCreators';
+import { createAttestationResponse } from "../../../utils/attestations/createAttestationResponse";
+
+const { IDENTITYDATA_CONTACT, IDENTITYDATA_PERSONAL_DETAILS, IDENTITYDATA_LOCATIONS, IDENTITYDATA_DOCUMENTS_AND_IMAGES, IDENTITYDATA_BANKING_INFORMATION } = primitives;
+import * as VDXF_Data from "verus-typescript-primitives/dist/vdxf/vdxfDataKeys";
+import { DrawerContentScrollView } from "@react-navigation/drawer";
+
+class LoginShareAttestation extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ attestationName: "",
+ attestationAcceptedAttestors: [],
+ attestationRequestedFields: [],
+ attestationRequestedVdxfKeys:[],
+ attestationID: "",
+ loading: false,
+ ready: false,
+ attestationDataURL: "",
+ signerFqn: this.props.route.params.signerFqn
+ };
+ const sdf = 234111
+ }
+
+ componentDidMount() {
+ this.updateDisplay();
+ }
+
+ cancel = () => {
+ if (this.props.route.params.cancel) {
+ this.props.route.params.cancel.cancel()
+ }
+ }
+
+ createAttestationReply = async () => {
+
+ const reply = await createAttestationResponse(this.state.attestationID, this.state.attestationRequestedVdxfKeys)
+ return reply;
+ }
+
+
+ updateDisplay = async () => {
+ const { deeplinkData } = this.props.route.params
+ const loginConsent = new primitives.LoginConsentRequest(deeplinkData);
+
+ const subjectKeys = {};
+ let attestationName = "";
+ let attestationAcceptedAttestors = [];
+ let attestationID = "";
+
+ const attestationDataURL = loginConsent.challenge.subject
+ .filter((permission) => permission.vdxfkey === primitives.LOGIN_CONSENT_PERSONALINFO_WEBHOOK_VDXF_KEY.vdxfid);
+
+ for (let i = 0; i < loginConsent.challenge.subject.length; i++) {
+
+ let permission = loginConsent.challenge.subject[i];
+
+ if (permission.vdxfkey == primitives.ATTESTATION_VIEW_REQUEST_NAME.vdxfid) {
+ attestationName = permission.data;
+ } else if (permission.vdxfkey == primitives.ATTESTATION_VIEW_REQUEST_ATTESTOR.vdxfid) {
+ let attestorFqn;
+
+ try {
+ const reply = await getIdentity(loginConsent.system_id, permission.data);
+ attestorFqn = reply.result.friendlyname;
+ } catch (e) {
+ console.log("Error getting attestation signer ", e);
+ return false;
+ }
+ attestationAcceptedAttestors.push(attestorFqn);
+
+ }
+ else {
+ subjectKeys[permission.data] = true;
+ }
+ };
+
+ let attestationData;
+ try {
+ attestationData = await requestAttestationData(ATTESTATIONS_PROVISIONED);
+ } catch (e) {
+ createAlert('Error Loading Attestations', e.message);
+ }
+
+ // check that the requested attestestation name is in the attestationData
+
+ let attestationRequestedFields = [];
+ const attestationDataKeys = Object.keys(attestationData);
+ const attestationDataValues = Object.values(attestationData);
+ let attestationRequestedVdxfKeys = loginConsent.challenge.subject
+ .map((permission) => permission.data);
+
+ for (let i = 0; i < attestationDataKeys.length; i++) {
+
+ for (let j = 0; j < attestationDataValues[i].data.length; j++) {
+
+ const vdxfobjKey = Object.keys(attestationDataValues[i].data[j])[0];
+ const vdxfobjValue = attestationDataValues[i].data[j][vdxfobjKey];
+
+ if (vdxfobjKey === VDXF_Data.MMRDescriptorKey().vdxfid) {
+
+ for (let k = 0; k < vdxfobjValue.datadescriptors.length; k++) {
+
+ const item = vdxfobjValue.datadescriptors[k].objectdata[VDXF_Data.DataDescriptorKey().vdxfid];
+
+ if (item.label === primitives.ATTESTATION_NAME.vdxfid) {
+ if (item.objectdata.message !== attestationName) {
+ continue;
+ }
+ } else if (item.label === primitives.ATTESTATION_VIEW_REQUEST_ATTESTOR.vdxfid) {
+ if (attestationAcceptedAttestors.indexOf(item.objectdata.message) === -1) {
+ continue;
+ }
+ } else if (subjectKeys[item.label]) {
+ let name;
+
+ if (name = IdentityVdxfidMap[item.label]?.name) {
+ attestationRequestedFields.push(name);
+ } else {
+ attestationRequestedFields.push(item.label);
+ }
+ }
+ }
+ if (attestationRequestedFields && attestationAcceptedAttestors) {
+ attestationID = attestationDataKeys[0];
+ }
+ }
+ }
+ }
+ this.setState({ attestationRequestedFields,
+ attestationAcceptedAttestors,
+ attestationName,
+ attestationID,
+ attestationDataURL: { vdxfkey: attestationDataURL[0].vdxfkey, uri: attestationDataURL[0].data },
+ attestationRequestedVdxfKeys });
+ }
+
+ async handleContinue() {
+ this.setState({ loading: true });
+
+ const createdAttestation = await this.createAttestationReply()
+
+ createAlert(
+ "Send Selected Attestation info",
+ "Are you sure you want to send your attestation data to: \n" + `${this.state.signerFqn}`,
+ [
+ {
+ text: "No",
+ onPress: () => {
+ resolveAlert();
+ },
+ },
+ {
+ text: "Yes",
+ onPress: () => {
+ resolveAlert();
+ handleAttestationDataSend(createdAttestation, this.state.attestationDataURL)
+ .then(() => {
+ this.setState({ loading: false });
+ this.props.route.params.onGoBack(true);
+ this.props.navigation.goBack();
+ this.cancel();
+ }).catch((e) => {
+
+ this.setState({ loading: false });
+ createAlert("Error, Failed to Send Attestation, server may be unavailable.", e.message);
+
+ })
+ },
+ },
+ ],
+ {
+ cancelable: false,
+ }
+ );
+
+
+ };
+
+ render() {
+ return LoginShareAttestationRender.call(this);
+ }
+}
+
+const mapStateToProps = (state) => {
+ return {
+ activeAccount: state.authentication.activeAccount,
+ encryptedPersonalData: state.personal
+ }
+};
+
+export default connect(mapStateToProps)(LoginShareAttestation);
\ No newline at end of file
diff --git a/src/containers/DeepLink/LoginShareAttestation/LoginShareAttestation.render.js b/src/containers/DeepLink/LoginShareAttestation/LoginShareAttestation.render.js
new file mode 100644
index 00000000..0253aa2d
--- /dev/null
+++ b/src/containers/DeepLink/LoginShareAttestation/LoginShareAttestation.render.js
@@ -0,0 +1,68 @@
+import React from "react";
+import { SafeAreaView, ScrollView, View } from "react-native";
+import { Divider, List, Button, Text } from "react-native-paper";
+
+import Styles from "../../../styles";
+
+import Colors from '../../../globals/colors';
+
+export const LoginShareAttestationRender = function (props) {
+
+ return (
+
+
+
+
+
+ Agree to share the following attestation data.
+
+
+ {`Attestation Name: `}{`${this.state.attestationName}`}
+
+ {this.state.attestationAcceptedAttestors &&
+ {`From: `}{`${this.state.attestationAcceptedAttestors[0]}`}
+ }
+
+
+ {this.state.attestationRequestedFields.map(request => {
+ return (
+
+
+
+
+
+ );
+ })}
+
+
+
+
+
+ this.cancel()}>
+ Cancel
+
+ this.handleContinue()}>
+ Accept
+
+
+
+ );
+};
diff --git a/src/containers/RootStack/DeepLinkStackScreens/DeepLinkStackScreens.js b/src/containers/RootStack/DeepLinkStackScreens/DeepLinkStackScreens.js
index ba899fa9..f87ab756 100644
--- a/src/containers/RootStack/DeepLinkStackScreens/DeepLinkStackScreens.js
+++ b/src/containers/RootStack/DeepLinkStackScreens/DeepLinkStackScreens.js
@@ -8,6 +8,8 @@ import InvoicePaymentConfiguration from '../../DeepLink/InvoicePaymentConfigurat
import PersonalSelectData from '../../DeepLink/PersonalSelectData/PersonalSelectData';
import ProfileStackScreens from '../ProfileStackScreens/ProfileStackScreens';
import LoginReceiveAttestation from '../../DeepLink/LoginReceiveAttestation/LoginReceiveAttestation';
+import LoginShareAttestation from '../../DeepLink/LoginShareAttestation/LoginShareAttestation';
+
const DeepLinkStack = createStackNavigator();
const DeepLinkStackScreens = props => {
@@ -66,6 +68,14 @@ const DeepLinkStackScreens = props => {
title: "Receive Attestation"
}}
/>
+ null,
+ title: "Share Attestation data"
+ }}
+ />
);
};
diff --git a/src/containers/RootStack/ServicesStackScreens/ServicesStackScreens.js b/src/containers/RootStack/ServicesStackScreens/ServicesStackScreens.js
index c5005baa..b6c4056c 100644
--- a/src/containers/RootStack/ServicesStackScreens/ServicesStackScreens.js
+++ b/src/containers/RootStack/ServicesStackScreens/ServicesStackScreens.js
@@ -6,7 +6,7 @@ import Service from '../../Services/Service/Service'
import WyreServiceAccountData from '../../Services/ServiceComponents/WyreService/WyreServiceAccount/WyreServiceAccountData/WyreServiceAccountData';
import WyreServiceAddPaymentMethod from '../../Services/ServiceComponents/WyreService/WyreServiceAccount/WyreServiceAddPaymentMethod/WyreServiceAddPaymentMethod';
import WyreServiceEditPaymentMethod from '../../Services/ServiceComponents/WyreService/WyreServiceAccount/WyreServiceEditPaymentMethod/WyreServiceEditPaymentMethod';
-
+import ViewAttestation from '../../Services/ServiceComponents/AttestationService/ViewAttestation/ViewAttestation';
const ServicesStack = createStackNavigator();
const ServicesStackScreens = props => {
@@ -43,6 +43,13 @@ const ServicesStackScreens = props => {
title: "Edit Account",
}}
/>
+
);
};
diff --git a/src/containers/Services/Service/Service.js b/src/containers/Services/Service/Service.js
index 83593652..6b942ded 100644
--- a/src/containers/Services/Service/Service.js
+++ b/src/containers/Services/Service/Service.js
@@ -3,11 +3,11 @@
*/
import React, { Component } from "react"
-import { PBAAS_PRECONVERT_SERVICE_ID, VERUSID_SERVICE_ID, WYRE_SERVICE_ID } from "../../../utils/constants/services";
+import { PBAAS_PRECONVERT_SERVICE_ID, VERUSID_SERVICE_ID, WYRE_SERVICE_ID, ATTESTATION_SERVICE_ID } from "../../../utils/constants/services";
import VerusIdService from "../ServiceComponents/VerusIdService/VerusIdService";
import WyreService from "../ServiceComponents/WyreService/WyreService";
import PbaasPreconvertService from "../ServiceComponents/PbaasPreconvertService/PbaasPreconvertService";
-
+import AttestationService from "../ServiceComponents/AttestationService/AttestationService";
class Service extends Component {
constructor(props) {
super(props);
@@ -18,7 +18,8 @@ class Service extends Component {
this.SERVICE_COMPONENTS = {
[WYRE_SERVICE_ID]: ,
[VERUSID_SERVICE_ID]: ,
- [PBAAS_PRECONVERT_SERVICE_ID]:
+ [PBAAS_PRECONVERT_SERVICE_ID]: ,
+ [ATTESTATION_SERVICE_ID]: ,
}
}
diff --git a/src/containers/Services/ServiceComponents/AttestationService/AttestationService.js b/src/containers/Services/ServiceComponents/AttestationService/AttestationService.js
new file mode 100644
index 00000000..d147de65
--- /dev/null
+++ b/src/containers/Services/ServiceComponents/AttestationService/AttestationService.js
@@ -0,0 +1,66 @@
+import React, { Component } from "react"
+import { connect } from 'react-redux'
+import { setServiceLoading } from "../../../../actions/actionCreators";
+import { createAlert } from "../../../../actions/actions/alert/dispatchers/alert";
+import { requestServiceStoredData } from "../../../../utils/auth/authBox";
+import { ATTESTATION_SERVICE_ID } from "../../../../utils/constants/services";
+import { VerusAttestationRender } from "./AttestationService.render";
+import { ATTESTATIONS_PROVISIONED } from "../../../../utils/constants/attestations";
+import { requestAttestationData } from "../../../../utils/auth/authBox";
+
+class AttestationService extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ attestations: {},
+ };
+ this.props.navigation.setOptions({title: 'Attestations'});
+ const sdf=234
+ }
+
+ async getAttestations() {
+ this.props.dispatch(setServiceLoading(true, ATTESTATION_SERVICE_ID));
+
+ try {
+ const attestationData = await requestAttestationData(ATTESTATIONS_PROVISIONED);
+ if (attestationData) {
+ this.setState({
+ attestations: attestationData
+ });
+ }
+ } catch (e) {
+ createAlert('Error Loading Attestations', e.message);
+ }
+
+ this.props.dispatch(setServiceLoading(false, ATTESTATION_SERVICE_ID));
+ }
+
+ componentDidMount() {
+
+ this.getAttestations();
+ }
+
+ viewDetails = (attestation) => {
+ this.props.navigation.navigate("ViewAttestation", {attestation});
+ }
+
+ componentDidUpdate(lastProps) {
+ // if (lastProps.encryptedIds !== this.props.encryptedIds) {
+ // this.getLinkedIds()
+ // }
+ }
+
+ render() {
+ return VerusAttestationRender.call(this);
+ }
+}
+
+const mapStateToProps = state => {
+
+ return {
+ loading: state.services.loading[ATTESTATION_SERVICE_ID],
+ attestestationdata: state.attestation
+ };
+};
+
+export default connect(mapStateToProps)(AttestationService);
\ No newline at end of file
diff --git a/src/containers/Services/ServiceComponents/AttestationService/AttestationService.render.js b/src/containers/Services/ServiceComponents/AttestationService/AttestationService.render.js
new file mode 100644
index 00000000..7934faf1
--- /dev/null
+++ b/src/containers/Services/ServiceComponents/AttestationService/AttestationService.render.js
@@ -0,0 +1,54 @@
+import React from "react";
+import { View, Text } from 'react-native'
+import styles from "../../../../styles";
+import AnimatedActivityIndicator from "../../../../components/AnimatedActivityIndicator";
+import {Divider, List} from 'react-native-paper';
+
+export const VerusAttestationRender = function () {
+ return (
+
+ {(this.props.loading) && (
+
+
+
+ )}
+ {!this.props.loading && (
+
+ {Object.values(this.state.attestations || {}).length === 0 && (
+ No attestations present
+ )}
+ {Object.values(this.state.attestations || {}).map((attestation, index) => {
+
+ return (
+
+ this.viewDetails(attestation)}
+ right={props => (
+
+ )}
+ />
+
+
+ );
+
+
+ })}
+
+ )}
+
+ );
+};
diff --git a/src/containers/Services/ServiceComponents/AttestationService/ViewAttestation/ViewAttestation.js b/src/containers/Services/ServiceComponents/AttestationService/ViewAttestation/ViewAttestation.js
new file mode 100644
index 00000000..257fec15
--- /dev/null
+++ b/src/containers/Services/ServiceComponents/AttestationService/ViewAttestation/ViewAttestation.js
@@ -0,0 +1,104 @@
+import React, { Component } from "react"
+import { connect } from 'react-redux'
+
+import { primitives } from "verusid-ts-client"
+
+import * as VDXF_Data from "verus-typescript-primitives/dist/vdxf/vdxfDataKeys";
+
+const { ATTESTATION_NAME } = primitives;
+import { IdentityVdxfidMap } from "verus-typescript-primitives/dist/vdxf/classes/IdentityData";
+import { SafeAreaView, ScrollView, View, Image } from 'react-native'
+
+import { Divider, List, Button, Text } from 'react-native-paper';
+import Styles from "../../../../../styles";
+import Colors from '../../../../../globals/colors';
+
+class ViewAttestation extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ attestationData: {},
+ signer: ""
+ };
+ }
+
+ componentDidMount() {
+ this.updateDisplay();
+ }
+
+ getAttestationData = (dataDescriptors) => {
+
+ const data = {};
+ dataDescriptors.forEach((dataDescriptor) => {
+ const label = dataDescriptor.objectdata[Object.keys(dataDescriptor.objectdata)[0]].label;
+ let key = "";
+
+ if (label === ATTESTATION_NAME.vdxfid) {
+ key = `Attestation name`
+ } else {
+ key = IdentityVdxfidMap[label]?.name || label;
+ }
+
+ const mime = dataDescriptor.objectdata[Object.keys(dataDescriptor.objectdata)[0]].mimetype || "";
+ if (mime.startsWith("text/")) {
+ data[key] = { "message": dataDescriptor.objectdata[Object.keys(dataDescriptor.objectdata)[0]].objectdata.message };
+ } else if (mime.startsWith("image/")) {
+ if (mime === "image/jpeg" || mime === "image/png") {
+ data[key] = { "image": `data:${mime};base64,${Buffer.from(dataDescriptor.objectdata[Object.keys(dataDescriptor.objectdata)[0]].objectdata, "hex").toString("base64")}` };
+ }
+ }
+ });
+
+ return data;
+
+ }
+
+ updateDisplay() {
+ const { attestation } = this.props.route.params
+
+ const signatureData = attestation.data.find((dataDescriptor) => Object.keys(dataDescriptor)[0] === VDXF_Data.SignatureDataKey().vdxfid)[VDXF_Data.SignatureDataKey().vdxfid];
+ const mmrData = attestation.data.find((dataDescriptor) => Object.keys(dataDescriptor)[0] === VDXF_Data.MMRDescriptorKey().vdxfid)[VDXF_Data.MMRDescriptorKey().vdxfid];
+
+ const containingData = this.getAttestationData(mmrData.datadescriptors);
+ this.setState({ attestationData: containingData, signer:attestation.signer });
+
+ }
+
+ render() {
+ return (
+
+
+
+
+
+ {`From: `}{`${this.state.signer}`}
+
+ {this.state.attestationData && Object.keys(this.state.attestationData).map(request => {
+ return (
+
+ this.state.attestationData[request]?.image ? : null}
+ />
+
+
+ );
+ })}
+
+
+ )
+ }
+}
+
+const mapStateToProps = (state) => {
+ return {
+ activeAccount: state.authentication.activeAccount,
+ encryptedPersonalData: state.personal
+ }
+};
+
+export default connect(mapStateToProps)(ViewAttestation);
\ No newline at end of file
diff --git a/src/images/servicelogo/index.js b/src/images/servicelogo/index.js
index 0becf58f..adba8100 100644
--- a/src/images/servicelogo/index.js
+++ b/src/images/servicelogo/index.js
@@ -1,8 +1,9 @@
-import { VERUSID_SERVICE_ID, WYRE_SERVICE_ID } from '../../utils/constants/services'
+import { VERUSID_SERVICE_ID, WYRE_SERVICE_ID, ATTESTATION_SERVICE_ID } from '../../utils/constants/services'
import WYRE_LIGHT from './wyre/wyre_light.svg'
import VERUSID_LIGHT from './verusid/verusid_light.svg'
export default {
[WYRE_SERVICE_ID]: { light: WYRE_LIGHT },
- [VERUSID_SERVICE_ID]: { light: VERUSID_LIGHT }
+ [VERUSID_SERVICE_ID]: { light: VERUSID_LIGHT },
+ [ATTESTATION_SERVICE_ID]: { light: VERUSID_LIGHT },
}
\ No newline at end of file
diff --git a/src/reducers/services.js b/src/reducers/services.js
index d637c2e0..ded58121 100644
--- a/src/reducers/services.js
+++ b/src/reducers/services.js
@@ -2,7 +2,7 @@
The personal reducer stores data used by services
*/
-import { VERUSID_SERVICE_ID, WYRE_SERVICE_ID, PBAAS_PRECONVERT_SERVICE_ID } from "../utils/constants/services";
+import { VERUSID_SERVICE_ID, WYRE_SERVICE_ID, PBAAS_PRECONVERT_SERVICE_ID, ATTESTATION_SERVICE_ID } from "../utils/constants/services";
import {
SET_SERVICE_ACCOUNT,
SIGN_OUT,
@@ -24,7 +24,8 @@ export const services = (
loading: {
[WYRE_SERVICE_ID]: false,
[VERUSID_SERVICE_ID]: false,
- [PBAAS_PRECONVERT_SERVICE_ID]: false
+ [PBAAS_PRECONVERT_SERVICE_ID]: false,
+ [ATTESTATION_SERVICE_ID]: false
},
},
action,
@@ -94,7 +95,8 @@ export const services = (
loading: {
[WYRE_SERVICE_ID]: false,
[VERUSID_SERVICE_ID]: false,
- [PBAAS_PRECONVERT_SERVICE_ID]: false
+ [PBAAS_PRECONVERT_SERVICE_ID]: false,
+ [ATTESTATION_SERVICE_ID]: false
},
};
default:
diff --git a/src/utils/asyncStore/serviceStoredDataStorage.js b/src/utils/asyncStore/serviceStoredDataStorage.js
index 09c51e13..2850d246 100644
--- a/src/utils/asyncStore/serviceStoredDataStorage.js
+++ b/src/utils/asyncStore/serviceStoredDataStorage.js
@@ -1,6 +1,6 @@
import AsyncStorage from "@react-native-async-storage/async-storage";
import { SERVICE_STORAGE_INTERNAL_KEY } from "../../../env/index";
-import { VERUSID_SERVICE_ID, WYRE_SERVICE_ID } from "../constants/services";
+import { VERUSID_SERVICE_ID, WYRE_SERVICE_ID, ATTESTATION_SERVICE_ID } from "../constants/services";
export const storeServiceStoredData = (data) => {
if (typeof data !== "object")
diff --git a/src/utils/attestations/createAttestationResponse.js b/src/utils/attestations/createAttestationResponse.js
new file mode 100644
index 00000000..55382eb0
--- /dev/null
+++ b/src/utils/attestations/createAttestationResponse.js
@@ -0,0 +1,37 @@
+import { requestAttestationData } from "../../utils/auth/authBox";
+import { ATTESTATIONS_PROVISIONED } from "../../utils/constants/attestations";
+import * as VDXF_Data from "verus-typescript-primitives/dist/vdxf/vdxfDataKeys";
+
+export const createAttestationResponse = async (attestationID, requiredKeys) => {
+
+ const attestationData = await requestAttestationData(ATTESTATIONS_PROVISIONED);
+
+ if (!attestationData[attestationID]) {
+ throw new Error(`Attestation not found in attestation data`);
+ }
+
+ const attestation = attestationData[attestationID];
+ const attestataionKeysToRemove = [];
+ const indexedDatadescriptor = {}
+
+ for (let i = 0; i < attestation.data.length; i++) {
+ if (Object.keys(attestation.data[i])[0] === VDXF_Data.MMRDescriptorKey().vdxfid) {
+
+ for (let j = 0; j < attestation.data[i][VDXF_Data.MMRDescriptorKey().vdxfid].datadescriptors.length; j++) {
+
+ const item = attestation.data[i][VDXF_Data.MMRDescriptorKey().vdxfid].datadescriptors[j].objectdata[VDXF_Data.DataDescriptorKey().vdxfid];
+
+ if (requiredKeys.indexOf(item.label) === -1) {
+ attestataionKeysToRemove.push(j)
+ } else {
+ indexedDatadescriptor[j] = attestation.data[i][VDXF_Data.MMRDescriptorKey().vdxfid].datadescriptors[j];
+ }
+
+ }
+ delete attestation.data[i][VDXF_Data.MMRDescriptorKey().vdxfid].datadescriptors
+ attestation.data[i][VDXF_Data.MMRDescriptorKey().vdxfid].datadescriptors = indexedDatadescriptor
+ }
+ };
+
+ return attestation
+}
\ No newline at end of file
diff --git a/src/utils/auth/authBox.js b/src/utils/auth/authBox.js
index 037c8698..3586e03e 100644
--- a/src/utils/auth/authBox.js
+++ b/src/utils/auth/authBox.js
@@ -176,4 +176,29 @@ export const requestServiceStoredData = async (service) => {
throw new Error("Unable to decrypt service stored data for " + service);
}
}
-};
\ No newline at end of file
+};
+
+export const requestAttestationData = async (dataType) => {
+ const state = store.getState()
+
+ if (
+ state.authentication.activeAccount == null
+ ) {
+ throw new Error("You must be signed in to retrieve attestation data");
+ } else if (state.attestation[dataType] == null) {
+ return {}
+ } else {
+ const password = await requestPassword()
+ const data = decryptkey(password, state.attestation[dataType])
+
+ if (data !== false) {
+ try {
+ return JSON.parse(data)
+ } catch(e) {
+ throw new Error("Unable to parse attestation data")
+ }
+ } else {
+ throw new Error("Unable to decrypt attestation data");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/utils/constants/services.js b/src/utils/constants/services.js
index ba1900b1..40177952 100644
--- a/src/utils/constants/services.js
+++ b/src/utils/constants/services.js
@@ -3,6 +3,7 @@ import { WYRE_SERVICE } from "./intervalConstants"
export const WYRE_SERVICE_ID = 'wyre_service'
export const VERUSID_SERVICE_ID = 'verusid_service'
export const PBAAS_PRECONVERT_SERVICE_ID = 'pbaas_preconvert'
+export const ATTESTATION_SERVICE_ID = 'attestation_service'
export const CONNECTED_SERVICE_DISPLAY_INFO = {
[WYRE_SERVICE_ID]: {
@@ -18,6 +19,11 @@ export const CONNECTED_SERVICE_DISPLAY_INFO = {
title: "Preconvert Currency",
description: "Participate in a PBaaS currency launch by sending your funds to the currency before it starts",
decentralized: true
+ },
+ [ATTESTATION_SERVICE_ID]: {
+ title: "Attestations",
+ description: "Stored attestations that can be used to prove information about you to services you use",
+ decentralized: true
}
}
@@ -25,7 +31,7 @@ export const CONNECTED_SERVICE_CHANNELS = {
[WYRE_SERVICE_ID]: WYRE_SERVICE
}
-export const CONNECTED_SERVICES = [VERUSID_SERVICE_ID, /*PBAAS_PRECONVERT_SERVICE_ID ,*/ WYRE_SERVICE_ID]
+export const CONNECTED_SERVICES = [VERUSID_SERVICE_ID, /*PBAAS_PRECONVERT_SERVICE_ID ,*/ WYRE_SERVICE_ID, ATTESTATION_SERVICE_ID]
// Wyre specific constants
export const WYRE_INDIVIDUAL_NAME = 'individualLegalName'
diff --git a/src/utils/deeplink/handlePersonalDataSend.js b/src/utils/deeplink/handlePersonalDataSend.js
index e67a76e6..404a7cd0 100644
--- a/src/utils/deeplink/handlePersonalDataSend.js
+++ b/src/utils/deeplink/handlePersonalDataSend.js
@@ -3,6 +3,12 @@ import * as primitives from "verus-typescript-primitives"
const handlers = {
+ [primitives.LOGIN_CONSENT_PERSONALINFO_WEBHOOK_VDXF_KEY.vdxfid]: async (uri, response) => {
+ return await axios.post(
+ uri,
+ response
+ );
+ },
[primitives.LOGIN_CONSENT_PERSONALINFO_WEBHOOK_VDXF_KEY.vdxfid]: async (uri, response) => {
return await axios.post(
uri,
@@ -14,5 +20,11 @@ const handlers = {
export const handlePersonalDataSend = (response, redirectinfo) => {
const { vdxfkey, uri } = redirectinfo
+ return handlers[vdxfkey] == null ? null : handlers[vdxfkey](uri, response);
+}
+
+export const handleAttestationDataSend = (response, redirectinfo) => {
+ const { vdxfkey, uri } = redirectinfo
+
return handlers[vdxfkey] == null ? null : handlers[vdxfkey](uri, response);
}
\ No newline at end of file
diff --git a/src/utils/nativeStore/attestationDataStorage.js b/src/utils/nativeStore/attestationDataStorage.js
index 1296e5db..9847bb10 100644
--- a/src/utils/nativeStore/attestationDataStorage.js
+++ b/src/utils/nativeStore/attestationDataStorage.js
@@ -63,7 +63,7 @@ export const loadAttestationDataForUser = async (accountHash) => {
if (allAttestationData[accountHash] == null)
return {
- attestations: null
+ attestations_provisioned: null
};
else return allAttestationData[accountHash];
};
diff --git a/yarn.lock b/yarn.lock
index 3c6eabd7..4bd255bf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3175,11 +3175,6 @@ bech32@2.0.0:
resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355"
integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==
-bech32@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355"
- integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==
-
bech32@^1.1.2, bech32@^1.1.3:
version "1.1.4"
resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9"
@@ -11587,7 +11582,6 @@ version_compare@0.0.3:
"verusd-rpc-ts-client@https://github.com/VerusCoin/verusd-rpc-ts-client.git":
version "0.1.0"
- uid "62d260563c23ecf9b3333355e8596191c764e415"
resolved "https://github.com/VerusCoin/verusd-rpc-ts-client.git#62d260563c23ecf9b3333355e8596191c764e415"
dependencies:
axios "1.6.5"