@bifold/core 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/lib/commonjs/components/inputs/BiometryControl.js.map +1 -1
  2. package/lib/commonjs/components/misc/CredentialCard.js +3 -2
  3. package/lib/commonjs/components/misc/CredentialCard.js.map +1 -1
  4. package/lib/commonjs/components/misc/FauxHeader.js +89 -0
  5. package/lib/commonjs/components/misc/FauxHeader.js.map +1 -0
  6. package/lib/commonjs/components/misc/QRScanner.js +1 -1
  7. package/lib/commonjs/components/misc/QRScanner.js.map +1 -1
  8. package/lib/commonjs/components/modals/DeveloperModal.js +43 -0
  9. package/lib/commonjs/components/modals/DeveloperModal.js.map +1 -0
  10. package/lib/commonjs/components/views/PushNotificationsContent.js.map +1 -1
  11. package/lib/commonjs/components/views/PushNotificationsDisabledContent.js.map +1 -1
  12. package/lib/commonjs/contexts/auth.js +24 -3
  13. package/lib/commonjs/contexts/auth.js.map +1 -1
  14. package/lib/commonjs/hooks/chat-messages.js +1 -1
  15. package/lib/commonjs/hooks/chat-messages.js.map +1 -1
  16. package/lib/commonjs/hooks/developer-mode.js +31 -0
  17. package/lib/commonjs/hooks/developer-mode.js.map +1 -0
  18. package/lib/commonjs/hooks/lockout.js +80 -0
  19. package/lib/commonjs/hooks/lockout.js.map +1 -0
  20. package/lib/commonjs/hooks/onboarding.js +23 -0
  21. package/lib/commonjs/hooks/onboarding.js.map +1 -0
  22. package/lib/commonjs/index.js +24 -0
  23. package/lib/commonjs/index.js.map +1 -1
  24. package/lib/commonjs/localization/en/index.js +2 -1
  25. package/lib/commonjs/localization/en/index.js.map +1 -1
  26. package/lib/commonjs/localization/fr/index.js +2 -1
  27. package/lib/commonjs/localization/fr/index.js.map +1 -1
  28. package/lib/commonjs/localization/pt-br/index.js +2 -1
  29. package/lib/commonjs/localization/pt-br/index.js.map +1 -1
  30. package/lib/commonjs/modules/openid/components/OpenIDCredentialCard.js +4 -5
  31. package/lib/commonjs/modules/openid/components/OpenIDCredentialCard.js.map +1 -1
  32. package/lib/commonjs/modules/openid/display.js +6 -3
  33. package/lib/commonjs/modules/openid/display.js.map +1 -1
  34. package/lib/commonjs/modules/openid/metadata.js +2 -1
  35. package/lib/commonjs/modules/openid/metadata.js.map +1 -1
  36. package/lib/commonjs/modules/openid/screens/OpenIDProofChangeCredential.js +128 -0
  37. package/lib/commonjs/modules/openid/screens/OpenIDProofChangeCredential.js.map +1 -0
  38. package/lib/commonjs/modules/openid/screens/OpenIDProofPresentation.js +99 -44
  39. package/lib/commonjs/modules/openid/screens/OpenIDProofPresentation.js.map +1 -1
  40. package/lib/commonjs/modules/openid/types.js.map +1 -1
  41. package/lib/commonjs/modules/openid/utils/utils.js +0 -14
  42. package/lib/commonjs/modules/openid/utils/utils.js.map +1 -1
  43. package/lib/commonjs/navigators/DeliveryStack.js +8 -0
  44. package/lib/commonjs/navigators/DeliveryStack.js.map +1 -1
  45. package/lib/commonjs/navigators/OnboardingScreens.js +0 -8
  46. package/lib/commonjs/navigators/OnboardingScreens.js.map +1 -1
  47. package/lib/commonjs/navigators/OnboardingStack.js +3 -4
  48. package/lib/commonjs/navigators/OnboardingStack.js.map +1 -1
  49. package/lib/commonjs/navigators/TabStack.js +11 -4
  50. package/lib/commonjs/navigators/TabStack.js.map +1 -1
  51. package/lib/commonjs/navigators/defaultStackOptions.js +2 -1
  52. package/lib/commonjs/navigators/defaultStackOptions.js.map +1 -1
  53. package/lib/commonjs/screens/Biometry.js.map +1 -1
  54. package/lib/commonjs/screens/NameWallet.js +4 -3
  55. package/lib/commonjs/screens/NameWallet.js.map +1 -1
  56. package/lib/commonjs/screens/OnboardingPages.js +8 -38
  57. package/lib/commonjs/screens/OnboardingPages.js.map +1 -1
  58. package/lib/commonjs/screens/PINChange.js +5 -1
  59. package/lib/commonjs/screens/PINChange.js.map +1 -1
  60. package/lib/commonjs/screens/PINCreate.js +4 -1
  61. package/lib/commonjs/screens/PINCreate.js.map +1 -1
  62. package/lib/commonjs/screens/PINEnter.js +114 -292
  63. package/lib/commonjs/screens/PINEnter.js.map +1 -1
  64. package/lib/commonjs/screens/PINVerify.js +181 -0
  65. package/lib/commonjs/screens/PINVerify.js.map +1 -0
  66. package/lib/commonjs/screens/PushNotifications.js.map +1 -1
  67. package/lib/commonjs/screens/Settings.js +9 -18
  68. package/lib/commonjs/screens/Settings.js.map +1 -1
  69. package/lib/commonjs/screens/ToggleBiometry.js +16 -24
  70. package/lib/commonjs/screens/ToggleBiometry.js.map +1 -1
  71. package/lib/commonjs/theme.js +2 -1
  72. package/lib/commonjs/theme.js.map +1 -1
  73. package/lib/commonjs/types/navigators.js +1 -0
  74. package/lib/commonjs/types/navigators.js.map +1 -1
  75. package/lib/commonjs/utils/oca.js +46 -17
  76. package/lib/commonjs/utils/oca.js.map +1 -1
  77. package/lib/module/components/inputs/BiometryControl.js.map +1 -1
  78. package/lib/module/components/misc/CredentialCard.js +3 -2
  79. package/lib/module/components/misc/CredentialCard.js.map +1 -1
  80. package/lib/module/components/misc/FauxHeader.js +80 -0
  81. package/lib/module/components/misc/FauxHeader.js.map +1 -0
  82. package/lib/module/components/misc/QRScanner.js +1 -1
  83. package/lib/module/components/misc/QRScanner.js.map +1 -1
  84. package/lib/module/components/modals/DeveloperModal.js +36 -0
  85. package/lib/module/components/modals/DeveloperModal.js.map +1 -0
  86. package/lib/module/components/views/PushNotificationsContent.js.map +1 -1
  87. package/lib/module/components/views/PushNotificationsDisabledContent.js.map +1 -1
  88. package/lib/module/contexts/auth.js +22 -1
  89. package/lib/module/contexts/auth.js.map +1 -1
  90. package/lib/module/hooks/chat-messages.js +1 -1
  91. package/lib/module/hooks/chat-messages.js.map +1 -1
  92. package/lib/module/hooks/developer-mode.js +24 -0
  93. package/lib/module/hooks/developer-mode.js.map +1 -0
  94. package/lib/module/hooks/lockout.js +70 -0
  95. package/lib/module/hooks/lockout.js.map +1 -0
  96. package/lib/module/hooks/onboarding.js +16 -0
  97. package/lib/module/hooks/onboarding.js.map +1 -0
  98. package/lib/module/index.js +4 -1
  99. package/lib/module/index.js.map +1 -1
  100. package/lib/module/localization/en/index.js +2 -1
  101. package/lib/module/localization/en/index.js.map +1 -1
  102. package/lib/module/localization/fr/index.js +2 -1
  103. package/lib/module/localization/fr/index.js.map +1 -1
  104. package/lib/module/localization/pt-br/index.js +2 -1
  105. package/lib/module/localization/pt-br/index.js.map +1 -1
  106. package/lib/module/modules/openid/components/OpenIDCredentialCard.js +4 -4
  107. package/lib/module/modules/openid/components/OpenIDCredentialCard.js.map +1 -1
  108. package/lib/module/modules/openid/display.js +6 -3
  109. package/lib/module/modules/openid/display.js.map +1 -1
  110. package/lib/module/modules/openid/metadata.js +2 -1
  111. package/lib/module/modules/openid/metadata.js.map +1 -1
  112. package/lib/module/modules/openid/screens/OpenIDProofChangeCredential.js +121 -0
  113. package/lib/module/modules/openid/screens/OpenIDProofChangeCredential.js.map +1 -0
  114. package/lib/module/modules/openid/screens/OpenIDProofPresentation.js +100 -45
  115. package/lib/module/modules/openid/screens/OpenIDProofPresentation.js.map +1 -1
  116. package/lib/module/modules/openid/types.js.map +1 -1
  117. package/lib/module/modules/openid/utils/utils.js +1 -12
  118. package/lib/module/modules/openid/utils/utils.js.map +1 -1
  119. package/lib/module/navigators/DeliveryStack.js +8 -0
  120. package/lib/module/navigators/DeliveryStack.js.map +1 -1
  121. package/lib/module/navigators/OnboardingScreens.js +0 -8
  122. package/lib/module/navigators/OnboardingScreens.js.map +1 -1
  123. package/lib/module/navigators/OnboardingStack.js +4 -5
  124. package/lib/module/navigators/OnboardingStack.js.map +1 -1
  125. package/lib/module/navigators/TabStack.js +11 -4
  126. package/lib/module/navigators/TabStack.js.map +1 -1
  127. package/lib/module/navigators/defaultStackOptions.js +2 -1
  128. package/lib/module/navigators/defaultStackOptions.js.map +1 -1
  129. package/lib/module/screens/Biometry.js.map +1 -1
  130. package/lib/module/screens/NameWallet.js +4 -3
  131. package/lib/module/screens/NameWallet.js.map +1 -1
  132. package/lib/module/screens/OnboardingPages.js +8 -38
  133. package/lib/module/screens/OnboardingPages.js.map +1 -1
  134. package/lib/module/screens/PINChange.js +5 -1
  135. package/lib/module/screens/PINChange.js.map +1 -1
  136. package/lib/module/screens/PINCreate.js +4 -1
  137. package/lib/module/screens/PINCreate.js.map +1 -1
  138. package/lib/module/screens/PINEnter.js +116 -294
  139. package/lib/module/screens/PINEnter.js.map +1 -1
  140. package/lib/module/screens/PINVerify.js +172 -0
  141. package/lib/module/screens/PINVerify.js.map +1 -0
  142. package/lib/module/screens/PushNotifications.js.map +1 -1
  143. package/lib/module/screens/Settings.js +7 -16
  144. package/lib/module/screens/Settings.js.map +1 -1
  145. package/lib/module/screens/ToggleBiometry.js +15 -23
  146. package/lib/module/screens/ToggleBiometry.js.map +1 -1
  147. package/lib/module/theme.js +2 -1
  148. package/lib/module/theme.js.map +1 -1
  149. package/lib/module/types/navigators.js +1 -0
  150. package/lib/module/types/navigators.js.map +1 -1
  151. package/lib/module/utils/oca.js +43 -15
  152. package/lib/module/utils/oca.js.map +1 -1
  153. package/lib/typescript/src/components/inputs/BiometryControl.d.ts.map +1 -1
  154. package/lib/typescript/src/components/misc/CredentialCard.d.ts.map +1 -1
  155. package/lib/typescript/src/components/misc/FauxHeader.d.ts +8 -0
  156. package/lib/typescript/src/components/misc/FauxHeader.d.ts.map +1 -0
  157. package/lib/typescript/src/components/modals/DeveloperModal.d.ts +7 -0
  158. package/lib/typescript/src/components/modals/DeveloperModal.d.ts.map +1 -0
  159. package/lib/typescript/src/contexts/auth.d.ts +1 -0
  160. package/lib/typescript/src/contexts/auth.d.ts.map +1 -1
  161. package/lib/typescript/src/hooks/developer-mode.d.ts +4 -0
  162. package/lib/typescript/src/hooks/developer-mode.d.ts.map +1 -0
  163. package/lib/typescript/src/hooks/lockout.d.ts +9 -0
  164. package/lib/typescript/src/hooks/lockout.d.ts.map +1 -0
  165. package/lib/typescript/src/hooks/onboarding.d.ts +2 -0
  166. package/lib/typescript/src/hooks/onboarding.d.ts.map +1 -0
  167. package/lib/typescript/src/index.d.ts +5 -2
  168. package/lib/typescript/src/index.d.ts.map +1 -1
  169. package/lib/typescript/src/localization/en/index.d.ts +1 -0
  170. package/lib/typescript/src/localization/en/index.d.ts.map +1 -1
  171. package/lib/typescript/src/localization/fr/index.d.ts +1 -0
  172. package/lib/typescript/src/localization/fr/index.d.ts.map +1 -1
  173. package/lib/typescript/src/localization/pt-br/index.d.ts +1 -0
  174. package/lib/typescript/src/localization/pt-br/index.d.ts.map +1 -1
  175. package/lib/typescript/src/modules/openid/components/OpenIDCredentialCard.d.ts.map +1 -1
  176. package/lib/typescript/src/modules/openid/display.d.ts.map +1 -1
  177. package/lib/typescript/src/modules/openid/metadata.d.ts +8 -1
  178. package/lib/typescript/src/modules/openid/metadata.d.ts.map +1 -1
  179. package/lib/typescript/src/modules/openid/screens/OpenIDProofChangeCredential.d.ts +6 -0
  180. package/lib/typescript/src/modules/openid/screens/OpenIDProofChangeCredential.d.ts.map +1 -0
  181. package/lib/typescript/src/modules/openid/screens/OpenIDProofPresentation.d.ts.map +1 -1
  182. package/lib/typescript/src/modules/openid/types.d.ts +9 -0
  183. package/lib/typescript/src/modules/openid/types.d.ts.map +1 -1
  184. package/lib/typescript/src/modules/openid/utils/utils.d.ts +1 -3
  185. package/lib/typescript/src/modules/openid/utils/utils.d.ts.map +1 -1
  186. package/lib/typescript/src/navigators/DeliveryStack.d.ts.map +1 -1
  187. package/lib/typescript/src/navigators/OnboardingScreens.d.ts +0 -1
  188. package/lib/typescript/src/navigators/OnboardingScreens.d.ts.map +1 -1
  189. package/lib/typescript/src/navigators/OnboardingStack.d.ts.map +1 -1
  190. package/lib/typescript/src/navigators/TabStack.d.ts.map +1 -1
  191. package/lib/typescript/src/navigators/defaultStackOptions.d.ts.map +1 -1
  192. package/lib/typescript/src/screens/Biometry.d.ts.map +1 -1
  193. package/lib/typescript/src/screens/OnboardingPages.d.ts +1 -1
  194. package/lib/typescript/src/screens/OnboardingPages.d.ts.map +1 -1
  195. package/lib/typescript/src/screens/PINChange.d.ts.map +1 -1
  196. package/lib/typescript/src/screens/PINCreate.d.ts.map +1 -1
  197. package/lib/typescript/src/screens/PINEnter.d.ts +0 -7
  198. package/lib/typescript/src/screens/PINEnter.d.ts.map +1 -1
  199. package/lib/typescript/src/screens/PINVerify.d.ts +13 -0
  200. package/lib/typescript/src/screens/PINVerify.d.ts.map +1 -0
  201. package/lib/typescript/src/screens/Settings.d.ts.map +1 -1
  202. package/lib/typescript/src/screens/ToggleBiometry.d.ts.map +1 -1
  203. package/lib/typescript/src/theme.d.ts +10 -25
  204. package/lib/typescript/src/theme.d.ts.map +1 -1
  205. package/lib/typescript/src/types/navigators.d.ts +14 -1
  206. package/lib/typescript/src/types/navigators.d.ts.map +1 -1
  207. package/lib/typescript/src/utils/oca.d.ts +7 -2
  208. package/lib/typescript/src/utils/oca.d.ts.map +1 -1
  209. package/package.json +3 -3
  210. package/src/components/inputs/BiometryControl.tsx +16 -13
  211. package/src/components/misc/CredentialCard.tsx +5 -2
  212. package/src/components/misc/FauxHeader.tsx +75 -0
  213. package/src/components/misc/QRScanner.tsx +1 -1
  214. package/src/components/modals/DeveloperModal.tsx +30 -0
  215. package/src/components/views/PushNotificationsContent.tsx +15 -15
  216. package/src/components/views/PushNotificationsDisabledContent.tsx +10 -10
  217. package/src/contexts/auth.tsx +33 -1
  218. package/src/hooks/chat-messages.tsx +1 -1
  219. package/src/hooks/developer-mode.ts +25 -0
  220. package/src/hooks/lockout.ts +77 -0
  221. package/src/hooks/onboarding.ts +16 -0
  222. package/src/hooks/usePINValidation.ts +3 -3
  223. package/src/index.ts +7 -0
  224. package/src/localization/en/index.ts +1 -0
  225. package/src/localization/fr/index.ts +1 -0
  226. package/src/localization/pt-br/index.ts +1 -0
  227. package/src/modules/openid/components/OpenIDCredentialCard.tsx +3 -4
  228. package/src/modules/openid/display.tsx +3 -0
  229. package/src/modules/openid/metadata.tsx +7 -1
  230. package/src/modules/openid/screens/OpenIDProofChangeCredential.tsx +132 -0
  231. package/src/modules/openid/screens/OpenIDProofPresentation.tsx +131 -59
  232. package/src/modules/openid/types.tsx +8 -0
  233. package/src/modules/openid/utils/utils.tsx +0 -14
  234. package/src/navigators/DeliveryStack.tsx +9 -0
  235. package/src/navigators/OnboardingScreens.ts +0 -10
  236. package/src/navigators/OnboardingStack.tsx +2 -6
  237. package/src/navigators/RootStack.tsx +1 -1
  238. package/src/navigators/TabStack.tsx +3 -2
  239. package/src/navigators/defaultStackOptions.tsx +1 -0
  240. package/src/screens/Biometry.tsx +1 -4
  241. package/src/screens/NameWallet.tsx +2 -2
  242. package/src/screens/OnboardingPages.tsx +9 -61
  243. package/src/screens/PINChange.tsx +6 -9
  244. package/src/screens/PINCreate.tsx +7 -18
  245. package/src/screens/PINEnter.tsx +114 -361
  246. package/src/screens/PINVerify.tsx +193 -0
  247. package/src/screens/PushNotifications.tsx +2 -2
  248. package/src/screens/Settings.tsx +6 -21
  249. package/src/screens/ToggleBiometry.tsx +20 -34
  250. package/src/theme.ts +34 -3
  251. package/src/types/navigators.ts +18 -1
  252. package/src/utils/oca.ts +60 -19
@@ -1,4 +1,4 @@
1
- import { useEffect, useMemo, useState } from 'react'
1
+ import { useCallback, useEffect, useMemo, useState } from 'react'
2
2
  import { DeviceEventEmitter } from 'react-native'
3
3
  import { useAgent } from '@credo-ts/react-hooks'
4
4
  import { useTranslation } from 'react-i18next'
@@ -31,6 +31,20 @@ import { isSdJwtProofRequest, isW3CProofRequest } from '../utils/utils'
31
31
 
32
32
  type OpenIDProofPresentationProps = StackScreenProps<DeliveryStackParams, Screens.OpenIDProofPresentation>
33
33
 
34
+ type SatisfiedCredentialsFormat = {
35
+ [inputDescriptorId: string]: {
36
+ id: string
37
+ claimFormat: string
38
+ }[]
39
+ }
40
+
41
+ type SelectedCredentialsFormat = {
42
+ [inputDescriptorId: string]: {
43
+ id: string
44
+ claimFormat: string
45
+ }
46
+ }
47
+
34
48
  const OpenIDProofPresentation: React.FC<OpenIDProofPresentationProps> = ({
35
49
  navigation,
36
50
  route: {
@@ -43,6 +57,9 @@ const OpenIDProofPresentation: React.FC<OpenIDProofPresentationProps> = ({
43
57
  const [credentialsRequested, setCredentialsRequested] = useState<
44
58
  Array<W3cCredentialRecord | SdJwtVcRecord | MdocRecord>
45
59
  >([])
60
+ const [satistfiedCredentialsSubmission, setSatistfiedCredentialsSubmission] = useState<SatisfiedCredentialsFormat>()
61
+ const [selectedCredentialsSubmission, setSelectedCredentialsSubmission] = useState<SelectedCredentialsFormat>()
62
+
46
63
  const { getW3CCredentialById, getSdJwtCredentialById } = useOpenIDCredentials()
47
64
 
48
65
  const { ColorPallet, ListItems, TextTheme } = useTheme()
@@ -104,53 +121,61 @@ const OpenIDProofPresentation: React.FC<OpenIDProofPresentationProps> = ({
104
121
  [credential]
105
122
  )
106
123
 
107
- const selectedCredentials:
108
- | {
109
- [inputDescriptorId: string]: {
110
- id: string
111
- claimFormat: string
112
- }
113
- }
114
- | undefined = useMemo(
115
- () =>
116
- submission?.entries.reduce((acc, entry) => {
117
- if (entry.isSatisfied) {
118
- //TODO: Support multiplae credentials
119
- return {
120
- ...acc,
121
- [entry.inputDescriptorId]: {
122
- id: entry.credentials[0].id,
123
- claimFormat: entry.credentials[0].claimFormat,
124
- },
125
- }
126
- }
127
- return acc
128
- }, {}),
129
- [submission]
130
- )
124
+ //This should run only once when the screen is mounted
125
+ useEffect(() => {
126
+ if (!submission) return
127
+ const creds = submission.entries.reduce((acc: SatisfiedCredentialsFormat, entry) => {
128
+ acc[entry.inputDescriptorId] = entry.credentials.map((cred) => ({
129
+ id: cred.id,
130
+ claimFormat: cred.claimFormat,
131
+ }))
132
+ return acc
133
+ }, {})
134
+ setSatistfiedCredentialsSubmission(creds)
135
+ }, [submission])
131
136
 
137
+ //Fetch all credentials satisfying the proof
132
138
  useEffect(() => {
133
139
  async function fetchCreds() {
134
- if (!selectedCredentials) return
140
+ if (!satistfiedCredentialsSubmission || satistfiedCredentialsSubmission.entries) return
135
141
 
136
142
  const creds: Array<W3cCredentialRecord | SdJwtVcRecord | MdocRecord> = []
137
143
 
138
- for (const [inputDescriptorID, { id, claimFormat }] of Object.entries(selectedCredentials)) {
139
- let credential: W3cCredentialRecord | SdJwtVcRecord | MdocRecord | undefined
140
- if (isW3CProofRequest(claimFormat)) {
141
- credential = await getW3CCredentialById(id)
142
- } else if (isSdJwtProofRequest(claimFormat)) {
143
- credential = await getSdJwtCredentialById(id)
144
- }
144
+ for (const [inputDescriptorID, credIDs] of Object.entries(satistfiedCredentialsSubmission)) {
145
+ for (const { id, claimFormat } of credIDs) {
146
+ let credential: W3cCredentialRecord | SdJwtVcRecord | MdocRecord | undefined
147
+ if (isW3CProofRequest(claimFormat)) {
148
+ credential = await getW3CCredentialById(id)
149
+ } else if (isSdJwtProofRequest(claimFormat)) {
150
+ credential = await getSdJwtCredentialById(id)
151
+ }
145
152
 
146
- if (credential && inputDescriptorID) {
147
- creds.push(credential)
153
+ if (credential && inputDescriptorID) {
154
+ creds.push(credential)
155
+ }
148
156
  }
149
157
  }
150
158
  setCredentialsRequested(creds)
151
159
  }
152
160
  fetchCreds()
153
- }, [selectedCredentials, getW3CCredentialById, getSdJwtCredentialById])
161
+ }, [satistfiedCredentialsSubmission, getW3CCredentialById, getSdJwtCredentialById])
162
+
163
+ //Once satisfied credentials are set and all credentials fetched, we select the first one of each submission to display on screen
164
+ useEffect(() => {
165
+ if (!satistfiedCredentialsSubmission || credentialsRequested?.length <= 0) return
166
+
167
+ const creds = Object.entries(satistfiedCredentialsSubmission).reduce(
168
+ (acc: SelectedCredentialsFormat, [inputDescriptorId, credentials]) => {
169
+ acc[inputDescriptorId] = {
170
+ id: credentials[0].id,
171
+ claimFormat: credentials[0].claimFormat,
172
+ }
173
+ return acc
174
+ },
175
+ {}
176
+ )
177
+ setSelectedCredentialsSubmission(creds)
178
+ }, [satistfiedCredentialsSubmission, credentialsRequested])
154
179
 
155
180
  const { verifierName } = useMemo(() => {
156
181
  return { verifierName: credential?.verifierHostName }
@@ -158,16 +183,15 @@ const OpenIDProofPresentation: React.FC<OpenIDProofPresentationProps> = ({
158
183
 
159
184
  const handleAcceptTouched = async () => {
160
185
  try {
161
- if (!agent || !credential.credentialsForRequest || !selectedCredentials) {
186
+ if (!agent || !credential.credentialsForRequest || !selectedCredentialsSubmission) {
162
187
  return
163
188
  }
164
189
  await shareProof({
165
190
  agent,
166
191
  authorizationRequest: credential.authorizationRequest,
167
192
  credentialsForRequest: credential.credentialsForRequest,
168
- selectedCredentials,
193
+ selectedCredentials: selectedCredentialsSubmission,
169
194
  })
170
-
171
195
  setAcceptModalVisible(true)
172
196
  } catch (err: unknown) {
173
197
  setButtonsVisible(true)
@@ -185,6 +209,47 @@ const OpenIDProofPresentation: React.FC<OpenIDProofPresentationProps> = ({
185
209
  navigation.getParent()?.navigate(TabStacks.HomeStack, { screen: Screens.Home })
186
210
  }
187
211
 
212
+ // Re-construct the selected credentials object based on user alt credential
213
+ const onCredChange = ({
214
+ inputDescriptorID,
215
+ id,
216
+ claimFormat,
217
+ }: {
218
+ inputDescriptorID: string
219
+ id: string
220
+ claimFormat: string
221
+ }) => {
222
+ setSelectedCredentialsSubmission((prev) => ({
223
+ ...prev,
224
+ [inputDescriptorID]: {
225
+ id,
226
+ claimFormat,
227
+ },
228
+ }))
229
+ }
230
+
231
+ const handleAltCredChange = useCallback(
232
+ (inputDescriptorID: string, selectedCredID: string, inputDescriptor: string) => {
233
+ const submittionEntries = submission?.entries.find((entry) => entry.inputDescriptorId === inputDescriptor)
234
+ const credsForEntry = submittionEntries?.credentials
235
+
236
+ if (!credsForEntry) return
237
+
238
+ navigation.navigate(Screens.OpenIDProofCredentialSelect, {
239
+ inputDescriptorID: inputDescriptorID,
240
+ selectedCredID: selectedCredID,
241
+ altCredIDs: credsForEntry.map((cred) => {
242
+ return {
243
+ id: cred.id,
244
+ claimFormat: cred.claimFormat,
245
+ }
246
+ }),
247
+ onCredChange: onCredChange,
248
+ })
249
+ },
250
+ [submission, navigation]
251
+ )
252
+
188
253
  const renderHeader = () => {
189
254
  return (
190
255
  <View style={styles.headerTextContainer}>
@@ -200,8 +265,6 @@ const OpenIDProofPresentation: React.FC<OpenIDProofPresentationProps> = ({
200
265
  const renderCard = (
201
266
  sub: FormattedSubmissionEntry,
202
267
  selectedCredential: FormattedSelectedCredentialEntry,
203
- //TODO: Support multiplae credentials
204
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
205
268
  hasMultipleCreds: boolean
206
269
  ) => {
207
270
  const credential = credentialsRequested.find((c) => c.id === selectedCredential.id)
@@ -209,33 +272,38 @@ const OpenIDProofPresentation: React.FC<OpenIDProofPresentationProps> = ({
209
272
  return null
210
273
  }
211
274
  const credentialDisplay = getCredentialForDisplay(credential)
212
- const fields = buildFieldsFromW3cCredsCredential(credentialDisplay)
213
275
  const requestedAttributes = selectedCredential.requestedAttributes
214
- const fieldsMapped = fields.filter((field) => requestedAttributes?.includes(field.name))
276
+ const fields = buildFieldsFromW3cCredsCredential(credentialDisplay, requestedAttributes)
215
277
  return (
216
278
  <CredentialCard
217
279
  credential={credential}
218
- displayItems={fieldsMapped as Attribute[]}
219
- //TODO: Support multiplae credentials
220
- // hasAltCredentials={hasMultipleCreds}
221
- // handleAltCredChange={selectAltCredentail}
280
+ displayItems={fields as Attribute[]}
281
+ hasAltCredentials={hasMultipleCreds}
282
+ handleAltCredChange={() => {
283
+ handleAltCredChange(sub.inputDescriptorId, selectedCredential.id, sub.inputDescriptorId)
284
+ }}
222
285
  />
223
286
  )
224
287
  }
225
288
 
226
289
  const renderBody = () => {
227
- if (!submission) return null
290
+ if (!selectedCredentialsSubmission || !submission) return null
228
291
 
229
292
  return (
230
293
  <View style={styles.credentialsList}>
231
- {submission.entries.map((s, i) => {
294
+ {Object.entries(selectedCredentialsSubmission).map(([inputDescriptorId, credentialSimplified], i) => {
232
295
  //TODO: Support multiplae credentials
233
- const selectedCredential = s.credentials[0]
234
296
 
235
297
  const globalSubmissionName = submission.name
236
298
  const globalSubmissionPurpose = submission.purpose
237
- const submissionName = s.name
238
- const submissionPurpose = s.purpose
299
+ const correspondingSubmission = submission.entries?.find((s) => s.inputDescriptorId === inputDescriptorId)
300
+ const submissionName = correspondingSubmission?.name
301
+ const submissionPurpose = correspondingSubmission?.purpose
302
+ const isSatisfied = correspondingSubmission?.isSatisfied
303
+ const credentialSubmittion = correspondingSubmission?.credentials.find(
304
+ (s) => s.id === credentialSimplified.id
305
+ )
306
+ const requestedAttributes = credentialSubmittion?.requestedAttributes
239
307
 
240
308
  const name = submissionName || globalSubmissionName || undefined
241
309
  const purpose = submissionPurpose || globalSubmissionPurpose || undefined
@@ -246,12 +314,16 @@ const OpenIDProofPresentation: React.FC<OpenIDProofPresentationProps> = ({
246
314
  <View style={styles.cardGroupContainer}>
247
315
  {name && purpose && (
248
316
  <View style={styles.cardGroupHeader}>
249
- <Text style={TextTheme.labelSubtitle}>{name}</Text>
250
- <Text style={TextTheme.labelSubtitle}>{purpose}</Text>
317
+ <Text style={TextTheme.bold}>{name}</Text>
318
+ <Text style={TextTheme.labelTitle}>{purpose}</Text>
251
319
  </View>
252
320
  )}
253
- {s.isSatisfied && selectedCredential?.requestedAttributes ? (
254
- renderCard(s, selectedCredential, s.credentials.length > 1)
321
+ {isSatisfied && requestedAttributes ? (
322
+ renderCard(
323
+ correspondingSubmission,
324
+ credentialSubmittion,
325
+ correspondingSubmission.credentials.length > 1
326
+ )
255
327
  ) : (
256
328
  <Text style={TextTheme.normal}>{t('ProofRequest.CredentialNotInWallet')}</Text>
257
329
  )}
@@ -295,14 +367,14 @@ const OpenIDProofPresentation: React.FC<OpenIDProofPresentationProps> = ({
295
367
  backgroundColor: ColorPallet.brand.secondaryBackground,
296
368
  }}
297
369
  >
298
- {selectedCredentials && Object.keys(selectedCredentials).length > 0 ? (
370
+ {selectedCredentialsSubmission && Object.keys(selectedCredentialsSubmission).length > 0 ? (
299
371
  <>
300
372
  {footerButton(
301
- t('Global.Accept'),
373
+ t('Global.Send'),
302
374
  handleAcceptTouched,
303
375
  ButtonType.Primary,
304
376
  testIdWithKey('AcceptCredentialOffer'),
305
- t('Global.Accept')
377
+ t('Global.Send')
306
378
  )}
307
379
  {footerButton(
308
380
  t('Global.Decline'),
@@ -86,6 +86,7 @@ export interface W3cCredentialDisplay {
86
86
  claimFormat: ClaimFormat
87
87
  validUntil: Date | undefined
88
88
  validFrom: Date | undefined
89
+ credentialSubject: CredentialSubjectRecord | undefined
89
90
  }
90
91
 
91
92
  export interface OpenId4VPRequestRecord extends OpenId4VcSiopResolvedAuthorizationRequest {
@@ -96,6 +97,13 @@ export interface OpenId4VPRequestRecord extends OpenId4VcSiopResolvedAuthorizati
96
97
  type: string
97
98
  }
98
99
 
100
+ interface DisplayInfo {
101
+ name: string
102
+ locale?: string
103
+ }
104
+
105
+ export type CredentialSubjectRecord = Record<string, { display: DisplayInfo[] }>
106
+
99
107
  export enum OpenIDCredentialType {
100
108
  W3cCredential,
101
109
  SdJwtVc,
@@ -1,6 +1,5 @@
1
1
  import { getDomainFromUrl } from '@credo-ts/core'
2
2
  import { Attribute, Field } from '@bifold/oca/build/legacy'
3
- import { W3cCredentialDisplay } from '../types'
4
3
 
5
4
  /**
6
5
  * Converts a camelCase string to a sentence format (first letter capitalized, rest in lower case).
@@ -53,19 +52,6 @@ export function formatDate(input: string | Date): string {
53
52
  })
54
53
  }
55
54
 
56
- export const getAttributeField = (display: W3cCredentialDisplay, searchKey: string): Attribute | undefined => {
57
- for (const [key, value] of Object.entries(display.attributes)) {
58
- if (searchKey === key) {
59
- return new Attribute({
60
- name: key,
61
- value: value as string | number | null,
62
- mimeType: typeof value === 'number' ? 'text/number' : 'text/plain',
63
- })
64
- }
65
- }
66
- return undefined
67
- }
68
-
69
55
  /**
70
56
  * Mostly used for mdoc crednetials
71
57
  */
@@ -13,6 +13,7 @@ import { useDefaultStackOptions } from './defaultStackOptions'
13
13
  import OpenIDProofPresentation from '../modules/openid/screens/OpenIDProofPresentation'
14
14
  import { TOKENS, useServices } from '../container-api'
15
15
  import OpenIDCredentialOffer from '../modules/openid/screens/OpenIDCredentialOffer'
16
+ import OpenIDProofCredentialSelect from '../modules/openid/screens/OpenIDProofChangeCredential'
16
17
 
17
18
  const DeliveryStack: React.FC = () => {
18
19
  const Stack = createStackNavigator<DeliveryStackParams>()
@@ -67,6 +68,14 @@ const DeliveryStack: React.FC = () => {
67
68
  ...ScreenOptionsDictionary[Screens.OpenIDProofPresentation],
68
69
  }}
69
70
  />
71
+ <Stack.Screen
72
+ name={Screens.OpenIDProofCredentialSelect}
73
+ component={OpenIDProofCredentialSelect}
74
+ options={{
75
+ title: t('Screens.ProofRequest'),
76
+ ...ScreenOptionsDictionary[Screens.OpenIDProofCredentialSelect],
77
+ }}
78
+ />
70
79
  </Stack.Navigator>
71
80
  )
72
81
  }
@@ -20,7 +20,6 @@ interface ScreenComponents {
20
20
  NameWallet: React.FC<StackScreenProps<ParamListBase>>
21
21
  Biometry: React.FC<StackScreenProps<ParamListBase>>
22
22
  PushNotifications: React.FC<StackScreenProps<ParamListBase>>
23
- Developer: React.FC<StackScreenProps<ParamListBase>>
24
23
  AttemptLockout: React.FC<StackScreenProps<ParamListBase>>
25
24
  OnboardingScreen: React.FC
26
25
  CreatePINScreen: React.FC
@@ -119,15 +118,6 @@ export const getOnboardingScreens = (
119
118
  ...ScreenOptionsDictionary[Screens.PushNotifications],
120
119
  }),
121
120
  },
122
- {
123
- name: Screens.Developer,
124
- component: components.Developer,
125
- options: () => ({
126
- title: t('Screens.Developer'),
127
- headerBackAccessibilityLabel: t('Global.Back'),
128
- ...ScreenOptionsDictionary[Screens.Developer],
129
- }),
130
- },
131
121
  {
132
122
  name: Screens.EnterPIN,
133
123
  children: components.EnterPINScreen,
@@ -2,7 +2,7 @@
2
2
  import { Agent } from '@credo-ts/core'
3
3
  import { StackActions, useNavigation, useNavigationState } from '@react-navigation/native'
4
4
  import { StackNavigationProp, createStackNavigator } from '@react-navigation/stack'
5
- import React, { useMemo, useCallback, useEffect } from 'react'
5
+ import React, { useCallback, useEffect, useMemo } from 'react'
6
6
  import { useTranslation } from 'react-i18next'
7
7
  import { DeviceEventEmitter } from 'react-native'
8
8
 
@@ -18,10 +18,10 @@ import { createCarouselStyle } from '../screens/OnboardingPages'
18
18
  import PINCreate from '../screens/PINCreate'
19
19
  import PINEnter from '../screens/PINEnter'
20
20
  import PushNotifications from '../screens/PushNotifications'
21
+ import { Config } from '../types/config'
21
22
  import { OnboardingStackParams } from '../types/navigators'
22
23
  import { WalletSecret } from '../types/security'
23
24
  import { State } from '../types/state'
24
- import { Config } from '../types/config'
25
25
 
26
26
  import { useDefaultStackOptions } from './defaultStackOptions'
27
27
  import { getOnboardingScreens } from './OnboardingScreens'
@@ -44,7 +44,6 @@ const OnboardingStack: React.FC<OnboardingStackProps> = ({ initializeAgent, agen
44
44
  pages,
45
45
  Biometry,
46
46
  Onboarding,
47
- Developer,
48
47
  { screen: Terms, version: termsVersion },
49
48
  onTutorialCompletedCurried,
50
49
  ScreenOptionsDictionary,
@@ -58,7 +57,6 @@ const OnboardingStack: React.FC<OnboardingStackProps> = ({ initializeAgent, agen
58
57
  TOKENS.SCREEN_ONBOARDING_PAGES,
59
58
  TOKENS.SCREEN_BIOMETRY,
60
59
  TOKENS.SCREEN_ONBOARDING,
61
- TOKENS.SCREEN_DEVELOPER,
62
60
  TOKENS.SCREEN_TERMS,
63
61
  TOKENS.FN_ONBOARDING_DONE,
64
62
  TOKENS.OBJECT_SCREEN_CONFIG,
@@ -172,7 +170,6 @@ const OnboardingStack: React.FC<OnboardingStackProps> = ({ initializeAgent, agen
172
170
  NameWallet,
173
171
  Biometry,
174
172
  PushNotifications,
175
- Developer,
176
173
  AttemptLockout,
177
174
  OnboardingScreen,
178
175
  CreatePINScreen,
@@ -181,7 +178,6 @@ const OnboardingStack: React.FC<OnboardingStackProps> = ({ initializeAgent, agen
181
178
  [
182
179
  SplashScreen,
183
180
  CreatePINScreen,
184
- Developer,
185
181
  EnterPINScreen,
186
182
  OnboardingScreen,
187
183
  Preface,
@@ -45,7 +45,7 @@ const RootStack: React.FC = () => {
45
45
  useEffect(() => {
46
46
  // Load state only if it hasn't been loaded yet
47
47
  if (store.stateLoaded) return
48
-
48
+
49
49
  loadState(dispatch).catch((err: unknown) => {
50
50
  const error = new BifoldError(t('Error.Title1044'), t('Error.Message1044'), (err as Error).message, 1001)
51
51
 
@@ -61,7 +61,7 @@ const TabStack: React.FC = () => {
61
61
  const { t } = useTranslation()
62
62
  const Tab = createBottomTabNavigator<TabStackParams>()
63
63
  const { assertNetworkConnected } = useNetwork()
64
- const { ColorPallet, TabTheme, TextTheme, Assets } = useTheme()
64
+ const { ColorPallet, TabTheme, TextTheme, Assets, NavigationTheme } = useTheme()
65
65
  const [orientation, setOrientation] = useState(OrientationType.PORTRAIT)
66
66
  const [store, dispatch] = useStore()
67
67
  const { agent } = useAgent()
@@ -133,7 +133,7 @@ const TabStack: React.FC = () => {
133
133
  }, [store.deepLink, agent, store.authentication.didAuthenticate, handleDeepLink])
134
134
 
135
135
  return (
136
- <SafeAreaView style={{ flex: 1, backgroundColor: ColorPallet.brand.primary }}>
136
+ <SafeAreaView style={{ flex: 1, backgroundColor: NavigationTheme.colors.primary }} edges={['left', 'right', 'top']}>
137
137
  <Tab.Navigator
138
138
  initialRouteName={TabStacks.HomeStack}
139
139
  screenOptions={{
@@ -296,6 +296,7 @@ const TabStack: React.FC = () => {
296
296
  }}
297
297
  />
298
298
  </Tab.Navigator>
299
+ <SafeAreaView style={{ backgroundColor: TabTheme.tabBarSecondaryBackgroundColor }} edges={['bottom']} />
299
300
  </SafeAreaView>
300
301
  )
301
302
  }
@@ -62,6 +62,7 @@ export const DefaultScreenOptionsDictionary: ScreenOptionsType = {
62
62
  },
63
63
  [Screens.OpenIDProofPresentation]: {
64
64
  headerShown: true,
65
+ headerRight: () => false,
65
66
  },
66
67
  }
67
68
 
@@ -34,10 +34,7 @@ const Biometry: React.FC = () => {
34
34
  }, [])
35
35
 
36
36
  return (
37
- <BiometryControl
38
- biometryEnabled={biometryEnabled}
39
- onBiometryToggle={handleBiometryToggle}
40
- >
37
+ <BiometryControl biometryEnabled={biometryEnabled} onBiometryToggle={handleBiometryToggle}>
41
38
  <View style={{ marginTop: 'auto', margin: 20 }}>
42
39
  <Button
43
40
  title={t('Global.Continue')}
@@ -88,12 +88,12 @@ const NameWallet: React.FC = () => {
88
88
  type: DispatchAction.UPDATE_WALLET_NAME,
89
89
  payload: [walletName],
90
90
  })
91
+ dispatch({ type: DispatchAction.DID_NAME_WALLET })
91
92
 
92
93
  if (agent) {
93
94
  agent.config.label = walletName
95
+ navigation.goBack()
94
96
  }
95
-
96
- dispatch({ type: DispatchAction.DID_NAME_WALLET })
97
97
  }
98
98
  }
99
99
 
@@ -1,23 +1,18 @@
1
- import { useNavigation } from '@react-navigation/native'
2
- import { StackNavigationProp } from '@react-navigation/stack'
3
- import React, { useRef } from 'react'
1
+ import React from 'react'
4
2
  import { useTranslation } from 'react-i18next'
5
- import { ScrollView, StyleSheet, View, TouchableWithoutFeedback } from 'react-native'
3
+ import { ScrollView, StyleSheet, View } from 'react-native'
6
4
  import { SvgProps } from 'react-native-svg'
7
5
 
8
6
  import CredentialList from '../assets/img/credential-list.svg'
9
7
  import ScanShare from '../assets/img/scan-share.svg'
10
8
  import Button, { ButtonType } from '../components/buttons/Button'
11
- import { DispatchAction } from '../contexts/reducers/store'
12
- import { useStore } from '../contexts/store'
13
9
  import { GenericFn } from '../types/fn'
14
- import { OnboardingStackParams, Screens } from '../types/navigators'
15
10
  import { testIdWithKey } from '../utils/testable'
16
11
 
17
12
  import { useTheme } from '../contexts/theme'
18
13
 
19
- import { OnboardingStyleSheet } from './Onboarding'
20
14
  import { ThemedText } from '../components/texts/ThemedText'
15
+ import { OnboardingStyleSheet } from './Onboarding'
21
16
 
22
17
  export const createCarouselStyle = (OnboardingTheme: any) => {
23
18
  return StyleSheet.create<OnboardingStyleSheet>({
@@ -136,32 +131,17 @@ const guides: Array<{ image: React.FC<SvgProps>; title: string; body: string; de
136
131
  },
137
132
  ]
138
133
 
139
- export const createPageWith = (
140
- PageImage: React.FC<SvgProps>,
141
- title: string,
142
- body: string,
143
- OnboardingTheme: any,
144
- devModeListener?: boolean,
145
- onDevModeTouched?: () => void
146
- ) => {
134
+ export const createPageWith = (PageImage: React.FC<SvgProps>, title: string, body: string, OnboardingTheme: any) => {
147
135
  const styles = createStyles(OnboardingTheme)
148
136
  const imageDisplayOptions = createImageDisplayOptions(OnboardingTheme)
149
- const titleElement = (
150
- <ThemedText style={styles.headerText} testID={testIdWithKey('HeaderText')}>
151
- {title}
152
- </ThemedText>
153
- )
137
+
154
138
  return (
155
139
  <ScrollView style={{ padding: 20 }}>
156
140
  <View style={{ alignItems: 'center' }}>{<PageImage style={imageDisplayOptions} />}</View>
157
141
  <View style={{ marginBottom: 20 }}>
158
- {devModeListener ? (
159
- <TouchableWithoutFeedback testID={testIdWithKey('DeveloperModeTouch')} onPress={onDevModeTouched}>
160
- {titleElement}
161
- </TouchableWithoutFeedback>
162
- ) : (
163
- titleElement
164
- )}
142
+ <ThemedText style={styles.headerText} testID={testIdWithKey('HeaderText')}>
143
+ {title}
144
+ </ThemedText>
165
145
  <ThemedText style={[styles.bodyText, { marginTop: 25 }]} testID={testIdWithKey('BodyText')}>
166
146
  {body}
167
147
  </ThemedText>
@@ -171,40 +151,8 @@ export const createPageWith = (
171
151
  }
172
152
 
173
153
  const OnboardingPages = (onTutorialCompleted: GenericFn, OnboardingTheme: any): Array<Element> => {
174
- const navigation = useNavigation<StackNavigationProp<OnboardingStackParams>>()
175
- const [, dispatch] = useStore()
176
- const onDevModeEnabled = () => {
177
- dispatch({
178
- type: DispatchAction.ENABLE_DEVELOPER_MODE,
179
- payload: [true],
180
- })
181
- navigation.getParent()?.navigate(Screens.Developer)
182
- }
183
- const developerOptionCount = useRef(0)
184
- const touchCountToEnableBiometrics = 9
185
-
186
- const incrementDeveloperMenuCounter = () => {
187
- if (developerOptionCount.current >= touchCountToEnableBiometrics) {
188
- developerOptionCount.current = 0
189
- if (onDevModeEnabled) {
190
- onDevModeEnabled()
191
- }
192
- return
193
- }
194
-
195
- developerOptionCount.current = developerOptionCount.current + 1
196
- }
197
154
  return [
198
- ...guides.map((g) =>
199
- createPageWith(
200
- g.image,
201
- g.title,
202
- g.body,
203
- OnboardingTheme,
204
- g.devModeListener,
205
- g.devModeListener ? incrementDeveloperMenuCounter : undefined
206
- )
207
- ),
155
+ ...guides.map((g) => createPageWith(g.image, g.title, g.body, OnboardingTheme)),
208
156
  CustomPages(onTutorialCompleted, OnboardingTheme),
209
157
  ]
210
158
  }