├── .nvmrc
├── app
├── .ruby-version
├── ios
│ ├── .ruby-version
│ ├── Media.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── iTunesArtwork.png
│ │ │ ├── iTunesArtwork_Dark.png
│ │ │ ├── iTunesArtwork_Tinted.png
│ │ │ └── Contents.json
│ ├── AriesBifold-Bridging-Header.h
│ ├── AriesBifold
│ │ ├── AppDelegate.h
│ │ ├── AriesBifold.entitlements
│ │ └── main.m
│ ├── AriesBifold.swift
│ ├── AriesBifold.xcworkspace
│ │ ├── xcshareddata
│ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── contents.xcworkspacedata
│ ├── .xcode.env
│ ├── AriesBifoldTests
│ │ └── Info.plist
│ └── GoogleService-Info.plist
├── .npmrc
├── __mocks__
│ ├── file.js
│ ├── style.js
│ ├── @credo-ts
│ │ └── react-native.ts
│ ├── react-native-fs.ts
│ ├── @hyperledger
│ │ ├── indy-vdr-react-native.ts
│ │ ├── anoncreds-react-native.ts
│ │ └── aries-askar-react-native.ts
│ ├── custom
│ │ ├── @react-navigation
│ │ │ ├── native.ts
│ │ │ └── core.ts
│ │ ├── react-native-camera.ts
│ │ └── react-native-localize.ts
│ ├── react-native-argon2.js
│ ├── @react-native-firebase
│ │ └── messaging.ts
│ ├── react-native-keychain.ts
│ ├── react-native-bcsc-core.ts
│ ├── @react-native-async-storage
│ │ └── async-storage.js
│ ├── react-native-volume-manager.ts
│ ├── react-native-permissions.ts
│ ├── @pexip
│ │ └── infinity-api.ts
│ ├── @react-native-clipboard
│ │ └── clipboard.js
│ ├── react-native-screenguard.ts
│ ├── react-native-incall-manager.ts
│ ├── react-i18next.ts
│ ├── react-native-tcp-socket
│ │ └── index.ts
│ ├── @react-navigation
│ │ ├── core.ts
│ │ └── native.ts
│ └── @react-native-community
│ │ └── netinfo.ts
├── reactNativePermissionsIOS.json
├── app.json
├── .bundle
│ └── config
├── react-native.config.js
├── android
│ ├── app
│ │ ├── debug.keystore
│ │ ├── release.keystore
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── res
│ │ │ │ │ ├── values
│ │ │ │ │ │ ├── strings.xml
│ │ │ │ │ │ ├── colors.xml
│ │ │ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ │ │ └── styles.xml
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ │ ├── drawable
│ │ │ │ │ │ ├── ic_launcher_mono.png
│ │ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ │ └── ic_launcher_play_store.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ ├── ic_launcher_round.png
│ │ │ │ │ │ └── ic_launcher_foreground.png
│ │ │ │ │ ├── drawable-hdpi
│ │ │ │ │ │ └── ic_notification.png
│ │ │ │ │ ├── drawable-mdpi
│ │ │ │ │ │ └── ic_notification.png
│ │ │ │ │ ├── drawable-xhdpi
│ │ │ │ │ │ └── ic_notification.png
│ │ │ │ │ ├── drawable-xxhdpi
│ │ │ │ │ │ └── ic_notification.png
│ │ │ │ │ ├── drawable-xxxhdpi
│ │ │ │ │ │ └── ic_notification.png
│ │ │ │ │ ├── mipmap-anydpi-v26
│ │ │ │ │ │ ├── ic_launcher.xml
│ │ │ │ │ │ └── ic_launcher_round.xml
│ │ │ │ │ └── layout
│ │ │ │ │ │ └── launch_screen.xml
│ │ │ │ ├── ic_launcher-playstore.png
│ │ │ │ └── assets
│ │ │ │ │ └── fonts
│ │ │ │ │ ├── BCSans-Bold.ttf
│ │ │ │ │ ├── BCSans-Italic.ttf
│ │ │ │ │ ├── BCSans-Regular.ttf
│ │ │ │ │ └── BCSans-BoldItalic.ttf
│ │ │ └── debug
│ │ │ │ └── AndroidManifest.xml
│ │ ├── proguard-rules.pro
│ │ ├── build_defs.bzl
│ │ ├── .idea
│ │ │ └── modules
│ │ │ │ └── app.iml
│ │ └── google-services.json
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── settings-gradle.lockfile
│ └── settings.gradle
├── src
│ ├── assets
│ │ ├── img
│ │ │ ├── analytics.png
│ │ │ ├── combo_card.png
│ │ │ ├── logo-large.png
│ │ │ ├── photo_card.png
│ │ │ ├── qr-code-scan.png
│ │ │ ├── FirstTutorial.jpg
│ │ │ ├── SecondTutorial.jpg
│ │ │ ├── ThirdTutorial.jpg
│ │ │ ├── logo-large@2x.png
│ │ │ ├── logo-large@3x.png
│ │ │ ├── no_photo_card.png
│ │ │ ├── notifications.png
│ │ │ ├── qr-code-phone.png
│ │ │ ├── selfie_example.png
│ │ │ ├── credential-scan.png
│ │ │ ├── logo-large-white.png
│ │ │ ├── list-of-credentials.jpg
│ │ │ ├── push-notifications.png
│ │ │ ├── tab-navigator-account.png
│ │ │ ├── card_not_found_highlight.png
│ │ │ ├── highlight_serial_barcode.png
│ │ │ ├── notifications-screencap.png
│ │ │ ├── proof-request-illustration.png
│ │ │ ├── transfer-account-two-phones.png
│ │ │ ├── credential-offer-illustration.png
│ │ │ ├── mobile-phone-scanning-laptop.jpg
│ │ │ └── credentialIcon.svg
│ │ └── fonts
│ │ │ ├── BCSans-Bold.ttf
│ │ │ ├── BCSans-Italic.ttf
│ │ │ ├── BCSans-Regular.ttf
│ │ │ ├── MaterialIcons.ttf
│ │ │ └── BCSans-BoldItalic.ttf
│ ├── events
│ │ ├── eventTypes.ts
│ │ └── alertEvents.ts
│ ├── utils
│ │ ├── splitSplice.ts
│ │ ├── expiration.ts
│ │ ├── mediator.ts
│ │ ├── analytics
│ │ │ └── analytics-singleton.ts
│ │ ├── links.ts
│ │ └── net-info-config.ts
│ ├── theme.ts
│ ├── configs
│ │ └── ledgers
│ │ │ └── indy
│ │ │ └── ledgers.ts
│ ├── bcsc-theme
│ │ ├── features
│ │ │ ├── deep-linking
│ │ │ │ ├── index.ts
│ │ │ │ ├── useHasPendingDeepLink.ts
│ │ │ │ └── DeepLinkViewModelContext.tsx
│ │ │ ├── verify
│ │ │ │ └── live-call
│ │ │ │ │ ├── utils
│ │ │ │ │ ├── formatCallTime.ts
│ │ │ │ │ └── clearTimeoutIfExists.ts
│ │ │ │ │ └── components
│ │ │ │ │ └── CallProcessingView.tsx
│ │ │ ├── webview
│ │ │ │ ├── MainWebViewScreen.tsx
│ │ │ │ ├── VerifyWebViewScreen.tsx
│ │ │ │ └── OnboardingWebViewScreen.tsx
│ │ │ ├── settings
│ │ │ │ ├── MainContactUsScreen.tsx
│ │ │ │ └── VerifyContactUsScreen.tsx
│ │ │ ├── account
│ │ │ │ ├── components
│ │ │ │ │ ├── AccountField.tsx
│ │ │ │ │ └── AccountPhoto.tsx
│ │ │ │ └── NicknameAccountScreen.tsx
│ │ │ ├── onboarding
│ │ │ │ └── OnboardingOptInAnalyticsScreen.tsx
│ │ │ ├── services
│ │ │ │ └── components
│ │ │ │ │ └── ServiceButton.tsx
│ │ │ └── home
│ │ │ │ └── components
│ │ │ │ └── HomeHeader.tsx
│ │ ├── api
│ │ │ ├── workflow
│ │ │ │ └── key-rotation.workflow.ts
│ │ │ └── hooks
│ │ │ │ ├── withAccountGuard.ts
│ │ │ │ └── useJwksApi.tsx
│ │ ├── types
│ │ │ └── cards.ts
│ │ ├── navigators
│ │ │ └── stack-utils.ts
│ │ ├── utils
│ │ │ ├── account-utils.ts
│ │ │ └── card-utils.ts
│ │ ├── components
│ │ │ ├── TabScreenWrapper.tsx
│ │ │ ├── HeaderBackButton.tsx
│ │ │ └── GenericCardImage.tsx
│ │ └── hooks
│ │ │ └── useBCSCApiClient.tsx
│ ├── localization
│ │ └── index.ts
│ ├── bcwallet-theme
│ │ ├── features
│ │ │ └── tours
│ │ │ │ ├── hooks
│ │ │ │ └── tour-image-dimensions.ts
│ │ │ │ └── index.ts
│ │ └── components
│ │ │ └── AddCredentialButton.tsx
│ ├── Root.tsx
│ ├── hooks
│ │ ├── useDebounce.tsx
│ │ └── useEventListener.tsx
│ ├── screens
│ │ └── WebDisplay.tsx
│ ├── components
│ │ └── LoadingIcon.tsx
│ └── services
│ │ └── version.ts
├── .prettierrc
├── __tests__
│ ├── components
│ │ ├── __snapshots__
│ │ │ ├── HomeHeaderView.test.tsx.snap
│ │ │ └── LoadingIcon.test.tsx.snap
│ │ ├── EmptyList.test.tsx
│ │ ├── HomeHeaderView.test.tsx
│ │ ├── AddCredentialButton.test.tsx
│ │ ├── ErrorTextBox.test.tsx
│ │ ├── LoadingIcon.test.tsx
│ │ ├── ProgressBar.test.tsx
│ │ └── NavigationContainerContext.test.tsx
│ ├── screens
│ │ ├── __snapshots__
│ │ │ ├── TransferQRDisplayScreen.test.tsx.snap
│ │ │ ├── ServiceLoginScreen.test.tsx.snap
│ │ │ ├── VerificationMethodSelectionScreen.test.tsx.snap
│ │ │ ├── EvidenceCaptureScreen.test.tsx.snap
│ │ │ ├── MainWebViewScreen.test.tsx.snap
│ │ │ ├── VerifyWebViewScreen.test.tsx.snap
│ │ │ └── OnboardingWebViewScreen.test.tsx.snap
│ │ ├── EditNicknameScreen.test.tsx
│ │ ├── NicknameAccountScreen.test.tsx
│ │ ├── MismatchedSerialScreen.test.tsx
│ │ ├── TransferQRDisplayScreen.test.tsx
│ │ ├── VerificationSuccessScreen.test.tsx
│ │ ├── TransferInformationScreen.test.tsx
│ │ ├── TransferInstructionsScreen.test.tsx
│ │ ├── AccountSetupSelectionScreen.test.tsx
│ │ ├── RemoveAccountConfirmationScreen.test.tsx
│ │ ├── AccountRenewalFinalWarningScreen.test.tsx
│ │ ├── MainWebViewScreen.test.tsx
│ │ ├── RemoteLogWarning.test.tsx
│ │ ├── VerifyWebViewScreen.test.tsx
│ │ ├── ResidentialAddressScreen.test.tsx
│ │ ├── ScanSerialScreen.test.tsx
│ │ ├── SetupStepsScreen.test.tsx
│ │ ├── SecureAppScreen.test.tsx
│ │ ├── StartCallScreen.test.tsx
│ │ ├── ManualSerialScreen.test.tsx
│ │ ├── TermsOfUseScreen.test.tsx
│ │ ├── AccountExpiredScreen.test.tsx
│ │ ├── MainSettingsScreen.test.tsx
│ │ ├── MainContactUsScreen.test.tsx
│ │ ├── LiveCallScreen.test.tsx
│ │ ├── PendingReviewScreen.test.tsx
│ │ ├── VerifyInPersonScreen.test.tsx
│ │ ├── VerifySettingsScreen.test.tsx
│ │ ├── IdentitySelectionScreen.test.tsx
│ │ ├── VerifyContactUsScreen.test.tsx
│ │ ├── EvidenceTypeListScreen.test.tsx
│ │ ├── OnboardingWebViewScreen.test.tsx
│ │ ├── SerialInstructionsScreen.test.tsx
│ │ ├── ForgetAllPairingsScreen.test.tsx
│ │ ├── SuccessfullySentScreen.test.tsx
│ │ ├── VideoInstructionsScreen.test.tsx
│ │ ├── BeforeYouCallScreen.test.tsx
│ │ ├── SettingsPrivacyPolicyScreen.test.tsx
│ │ ├── VideoTooLongScreen.test.tsx
│ │ ├── CallBusyOrClosedScreen.test.tsx
│ │ ├── OnboardingPrivacyPolicyScreen.test.tsx
│ │ ├── AccountRenewalInformationScreen.test.tsx
│ │ ├── AccountRenewalFirstWarningScreen.test.tsx
│ │ ├── VerificationMethodSelectionScreen.test.tsx
│ │ ├── DualIdentificationRequiredScreen.test.tsx
│ │ ├── PhotoReviewScreen.test.tsx
│ │ ├── EnterBirthdateScreen.test.tsx
│ │ ├── AdditionalIdentificationRequiredScreen.test.tsx
│ │ ├── Developer.test.tsx
│ │ ├── NotificationsScreen.test.tsx
│ │ ├── EmailConfirmationScreen.test.tsx
│ │ ├── IDPhotoInformationScreen.test.tsx
│ │ ├── VideoReviewScreen.test.tsx
│ │ ├── OnboardingOptInAnalyticsScreen.test.tsx
│ │ ├── PhotoInstructionsScreen.test.tsx
│ │ ├── InformationRequiredScreen.test.tsx
│ │ └── PersonCredential.test.tsx
│ ├── contexts
│ │ └── auth.ts
│ ├── helpers
│ │ └── Utils.test.ts
│ └── bcsc-theme
│ │ └── components
│ │ ├── __snapshots__
│ │ └── PairingCodeTextInput.test.tsx.snap
│ │ └── LoadingScreenContent.test.tsx
├── .prettierignore
├── Gemfile
├── declarations.d.ts
├── babel.config.js
└── tsconfig.json
├── packages
└── bcsc-core
│ ├── .watchmanconfig
│ ├── .yarnrc.yml
│ ├── src
│ └── __tests__
│ │ └── index.test.tsx
│ ├── tsconfig.build.json
│ ├── babel.config.js
│ ├── android
│ ├── src
│ │ ├── main
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── bcsccore
│ │ │ │ │ ├── bcsc-file-port
│ │ │ │ │ ├── consumer-rules.pro
│ │ │ │ │ ├── src
│ │ │ │ │ │ └── main
│ │ │ │ │ │ │ └── java
│ │ │ │ │ │ │ └── com
│ │ │ │ │ │ │ └── bcsccore
│ │ │ │ │ │ │ └── fileport
│ │ │ │ │ │ │ ├── encryption
│ │ │ │ │ │ │ ├── KeySource.java
│ │ │ │ │ │ │ └── Encryption.java
│ │ │ │ │ │ │ └── decryption
│ │ │ │ │ │ │ ├── DecryptionException.java
│ │ │ │ │ │ │ └── FileDecryptor.java
│ │ │ │ │ ├── proguard-rules.pro
│ │ │ │ │ └── build.gradle
│ │ │ │ │ └── bcsc-keypair-port
│ │ │ │ │ ├── core
│ │ │ │ │ └── exceptions
│ │ │ │ │ │ ├── KeypairGenerationException.java
│ │ │ │ │ │ └── AlertKey.java
│ │ │ │ │ └── build.gradle.template
│ │ │ ├── AndroidManifestNew.xml
│ │ │ └── AndroidManifest.xml
│ │ └── newarch
│ │ │ └── BcscCoreSpec.kt
│ └── gradle.properties
│ ├── ios
│ ├── BcscCore-Bridging-Header.h
│ └── JOSEException.swift
│ ├── react-native.config.js
│ ├── README.md
│ ├── tsconfig.json
│ ├── turbo.json
│ ├── BcscCore.podspec
│ └── eslint.config.mjs
├── .editorconfig
├── .tool-versions
├── .yarnrc.yml
├── .github
├── ISSUE_TEMPLATE
│ ├── 4-general.md
│ ├── 2-feature-request.md
│ ├── 1-bug-report.md
│ └── 3-help.md
├── pull_request_template.md
└── workflows
│ ├── scanner.yml
│ └── actions
│ ├── setup-node
│ └── action.yml
│ ├── export-ios-archive
│ └── action.yml
│ └── send-rocketchat-notification
│ └── action.yml
├── .vscode
├── extensions.json
└── settings.json
├── docs
├── hot-reload-link-2.png
├── intellij-debug-btn.png
├── intellij-debugging.png
├── BCWallet_Architecture.png
├── Emulator-debug-menu.png
├── extended-controls-kebob.png
├── intellij-run-debug-config.png
└── android-studio-java-setting.png
├── release.xcconfig
├── scripts
├── gpublish
│ ├── README.md
│ └── package.json
├── makeauthkey.sh
├── bump_ios_build.sh
└── makepp.sh
├── update-lock-files
├── COMPLIANCE.yaml
├── commitlint.config.js
├── .yarn
└── patches
│ ├── @credo-ts-indy-vdr-npm-0.5.17-aa0b05041f.patch
│ ├── @hyperledger-indy-vdr-shared-npm-0.2.2-b989282fc6.patch
│ ├── @animo-id-pex-npm-4.1.1-alpha.0-f29edfffa2.patch
│ └── @sphereon-pex-npm-5.0.0-unstable.24-921df3a8ac.patch
├── export-options-bcw.plist
├── export-options-sa.plist
├── .sonarcloud.properties
├── devops
└── charts
│ └── loki-logstack
│ ├── templates
│ └── routes.yaml
│ └── Chart.yaml
├── CONTRIBUTING.md
├── options-dev.plist
├── PATCH_NOTES.md
├── ios-certificate.md
└── .gitignore
/.nvmrc:
--------------------------------------------------------------------------------
1 | 20.19.2
--------------------------------------------------------------------------------
/app/.ruby-version:
--------------------------------------------------------------------------------
1 | 2.7.8
2 |
--------------------------------------------------------------------------------
/app/ios/.ruby-version:
--------------------------------------------------------------------------------
1 | 2.7.8
2 |
--------------------------------------------------------------------------------
/app/.npmrc:
--------------------------------------------------------------------------------
1 | legacy-peer-deps=true
2 |
--------------------------------------------------------------------------------
/packages/bcsc-core/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | end_of_line = lf
3 |
--------------------------------------------------------------------------------
/app/__mocks__/file.js:
--------------------------------------------------------------------------------
1 | export default ''
2 |
--------------------------------------------------------------------------------
/app/__mocks__/style.js:
--------------------------------------------------------------------------------
1 | export default ''
2 |
--------------------------------------------------------------------------------
/app/__mocks__/@credo-ts/react-native.ts:
--------------------------------------------------------------------------------
1 | export {}
2 |
--------------------------------------------------------------------------------
/packages/bcsc-core/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | nmHoistingLimits: workspaces
2 |
--------------------------------------------------------------------------------
/app/reactNativePermissionsIOS.json:
--------------------------------------------------------------------------------
1 | ["Camera", "Notifications"]
2 |
--------------------------------------------------------------------------------
/app/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "BCWallet",
3 | "displayName": "BC Wallet"
4 | }
--------------------------------------------------------------------------------
/packages/bcsc-core/src/__tests__/index.test.tsx:
--------------------------------------------------------------------------------
1 | it.todo('write a test');
2 |
--------------------------------------------------------------------------------
/.tool-versions:
--------------------------------------------------------------------------------
1 | nodejs 20.19.2
2 | python 3.11.2
3 | java zulu-17.56.15
4 | yarn 4.9.2
--------------------------------------------------------------------------------
/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | compressionLevel: 0
2 | enableGlobalCache: false
3 | nodeLinker: node-modules
--------------------------------------------------------------------------------
/app/.bundle/config:
--------------------------------------------------------------------------------
1 | ---
2 | BUNDLE_FORCE_RUBY_PLATFORM: "1"
3 | BUNDLE_FROZEN: "true"
4 |
--------------------------------------------------------------------------------
/app/react-native.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | assets: ['./src/assets/fonts'],
3 | }
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/4-general.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "General issue"
3 | about: For everything else
4 | ---
5 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
3 | }
4 |
--------------------------------------------------------------------------------
/docs/hot-reload-link-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/docs/hot-reload-link-2.png
--------------------------------------------------------------------------------
/docs/intellij-debug-btn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/docs/intellij-debug-btn.png
--------------------------------------------------------------------------------
/docs/intellij-debugging.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/docs/intellij-debugging.png
--------------------------------------------------------------------------------
/app/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/debug.keystore
--------------------------------------------------------------------------------
/docs/BCWallet_Architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/docs/BCWallet_Architecture.png
--------------------------------------------------------------------------------
/docs/Emulator-debug-menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/docs/Emulator-debug-menu.png
--------------------------------------------------------------------------------
/packages/bcsc-core/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig",
3 | "exclude": ["example", "lib"]
4 | }
5 |
--------------------------------------------------------------------------------
/app/android/app/release.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/release.keystore
--------------------------------------------------------------------------------
/app/ios/Media.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/app/src/assets/img/analytics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/analytics.png
--------------------------------------------------------------------------------
/docs/extended-controls-kebob.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/docs/extended-controls-kebob.png
--------------------------------------------------------------------------------
/app/src/assets/img/combo_card.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/combo_card.png
--------------------------------------------------------------------------------
/app/src/assets/img/logo-large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/logo-large.png
--------------------------------------------------------------------------------
/app/src/assets/img/photo_card.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/photo_card.png
--------------------------------------------------------------------------------
/app/src/assets/img/qr-code-scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/qr-code-scan.png
--------------------------------------------------------------------------------
/app/src/events/eventTypes.ts:
--------------------------------------------------------------------------------
1 | export enum BCWalletEventTypes {
2 | ADD_CREDENTIAL_PRESSED = 'AddCredentialPressed',
3 | }
4 |
--------------------------------------------------------------------------------
/docs/intellij-run-debug-config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/docs/intellij-run-debug-config.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | BC Wallet
3 |
4 |
--------------------------------------------------------------------------------
/app/src/assets/fonts/BCSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/fonts/BCSans-Bold.ttf
--------------------------------------------------------------------------------
/app/src/assets/img/FirstTutorial.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/FirstTutorial.jpg
--------------------------------------------------------------------------------
/app/src/assets/img/SecondTutorial.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/SecondTutorial.jpg
--------------------------------------------------------------------------------
/app/src/assets/img/ThirdTutorial.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/ThirdTutorial.jpg
--------------------------------------------------------------------------------
/app/src/assets/img/logo-large@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/logo-large@2x.png
--------------------------------------------------------------------------------
/app/src/assets/img/logo-large@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/logo-large@3x.png
--------------------------------------------------------------------------------
/app/src/assets/img/no_photo_card.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/no_photo_card.png
--------------------------------------------------------------------------------
/app/src/assets/img/notifications.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/notifications.png
--------------------------------------------------------------------------------
/app/src/assets/img/qr-code-phone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/qr-code-phone.png
--------------------------------------------------------------------------------
/app/src/assets/img/selfie_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/selfie_example.png
--------------------------------------------------------------------------------
/docs/android-studio-java-setting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/docs/android-studio-java-setting.png
--------------------------------------------------------------------------------
/packages/bcsc-core/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:react-native-builder-bob/babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/app/__mocks__/react-native-fs.ts:
--------------------------------------------------------------------------------
1 | const ReactNativeFS = {
2 | RNFSFileTypeRegular: {},
3 | }
4 |
5 | export default ReactNativeFS
6 |
--------------------------------------------------------------------------------
/app/src/assets/fonts/BCSans-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/fonts/BCSans-Italic.ttf
--------------------------------------------------------------------------------
/app/src/assets/fonts/BCSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/fonts/BCSans-Regular.ttf
--------------------------------------------------------------------------------
/app/src/assets/fonts/MaterialIcons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/fonts/MaterialIcons.ttf
--------------------------------------------------------------------------------
/app/src/assets/img/credential-scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/credential-scan.png
--------------------------------------------------------------------------------
/app/src/assets/img/logo-large-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/logo-large-white.png
--------------------------------------------------------------------------------
/release.xcconfig:
--------------------------------------------------------------------------------
1 | DEVELOPMENT_TEAM=L796QSLV3E
2 | CODE_SIGN_STYLE = Automatic
3 | CODE_SIGN_IDENTITY =
4 | PROVISIONING_PROFILE_SPECIFIER =
--------------------------------------------------------------------------------
/app/src/assets/fonts/BCSans-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/fonts/BCSans-BoldItalic.ttf
--------------------------------------------------------------------------------
/app/src/assets/img/list-of-credentials.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/list-of-credentials.jpg
--------------------------------------------------------------------------------
/app/src/assets/img/push-notifications.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/push-notifications.png
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/main/java/com/bcsccore/bcsc-file-port/consumer-rules.pro:
--------------------------------------------------------------------------------
1 | # No consumer ProGuard rules needed for file port
2 |
--------------------------------------------------------------------------------
/app/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/assets/img/tab-navigator-account.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/tab-navigator-account.png
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/main/AndroidManifestNew.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/src/assets/img/card_not_found_highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/card_not_found_highlight.png
--------------------------------------------------------------------------------
/app/src/assets/img/highlight_serial_barcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/highlight_serial_barcode.png
--------------------------------------------------------------------------------
/app/src/assets/img/notifications-screencap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/notifications-screencap.png
--------------------------------------------------------------------------------
/app/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "semi": false,
4 | "singleQuote": true,
5 | "plugins": ["prettier-plugin-organize-imports"]
6 | }
7 |
--------------------------------------------------------------------------------
/app/android/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/ios/AriesBifold-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 |
--------------------------------------------------------------------------------
/app/ios/AriesBifold/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : RCTAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/app/src/assets/img/proof-request-illustration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/proof-request-illustration.png
--------------------------------------------------------------------------------
/app/src/assets/img/transfer-account-two-phones.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/transfer-account-two-phones.png
--------------------------------------------------------------------------------
/app/__mocks__/@hyperledger/indy-vdr-react-native.ts:
--------------------------------------------------------------------------------
1 | const IndyVDRReactNative = {
2 | install: jest.fn(),
3 | }
4 |
5 | export default IndyVDRReactNative
6 |
--------------------------------------------------------------------------------
/app/android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #003468
4 |
--------------------------------------------------------------------------------
/app/src/assets/img/credential-offer-illustration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/credential-offer-illustration.png
--------------------------------------------------------------------------------
/app/src/assets/img/mobile-phone-scanning-laptop.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/src/assets/img/mobile-phone-scanning-laptop.jpg
--------------------------------------------------------------------------------
/app/__mocks__/@hyperledger/anoncreds-react-native.ts:
--------------------------------------------------------------------------------
1 | const AnonCredsReactNative = {
2 | install: jest.fn(),
3 | }
4 |
5 | export default AnonCredsReactNative
6 |
--------------------------------------------------------------------------------
/app/__mocks__/@hyperledger/aries-askar-react-native.ts:
--------------------------------------------------------------------------------
1 | const AriesAskarReactNative = {
2 | install: jest.fn(),
3 | }
4 |
5 | export default AriesAskarReactNative
6 |
--------------------------------------------------------------------------------
/app/android/app/src/main/assets/fonts/BCSans-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/assets/fonts/BCSans-Bold.ttf
--------------------------------------------------------------------------------
/app/android/app/src/main/assets/fonts/BCSans-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/assets/fonts/BCSans-Italic.ttf
--------------------------------------------------------------------------------
/app/__mocks__/custom/@react-navigation/native.ts:
--------------------------------------------------------------------------------
1 | const useFocusEffect = jest.fn()
2 | const useIsFocused = jest.fn()
3 |
4 | export { useFocusEffect, useIsFocused }
5 |
--------------------------------------------------------------------------------
/app/android/app/src/main/assets/fonts/BCSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/assets/fonts/BCSans-Regular.ttf
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/android/app/src/main/assets/fonts/BCSans-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/assets/fonts/BCSans-BoldItalic.ttf
--------------------------------------------------------------------------------
/app/android/app/src/main/res/drawable/ic_launcher_mono.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/drawable/ic_launcher_mono.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/drawable/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/drawable/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/ios/Media.xcassets/AppIcon.appiconset/iTunesArtwork.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/ios/Media.xcassets/AppIcon.appiconset/iTunesArtwork.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/drawable-hdpi/ic_notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/drawable-hdpi/ic_notification.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/drawable-mdpi/ic_notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/drawable-mdpi/ic_notification.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/app/__mocks__/react-native-argon2.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line
2 | const argon2 = jest.fn().mockReturnValue({ rawHash: Promise.resolve('1234567890') })
3 |
4 | export default argon2
5 |
--------------------------------------------------------------------------------
/app/android/app/src/main/res/drawable-xhdpi/ic_notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/drawable-xhdpi/ic_notification.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/drawable-xxhdpi/ic_notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/drawable-xxhdpi/ic_notification.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/drawable-xxxhdpi/ic_notification.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/drawable-xxxhdpi/ic_notification.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/drawable/ic_launcher_play_store.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/drawable/ic_launcher_play_store.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/ios/Media.xcassets/AppIcon.appiconset/iTunesArtwork_Dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/ios/Media.xcassets/AppIcon.appiconset/iTunesArtwork_Dark.png
--------------------------------------------------------------------------------
/app/__tests__/components/__snapshots__/HomeHeaderView.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`HomeHeaderView Component renders correctly 1`] = `null`;
4 |
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/ios/Media.xcassets/AppIcon.appiconset/iTunesArtwork_Tinted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/ios/Media.xcassets/AppIcon.appiconset/iTunesArtwork_Tinted.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bcgov/bc-wallet-mobile/HEAD/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/android/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #003468
4 |
--------------------------------------------------------------------------------
/app/.prettierignore:
--------------------------------------------------------------------------------
1 | package-lock.json
2 | app.json
3 | ios/
4 | android/
5 | node_modules/
6 | generate-app-package-json.js
7 | src/configs/ledgers/indy/ledgers.json
8 | .gitignore
9 | coverage/
10 |
--------------------------------------------------------------------------------
/packages/bcsc-core/android/gradle.properties:
--------------------------------------------------------------------------------
1 | BcscCore_kotlinVersion=2.0.21
2 | BcscCore_minSdkVersion=24
3 | BcscCore_targetSdkVersion=35
4 | BcscCore_compileSdkVersion=35
5 | BcscCore_ndkVersion=27.1.12297006
6 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "search.exclude": {
3 | "**/node_modules": true,
4 | },
5 | "[helm]": {
6 | "editor.formatOnSave": false
7 | },
8 | "typescript.tsdk": "node_modules/typescript/lib"
9 | }
--------------------------------------------------------------------------------
/app/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
3 | ruby ">= 2.6.10"
4 | gem 'cocoapods', '~> 1.14.3'
5 | gem 'activesupport', '~> 7.0.8'
6 |
--------------------------------------------------------------------------------
/app/ios/AriesBifold.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AriesBifold.swift
3 | // AriesBifold
4 | //
5 | // Created by James Ebert on 3/12/21.
6 | // Copyright © 2021 Facebook. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
--------------------------------------------------------------------------------
/app/src/utils/splitSplice.ts:
--------------------------------------------------------------------------------
1 | export const splitSplice = (str: string, index: number, count: number, add: string): string => {
2 | const ar = str.split('')
3 | ar.splice(index, count, add)
4 | return ar.join('')
5 | }
6 |
--------------------------------------------------------------------------------
/app/src/theme.ts:
--------------------------------------------------------------------------------
1 | import { BCSCTheme } from '@bcsc-theme/theme'
2 | import { BCWalletTheme } from '@bcwallet-theme/theme'
3 | import { ITheme } from '@bifold/core'
4 |
5 | export const themes: ITheme[] = [BCWalletTheme, BCSCTheme]
6 |
--------------------------------------------------------------------------------
/app/__mocks__/@react-native-firebase/messaging.ts:
--------------------------------------------------------------------------------
1 | const messaging = jest.fn().mockReturnValue({
2 | setBackgroundMessageHandler: jest.fn(),
3 | onMessage: jest.fn(),
4 | requestPermission: jest.fn(),
5 | })
6 |
7 | export default messaging
8 |
--------------------------------------------------------------------------------
/app/android/settings-gradle.lockfile:
--------------------------------------------------------------------------------
1 | # This is a Gradle generated file for dependency locking.
2 | # Manual edits can break the build and are not advised.
3 | # This file is expected to be part of source control.
4 | empty=incomingCatalogForLibs0
5 |
--------------------------------------------------------------------------------
/app/__mocks__/react-native-keychain.ts:
--------------------------------------------------------------------------------
1 | const ACCESS_CONTROL = jest.fn()
2 | const ACCESSIBLE = jest.fn()
3 | const SECURITY_LEVEL = jest.fn()
4 | const STORAGE_TYPE = jest.fn()
5 |
6 | export { ACCESSIBLE, ACCESS_CONTROL, SECURITY_LEVEL, STORAGE_TYPE }
7 |
--------------------------------------------------------------------------------
/app/__mocks__/react-native-bcsc-core.ts:
--------------------------------------------------------------------------------
1 | const getAccount = jest.fn()
2 | const removeAccount = jest.fn()
3 | const createQuickLoginJWT = jest.fn()
4 | const decodePayload = jest.fn()
5 |
6 | export { createQuickLoginJWT, decodePayload, getAccount, removeAccount }
7 |
--------------------------------------------------------------------------------
/app/src/configs/ledgers/indy/ledgers.ts:
--------------------------------------------------------------------------------
1 | import { IndyVdrPoolConfig } from '@credo-ts/indy-vdr'
2 |
3 | import _ledgers from './ledgers.json'
4 |
5 | const filePersistedLedgers: IndyVdrPoolConfig[] = _ledgers ?? []
6 |
7 | export default filePersistedLedgers
8 |
--------------------------------------------------------------------------------
/packages/bcsc-core/ios/BcscCore-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | // Add this line for new architecture support when needed
5 | #ifdef RCT_NEW_ARCH_ENABLED
6 | #import "RNBcscCoreSpec.h"
7 | #endif
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/newarch/BcscCoreSpec.kt:
--------------------------------------------------------------------------------
1 | package com.bcsccore
2 |
3 | import com.facebook.react.bridge.ReactApplicationContext
4 |
5 | abstract class BcscCoreSpec internal constructor(context: ReactApplicationContext) :
6 | NativeBcscCoreSpec(context) {
7 | }
8 |
--------------------------------------------------------------------------------
/scripts/gpublish/README.md:
--------------------------------------------------------------------------------
1 | This is a script to help publish to the Google Play API so that
2 | we have an automated end-to-end CICD pipeline.
3 |
4 | When you make changes, make sure it publish it to npm with
5 | `npm publish`.
6 |
7 | Usage:
8 |
9 | `npx @bcgov/gpublish`
10 |
--------------------------------------------------------------------------------
/app/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'BCWallet'
2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3 | include ':app'
4 | includeBuild('../node_modules/@react-native/gradle-plugin')
5 |
--------------------------------------------------------------------------------
/scripts/makeauthkey.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -eau -o pipefail
3 |
4 | KEY_PATH=$RUNNER_TEMP/AuthKey.p9
5 |
6 | echo ">> Build API AuthKey Starting... 🤞"
7 |
8 | echo "${AUTHKEY_P8}" >"${KEY_PATH}"
9 | md5 "$KEY_PATH"
10 |
11 | echo ">> Build API AuthKey Finished. 🤗"
12 |
13 | exit 0
14 |
--------------------------------------------------------------------------------
/app/__mocks__/@react-native-async-storage/async-storage.js:
--------------------------------------------------------------------------------
1 | const store = {}
2 |
3 | export default class AsyncStorage {
4 | static getItem = (key) => {
5 | return store[key]
6 | }
7 |
8 | static setItem = (key, value) => {
9 | store[key] = value
10 |
11 | return null
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/declarations.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.svg' {
2 | import { SvgProps } from 'react-native-svg'
3 | const content: React.FC
4 | export default content
5 | }
6 |
7 | declare module '*.png'
8 | declare module '*.jpg'
9 | declare module '*.jpeg'
10 |
11 | declare module 'react-native-argon2'
12 |
--------------------------------------------------------------------------------
/app/ios/AriesBifold/AriesBifold.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | aps-environment
6 | development
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip
4 | networkTimeout=10000
5 | alidateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/app/ios/AriesBifold.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/update-lock-files:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(git --exec-path)/git-sh-setup"
3 |
4 | require_clean_work_tree "update lock files"
5 |
6 | yarn install
7 | ( cd app/ios; pod install )
8 | ( cd app/android; ./gradlew app:dependencies --write-locks )
9 |
10 | git add .
11 | git commit -sm "chore:update lock files" --no-verify
12 |
--------------------------------------------------------------------------------
/app/ios/AriesBifold.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/packages/bcsc-core/react-native.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @type {import('@react-native-community/cli-types').UserDependencyConfig}
3 | */
4 | module.exports = {
5 | dependency: {
6 | platforms: {
7 | android: {
8 | cmakeListsPath: 'generated/jni/CMakeLists.txt',
9 | },
10 | },
11 | },
12 | };
13 |
--------------------------------------------------------------------------------
/app/ios/AriesBifold.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/COMPLIANCE.yaml:
--------------------------------------------------------------------------------
1 | name: compliance
2 | description: |
3 | This document is used to track a projects PIA and STRA
4 | compliance.
5 | spec:
6 | - name: PIA
7 | status: in-progress
8 | last-updated: '2021-09-27T21:00:51.557Z'
9 | - name: STRA
10 | status: in-progress
11 | last-updated: '2021-09-27T21:00:51.557Z'
12 |
--------------------------------------------------------------------------------
/app/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/__mocks__/react-native-volume-manager.ts:
--------------------------------------------------------------------------------
1 | export const VolumeManager = {
2 | getVolume: jest.fn().mockResolvedValue({ volume: 0.5 }),
3 | setVolume: jest.fn().mockResolvedValue({ volume: 0.5 }),
4 | showNativeVolumeUI: jest.fn().mockResolvedValue({ show: true }),
5 | addVolumeListener: jest.fn(() => ({
6 | remove: jest.fn(),
7 | })),
8 | }
9 |
--------------------------------------------------------------------------------
/app/__mocks__/react-native-permissions.ts:
--------------------------------------------------------------------------------
1 | const check = jest.fn()
2 | const request = jest.fn().mockResolvedValue('not-granted')
3 |
4 | const PERMISSIONS = {
5 | ANDROID: {
6 | POST_NOTIFICATIONS: 'POST_NOTIFICATIONS',
7 | },
8 | }
9 |
10 | const RESULTS = {
11 | GRANTED: 'granted',
12 | }
13 |
14 | export { PERMISSIONS, RESULTS, check, request }
15 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/deep-linking/index.ts:
--------------------------------------------------------------------------------
1 | export { DeepLinkViewModel } from './DeepLinkViewModel'
2 | export { DeepLinkViewModelProvider, useDeepLinkViewModel } from './DeepLinkViewModelContext'
3 | export { DeepLinkService, type DeepLinkHandler, type DeepLinkPayload } from './services/deep-linking'
4 | export { useHasPendingDeepLink } from './useHasPendingDeepLink'
5 |
--------------------------------------------------------------------------------
/scripts/bump_ios_build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -xaou pipefail
3 |
4 | # /usr/libexec/PlistBuddy \
5 | # -c "Set :CFBundleVersion ${GITHUB_RUN_NUMBER}" "$1"
6 |
7 | # /usr/libexec/PlistBuddy \
8 | # -c "Set :CFBundleShortVersionString ${VERSION_STRING}" "$1"
9 |
10 | agvtool new-version ${CURRENT_PROJECT_VERSION}
11 | agvtool new-marketing-version ${MARKETING_VERSION}
12 |
--------------------------------------------------------------------------------
/app/__mocks__/@pexip/infinity-api.ts:
--------------------------------------------------------------------------------
1 | export const requestToken = jest.fn()
2 | export const refreshToken = jest.fn()
3 | export const callsWebrtcParticipant = jest.fn()
4 | export const newCandidate = jest.fn()
5 | export const disconnectCall = jest.fn()
6 | export const withPin = jest.fn((fetcher: any) => fetcher)
7 | export const withToken = jest.fn((fetcher: any) => fetcher)
8 |
--------------------------------------------------------------------------------
/app/__tests__/screens/__snapshots__/TransferQRDisplayScreen.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`TransferQRDisplay renders correctly 1`] = `
4 |
14 | `;
15 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/2-feature-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "Feature request"
3 | about: Suggest a new feature for BC Wallet
4 | ---
5 |
6 |
7 | ### Description of feature / user story
8 |
9 | ### Acceptance Criteria
10 |
11 | ### Wireframes or relevant image assets / links
--------------------------------------------------------------------------------
/app/src/localization/index.ts:
--------------------------------------------------------------------------------
1 | import { translationResources } from '@bifold/core'
2 | import merge from 'lodash.merge'
3 |
4 | import en from './en'
5 | import fr from './fr'
6 | import ptBr from './pt-br'
7 |
8 | export const localization = merge({}, translationResources, {
9 | en: { translation: en },
10 | fr: { translation: fr },
11 | 'pt-BR': { translation: ptBr },
12 | })
13 |
--------------------------------------------------------------------------------
/packages/bcsc-core/ios/JOSEException.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Common.swift
3 | // jose
4 | //
5 | // Created by marcosc on 2016-12-08.
6 | // Copyright © 2016 idim. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct JOSEException: Error {
12 | let description: String
13 | init(_ description: String) {
14 | self.description = description
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/__mocks__/@react-native-clipboard/clipboard.js:
--------------------------------------------------------------------------------
1 | // @react-native-clipboard/clipboard mock
2 | module.exports = {
3 | getString: jest.fn(() => Promise.resolve('mocked clipboard content')), // eslint-disable-line no-undef
4 | setString: jest.fn(() => Promise.resolve()), // eslint-disable-line no-undef
5 | hasString: jest.fn(() => Promise.resolve(true)), // eslint-disable-line no-undef
6 | }
7 |
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/__tests__/contexts/auth.ts:
--------------------------------------------------------------------------------
1 | const authContext = {
2 | getWalletSecret: jest.fn(),
3 | removeSavedWalletSecret: jest.fn(),
4 | checkWalletPIN: jest.fn(),
5 | commitWalletToKeychain: jest.fn(),
6 | setPIN: jest.fn(),
7 | isBiometricsActive: jest.fn(),
8 | disableBiometrics: jest.fn(),
9 | rekeyWallet: jest.fn(),
10 | lockOutUser: jest.fn(),
11 | }
12 |
13 | export default authContext
14 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/api/workflow/key-rotation.workflow.ts:
--------------------------------------------------------------------------------
1 | export async function checkKeyStatus() {
2 | // keys can be rotated for the following reasons:
3 | // - 90 days have passed
4 | // - key is not valid
5 | }
6 | export async function rotateKeys() {
7 | // get current keys
8 | // get new keys
9 | // end date old keys
10 | // save new keys to device
11 | // save new keys to server
12 | // check new keys work
13 | }
14 |
--------------------------------------------------------------------------------
/app/__mocks__/custom/@react-navigation/core.ts:
--------------------------------------------------------------------------------
1 | const navigate = jest.fn()
2 |
3 | const navigation = {
4 | navigate,
5 | setOptions: jest.fn(),
6 | getParent: jest.fn(() => ({
7 | navigate,
8 | })),
9 | getState: jest.fn(() => ({
10 | index: jest.fn(),
11 | })),
12 | goBack: jest.fn(),
13 | pop: jest.fn(),
14 | reset: jest.fn(),
15 | }
16 |
17 | const useNavigation = () => {
18 | return navigation
19 | }
20 |
21 | export { useNavigation }
22 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'signed-off-by': [2, 'always', 'Signed-off-by:'],
4 | 'type-enum': [2, 'always', [
5 | 'feat',
6 | 'fix',
7 | 'docs',
8 | 'style',
9 | 'refactor',
10 | 'perf',
11 | 'test',
12 | 'chore',
13 | 'revert',
14 | ]],
15 | 'type-case': [2, 'always', 'lower-case'],
16 | 'type-empty': [2, 'never'],
17 | 'subject-empty': [2, 'never'],
18 | },
19 | }
20 |
--------------------------------------------------------------------------------
/app/__mocks__/react-native-screenguard.ts:
--------------------------------------------------------------------------------
1 | // Mock for react-native-screenguard
2 | const ScreenGuardModule = {
3 | register: jest.fn(),
4 | unregister: jest.fn(),
5 | registerScreenRecording: jest.fn(),
6 | unregisterScreenRecording: jest.fn(),
7 | enableBlurScreen: jest.fn(),
8 | disableBlurScreen: jest.fn(),
9 | addListener: jest.fn(() => ({
10 | remove: jest.fn(),
11 | })),
12 | removeListeners: jest.fn(),
13 | }
14 |
15 | export default ScreenGuardModule
16 |
--------------------------------------------------------------------------------
/app/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/1-bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "Bug report"
3 | about: Create a report to help us improve
4 | ---
5 |
6 |
7 |
8 | ### Description of problem
9 |
10 | ### Expected behavior
11 |
12 | ### Steps to reproduce
13 |
14 | ### Screenshots and/or log output
15 |
16 | ### Environment
17 |
18 | Build #:
19 |
20 | Android Device Model:
21 |
22 | iOS Device Model:
23 |
24 | ### Workaround
25 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/verify/live-call/utils/formatCallTime.ts:
--------------------------------------------------------------------------------
1 | export const formatCallTime = (seconds: number): string => {
2 | const hours = Math.floor(seconds / 3600)
3 | const minutes = Math.floor((seconds % 3600) / 60)
4 | const remainingSeconds = seconds % 60
5 |
6 | if (hours > 0) {
7 | return `${hours}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`
8 | } else {
9 | return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/app/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/ios/.xcode.env:
--------------------------------------------------------------------------------
1 | # This `.xcode.env` file is versioned and is used to source the environment
2 | # used when running script phases inside Xcode.
3 | # To customize your local environment, you can create an `.xcode.env.local`
4 | # file that is not versioned.
5 | # NODE_BINARY variable contains the PATH to the node executable.
6 | #
7 | # Customize the NODE_BINARY variable here.
8 | # For example, to use nvm with brew, add the following line
9 | # . "$(brew --prefix nvm)/nvm.sh" --no-use
10 | export NODE_BINARY=$(command -v node)
11 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/verify/live-call/utils/clearTimeoutIfExists.ts:
--------------------------------------------------------------------------------
1 | export const clearTimeoutIfExists = (timeoutRef: React.MutableRefObject) => {
2 | if (timeoutRef.current) {
3 | clearTimeout(timeoutRef.current)
4 | timeoutRef.current = null
5 | }
6 | }
7 |
8 | export const clearIntervalIfExists = (intervalRef: React.MutableRefObject) => {
9 | if (intervalRef.current) {
10 | clearInterval(intervalRef.current)
11 | intervalRef.current = null
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/__mocks__/react-native-incall-manager.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | start: jest.fn(),
3 | stop: jest.fn(),
4 | setKeepScreenOn: jest.fn(),
5 | setSpeakerphoneOn: jest.fn(),
6 | setForceSpeakerphoneOn: jest.fn(),
7 | setMicrophoneMute: jest.fn(),
8 | checkRecordPermission: jest.fn().mockResolvedValue('granted'),
9 | checkCameraPermission: jest.fn().mockResolvedValue('granted'),
10 | requestRecordPermission: jest.fn().mockResolvedValue('granted'),
11 | requestCameraPermission: jest.fn().mockResolvedValue('granted'),
12 | }
13 |
--------------------------------------------------------------------------------
/app/__tests__/screens/__snapshots__/ServiceLoginScreen.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`ServiceLogin renders correctly 1`] = `
4 |
20 |
23 |
24 | `;
25 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/deep-linking/useHasPendingDeepLink.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react'
2 | import { useDeepLinkViewModel } from './DeepLinkViewModelContext'
3 |
4 | export const useHasPendingDeepLink = () => {
5 | const viewModel = useDeepLinkViewModel()
6 |
7 | const [hasPending, setHasPending] = useState(viewModel.hasPendingDeepLink)
8 |
9 | useEffect(() => {
10 | return viewModel.onPendingStateChange((pending) => {
11 | setHasPending(pending)
12 | })
13 | }, [viewModel])
14 |
15 | return hasPending
16 | }
17 |
--------------------------------------------------------------------------------
/scripts/gpublish/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@bcgov/gpublish",
3 | "version": "1.2.0",
4 | "description": "Scripts to help automate Google Play API access",
5 | "main": "index.js",
6 | "bin": "index.js",
7 | "files": [
8 | "index.js",
9 | "package.json",
10 | "README.md"
11 | ],
12 | "scripts": {
13 | "test": "echo \"Error: no test specified\" && exit 1"
14 | },
15 | "author": "Jason C. Leach > Build Provisioning Profile... 🤞"
7 | echo ">> Provisioning Profile Home = ${PP_DIR}"
8 |
9 | UUID=$(/usr/libexec/plistbuddy -c Print:UUID /dev/stdin <<< `echo "${PROVISIONING_PROFILE}" | base64 -d | security cms -D`)
10 | base64 -d <<< "${PROVISIONING_PROFILE}" >${UUID}.mobileprovision
11 | md5 "${UUID}.mobileprovision"
12 | mkdir -p "${PP_DIR}"
13 | cp ${UUID}.mobileprovision "${PP_DIR}/"
14 |
15 | echo ">> Build Provisioning Profile. 🤗"
16 |
17 | exit
18 |
--------------------------------------------------------------------------------
/app/src/utils/expiration.ts:
--------------------------------------------------------------------------------
1 | export const expirationOverrideInMinutes = (
2 | enabledAt: Date,
3 | autoDisableRemoteLoggingIntervalInMinutes: number
4 | ): number => {
5 | const now = Date.now()
6 | const enabledAtTime = enabledAt.getTime()
7 | const autoDisableIntervalInMilliseconds = autoDisableRemoteLoggingIntervalInMinutes * 60000
8 |
9 | if (enabledAtTime < now - autoDisableIntervalInMilliseconds) {
10 | return 0
11 | }
12 |
13 | const diffInMinutes = Math.floor((now - enabledAtTime) / 60000)
14 | return autoDisableRemoteLoggingIntervalInMinutes - diffInMinutes
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/events/alertEvents.ts:
--------------------------------------------------------------------------------
1 | // Alert interaction types (display, action ie: 'OK' button pressed)
2 | export enum AlertInteractionEvent {
3 | ALERT_DISPLAY = 'alert_display',
4 | ALERT_ACTION = 'alert_action',
5 | }
6 |
7 | /**
8 | * Alert events
9 | *
10 | * TODO (MD): combine all Android and iOS alert events from `ias-android` and `ias-ios` current code ie: AlertKey.java...
11 | * and add all mapped values from `bcsc_alerts.json` to translation files
12 | */
13 | export enum AlertEvent {
14 | ADD_CARD_CAMERA_BROKEN = 'add_card_camera_broken',
15 | // ... other alert events go here
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/utils/mediator.ts:
--------------------------------------------------------------------------------
1 | import { Agent, MediatorPickupStrategy } from '@credo-ts/core'
2 |
3 | export const batchPickup = async (agent: Agent): Promise => {
4 | try {
5 | for (let i = 0; i < 2; i++) {
6 | agent.config.logger.debug(`Batch pickup attempt ${i + 1}`)
7 | agent.mediationRecipient.initiateMessagePickup(undefined, MediatorPickupStrategy.Implicit)
8 | await new Promise((resolve) => setTimeout(resolve, 50)) // wait for .05 seconds before next pickup
9 | }
10 | } catch (error) {
11 | agent.config.logger.error(`Error during batch pickup: ${error}`)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/.yarn/patches/@credo-ts-indy-vdr-npm-0.5.17-aa0b05041f.patch:
--------------------------------------------------------------------------------
1 | diff --git a/build/pool/IndyVdrPool.js b/build/pool/IndyVdrPool.js
2 | index 7c157d6754dcba7526100f67dbed3c86b335b0cc..56437364edcb3d16e998fb4766d7b14cae63430f 100644
3 | --- a/build/pool/IndyVdrPool.js
4 | +++ b/build/pool/IndyVdrPool.js
5 | @@ -17,7 +17,7 @@ class IndyVdrPool {
6 | }
7 | connect() {
8 | if (this._pool) {
9 | - throw new error_1.IndyVdrError('Cannot connect to pool, already connected.');
10 | + return;
11 | }
12 | this._pool = new indy_vdr_shared_1.PoolCreate({
13 | parameters: {
14 |
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/main/java/com/bcsccore/bcsc-file-port/src/main/java/com/bcsccore/fileport/decryption/DecryptionException.java:
--------------------------------------------------------------------------------
1 | package com.bcsccore.fileport.decryption;
2 |
3 | /**
4 | * Exception thrown when file decryption fails
5 | */
6 | public class DecryptionException extends Exception {
7 |
8 | public DecryptionException(String message) {
9 | super(message);
10 | }
11 |
12 | public DecryptionException(String message, Throwable cause) {
13 | super(message, cause);
14 | }
15 |
16 | public DecryptionException(Throwable cause) {
17 | super(cause);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/__tests__/components/EmptyList.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import EmptyList from '@bcwallet-theme/components/EmptyList'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 |
7 | describe('EmptyList Component', () => {
8 | beforeEach(() => {
9 | jest.useFakeTimers()
10 | })
11 |
12 | afterEach(() => {
13 | jest.useRealTimers()
14 | })
15 | test('renders correctly', () => {
16 | const tree = render(
17 |
18 |
19 |
20 | )
21 | expect(tree).toMatchSnapshot()
22 | })
23 | })
24 |
--------------------------------------------------------------------------------
/app/src/bcwallet-theme/features/tours/hooks/tour-image-dimensions.ts:
--------------------------------------------------------------------------------
1 | import { useWindowDimensions } from 'react-native'
2 |
3 | const useTourImageDimensions = () => {
4 | const { width: windowWidth, height: windowHeight } = useWindowDimensions() // NOSONAR
5 | const totalHorizontalImagePadding = 90
6 | const portraitMode = windowHeight > windowWidth
7 | const imageWidth = Math.floor(
8 | portraitMode ? windowWidth - totalHorizontalImagePadding : windowHeight - totalHorizontalImagePadding
9 | )
10 | const imageHeight = Math.floor(imageWidth * 0.66)
11 |
12 | return { imageWidth, imageHeight }
13 | }
14 |
15 | export default useTourImageDimensions
16 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/api/hooks/withAccountGuard.ts:
--------------------------------------------------------------------------------
1 | import { getAccount } from 'react-native-bcsc-core'
2 |
3 | /**
4 | * This is a wrapper function to centralize checking for an account before executing a function.
5 | *
6 | * @param fn Function that `withAccount` will wrap, which requires an account to be present.
7 | * @returns The executed function with the account passed as an argument.
8 | */
9 | export const withAccount = async (fn: (account: any) => Promise): Promise => {
10 | const account = await getAccount()
11 | if (!account) {
12 | throw new Error('No account found. Please register first.')
13 | }
14 |
15 | return fn(account)
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/webview/MainWebViewScreen.tsx:
--------------------------------------------------------------------------------
1 | import { BCSCMainStackParams, BCSCScreens } from '@/bcsc-theme/types/navigators'
2 | import { RouteProp } from '@react-navigation/native'
3 | import React from 'react'
4 | import { WebViewContent } from './WebViewContent'
5 |
6 | interface MainWebViewScreenProps {
7 | route: RouteProp
8 | }
9 |
10 | const MainWebViewScreen: React.FC = ({ route }) => {
11 | const { url, injectedJavascript } = route.params
12 |
13 | return
14 | }
15 |
16 | export { MainWebViewScreen }
17 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/webview/VerifyWebViewScreen.tsx:
--------------------------------------------------------------------------------
1 | import { BCSCScreens, BCSCVerifyStackParams } from '@/bcsc-theme/types/navigators'
2 | import { RouteProp } from '@react-navigation/native'
3 | import React from 'react'
4 | import { WebViewContent } from './WebViewContent'
5 |
6 | interface VerifyWebViewScreenProps {
7 | route: RouteProp
8 | }
9 |
10 | const VerifyWebViewScreen: React.FC = ({ route }) => {
11 | const { url, injectedJavascript } = route.params
12 |
13 | return
14 | }
15 |
16 | export { VerifyWebViewScreen }
17 |
--------------------------------------------------------------------------------
/packages/bcsc-core/README.md:
--------------------------------------------------------------------------------
1 | # react-native-bcsc-core
2 |
3 | Functionality and data access for legacy bcsc application.
4 |
5 | ## Installation
6 |
7 | ```sh
8 | npm install react-native-bcsc-core
9 | ```
10 |
11 | ## Usage
12 |
13 |
14 | ```js
15 | import { multiply } from 'react-native-bcsc-core';
16 |
17 | // ...
18 |
19 | const result = multiply(3, 7);
20 | ```
21 |
22 |
23 | ## Contributing
24 |
25 | See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
26 |
27 | ## License
28 |
29 | MIT
30 |
31 | ---
32 |
33 | Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
34 |
--------------------------------------------------------------------------------
/.yarn/patches/@hyperledger-indy-vdr-shared-npm-0.2.2-b989282fc6.patch:
--------------------------------------------------------------------------------
1 | diff --git a/build/types/IndyVdr.d.ts b/build/types/IndyVdr.d.ts
2 | index 99f5d50a851462c8c41e52ceb49795feebce0b4e..3aa7890e1f3c422daa6ec82fd6b42d0b924d18b5 100644
3 | --- a/build/types/IndyVdr.d.ts
4 | +++ b/build/types/IndyVdr.d.ts
5 | @@ -11,6 +11,11 @@ export interface IndyVdr {
6 | setCacheDirectory(options: {
7 | path: string;
8 | }): void;
9 | + setLedgerTxnCache(options: {
10 | + capacity: number;
11 | + expiry_offset_ms: number;
12 | + path?: string;
13 | + }): void;
14 | setDefaultLogger(): void;
15 | setProtocolVersion(options: {
16 | version: number;
17 |
--------------------------------------------------------------------------------
/.yarn/patches/@animo-id-pex-npm-4.1.1-alpha.0-f29edfffa2.patch:
--------------------------------------------------------------------------------
1 | diff --git a/package.json b/package.json
2 | index becc91ce9fd93bb8ec6d6fc401fa208274c5b0a7..b881d21b40012126fb1901b1e5940fafecce90dc 100644
3 | --- a/package.json
4 | +++ b/package.json
5 | @@ -20,7 +20,6 @@
6 | "DIF"
7 | ],
8 | "scripts": {
9 | - "preinstall": "npx only-allow pnpm",
10 | "build": "run-s build:*",
11 | "build:generateFieldv1Schema": "ts-json-schema-generator -p resources/schema-generator-interfaces/filterV1.ts > resources/FilterV1.schema.json",
12 | "build:generateFieldv2Schema": "ts-json-schema-generator -p resources/schema-generator-interfaces/filterV2.ts > resources/FilterV2.schema.json",
13 |
--------------------------------------------------------------------------------
/app/android/app/src/main/res/layout/launch_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/types/cards.ts:
--------------------------------------------------------------------------------
1 | export enum BCSCCardType {
2 | Combined = 'BC Services Card Combo', // IAS compatible value
3 | Photo = 'BC Services Card Photo', // IAS compatible value
4 | NonPhoto = 'BC Services Card Non-Photo', // IAS compatible value
5 | Other = 'Non BC Services Card(s)', // Local value for non-BCSC cards (IAS value is undefined)
6 | None = 'None', // Local value when no card is present
7 | }
8 |
9 | export enum BCSCCardProcess {
10 | BCSCPhoto = 'IDIM L3 Remote BCSC Photo Identity Verification',
11 | BCSCNonPhoto = 'IDIM L3 Remote BCSC Non-Photo Identity Verification',
12 | NonBCSC = 'IDIM L3 Remote Non-BCSC Identity Verification',
13 | None = 'N/A',
14 | }
15 |
--------------------------------------------------------------------------------
/export-options-bcw.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | teamID
6 | L796QSLV3E
7 | method
8 | app-store
9 | signingStyle
10 | manual
11 | stripSwiftSymbols
12 |
13 | uploadBitcode
14 |
15 | uploadSymbols
16 |
17 | provisioningProfiles
18 |
19 | ca.bc.gov.BCWallet
20 | 7a6bfbda-8f83-441e-b709-b57b1863b627
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/android/app/build_defs.bzl:
--------------------------------------------------------------------------------
1 | """Helper definitions to glob .aar and .jar targets"""
2 |
3 | def create_aar_targets(aarfiles):
4 | for aarfile in aarfiles:
5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
6 | lib_deps.append(":" + name)
7 | android_prebuilt_aar(
8 | name = name,
9 | aar = aarfile,
10 | )
11 |
12 | def create_jar_targets(jarfiles):
13 | for jarfile in jarfiles:
14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
15 | lib_deps.append(":" + name)
16 | prebuilt_jar(
17 | name = name,
18 | binary_jar = jarfile,
19 | )
20 |
--------------------------------------------------------------------------------
/.yarn/patches/@sphereon-pex-npm-5.0.0-unstable.24-921df3a8ac.patch:
--------------------------------------------------------------------------------
1 | diff --git a/package.json b/package.json
2 | index 9ab8d81ceb3728acd0e38a00af46881f93e68584..935b51ac44ad3a641c4e3b5006b681994d456143 100644
3 | --- a/package.json
4 | +++ b/package.json
5 | @@ -67,7 +67,6 @@
6 | "printWidth": 150
7 | },
8 | "scripts": {
9 | - "preinstall": "npx only-allow pnpm",
10 | "build": "run-s build:*",
11 | "build:generateFieldv1Schema": "ts-json-schema-generator -p resources/schema-generator-interfaces/filterV1.ts > resources/FilterV1.schema.json",
12 | "build:generateFieldv2Schema": "ts-json-schema-generator -p resources/schema-generator-interfaces/filterV2.ts > resources/FilterV2.schema.json",
13 |
--------------------------------------------------------------------------------
/export-options-sa.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | teamID
6 | L796QSLV3E
7 | method
8 | app-store-connect
9 | signingStyle
10 | manual
11 | stripSwiftSymbols
12 |
13 | uploadBitcode
14 |
15 | uploadSymbols
16 |
17 | provisioningProfiles
18 |
19 | ca.bc.gov.iddev.servicescard
20 | 4f031630-16e4-4f8d-8723-a3d920577416
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/webview/OnboardingWebViewScreen.tsx:
--------------------------------------------------------------------------------
1 | import { BCSCOnboardingStackParams, BCSCScreens } from '@/bcsc-theme/types/navigators'
2 | import { RouteProp } from '@react-navigation/native'
3 | import React from 'react'
4 | import { WebViewContent } from './WebViewContent'
5 |
6 | interface OnboardingWebViewScreenProps {
7 | route: RouteProp
8 | }
9 |
10 | const OnboardingWebViewScreen: React.FC = ({ route }) => {
11 | const { url, injectedJavascript } = route.params
12 |
13 | return
14 | }
15 |
16 | export { OnboardingWebViewScreen }
17 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | # Summary of Changes
2 |
3 | Replace this text with a high-level summary of the changes included in this PR.
4 |
5 | # Testing Instructions
6 |
7 | Replace this text with detailed instructions on how to test the changes included in this PR.
8 |
9 | # Acceptance Criteria
10 |
11 | Replace this text with the acceptance criteria that must be met for this PR to be approved.
12 |
13 | # Screenshots, videos, or gifs
14 |
15 | Replace this text with embedded media for UI changes if they are included in this PR. If there are none, simply enter N/A
16 |
17 | # Related Issues
18 |
19 | Replace this text with tagged issue #'s that are relevant to this PR. If there are none, simply enter N/A
20 |
--------------------------------------------------------------------------------
/app/src/assets/img/credentialIcon.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/app/__tests__/components/HomeHeaderView.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import HomeHeaderView from '@bcwallet-theme/components/HomeHeaderView'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 |
7 | describe('HomeHeaderView Component', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | test('renders correctly', () => {
18 | const tree = render(
19 |
20 |
21 |
22 | )
23 | expect(tree).toMatchSnapshot()
24 | })
25 | })
26 |
--------------------------------------------------------------------------------
/app/src/utils/analytics/analytics-singleton.ts:
--------------------------------------------------------------------------------
1 | import { AnalyticsTracker } from './analytics-tracker'
2 |
3 | const ANALYTICS_SINGLEAPP_NAMESPACE = 'singleapp_client'
4 | const ANALYTICS_SINGLEAPP_ENDPOINT = __DEV__ ? 'localhost:9090' : '' // TODO (MD): Add production endpoint
5 |
6 | declare global {
7 | // eslint-disable-next-line no-var
8 | var __ANALYTICS_TRACKER_SINGLETON__: AnalyticsTracker | undefined
9 | }
10 |
11 | // Hot-reload safe singleton instance of AnalyticsTracker
12 | export const Analytics =
13 | globalThis.__ANALYTICS_TRACKER_SINGLETON__ ??
14 | (globalThis.__ANALYTICS_TRACKER_SINGLETON__ = new AnalyticsTracker(
15 | ANALYTICS_SINGLEAPP_NAMESPACE,
16 | ANALYTICS_SINGLEAPP_ENDPOINT
17 | ))
18 |
--------------------------------------------------------------------------------
/app/src/bcwallet-theme/features/tours/index.ts:
--------------------------------------------------------------------------------
1 | import { BaseTourID, TourStep } from '@bifold/core'
2 |
3 | import { credentialOfferTourSteps } from './CredentialOfferTourSteps'
4 | import { credentialsTourSteps } from './CredentialsTourSteps'
5 | import { homeTourSteps } from './HomeTourSteps'
6 | import { proofRequestTourSteps } from './ProofRequestTourSteps'
7 |
8 | // to extend, add " | BCTourID" where BCTourID has tour IDs specific to BC Wallet
9 | export type TourID = BaseTourID
10 |
11 | type Tours = {
12 | [key in TourID]: TourStep[]
13 | }
14 |
15 | const tours: Tours = {
16 | homeTourSteps,
17 | credentialsTourSteps,
18 | credentialOfferTourSteps,
19 | proofRequestTourSteps,
20 | }
21 |
22 | export default tours
23 |
--------------------------------------------------------------------------------
/app/__tests__/components/AddCredentialButton.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import AddCredentialButton from '@bcwallet-theme/components/AddCredentialButton'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 |
7 | describe('AddCredentialButton Component', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 | test('renders correctly', () => {
17 | const tree = render(
18 |
19 |
20 |
21 | )
22 | expect(tree).toMatchSnapshot()
23 | })
24 | })
25 |
--------------------------------------------------------------------------------
/app/__tests__/components/ErrorTextBox.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import ErrorTextBox from '../../src/components/ErrorTextBox'
6 |
7 | describe('ErrorTextBox Component', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 | test('renders correctly', () => {
17 | const tree = render(
18 |
19 | Lorem ipsum sit dolar
20 |
21 | )
22 |
23 | expect(tree).toMatchSnapshot()
24 | })
25 | })
26 |
--------------------------------------------------------------------------------
/app/__tests__/screens/EditNicknameScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import EditNicknameScreen from '../../src/bcsc-theme/features/account/EditNicknameScreen'
6 |
7 | describe('EditNickname', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const tree = render(
19 |
20 |
21 |
22 | )
23 |
24 | expect(tree).toMatchSnapshot()
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/app/src/Root.tsx:
--------------------------------------------------------------------------------
1 | import { BCState, Mode } from '@/store'
2 | import BCSCRootStack from '@bcsc-theme/navigators/RootStack'
3 | import { RootStack as BCWalletRootStack, useStore } from '@bifold/core'
4 | import { BCSCApiClientProvider } from './bcsc-theme/contexts/BCSCApiClientContext'
5 | import { BCSCLoadingProvider } from './bcsc-theme/contexts/BCSCLoadingContext'
6 |
7 | const Root: React.FC = () => {
8 | const [store] = useStore()
9 |
10 | return store.mode === Mode.BCSC ? (
11 |
12 |
13 |
14 |
15 |
16 | ) : (
17 |
18 | )
19 | }
20 |
21 | export default Root
22 |
--------------------------------------------------------------------------------
/app/__tests__/screens/NicknameAccountScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import NicknameAccountScreen from '../../src/bcsc-theme/features/account/NicknameAccountScreen'
6 |
7 | describe('NicknameAccount', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const tree = render(
19 |
20 |
21 |
22 | )
23 |
24 | expect(tree).toMatchSnapshot()
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/navigators/stack-utils.ts:
--------------------------------------------------------------------------------
1 | import { StackNavigationOptions } from '@react-navigation/stack'
2 | import { createHeaderWithoutBanner } from '../components/HeaderWithBanner'
3 |
4 | /**
5 | * Returns default screen options for modal presentations.
6 | *
7 | * @param {string} title - The title of the modal screen.
8 | * @returns {*} {StackNavigationOptions} The default modal screen options.
9 | */
10 | export function getDefaultModalOptions(title?: string): StackNavigationOptions {
11 | return {
12 | presentation: 'modal',
13 | headerShown: true,
14 | headerLeft: () => null,
15 | title: title,
16 | headerShadowVisible: false,
17 | header: createHeaderWithoutBanner,
18 | gestureEnabled: true,
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/__mocks__/custom/react-native-camera.ts:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const Constants = {
4 | device: {},
5 | torch: {
6 | on: 'on',
7 | off: 'off',
8 | auto: 'auto',
9 | },
10 | isActive: false,
11 | codeScanner: {},
12 | }
13 |
14 | class Camera extends React.Component {
15 | static Constants = Constants
16 | render() {
17 | return null
18 | }
19 | }
20 |
21 | Camera.Constants = Constants
22 | const useCameraDevice = jest.fn()
23 | const useCodeScanner = jest.fn()
24 | const useCameraFormat = jest.fn()
25 | const useCameraPermission = jest.fn(() => ({
26 | hasPermission: true,
27 | requestPermission: jest.fn(),
28 | }))
29 | export { Camera, useCameraDevice, useCameraFormat, useCameraPermission, useCodeScanner }
30 |
--------------------------------------------------------------------------------
/app/__tests__/screens/MismatchedSerialScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import MismatchedSerialScreen from '../../src/bcsc-theme/features/verify/MismatchedSerialScreen'
6 |
7 | describe('MismatchedSerial', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const tree = render(
19 |
20 |
21 |
22 | )
23 |
24 | expect(tree).toMatchSnapshot()
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/main/java/com/bcsccore/bcsc-keypair-port/core/exceptions/KeypairGenerationException.java:
--------------------------------------------------------------------------------
1 | package com.bcsccore.keypair.core.exceptions;
2 |
3 | /**
4 | * Specific exception for key pair generation failures.
5 | * This exception is thrown when Android KeyStore operations fail
6 | * during key pair generation or retrieval.
7 | */
8 | public class KeypairGenerationException extends BcscException {
9 |
10 | /**
11 | * Create a keypair generation exception with a developer message.
12 | * @param devMessage the message describing what went wrong during key generation
13 | */
14 | public KeypairGenerationException(String devMessage) {
15 | super(AlertKey.ADD_CARD_KEYPAIR_GENERATION, devMessage);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/.sonarcloud.properties:
--------------------------------------------------------------------------------
1 | #
2 | # SPDX-License-Identifier: Apache-2.0
3 | #
4 |
5 | # Path to sources
6 | sonar.sources=.
7 | sonar.exclusions=**/CredentialOfferTourSteps.tsx,**/CredentialsTourSteps.tsx,**/HomeTourSteps.tsx,**/ProofRequestTourSteps.tsx,**/localization/**/index.ts,**/packages/bcsc-core/ios/**,**/packages/bcsc-core/android/**,**/__tests__/**/*.ts,**/__tests__/**/*.tsx,**/__mocks__/**/*.ts,**/__mocks__/**/*.tsx,**/*.test.ts,**/*.test.tsx
8 |
9 | #sonar.inclusions=
10 |
11 | # Path to tests
12 | #sonar.tests=
13 | #sonar.test.exclusions=
14 | #sonar.test.inclusions=
15 |
16 | # Source encoding
17 | #sonar.sourceEncoding=UTF-8
18 |
19 | # Exclusions for copy-paste detection
20 | sonar.cpd.exclusions=**/__tests__/**/*,**/__mocks__/**/*,**/request-templates.ts
21 |
--------------------------------------------------------------------------------
/app/__tests__/screens/TransferQRDisplayScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import TransferQRDisplayScreen from '../../src/bcsc-theme/features/account-transfer/TransferQRDisplayScreen'
6 |
7 | describe('TransferQRDisplay', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const tree = render(
19 |
20 |
21 |
22 | )
23 |
24 | expect(tree).toMatchSnapshot()
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/app/__tests__/screens/VerificationSuccessScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import VerificationSuccessScreen from '../../src/bcsc-theme/features/verify/VerificationSuccessScreen'
6 |
7 | describe('VerificationSuccess', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const tree = render(
19 |
20 |
21 |
22 | )
23 |
24 | expect(tree).toMatchSnapshot()
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/app/src/utils/links.ts:
--------------------------------------------------------------------------------
1 | import { BCSC_APPLE_STORE_URL, BCSC_GOOGLE_PLAY_STORE_URL } from '@/constants'
2 | import { Linking, Platform } from 'react-native'
3 |
4 | export const openLink = async (url: string) => {
5 | // Only `https://` is allowed. Update manifest as needed.
6 | const supported = await Linking.canOpenURL(url)
7 |
8 | if (supported) {
9 | // Will open in device browser.
10 | await Linking.openURL(url)
11 | }
12 | }
13 |
14 | /**
15 | * Get the BCSC App Store URL based on the platform.
16 | *
17 | * @returns {*} {string} The BCSC app store URL.
18 | */
19 | export const getBCSCAppStoreUrl = (): string => {
20 | if (Platform.OS === 'ios') {
21 | return BCSC_APPLE_STORE_URL
22 | }
23 |
24 | return BCSC_GOOGLE_PLAY_STORE_URL
25 | }
26 |
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/main/java/com/bcsccore/bcsc-file-port/src/main/java/com/bcsccore/fileport/decryption/FileDecryptor.java:
--------------------------------------------------------------------------------
1 | package com.bcsccore.fileport.decryption;
2 |
3 | /**
4 | * Interface for decrypting file content
5 | */
6 | public interface FileDecryptor {
7 |
8 | /**
9 | * Decrypt encrypted file content
10 | * @param encryptedContent the encrypted byte array
11 | * @return decrypted content as string
12 | * @throws DecryptionException if decryption fails
13 | */
14 | String decrypt(byte[] encryptedContent) throws DecryptionException;
15 |
16 | /**
17 | * Check if decryption is available/initialized
18 | * @return true if decryptor is ready to use
19 | */
20 | boolean isAvailable();
21 | }
22 |
--------------------------------------------------------------------------------
/app/__tests__/screens/TransferInformationScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import TransferInformationScreen from '../../src/bcsc-theme/features/account-transfer/TransferInformationScreen'
6 |
7 | describe('TransferInformation', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const tree = render(
19 |
20 |
21 |
22 | )
23 |
24 | expect(tree).toMatchSnapshot()
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/3-help.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "Help request"
3 | about: Let us know where you're getting stuck
4 | ---
5 |
6 |
7 |
8 | ### Description of problem
9 |
10 | ### Steps taken to solve
11 |
12 | - [ ] Read through docs in this repo and (bifold-wallet)[github.com/openwallet-foundation/bifold-wallet]
13 | - [ ] Posted in OpenWallet Foundation Discord
14 |
15 | ### Screenshots and/or log output
16 |
17 | ### Development Environment
18 |
19 | - [ ] Android Emulator
20 | - [ ] Android Device
21 | - [ ] iOS Simulator
22 | - [ ] iOS Device
23 | - [ ] Mac (Intel)
24 | - [ ] Mac (Apple Silicon)
25 | - [ ] Linux
26 | - [ ] Windows
27 |
--------------------------------------------------------------------------------
/app/__tests__/screens/TransferInstructionsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import TransferInstructionsScreen from '../../src/bcsc-theme/features/account-transfer/TransferInstructionsScreen'
6 |
7 | describe('TransferInstructions', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const tree = render(
19 |
20 |
21 |
22 | )
23 |
24 | expect(tree).toMatchSnapshot()
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/devops/charts/loki-logstack/templates/routes.yaml:
--------------------------------------------------------------------------------
1 | kind: Route
2 | apiVersion: route.openshift.io/v1
3 | metadata:
4 | name: {{include "logstack.fullname" .}}-proxy
5 | labels: {{- include "logstack.labels" . | nindent 4}}
6 | annotations: {{- toYaml .Values.route.annotations | nindent 4}}
7 | spec:
8 | {{- if .Values.route.host }}
9 | host: {{ .Values.route.host }}
10 | {{- end }}
11 | to:
12 | kind: Service
13 | name: {{include "logstack.fullname" .}}-proxy
14 | weight: 100
15 | port:
16 | {{- range $name, $port := .Values.services.proxy }}
17 | {{- if eq .name "http" }}
18 | targetPort: {{ .port }}
19 | {{- end }}
20 | {{- end }}
21 | tls:
22 | termination: edge
23 | insecureEdgeTerminationPolicy: Redirect
24 | wildcardPolicy: None
25 |
--------------------------------------------------------------------------------
/app/__tests__/screens/AccountSetupSelectionScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import AccountSetupSelectionScreen from '../../src/bcsc-theme/features/account-transfer/AccountSetupSelectionScreen'
6 |
7 | describe('AccountSetupSelection', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const tree = render(
19 |
20 |
21 |
22 | )
23 |
24 | expect(tree).toMatchSnapshot()
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/app/src/hooks/useDebounce.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react'
2 |
3 | /**
4 | * A custom React hook that debounces a value.
5 | *
6 | * @template T The type of the value to be debounced.
7 | * @param {T} value The value to be debounced.
8 | * @param {number} delayMs The debounce delay in milliseconds.
9 | * @returns {*} {T} The debounced value.
10 | */
11 | export const useDebounce = (value: T, delayMs: number) => {
12 | const [debouncedValue, setDebouncedValue] = useState(value)
13 |
14 | useEffect(() => {
15 | const debounceHandler = setTimeout(() => setDebouncedValue(value), delayMs)
16 |
17 | // Cleanup timeout if value or delay changes
18 | return () => clearTimeout(debounceHandler)
19 | }, [value, delayMs])
20 |
21 | return debouncedValue
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/settings/MainContactUsScreen.tsx:
--------------------------------------------------------------------------------
1 | import { BCSCMainStackParams, BCSCScreens } from '@/bcsc-theme/types/navigators'
2 | import { ScreenWrapper } from '@bifold/core'
3 | import { StackNavigationProp } from '@react-navigation/stack'
4 | import React from 'react'
5 | import { ContactUsContent } from './ContactUsContent'
6 |
7 | type MainContactUsScreenProps = {
8 | navigation: StackNavigationProp
9 | }
10 |
11 | /**
12 | * Contact Us screen for the Main stack.
13 | * Wraps ContactUsContent with proper navigation typing.
14 | */
15 | export const MainContactUsScreen: React.FC = () => {
16 | return (
17 |
18 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/app/__tests__/screens/RemoveAccountConfirmationScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import RemoveAccountConfirmationScreen from '../../src/bcsc-theme/features/account/RemoveAccountConfirmationScreen'
6 |
7 | describe('RemoveAccountConfirmation', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const tree = render(
19 |
20 |
21 |
22 | )
23 |
24 | expect(tree).toMatchSnapshot()
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/app/__tests__/screens/__snapshots__/VerificationMethodSelectionScreen.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`VerificationMethodSelection renders correctly 1`] = `
4 |
23 |
32 |
33 |
34 |
35 | `;
36 |
--------------------------------------------------------------------------------
/app/__tests__/screens/AccountRenewalFinalWarningScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import { AccountRenewalFinalWarningScreen } from '../../src/bcsc-theme/features/account/AccountRenewalFinalWarningScreen'
6 |
7 | describe('AccountRenewalFinalWarning', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const tree = render(
19 |
20 |
21 |
22 | )
23 |
24 | expect(tree).toMatchSnapshot()
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/settings/VerifyContactUsScreen.tsx:
--------------------------------------------------------------------------------
1 | import { BCSCScreens, BCSCVerifyStackParams } from '@/bcsc-theme/types/navigators'
2 | import { ScreenWrapper } from '@bifold/core'
3 | import { StackNavigationProp } from '@react-navigation/stack'
4 | import React from 'react'
5 | import { ContactUsContent } from './ContactUsContent'
6 |
7 | type VerifyContactUsScreenProps = {
8 | navigation: StackNavigationProp
9 | }
10 |
11 | /**
12 | * Contact Us screen for the Verify stack.
13 | * Wraps ContactUsContent with proper navigation typing.
14 | */
15 | export const VerifyContactUsScreen: React.FC = () => {
16 | return (
17 |
18 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/deep-linking/DeepLinkViewModelContext.tsx:
--------------------------------------------------------------------------------
1 | import React, { createContext, useContext } from 'react'
2 | import { DeepLinkViewModel } from './DeepLinkViewModel'
3 |
4 | const DeepLinkViewModelContext = createContext(null)
5 |
6 | export const DeepLinkViewModelProvider: React.FC<{
7 | viewModel: DeepLinkViewModel
8 | children: React.ReactNode
9 | }> = ({ viewModel, children }) => {
10 | return {children}
11 | }
12 |
13 | export const useDeepLinkViewModel = () => {
14 | const context = useContext(DeepLinkViewModelContext)
15 | if (!context) {
16 | throw new Error('useDeepLinkViewModel must be used within a DeepLinkViewModelProvider')
17 | }
18 |
19 | return context
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/utils/account-utils.ts:
--------------------------------------------------------------------------------
1 | import { formStringLengths } from '@/constants'
2 | import { BCState } from '@/store'
3 |
4 | // Helper function to check if a nickname exists
5 | export const hasNickname = (state: BCState, nickname: string): boolean => {
6 | return state.bcsc.nicknames.includes(nickname)
7 | }
8 |
9 | export const getNicknameValidationErrorKey = (state: BCState, nickname: string): string | null => {
10 | if (nickname.length < formStringLengths.minimumLength) {
11 | return 'BCSC.NicknameAccount.EmptyNameTitle'
12 | }
13 |
14 | if (nickname.length > formStringLengths.maximumLength) {
15 | return 'BCSC.NicknameAccount.CharCountTitle'
16 | }
17 |
18 | if (hasNickname(state, nickname)) {
19 | return 'BCSC.NicknameAccount.NameAlreadyExists'
20 | }
21 |
22 | return null
23 | }
24 |
--------------------------------------------------------------------------------
/app/__tests__/screens/MainWebViewScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import { MainWebViewScreen } from '../../src/bcsc-theme/features/webview/MainWebViewScreen'
6 |
7 | describe('MainWebView', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const route = { params: { url: 'https://example.com', title: 'Test' } }
19 | const tree = render(
20 |
21 |
22 |
23 | )
24 |
25 | expect(tree).toMatchSnapshot()
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/.github/workflows/scanner.yml:
--------------------------------------------------------------------------------
1 | name: Virus Scanner
2 | permissions:
3 | contents: read
4 |
5 | on:
6 | push:
7 | branches: [main]
8 | pull_request:
9 | branches: [main]
10 |
11 | jobs:
12 | shai-hulud-scan:
13 | runs-on: ubuntu-22.04
14 | name: Scan code for Shai-hulud virus
15 | steps:
16 | - name: Checkout bc-wallet-mobile
17 | uses: actions/checkout@v4
18 | with:
19 | path: bc-wallet-mobile
20 |
21 | - name: Checkout Shai-hulud scanner
22 | uses: actions/checkout@v4
23 | with:
24 | repository: CyberDracula/shai-hulud-2-scanner
25 | path: shai-hulud-2-scanner
26 |
27 | - name: Run Shai-hulud virus scanner
28 | working-directory: shai-hulud-2-scanner
29 | run: node scan.js --fail-on=critical ../bc-wallet-mobile
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/__tests__/screens/RemoteLogWarning.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import RemoteLogWarning from '../../src/screens/RemoteLogWarning'
6 |
7 | jest.mock('react-native-splash-screen', () => ({}))
8 |
9 | describe('RemoteLogWarning Screen', () => {
10 | beforeEach(() => {
11 | jest.useFakeTimers()
12 | })
13 |
14 | afterEach(() => {
15 | jest.clearAllMocks()
16 | jest.useRealTimers()
17 | })
18 |
19 | test('screen renders correctly', () => {
20 | const tree = render(
21 |
22 |
23 |
24 | )
25 |
26 | expect(tree).toMatchSnapshot()
27 | })
28 | })
29 |
--------------------------------------------------------------------------------
/app/__tests__/screens/VerifyWebViewScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import { VerifyWebViewScreen } from '../../src/bcsc-theme/features/webview/VerifyWebViewScreen'
6 |
7 | describe('VerifyWebView', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const route = { params: { url: 'https://example.com', title: 'Test' } }
19 | const tree = render(
20 |
21 |
22 |
23 | )
24 |
25 | expect(tree).toMatchSnapshot()
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/app/__mocks__/react-i18next.ts:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
4 | const reactI18Next: any = jest.createMockFromModule('react-i18next')
5 |
6 | reactI18Next.useTranslation = () => {
7 | return {
8 | t: (str: string) => str,
9 | i18n: {
10 | changeLanguage: () => new Promise(() => {}),
11 | language: 'en',
12 | t: (str: string) => str,
13 | },
14 | }
15 | }
16 |
17 | reactI18Next.Trans = ({ children, i18nKey }: { children?: React.ReactNode; i18nKey?: string }) => {
18 | return React.createElement('span', {}, children || i18nKey || '')
19 | }
20 | reactI18Next.Trans.displayName = 'Trans'
21 |
22 | reactI18Next.initReactI18next = {
23 | type: '3rdParty',
24 | init: jest.fn(),
25 | }
26 |
27 | module.exports = reactI18Next
28 |
29 | export default {}
30 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## How to Contribute
2 |
3 | Government employees, public and members of the private sector are encouraged to contribute to the repository by **forking and submitting a pull request**.
4 |
5 | (If you are new to GitHub, you might start with a [basic tutorial](https://help.github.com/articles/set-up-git) and check out a more detailed guide to [pull requests](https://help.github.com/articles/using-pull-requests/).)
6 |
7 | Pull requests will be evaluated by the repository guardians on a schedule and if deemed beneficial will be committed to the master.
8 |
9 | All contributors retain the original copyright to their stuff, but by contributing to this project, you grant a world-wide, royalty-free, perpetual, irrevocable, non-exclusive, transferable license to all users **under the terms of the license under which this project is distributed.**
10 |
--------------------------------------------------------------------------------
/app/__tests__/components/LoadingIcon.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import LoadingIcon from '../../src/components/LoadingIcon'
6 |
7 | describe('LoadingIcon Component', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 | test('renders correctly', () => {
17 | const size = 50 // arbitrary
18 | const color = '#333' // arbitrary
19 | const active = true // arbitrary
20 | const tree = render(
21 |
22 |
23 |
24 | )
25 | expect(tree).toMatchSnapshot()
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/options-dev.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | compileBitcode
6 |
7 | destination
8 | export
9 | method
10 | development
11 | provisioningProfiles
12 |
13 | ca.bc.gov.BCWallet
14 | BC Wallet - Development Jason
15 |
16 | signingCertificate
17 | 67D6BA0FEC3E43792AABC24ED686303A9E3BB23F
18 | signingStyle
19 | manual
20 | stripSwiftSymbols
21 |
22 | teamID
23 | L796QSLV3E
24 | thinning
25 | <none>
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/__tests__/components/__snapshots__/LoadingIcon.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`LoadingIcon Component renders correctly 1`] = `
4 |
16 |
37 |
38 |
39 |
40 | `;
41 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/account/components/AccountField.tsx:
--------------------------------------------------------------------------------
1 | import { ThemedText, useTheme } from '@bifold/core'
2 | import React from 'react'
3 | import { StyleSheet, View, ViewStyle } from 'react-native'
4 |
5 | export interface AccountFieldProps {
6 | label: string
7 | value: string
8 | style?: ViewStyle
9 | }
10 |
11 | const AccountField: React.FC = ({ label, value, style }) => {
12 | const { Spacing } = useTheme()
13 |
14 | const styles = StyleSheet.create({
15 | label: {
16 | marginBottom: Spacing.xs,
17 | },
18 | })
19 |
20 | return (
21 |
22 |
23 | {label}
24 |
25 | {value}
26 |
27 | )
28 | }
29 |
30 | export default AccountField
31 |
--------------------------------------------------------------------------------
/app/babel.config.js:
--------------------------------------------------------------------------------
1 | const presets = ['module:@react-native/babel-preset']
2 | const plugins = [
3 | [
4 | 'module-resolver',
5 | {
6 | root: ['.'],
7 | extensions: ['.tsx', 'ts'],
8 | alias: {
9 | '@': './src',
10 | '@assets': './src/assets',
11 | '@bcwallet-theme': './src/bcwallet-theme',
12 | '@bcsc-theme': './src/bcsc-theme',
13 | '@components': './src/components',
14 | '@events': './src/events',
15 | '@hooks': './src/hooks',
16 | '@screens': './src/screens',
17 | '@services': './src/services',
18 | '@types': './src/types',
19 | '@utils': './src/utils',
20 | },
21 | },
22 | ],
23 | ]
24 |
25 | if (process.env['ENV'] === 'prod') {
26 | plugins.push('transform-remove-console')
27 | }
28 |
29 | module.exports = {
30 | presets,
31 | plugins,
32 | }
33 |
--------------------------------------------------------------------------------
/app/__mocks__/react-native-tcp-socket/index.ts:
--------------------------------------------------------------------------------
1 | let aNode: any = undefined
2 |
3 | const ports = {
4 | connect: 8001,
5 | error: 8002,
6 | timeout: 8003,
7 | }
8 |
9 | const on = (event: any, cb: any) => {
10 | switch (event) {
11 | case 'timeout':
12 | if (aNode.port === ports.timeout) {
13 | cb()
14 | }
15 | break
16 | case 'error':
17 | if (aNode.port === ports.error) {
18 | cb()
19 | }
20 | break
21 | default:
22 | break
23 | }
24 | }
25 |
26 | const client = {
27 | on,
28 | destroy: jest.fn(),
29 | setTimeout: jest.fn(),
30 | removeAllListeners: jest.fn(),
31 | }
32 |
33 | const createConnection = jest.fn((node, cb) => {
34 | aNode = node
35 |
36 | if (node.port === ports.connect) {
37 | cb()
38 | }
39 |
40 | return client
41 | })
42 |
43 | export default { createConnection }
44 |
--------------------------------------------------------------------------------
/app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig-base.json",
3 | "compilerOptions": {
4 | "outDir": "./lib",
5 | "declaration": true,
6 | "skipLibCheck": true,
7 | "baseUrl": ".",
8 | "paths": {
9 | "@/*": ["src/*"],
10 | "@assets/*": ["src/assets/*"],
11 | "@bcwallet-theme/*": ["src/bcwallet-theme/*"],
12 | "@bcsc-theme/*": ["src/bcsc-theme/*"],
13 | "@components/*": ["src/components/*"],
14 | "@events/*": ["src/events/*"],
15 | "@hooks/*": ["src/hooks/*"],
16 | "@screens/*": ["src/screens/*"],
17 | "@services/*": ["src/services/*"],
18 | "@types/*": ["src/types/*"],
19 | "@utils/*": ["src/utils/*"],
20 | "react-native-bcsc-core": ["../packages/bcsc-core/src"]
21 | }
22 | },
23 | "exclude": ["node_modules", "metro.config.js", "babel.config.js", "jest.config.js", "jestSetup.js"]
24 | }
25 |
--------------------------------------------------------------------------------
/app/__mocks__/@react-navigation/core.ts:
--------------------------------------------------------------------------------
1 | const navigate = jest.fn()
2 | const dispatch = jest.fn()
3 | const replace = jest.fn()
4 | const navigation = {
5 | __timestamp: process.hrtime(),
6 | navigate,
7 | replace,
8 | setOptions: jest.fn(),
9 | getParent: () => {
10 | return {
11 | navigate,
12 | dispatch,
13 | replace,
14 | }
15 | },
16 | getState: jest.fn(() => ({
17 | index: jest.fn(),
18 | })),
19 | goBack: jest.fn(),
20 | pop: jest.fn(),
21 | reset: jest.fn(),
22 | isFocused: () => true,
23 | dispatch,
24 | }
25 |
26 | const useNavigation = () => {
27 | return navigation
28 | }
29 |
30 | const useIsFocused = () => {
31 | return true
32 | }
33 |
34 | const CommonActions = {
35 | navigate: jest.fn(),
36 | reset: jest.fn(),
37 | goBack: jest.fn(),
38 | }
39 |
40 | export { CommonActions, useIsFocused, useNavigation }
41 |
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/main/java/com/bcsccore/bcsc-file-port/src/main/java/com/bcsccore/fileport/encryption/Encryption.java:
--------------------------------------------------------------------------------
1 | package com.bcsccore.fileport.encryption;
2 |
3 | /**
4 | * Interface for encryption/decryption operations.
5 | * This is a self-contained copy of the original BCSC Encryption interface.
6 | */
7 | public interface Encryption {
8 | /**
9 | * Encrypt a message string into bytes
10 | * @param message The string to encrypt
11 | * @return Encrypted bytes
12 | * @throws Exception if encryption fails
13 | */
14 | byte[] encrypt(String message) throws Exception;
15 |
16 | /**
17 | * Decrypt bytes back to a string
18 | * @param bytes The encrypted bytes to decrypt
19 | * @return Decrypted string
20 | * @throws Exception if decryption fails
21 | */
22 | String decrypt(byte[] bytes) throws Exception;
23 | }
24 |
--------------------------------------------------------------------------------
/app/__tests__/screens/ResidentialAddressScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import { ResidentialAddressScreen } from '../../src/bcsc-theme/features/verify/ResidentialAddressScreen'
6 |
7 | describe('ResidentialAddress', () => {
8 | let mockNavigation: any
9 | let mockRoute: any
10 |
11 | beforeEach(() => {
12 | jest.clearAllMocks()
13 | jest.useFakeTimers()
14 | })
15 |
16 | afterEach(() => {
17 | jest.useRealTimers()
18 | })
19 |
20 | it('renders correctly', () => {
21 | const tree = render(
22 |
23 |
24 |
25 | )
26 |
27 | expect(tree).toMatchSnapshot()
28 | })
29 | })
30 |
--------------------------------------------------------------------------------
/packages/bcsc-core/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "rootDir": ".",
4 | "paths": {
5 | "react-native-bcsc-core": ["./src/index"]
6 | },
7 | "allowUnreachableCode": false,
8 | "allowUnusedLabels": false,
9 | "esModuleInterop": true,
10 | "forceConsistentCasingInFileNames": true,
11 | "jsx": "react-jsx",
12 | "lib": ["ESNext"],
13 | "module": "ESNext",
14 | "moduleResolution": "bundler",
15 | "noEmit": true,
16 | "noFallthroughCasesInSwitch": true,
17 | "noImplicitReturns": true,
18 | "noImplicitUseStrict": false,
19 | "noStrictGenericChecks": false,
20 | "noUncheckedIndexedAccess": true,
21 | "noUnusedLocals": true,
22 | "noUnusedParameters": true,
23 | "resolveJsonModule": true,
24 | "skipLibCheck": true,
25 | "strict": true,
26 | "target": "ESNext",
27 | "verbatimModuleSyntax": true
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/__tests__/screens/ScanSerialScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import ScanSerialScreen from '../../src/bcsc-theme/features/verify/ScanSerialScreen'
7 |
8 | describe('ScanSerial', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/SetupStepsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import SetupStepsScreen from '../../src/bcsc-theme/features/verify/SetupStepsScreen'
7 |
8 | describe('SetupSteps', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/android/app/.idea/modules/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/__tests__/screens/SecureAppScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { SecureAppScreen } from '../../src/bcsc-theme/features/onboarding/SecureAppScreen'
7 |
8 | describe('SecureApp', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/StartCallScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import StartCallScreen from '../../src/bcsc-theme/features/verify/live-call/StartCallScreen'
7 |
8 | describe('StartCall', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/src/bcwallet-theme/components/AddCredentialButton.tsx:
--------------------------------------------------------------------------------
1 | import { ButtonLocation, IconButton, testIdWithKey } from '@bifold/core'
2 | import React, { useCallback } from 'react'
3 | import { useTranslation } from 'react-i18next'
4 | import { DeviceEventEmitter } from 'react-native'
5 |
6 | import { BCWalletEventTypes } from '../../events/eventTypes'
7 |
8 | const AddCredentialButton = () => {
9 | const { t } = useTranslation()
10 |
11 | const activateSlider = useCallback(() => {
12 | DeviceEventEmitter.emit(BCWalletEventTypes.ADD_CREDENTIAL_PRESSED, true)
13 | }, [])
14 |
15 | return (
16 |
23 | )
24 | }
25 |
26 | export default AddCredentialButton
27 |
--------------------------------------------------------------------------------
/app/__tests__/screens/ManualSerialScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import ManualSerialScreen from '../../src/bcsc-theme/features/verify/ManualSerialScreen'
7 |
8 | describe('ManualSerial', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/TermsOfUseScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { TermsOfUseScreen } from '../../src/bcsc-theme/features/onboarding/TermsOfUseScreen'
7 |
8 | describe('TermsOfUse', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/AccountExpiredScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { AccountExpiredScreen } from '../../src/bcsc-theme/features/account/AccountExpiredScreen'
7 |
8 | describe('AccountExpired', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/MainSettingsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { MainSettingsScreen } from '../../src/bcsc-theme/features/settings/MainSettingsScreen'
7 |
8 | describe('MainSettings', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/src/utils/net-info-config.ts:
--------------------------------------------------------------------------------
1 | import { NetInfoConfiguration } from '@react-native-community/netinfo'
2 | import Config from 'react-native-config'
3 |
4 | // We don't want to actually request an invitation from the mediator
5 | // (which follows the '?') so we just use the base URL
6 | const fullMedUrl = Config.MEDIATOR_URL || ''
7 | let endIndex = fullMedUrl.indexOf('?')
8 | if (endIndex === -1) {
9 | endIndex = fullMedUrl.length
10 | }
11 | const reachabilityUrl = fullMedUrl.substring(0, endIndex)
12 |
13 | // Links to docs: https://github.com/react-native-netinfo/react-native-netinfo/tree/master?tab=readme-ov-file#netinfoconfiguration
14 | export const netInfoConfig: Partial = {
15 | useNativeReachability: false,
16 | reachabilityUrl,
17 | reachabilityTest: async (response: Response) => {
18 | return response.status >= 200 && response.status <= 299
19 | },
20 | reachabilityRequestTimeout: 3000,
21 | }
22 |
--------------------------------------------------------------------------------
/app/__tests__/screens/MainContactUsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { MainContactUsScreen } from '../../src/bcsc-theme/features/settings/MainContactUsScreen'
7 |
8 | describe('MainContactUs', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/LiveCallScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import LiveCallScreen from '../../src/bcsc-theme/features/verify/live-call/LiveCallScreen'
7 |
8 | describe('LiveCall', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 |
30 | tree.unmount()
31 | })
32 | })
33 |
--------------------------------------------------------------------------------
/app/__tests__/screens/PendingReviewScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import PendingReviewScreen from '../../src/bcsc-theme/features/verify/send-video/PendingReviewScreen'
7 |
8 | describe('PendingReview', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/VerifyInPersonScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import VerifyInPersonScreen from '../../src/bcsc-theme/features/verify/in-person/VerifyInPersonScreen'
7 |
8 | describe('VerifyInPerson', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/VerifySettingsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { VerifySettingsScreen } from '../../src/bcsc-theme/features/settings/VerifySettingsScreen'
7 |
8 | describe('VerifySettings', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/.github/workflows/actions/setup-node/action.yml:
--------------------------------------------------------------------------------
1 | # based on https://github.com/hyperledger/aries-framework-javascript-ext/blob/main/.github/actions/setup-node/action.yml
2 | name: Setup NodeJS
3 | description: Setup NodeJS with caching
4 | author: "timo@animo.id"
5 |
6 | inputs:
7 | node-version:
8 | description: Select the nodejs version to use
9 | required: false
10 | default: "20.19.2"
11 |
12 | runs:
13 | using: composite
14 | steps:
15 | - name: Setup node v${{ inputs.node-version }}
16 | uses: actions/setup-node@v4
17 | with:
18 | node-version: ${{ inputs.node-version }}
19 | registry-url: "https://registry.npmjs.org/"
20 |
21 | - name: Enable corepack and setup Yarn 4.9.2
22 | shell: bash
23 | run: |
24 | corepack enable
25 | corepack prepare yarn@4.9.2 --activate
26 |
27 | - name: Node Version
28 | shell: bash
29 | run: |
30 | node -v && yarn -v
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/IdentitySelectionScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import IdentitySelectionScreen from '../../src/bcsc-theme/features/verify/IdentitySelectionScreen'
7 |
8 | describe('IdentitySelection', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/VerifyContactUsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { VerifyContactUsScreen } from '../../src/bcsc-theme/features/settings/VerifyContactUsScreen'
7 |
8 | describe('VerifyContactUs', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/ios/Media.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "iTunesArtwork.png",
5 | "idiom" : "universal",
6 | "platform" : "ios",
7 | "size" : "1024x1024"
8 | },
9 | {
10 | "appearances" : [
11 | {
12 | "appearance" : "luminosity",
13 | "value" : "dark"
14 | }
15 | ],
16 | "filename" : "iTunesArtwork_Dark.png",
17 | "idiom" : "universal",
18 | "platform" : "ios",
19 | "size" : "1024x1024"
20 | },
21 | {
22 | "appearances" : [
23 | {
24 | "appearance" : "luminosity",
25 | "value" : "tinted"
26 | }
27 | ],
28 | "filename" : "iTunesArtwork_Tinted.png",
29 | "idiom" : "universal",
30 | "platform" : "ios",
31 | "size" : "1024x1024"
32 | }
33 | ],
34 | "info" : {
35 | "author" : "xcode",
36 | "version" : 1
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/__tests__/screens/EvidenceTypeListScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import EvidenceTypeListScreen from '../../src/bcsc-theme/features/verify/non-photo/EvidenceTypeListScreen'
7 |
8 | describe('EvidenceTypeList', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/OnboardingWebViewScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import { OnboardingWebViewScreen } from '../../src/bcsc-theme/features/webview/OnboardingWebViewScreen'
6 |
7 | describe('OnboardingWebView', () => {
8 | beforeEach(() => {
9 | jest.clearAllMocks()
10 | jest.useFakeTimers()
11 | })
12 |
13 | afterEach(() => {
14 | jest.useRealTimers()
15 | })
16 |
17 | it('renders correctly', () => {
18 | const route = {
19 | key: 'onboarding-webview',
20 | name: 'OnboardingWebView',
21 | params: { url: 'https://example.com', title: 'Test' },
22 | } as any
23 | const tree = render(
24 |
25 |
26 |
27 | )
28 |
29 | expect(tree).toMatchSnapshot()
30 | })
31 | })
32 |
--------------------------------------------------------------------------------
/app/__tests__/screens/SerialInstructionsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import SerialInstructionsScreen from '../../src/bcsc-theme/features/verify/SerialInstructionsScreen'
7 |
8 | describe('SerialInstructions', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/PATCH_NOTES.md:
--------------------------------------------------------------------------------
1 | ### Patches
2 |
3 | #### @credo-ts-anoncreds-npm-0.5.13-446ac3168e.patch
4 | Bugs fixed by massaging qualified vs unqualified identifiers
5 |
6 | #### @credo-ts-core-npm-0.5.13-725ab940d0.patch
7 | Fixes three separate issues. One, fix websocket close handling to allow graceful agent shutdown. Two, proper lookup to catch all formats of AnonCreds credentials. Three, dif presentation bug fix for MDoc / OID4VC
8 |
9 | #### @credo-ts-indy-vdr-npm-0.5.13-007d41ad5c.patch
10 | Prevent error on agent restart when same IndyVDR pool is reused. Prevent bug with revocation registry interval
11 |
12 | #### @hyperledger-indy-vdr-react-native-npm-0.2.2-627d424b96.patch
13 | #### @hyperledger-indy-vdr-shared-npm-0.2.2-b989282fc6.patch
14 | Patches adding support for caching by grabbing the 0.4.3 indy-vdr binary from github. There's also some changes to the cpp FFIs
15 |
16 | #### @sphereon-pex-npm-3.3.3-144d9252ec.patch
17 | Fixes local-dev-only bug with yarn install
--------------------------------------------------------------------------------
/app/__tests__/screens/ForgetAllPairingsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { ForgetAllPairingsScreen } from '../../src/bcsc-theme/features/settings/ForgetAllPairingsScreen'
7 |
8 | describe('ForgetAllPairings', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/SuccessfullySentScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import SuccessfullySentScreen from '../../src/bcsc-theme/features/verify/send-video/SuccessfullySentScreen'
7 |
8 | describe('SuccessfullySent', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/VideoInstructionsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import VideoInstructionsScreen from '../../src/bcsc-theme/features/verify/send-video/VideoInstructionsScreen'
7 |
8 | describe('VideoInstructions', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/helpers/Utils.test.ts:
--------------------------------------------------------------------------------
1 | import { expirationOverrideInMinutes } from '@utils/expiration'
2 |
3 | import MockDate from 'mockdate'
4 |
5 | jest.useFakeTimers({ legacyFakeTimers: true })
6 |
7 | describe('Helpers', () => {
8 | beforeAll(() => {
9 | // Set the date to a fixed point in time
10 | MockDate.set('2024-07-09T21:56:44.200Z')
11 | })
12 |
13 | afterAll(() => {
14 | // Reset the date to the current date after tests
15 | MockDate.reset()
16 | })
17 |
18 | test('computes expiration override correctly', () => {
19 | const dateInThePast = new Date('2024-07-09T21:23:44.200Z')
20 | const value = expirationOverrideInMinutes(dateInThePast, 60)
21 |
22 | expect(value).toBe(27)
23 | })
24 |
25 | test('ignore distant expirations ', () => {
26 | const dateInThePast = new Date('2024-07-09T19:23:44.200Z')
27 | const value = expirationOverrideInMinutes(dateInThePast, 60)
28 |
29 | expect(value).toBe(0)
30 | })
31 | })
32 |
--------------------------------------------------------------------------------
/app/__tests__/screens/BeforeYouCallScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import BeforeYouCallScreen from '../../src/bcsc-theme/features/verify/live-call/BeforeYouCallScreen'
7 |
8 | describe('BeforeYouCall', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/utils/card-utils.ts:
--------------------------------------------------------------------------------
1 | import { BCSCCardProcess, BCSCCardType } from '../types/cards'
2 |
3 | /**
4 | * Get the card process for a given card type.
5 | *
6 | * @throws {Error} If the card type is invalid or None.
7 | * @param {BCSCCardType} cardType - The type of BCSC card.
8 | * @returns {*} {BCSCCardProcess} The corresponding card process.
9 | */
10 | export function getCardProcessForCardType(cardType: BCSCCardType): BCSCCardProcess | null {
11 | switch (cardType) {
12 | case BCSCCardType.Combined:
13 | return BCSCCardProcess.BCSCPhoto
14 | case BCSCCardType.Photo:
15 | return BCSCCardProcess.BCSCPhoto
16 | case BCSCCardType.NonPhoto:
17 | return BCSCCardProcess.BCSCNonPhoto
18 | case BCSCCardType.Other:
19 | return BCSCCardProcess.NonBCSC
20 | case BCSCCardType.None:
21 | return null // No card -> no card process
22 | default:
23 | return null // Unknown card type -> no card process
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/bcsc-core/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://turbo.build/schema.json",
3 | "pipeline": {
4 | "build:android": {
5 | "env": ["ORG_GRADLE_PROJECT_newArchEnabled"],
6 | "inputs": [
7 | "package.json",
8 | "android",
9 | "!android/build",
10 | "src/*.ts",
11 | "src/*.tsx",
12 | "example/package.json",
13 | "example/android",
14 | "!example/android/.gradle",
15 | "!example/android/build",
16 | "!example/android/app/build"
17 | ],
18 | "outputs": []
19 | },
20 | "build:ios": {
21 | "env": ["RCT_NEW_ARCH_ENABLED"],
22 | "inputs": [
23 | "package.json",
24 | "*.podspec",
25 | "ios",
26 | "src/*.ts",
27 | "src/*.tsx",
28 | "example/package.json",
29 | "example/ios",
30 | "!example/ios/build",
31 | "!example/ios/Pods"
32 | ],
33 | "outputs": []
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/__tests__/screens/SettingsPrivacyPolicyScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { SettingsPrivacyPolicyScreen } from '../../src/bcsc-theme/features/settings/SettingsPrivacyPolicyScreen'
7 |
8 | describe('SettingsPrivacyPolicy', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/VideoTooLongScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import VideoTooLongScreen from '../../src/bcsc-theme/features/verify/send-video/VideoTooLongScreen'
7 |
8 | describe('VideoTooLong', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/CallBusyOrClosedScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import CallBusyOrClosedScreen from '../../src/bcsc-theme/features/verify/live-call/CallBusyOrClosedScreen'
7 |
8 | describe('CallBusyOrClosed', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/OnboardingPrivacyPolicyScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { OnboardingPrivacyPolicyScreen } from '../../src/bcsc-theme/features/onboarding/OnboardingPrivacyPolicyScreen'
7 |
8 | describe('OnboardingPrivacyPolicy', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/components/TabScreenWrapper.tsx:
--------------------------------------------------------------------------------
1 | import { useTheme } from '@bifold/core'
2 | import React, { ComponentProps, PropsWithChildren } from 'react'
3 | import { ScrollView } from 'react-native'
4 | import { SafeAreaView } from 'react-native-safe-area-context'
5 |
6 | interface TabScreenWrapperProps extends PropsWithChildren {
7 | edges?: ('top' | 'left' | 'right' | 'bottom')[]
8 | scrollViewProps?: ComponentProps
9 | }
10 |
11 | const TabScreenWrapper: React.FC = ({
12 | edges = ['left', 'right'],
13 | children,
14 | scrollViewProps,
15 | }) => {
16 | const { ColorPalette } = useTheme()
17 |
18 | return (
19 |
20 |
21 | {children}
22 |
23 |
24 | )
25 | }
26 |
27 | export default TabScreenWrapper
28 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/account/components/AccountPhoto.tsx:
--------------------------------------------------------------------------------
1 | import { useTheme } from '@bifold/core'
2 | import React from 'react'
3 | import { Image, StyleSheet, View } from 'react-native'
4 |
5 | // Placholder for now
6 | const AccountPhoto: React.FC<{ photoUri: string | null }> = ({ photoUri }) => {
7 | const { Spacing, ColorPalette } = useTheme()
8 |
9 | const styles = StyleSheet.create({
10 | container: {
11 | width: 130,
12 | height: 180,
13 | backgroundColor: ColorPalette.grayscale.lightGrey,
14 | marginBottom: Spacing.md,
15 | justifyContent: 'center',
16 | alignItems: 'center',
17 | overflow: 'hidden',
18 | },
19 | photo: {
20 | width: '100%',
21 | height: '100%',
22 | resizeMode: 'cover',
23 | },
24 | })
25 |
26 | return (
27 | {photoUri ? : null}
28 | )
29 | }
30 |
31 | export default AccountPhoto
32 |
--------------------------------------------------------------------------------
/app/__tests__/screens/AccountRenewalInformationScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { AccountRenewalInformationScreen } from '../../src/bcsc-theme/features/account/AccountRenewalInformationScreen'
7 |
8 | describe('AccountRenewalInformation', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/AccountRenewalFirstWarningScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { AccountRenewalFirstWarningScreen } from '../../src/bcsc-theme/features/account/AccountRenewalFirstWarningScreen'
7 |
8 | describe('AccountRenewalFirstWarning', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/VerificationMethodSelectionScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import VerificationMethodSelectionScreen from '../../src/bcsc-theme/features/verify/VerificationMethodSelectionScreen'
7 |
8 | describe('VerificationMethodSelection', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__mocks__/@react-native-community/netinfo.ts:
--------------------------------------------------------------------------------
1 | const defaultState = {
2 | type: 'cellular',
3 | isConnected: true,
4 | isInternetReachable: true,
5 | details: {
6 | isConnectionExpensive: true,
7 | cellularGeneration: '3g',
8 | },
9 | }
10 |
11 | const NetInfoStateType = {
12 | unknown: 'unknown',
13 | none: 'none',
14 | cellular: 'cellular',
15 | wifi: 'wifi',
16 | bluetooth: 'bluetooth',
17 | ethernet: 'ethernet',
18 | wimax: 'wimax',
19 | vpn: 'vpn',
20 | other: 'other',
21 | }
22 |
23 | const RNCNetInfoMock = {
24 | NetInfoStateType,
25 | configure: jest.fn(),
26 | fetch: jest.fn(),
27 | refresh: jest.fn(),
28 | addEventListener: jest.fn(),
29 | useNetInfo: jest.fn(),
30 | }
31 |
32 | RNCNetInfoMock.fetch.mockResolvedValue(defaultState)
33 | RNCNetInfoMock.refresh.mockResolvedValue(defaultState)
34 | RNCNetInfoMock.useNetInfo.mockReturnValue(defaultState)
35 | RNCNetInfoMock.addEventListener.mockReturnValue(jest.fn())
36 |
37 | export default RNCNetInfoMock
38 |
--------------------------------------------------------------------------------
/app/__tests__/screens/DualIdentificationRequiredScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import DualIdentificationRequiredScreen from '../../src/bcsc-theme/features/verify/non-photo/DualIdentificationRequiredScreen'
7 |
8 | describe('DualIdentificationRequired', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/ios/AriesBifoldTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | UIAppFonts
24 |
25 | MaterialIcons.ttf
26 | MaterialCommunityIcons.ttf
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/__tests__/screens/PhotoReviewScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import PhotoReviewScreen from '../../src/bcsc-theme/features/verify/PhotoReviewScreen'
7 |
8 | describe('PhotoReview', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const route = { params: { photoPath: 'file://test.jpg' } }
23 | const tree = render(
24 |
25 |
26 |
27 | )
28 |
29 | expect(tree).toMatchSnapshot()
30 | })
31 | })
32 |
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/main/java/com/bcsccore/bcsc-keypair-port/core/exceptions/AlertKey.java:
--------------------------------------------------------------------------------
1 | package com.bcsccore.keypair.core.exceptions;
2 |
3 | /**
4 | * Enumeration of error keys used for identifying different types of exceptions.
5 | * This is a simplified version of the original AlertKey enum with only the
6 | * keys needed for key pair operations.
7 | */
8 | public enum AlertKey {
9 |
10 | // General error
11 | GENERAL,
12 |
13 | // Key pair related errors
14 | ADD_CARD_KEYPAIR_GENERATION,
15 | ERR_108_UNABLE_TO_DELETE_KEY_PAIR,
16 | ERR_207_UNABLE_TO_SIGN_CLAIMS_SET,
17 |
18 | // Server and network errors
19 | SERVER_ERROR,
20 | NO_INTERNET,
21 | SERVER_TIMEOUT,
22 |
23 | // Token related errors
24 | INVALID_TOKEN,
25 | NO_TOKENS_RETURNED;
26 |
27 | /**
28 | * Get a string representation of this alert key.
29 | * @return the name of the enum constant
30 | */
31 | public String getKeyString() {
32 | return this.name();
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/app/__tests__/screens/EnterBirthdateScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import EnterBirthdateScreen from '../../src/bcsc-theme/features/verify/EnterBirthdate/EnterBirthdateScreen'
7 |
8 | describe('EnterBirthdate', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | jest.setSystemTime(new Date('2025-12-03T00:00:00.000Z'))
16 | })
17 |
18 | afterEach(() => {
19 | jest.useRealTimers()
20 | })
21 |
22 | it('renders correctly', () => {
23 | const tree = render(
24 |
25 |
26 |
27 | )
28 |
29 | expect(tree).toMatchSnapshot()
30 | })
31 | })
32 |
--------------------------------------------------------------------------------
/app/ios/GoogleService-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | API_KEY
6 | AIzaSyCL37I5zpWEauPopROBm6d64bGDiimAvZE
7 | GCM_SENDER_ID
8 | 1008044298583
9 | PLIST_VERSION
10 | 1
11 | BUNDLE_ID
12 | ca.bc.gov.BCWallet
13 | PROJECT_ID
14 | bc-wallet-mobile
15 | STORAGE_BUCKET
16 | bc-wallet-mobile.appspot.com
17 | IS_ADS_ENABLED
18 |
19 | IS_ANALYTICS_ENABLED
20 |
21 | IS_APPINVITE_ENABLED
22 |
23 | IS_GCM_ENABLED
24 |
25 | IS_SIGNIN_ENABLED
26 |
27 | GOOGLE_APP_ID
28 | 1:1008044298583:ios:76bfc02e8a3c04f844ae12
29 |
30 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/components/HeaderBackButton.tsx:
--------------------------------------------------------------------------------
1 | import { ButtonLocation, IconButton } from '@bifold/core'
2 | import { HeaderBackButtonProps } from '@react-navigation/elements'
3 | import { Platform } from 'react-native'
4 |
5 | /**
6 | * Shared Header Back Button component that navigates back on press.
7 | *
8 | * @returns {*} {JSX.Element}
9 | */
10 | export const HeaderBackButton = (props: HeaderBackButtonProps) => {
11 | return (
12 | props.onPress?.()}
18 | />
19 | )
20 | }
21 |
22 | /**
23 | * Creates a Header Back Button component.
24 | *
25 | * @returns {*} {JSX.Element}
26 | */
27 | export const createHeaderBackButton = (props: HeaderBackButtonProps) => {
28 | return
29 | }
30 |
--------------------------------------------------------------------------------
/app/__tests__/screens/AdditionalIdentificationRequiredScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import AdditionalIdentificationRequiredScreen from '../../src/bcsc-theme/features/verify/non-photo/AdditionalIdentificationRequiredScreen'
7 |
8 | describe('AdditionalIdentificationRequired', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
25 |
26 | )
27 |
28 | expect(tree).toMatchSnapshot()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/__tests__/screens/Developer.test.tsx:
--------------------------------------------------------------------------------
1 | import { AuthProvider } from '@bifold/core'
2 | import { render } from '@testing-library/react-native'
3 | import React from 'react'
4 |
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import Developer from '../../src/screens/Developer'
7 |
8 | describe('Developer Screen', () => {
9 | beforeEach(() => {
10 | // Silence console.error because it will print a warning about Switch
11 | // "Warning: dispatchCommand was called with a ref ...".
12 | jest.spyOn(console, 'error').mockImplementation(() => {
13 | return null
14 | })
15 | jest.useFakeTimers()
16 | })
17 |
18 | afterEach(() => {
19 | jest.clearAllMocks()
20 | jest.useRealTimers()
21 | })
22 |
23 | test('screen renders correctly', () => {
24 | const tree = render(
25 |
26 |
27 |
28 |
29 |
30 | )
31 |
32 | expect(tree).toMatchSnapshot()
33 | })
34 | })
35 |
--------------------------------------------------------------------------------
/app/__tests__/screens/NotificationsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { NotificationsScreen } from '../../src/bcsc-theme/features/onboarding/NotificationsScreen'
7 |
8 | jest.mock('@assets/img/notifications.png', () => ({ uri: 'mock-notification-image' }))
9 |
10 | describe('Notifications', () => {
11 | let mockNavigation: any
12 |
13 | beforeEach(() => {
14 | mockNavigation = useNavigation()
15 | jest.clearAllMocks()
16 | jest.useFakeTimers()
17 | })
18 |
19 | afterEach(() => {
20 | jest.useRealTimers()
21 | })
22 |
23 | it('renders correctly', () => {
24 | const tree = render(
25 |
26 |
27 |
28 | )
29 |
30 | expect(tree).toMatchSnapshot()
31 | })
32 | })
33 |
--------------------------------------------------------------------------------
/app/__tests__/components/ProgressBar.test.tsx:
--------------------------------------------------------------------------------
1 | import { render, waitFor } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { BasicAppContext } from '../../__mocks__/helpers/app'
5 | import ProgressBar from '../../src/components/ProgressBar'
6 |
7 | describe('ProgressBar Component', () => {
8 | beforeAll(() => {
9 | jest.useFakeTimers()
10 | })
11 |
12 | afterAll(() => {
13 | jest.useRealTimers()
14 | })
15 |
16 | test('renders correctly', () => {
17 | const tree = render(
18 |
19 |
20 |
21 | )
22 |
23 | waitFor(() => {
24 | expect(tree).toMatchSnapshot()
25 | })
26 | })
27 |
28 | test('renders correctly in dark mode', () => {
29 | const tree = render(
30 |
31 |
32 |
33 | )
34 |
35 | waitFor(() => {
36 | expect(tree).toMatchSnapshot()
37 | })
38 | })
39 | })
40 |
--------------------------------------------------------------------------------
/app/__tests__/screens/EmailConfirmationScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import EmailConfirmationScreen from '../../src/bcsc-theme/features/verify/email/EmailConfirmationScreen'
7 |
8 | describe('EmailConfirmation', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const route = { params: { emailAddressId: 'test-email-id' } }
23 | const tree = render(
24 |
25 |
26 |
27 | )
28 |
29 | expect(tree).toMatchSnapshot()
30 | })
31 | })
32 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/verify/live-call/components/CallProcessingView.tsx:
--------------------------------------------------------------------------------
1 | import { ThemedText, useTheme } from '@bifold/core'
2 | import { ActivityIndicator, StyleSheet } from 'react-native'
3 | import { SafeAreaView } from 'react-native-safe-area-context'
4 |
5 | type CallProcessingViewProps = {
6 | message?: string
7 | }
8 |
9 | const CallProcessingView = ({ message }: CallProcessingViewProps) => {
10 | const { Spacing, ColorPalette } = useTheme()
11 | const styles = StyleSheet.create({
12 | pageContainer: {
13 | flex: 1,
14 | justifyContent: 'center',
15 | alignItems: 'center',
16 | backgroundColor: ColorPalette.brand.primaryBackground,
17 | },
18 | })
19 |
20 | return (
21 |
22 |
23 | {message}
24 |
25 |
26 |
27 | )
28 | }
29 |
30 | export default CallProcessingView
31 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/components/GenericCardImage.tsx:
--------------------------------------------------------------------------------
1 | import CardDetails from '@assets/img/card-details.svg'
2 | import { useTheme } from '@bifold/core'
3 | import React from 'react'
4 | import { View } from 'react-native'
5 |
6 | export const GENERIC_CARD_SIZE_SMALL = { height: 45, width: 72 }
7 | export const GENERIC_CARD_SIZE_MEDIUM = { height: 75, width: 120 }
8 |
9 | interface GenericCardImageProps {
10 | height?: number
11 | width?: number
12 | }
13 |
14 | const GenericCardImage = ({ height, width }: GenericCardImageProps) => {
15 | const { ColorPalette, Spacing } = useTheme()
16 |
17 | return (
18 |
27 |
28 |
29 | )
30 | }
31 |
32 | export default GenericCardImage
33 |
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/main/java/com/bcsccore/bcsc-file-port/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
23 | # Keep file port classes
24 | -keep class com.bcsccore.fileport.** { *; }
25 | -keepclassmembers class com.bcsccore.fileport.** { *; }
26 |
--------------------------------------------------------------------------------
/app/__tests__/screens/IDPhotoInformationScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import IDPhotoInformationScreen from '../../src/bcsc-theme/features/verify/non-photo/IDPhotoInformationScreen'
7 |
8 | jest.mock('@assets/img/credential-scan.png', () => 1)
9 |
10 | describe('IDPhotoInformation', () => {
11 | let mockNavigation: any
12 |
13 | beforeEach(() => {
14 | mockNavigation = useNavigation()
15 | jest.clearAllMocks()
16 | jest.useFakeTimers()
17 | })
18 |
19 | afterEach(() => {
20 | jest.useRealTimers()
21 | })
22 |
23 | it('renders correctly', () => {
24 | const tree = render(
25 |
26 |
27 |
28 | )
29 |
30 | expect(tree).toMatchSnapshot()
31 | })
32 | })
33 |
--------------------------------------------------------------------------------
/app/__tests__/screens/VideoReviewScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import VideoReviewScreen from '../../src/bcsc-theme/features/verify/send-video/VideoReviewScreen'
7 |
8 | describe('VideoReview', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const route = { params: { videoPath: 'file://test.mp4', videoThumbnailPath: 'file://thumbnail.jpg' } }
23 | const tree = render(
24 |
25 |
26 |
27 | )
28 |
29 | expect(tree).toMatchSnapshot()
30 | })
31 | })
32 |
--------------------------------------------------------------------------------
/app/__tests__/screens/__snapshots__/EvidenceCaptureScreen.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`EvidenceCapture renders correctly 1`] = `
4 |
12 |
28 |
37 |
44 | BCSC.CameraDisclosure.NoCameraAvailable
45 |
46 |
47 |
48 |
49 | `;
50 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/account/NicknameAccountScreen.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback } from 'react'
2 |
3 | import { BCSCScreens } from '@/bcsc-theme/types/navigators'
4 | import { BCDispatchAction, BCState } from '@/store'
5 | import { useStore } from '@bifold/core'
6 | import { CommonActions, useNavigation } from '@react-navigation/native'
7 | import NicknameForm from './components/NicknameForm'
8 |
9 | const NicknameAccountScreen: React.FC = () => {
10 | const navigation = useNavigation()
11 | const [, dispatch] = useStore()
12 |
13 | const handleSubmit = useCallback(
14 | (trimmedNickname: string) => {
15 | dispatch({ type: BCDispatchAction.ADD_NICKNAME, payload: [trimmedNickname] })
16 | dispatch({ type: BCDispatchAction.SELECT_ACCOUNT, payload: [trimmedNickname] })
17 | navigation.dispatch(CommonActions.reset({ index: 0, routes: [{ name: BCSCScreens.SetupSteps }] }))
18 | },
19 | [dispatch, navigation]
20 | )
21 |
22 | return
23 | }
24 |
25 | export default NicknameAccountScreen
26 |
--------------------------------------------------------------------------------
/app/__tests__/screens/OnboardingOptInAnalyticsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { OnboardingOptInAnalyticsScreen } from '../../src/bcsc-theme/features/onboarding/OnboardingOptInAnalyticsScreen'
7 |
8 | jest.mock('@assets/img/notifications.png', () => ({ uri: 'mock-notification-image' }))
9 |
10 | describe('OnboardingOptInAnalytics', () => {
11 | let mockNavigation: any
12 |
13 | beforeEach(() => {
14 | mockNavigation = useNavigation()
15 | jest.clearAllMocks()
16 | jest.useFakeTimers()
17 | })
18 |
19 | afterEach(() => {
20 | jest.useRealTimers()
21 | })
22 |
23 | it('renders correctly', () => {
24 | const tree = render(
25 |
26 |
27 |
28 | )
29 |
30 | expect(tree).toMatchSnapshot()
31 | })
32 | })
33 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/onboarding/OnboardingOptInAnalyticsScreen.tsx:
--------------------------------------------------------------------------------
1 | import { BCSCOnboardingStackParams, BCSCScreens } from '@/bcsc-theme/types/navigators'
2 | import { StackNavigationProp } from '@react-navigation/stack'
3 | import React from 'react'
4 | import { OnboardingOptInAnalyticsContent } from './components/OnboardingOptInAnalyticsContent'
5 |
6 | interface OnboardingOptInAnalyticsScreenProps {
7 | navigation: StackNavigationProp
8 | }
9 |
10 | /**
11 | * Opt-In Analytics screen component that allows users to choose whether to participate in analytics data collection.
12 | * @returns {*} {JSX.Element} The OnboardingOptInAnalyticsScreen component.
13 | */
14 | export const OnboardingOptInAnalyticsScreen: React.FC = ({
15 | navigation,
16 | }: OnboardingOptInAnalyticsScreenProps): JSX.Element => {
17 | const onPress = () => {
18 | navigation.navigate(BCSCScreens.OnboardingTermsOfUse)
19 | }
20 |
21 | return
22 | }
23 |
--------------------------------------------------------------------------------
/app/__tests__/screens/PhotoInstructionsScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import PhotoInstructionsScreen from '../../src/bcsc-theme/features/verify/PhotoInstructionsScreen'
7 |
8 | describe('PhotoInstructions', () => {
9 | let mockNavigation: any
10 |
11 | beforeEach(() => {
12 | mockNavigation = useNavigation()
13 | jest.clearAllMocks()
14 | jest.useFakeTimers()
15 | })
16 |
17 | afterEach(() => {
18 | jest.useRealTimers()
19 | })
20 |
21 | it('renders correctly', () => {
22 | const tree = render(
23 |
24 |
28 |
29 | )
30 |
31 | expect(tree).toMatchSnapshot()
32 | })
33 | })
34 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/api/hooks/useJwksApi.tsx:
--------------------------------------------------------------------------------
1 | import { useCallback, useMemo } from 'react'
2 | import BCSCApiClient from '../client'
3 |
4 | export interface JWK {
5 | kty: string
6 | e: string
7 | kid: string
8 | alg: string
9 | n: string
10 | }
11 | export type Keys = JWK[]
12 |
13 | export type JWKResponseData = {
14 | keys: Keys
15 | }
16 |
17 | const useJwksApi = (apiClient: BCSCApiClient) => {
18 | const getJwks = useCallback(async (): Promise => {
19 | const {
20 | data: { keys },
21 | } = await apiClient.get(apiClient.endpoints.jwksURI, {
22 | skipBearerAuth: true, // this endpoint does not require an access token
23 | })
24 | return keys
25 | }, [apiClient])
26 |
27 | const getFirstJwk = useCallback(async (): Promise => {
28 | const keys = await getJwks()
29 | return keys.length > 0 ? keys[0] : null
30 | }, [getJwks])
31 |
32 | return useMemo(
33 | () => ({
34 | getJwks,
35 | getFirstJwk,
36 | }),
37 | [getJwks, getFirstJwk]
38 | )
39 | }
40 |
41 | export default useJwksApi
42 |
--------------------------------------------------------------------------------
/.github/workflows/actions/export-ios-archive/action.yml:
--------------------------------------------------------------------------------
1 | name: Export Signed iOS Archive
2 | description: Export a signed iOS Archive
3 |
4 | inputs:
5 | export_options:
6 | description: |
7 | The file containing the export options to use
8 | for signing the archive.
9 | required: true
10 | output_artifact_ref:
11 | description: |
12 | The reference ID / name of the uploaded GitHub artifact
13 | stored in GitHub by the upload action.
14 | required: true
15 |
16 | runs:
17 | using: composite
18 | steps:
19 | - name: Sign & Export
20 | shell: bash
21 | run: |
22 | xcodebuild \
23 | -exportArchive \
24 | -archivePath AriesBifold.xcarchive \
25 | -exportPath export \
26 | -exportOptionsPlist ./${{ inputs.export_options }} \
27 | -verbose
28 |
29 | - name: Upload signed artifact
30 | uses: actions/upload-artifact@v4
31 | with:
32 | name: ${{ inputs.output_artifact_ref }}
33 | path: export/BCWallet.ipa
34 | if-no-files-found: error
35 | retention-days: 7
36 |
--------------------------------------------------------------------------------
/app/__mocks__/@react-navigation/native.ts:
--------------------------------------------------------------------------------
1 | const navigate = jest.fn()
2 | const dispatch = jest.fn()
3 | const replace = jest.fn()
4 | const navigation = {
5 | __timestamp: process.hrtime(),
6 | navigate,
7 | replace,
8 | setOptions: jest.fn(),
9 | getParent: () => {
10 | return {
11 | navigate,
12 | dispatch,
13 | replace,
14 | }
15 | },
16 | getState: jest.fn(() => ({
17 | index: jest.fn(),
18 | })),
19 | goBack: jest.fn(),
20 | canGoBack: jest.fn(),
21 | pop: jest.fn(),
22 | reset: jest.fn(),
23 | isFocused: () => true,
24 | dispatch,
25 | }
26 |
27 | const useNavigation = () => {
28 | return navigation
29 | }
30 |
31 | const useIsFocused = () => {
32 | return true
33 | }
34 |
35 | const useRoute = jest.fn().mockReturnValue({ params: {} })
36 |
37 | const CommonActions = {
38 | navigate: jest.fn(),
39 | reset: jest.fn(),
40 | goBack: jest.fn(),
41 | }
42 |
43 | const useFocusEffect = jest.fn()
44 | const createNavigatorFactory = jest.fn()
45 |
46 | export { CommonActions, createNavigatorFactory, useFocusEffect, useIsFocused, useNavigation, useRoute }
47 |
--------------------------------------------------------------------------------
/packages/bcsc-core/BcscCore.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 |
5 | Pod::Spec.new do |s|
6 | s.name = "BcscCore"
7 | s.version = package["version"]
8 | s.summary = package["description"]
9 | s.homepage = package["homepage"]
10 | s.license = package["license"]
11 | s.authors = package["author"]
12 |
13 | s.platforms = { :ios => "12.0" } # Or your min_ios_version_supported
14 |
15 | s.source = { :git => "https://github.com/bcgov/bc-wallet-mobile.git", :tag => "#{s.version}" }
16 |
17 | s.source_files = "ios/**/*.{h,m,mm,cpp,swift}"
18 | s.public_header_files = "ios/**/*.h"
19 |
20 | s.swift_version = '5.0'
21 | s.module_name = 'BcscCore'
22 |
23 | # Disable Swift optimizations to prevent cryptographic operations from being broken
24 | s.pod_target_xcconfig = {
25 | 'SWIFT_OPTIMIZATION_LEVEL' => '-Onone'
26 | }
27 |
28 | if respond_to?(:install_modules_dependencies, true)
29 | install_modules_dependencies(s)
30 | else
31 | s.dependency "React-Core"
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/packages/bcsc-core/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | import { fixupConfigRules } from '@eslint/compat';
2 | import { FlatCompat } from '@eslint/eslintrc';
3 | import js from '@eslint/js';
4 | import { defineConfig } from 'eslint/config';
5 | import path from 'node:path';
6 | import { fileURLToPath } from 'node:url';
7 |
8 | const __filename = fileURLToPath(import.meta.url);
9 | const __dirname = path.dirname(__filename);
10 | const compat = new FlatCompat({
11 | baseDirectory: __dirname,
12 | recommendedConfig: js.configs.recommended,
13 | allConfig: js.configs.all,
14 | });
15 |
16 | export default defineConfig([
17 | {
18 | extends: fixupConfigRules(compat.extends('@react-native', 'prettier')),
19 | rules: {
20 | 'react/react-in-jsx-scope': 'off',
21 | 'prettier/prettier': [
22 | 'error',
23 | {
24 | printWidth: 120,
25 | quoteProps: 'consistent',
26 | singleQuote: true,
27 | tabWidth: 2,
28 | trailingComma: 'es5',
29 | useTabs: false,
30 | },
31 | ],
32 | },
33 | ignores: ['node_modules/', 'lib/'],
34 | },
35 | ]);
36 |
--------------------------------------------------------------------------------
/ios-certificate.md:
--------------------------------------------------------------------------------
1 | # How to Re-Trust Your iOS Signing Certificate
2 |
3 | Occasionally, you may encounter a build issue on iOS that requires you to re-trust your signing certificate. Follow these steps to resolve the issue:
4 |
5 | 1. Open **Xcode**.
6 | 2. Go to the **Signing & Capabilities** tab of your project.
7 | 3. In the iOS section, locate the problematic certificate (it should be marked with an error). Note the certificate’s identifier or number.
8 | 4. Press `Cmd + Spacebar` to open Spotlight Search.
9 | 5. Search for and open **Keychain Access**.
10 | 6. In Keychain Access, select **My Certificates** under the **login** keychain.
11 | 7. Find the certificate matching the identifier or number from step 3.
12 | 8. Double-click the certificate to open its details.
13 | 9. Expand the **Trust** section.
14 | 10. Set **When using this certificate** to **Always Trust**.
15 | 11. Close the certificate details window.
16 | 12. Reopen **Xcode**.
17 | 13. Return to the **Signing & Capabilities** tab and click the **Repair Trust** button if available.
18 |
19 | Your signing certificate should now be trusted and the build issue resolved.
20 |
--------------------------------------------------------------------------------
/app/__tests__/screens/InformationRequiredScreen.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import { BCSCLoadingProvider } from '../../src/bcsc-theme/contexts/BCSCLoadingContext'
7 | import InformationRequiredScreen from '../../src/bcsc-theme/features/verify/send-video/InformationRequiredScreen'
8 |
9 | describe('InformationRequired', () => {
10 | let mockNavigation: any
11 |
12 | beforeEach(() => {
13 | mockNavigation = useNavigation()
14 | jest.clearAllMocks()
15 | jest.useFakeTimers()
16 | })
17 |
18 | afterEach(() => {
19 | jest.useRealTimers()
20 | })
21 |
22 | it('renders correctly', () => {
23 | const tree = render(
24 |
25 |
26 |
27 |
28 |
29 | )
30 |
31 | expect(tree).toMatchSnapshot()
32 | })
33 | })
34 |
--------------------------------------------------------------------------------
/app/__tests__/screens/__snapshots__/MainWebViewScreen.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`MainWebView renders correctly 1`] = `
4 |
40 | `;
41 |
--------------------------------------------------------------------------------
/app/__tests__/bcsc-theme/components/__snapshots__/PairingCodeTextInput.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`PairingCodeTextInput Component Rendering renders correctly 1`] = `
4 |
12 |
43 |
44 | `;
45 |
--------------------------------------------------------------------------------
/app/__tests__/screens/__snapshots__/VerifyWebViewScreen.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`VerifyWebView renders correctly 1`] = `
4 |
40 | `;
41 |
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/main/java/com/bcsccore/bcsc-file-port/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 35
5 |
6 | defaultConfig {
7 | minSdkVersion 23
8 | targetSdkVersion 35
9 | versionCode 1
10 | versionName "1.0"
11 |
12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
13 | }
14 |
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 |
22 | compileOptions {
23 | sourceCompatibility JavaVersion.VERSION_1_8
24 | targetCompatibility JavaVersion.VERSION_1_8
25 | }
26 | }
27 |
28 | dependencies {
29 | implementation 'androidx.appcompat:appcompat:1.6.1'
30 | implementation 'androidx.annotation:annotation:1.7.0'
31 |
32 | testImplementation 'junit:junit:4.13.2'
33 | androidTestImplementation 'androidx.test.ext:junit:1.1.5'
34 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
35 | }
36 |
--------------------------------------------------------------------------------
/app/__tests__/screens/__snapshots__/OnboardingWebViewScreen.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`OnboardingWebView renders correctly 1`] = `
4 |
40 | `;
41 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/hooks/useBCSCApiClient.tsx:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 | import BCSCApiClient from '../api/client'
3 | import { BCSCApiClientContext } from '../contexts/BCSCApiClientContext'
4 |
5 | // Hook to be used for API calls, will throw if not configured properly
6 | export const useBCSCApiClient = (): BCSCApiClient => {
7 | const context = useContext(BCSCApiClientContext)
8 |
9 | if (!context) {
10 | throw new Error('useBCSCApiClient must be used within a BCSCApiClientProvider')
11 | }
12 |
13 | if (context.error) {
14 | throw new Error(`BCSC client error: ${context.error}`)
15 | }
16 |
17 | if (!context.client || !context.isClientReady) {
18 | throw new Error('BCSC client not ready. Make sure BCSCApiClientProvider is properly configured.')
19 | }
20 |
21 | return context.client
22 | }
23 |
24 | // Hook that doesn't throw, useful for checking readiness state
25 | export const useBCSCApiClientState = () => {
26 | const context = useContext(BCSCApiClientContext)
27 |
28 | if (!context) {
29 | throw new Error('useBCSCClientState must be used within a BCSCApiClientProvider')
30 | }
31 |
32 | return context
33 | }
34 |
--------------------------------------------------------------------------------
/packages/bcsc-core/android/src/main/java/com/bcsccore/bcsc-keypair-port/build.gradle.template:
--------------------------------------------------------------------------------
1 | // Build.gradle template for using the BC Services Card KeyPair functionality
2 | // Add these dependencies to your app's build.gradle file
3 |
4 | android {
5 | compileSdkVersion 34
6 |
7 | defaultConfig {
8 | minSdkVersion 23 // Required for Android KeyStore features
9 | targetSdkVersion 34
10 | }
11 |
12 | compileOptions {
13 | sourceCompatibility JavaVersion.VERSION_1_8
14 | targetCompatibility JavaVersion.VERSION_1_8
15 | }
16 | }
17 |
18 | dependencies {
19 | // Required: Nimbus JOSE library for JWT operations
20 | implementation 'com.nimbusds:nimbus-jose-jwt:9.37.3'
21 |
22 | // Required: Android annotations
23 | implementation 'androidx.annotation:annotation:1.7.0'
24 |
25 | // Required: Gson for JSON serialization (used by SimpleKeyPairInfoSource)
26 | implementation 'com.google.code.gson:gson:2.10.1'
27 |
28 | // Optional: If you want to use more advanced storage instead of SharedPreferences
29 | // implementation 'androidx.security:security-crypto:1.1.0-alpha06'
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/services/components/ServiceButton.tsx:
--------------------------------------------------------------------------------
1 | import { ThemedText, useTheme } from '@bifold/core'
2 | import React from 'react'
3 | import { StyleSheet, TouchableOpacity } from 'react-native'
4 |
5 | interface ServiceButtonProps {
6 | title: string
7 | description?: string
8 | onPress: () => void
9 | }
10 |
11 | const ServiceButton: React.FC = ({ title, description, onPress }) => {
12 | const { ColorPalette, Spacing } = useTheme()
13 |
14 | const styles = StyleSheet.create({
15 | container: {
16 | padding: Spacing.md,
17 | backgroundColor: ColorPalette.brand.secondaryBackground,
18 | },
19 | title: {
20 | marginBottom: Spacing.sm,
21 | color: ColorPalette.brand.primary,
22 | },
23 | })
24 |
25 | return (
26 |
27 |
28 | {title}
29 |
30 | {description ? {description} : null}
31 |
32 | )
33 | }
34 |
35 | export default ServiceButton
36 |
--------------------------------------------------------------------------------
/app/__tests__/screens/PersonCredential.test.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react-native'
2 | import React from 'react'
3 |
4 | import { useNavigation } from '../../__mocks__/custom/@react-navigation/core'
5 | import { BasicAppContext } from '../../__mocks__/helpers/app'
6 | import PersonCredential from '../../src/bcwallet-theme/features/person-flow/screens/PersonCredential'
7 |
8 | describe('Person Credential Screen', () => {
9 | beforeEach(() => {
10 | // Silence console.error because it will print a warning about Switch
11 | // "Warning: dispatchCommand was called with a ref ...".
12 | jest.spyOn(console, 'error').mockImplementation(() => {
13 | return null
14 | })
15 | jest.useFakeTimers()
16 | })
17 |
18 | afterEach(() => {
19 | jest.clearAllMocks()
20 | jest.useRealTimers()
21 | })
22 |
23 | test('screen renders correctly', () => {
24 | const navigation = useNavigation()
25 | const tree = render(
26 |
27 |
28 |
29 | )
30 |
31 | expect(tree).toMatchSnapshot()
32 | })
33 | })
34 |
--------------------------------------------------------------------------------
/app/ios/AriesBifold/main.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char *argv[])
6 | {
7 | struct rlimit rlim;
8 | unsigned long long NEW_SOFT_LIMIT = 1024;
9 |
10 | //Fetch existing file limits, adjust file limits if possible
11 | if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
12 | NSLog(@"Current soft RLimit: %llu", rlim.rlim_cur);
13 | NSLog(@"Current hard RLimit: %llu", rlim.rlim_max);
14 |
15 | // Adjust only if the limit is less than NEW_SOFT_LIMIT
16 | if(rlim.rlim_cur < NEW_SOFT_LIMIT){
17 | rlim.rlim_cur = NEW_SOFT_LIMIT;
18 | }
19 |
20 | if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
21 | NSLog(@"Can't set RLimits");
22 | }
23 | } else {
24 | NSLog(@"Can't fetch RLimits");
25 | }
26 |
27 | // Re-fetch file limits
28 | if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
29 | NSLog(@"New soft RLimit: %llu", rlim.rlim_cur);
30 | NSLog(@"New hard RLimit: %llu", rlim.rlim_max);
31 | } else {
32 | NSLog(@"Can't fetch RLimits");
33 | }
34 |
35 | @autoreleasepool {
36 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/app/android/app/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "1008044298583",
4 | "project_id": "bc-wallet-mobile",
5 | "storage_bucket": "bc-wallet-mobile.appspot.com"
6 | },
7 | "client": [
8 | {
9 | "client_info": {
10 | "mobilesdk_app_id": "1:1008044298583:android:56bf7c25b882152a44ae12",
11 | "android_client_info": {
12 | "package_name": "ca.bc.gov.BCWallet"
13 | }
14 | },
15 | "oauth_client": [
16 | {
17 | "client_id": "1008044298583-12lpkisi403oa5bc5hs0800o48cl4nhj.apps.googleusercontent.com",
18 | "client_type": 3
19 | }
20 | ],
21 | "api_key": [
22 | {
23 | "current_key": "AIzaSyB9TMILh7AQmEGCdwvvmDeN-WG4G345p9I"
24 | }
25 | ],
26 | "services": {
27 | "appinvite_service": {
28 | "other_platform_oauth_client": [
29 | {
30 | "client_id": "1008044298583-12lpkisi403oa5bc5hs0800o48cl4nhj.apps.googleusercontent.com",
31 | "client_type": 3
32 | }
33 | ]
34 | }
35 | }
36 | }
37 | ],
38 | "configuration_version": "1"
39 | }
--------------------------------------------------------------------------------
/app/__tests__/bcsc-theme/components/LoadingScreenContent.test.tsx:
--------------------------------------------------------------------------------
1 | import { LoadingScreenContent } from '@/bcsc-theme/features/splash-loading/LoadingScreenContent'
2 | import { render } from '@testing-library/react-native'
3 |
4 | describe('LoadingScreenContent Component', () => {
5 | it('renders message', () => {
6 | const tree = render()
7 |
8 | expect(tree.getByText('TEST_LOADINGSCREENCONTENT')).toBeTruthy()
9 | })
10 |
11 | it('runs onLoaded callback when loading is false', () => {
12 | const onLoadedMock = jest.fn()
13 |
14 | render()
15 |
16 | expect(onLoadedMock).toHaveBeenCalledTimes(1)
17 | })
18 |
19 | it('does not run onLoaded callback when loading is true', () => {
20 | const onLoadedMock = jest.fn()
21 |
22 | const { rerender } = render()
23 |
24 | expect(onLoadedMock).not.toHaveBeenCalled()
25 |
26 | rerender()
27 |
28 | expect(onLoadedMock).toHaveBeenCalledTimes(1)
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/app/src/bcsc-theme/features/home/components/HomeHeader.tsx:
--------------------------------------------------------------------------------
1 | import GenericCardImage from '@/bcsc-theme/components/GenericCardImage'
2 | import { ThemedText, useTheme } from '@bifold/core'
3 | import React from 'react'
4 | import { StyleSheet, View } from 'react-native'
5 |
6 | interface HomeHeaderProps {
7 | name: string
8 | fontSize?: number
9 | cardSize?: {
10 | height: number
11 | width: number
12 | }
13 | }
14 |
15 | const HomeHeader: React.FC = ({ name, cardSize, fontSize }) => {
16 | const { Spacing } = useTheme()
17 |
18 | const styles = StyleSheet.create({
19 | container: {
20 | padding: Spacing.md,
21 | },
22 | idContainer: {
23 | justifyContent: 'center',
24 | alignItems: 'center',
25 | },
26 | })
27 |
28 | return (
29 |
30 |
31 |
32 |
33 | {name}
34 |
35 |
36 |
37 | )
38 | }
39 |
40 | export default HomeHeader
41 |
--------------------------------------------------------------------------------
/app/src/screens/WebDisplay.tsx:
--------------------------------------------------------------------------------
1 | import { SafeAreaModal } from '@bifold/core'
2 | import React from 'react'
3 | import { StyleSheet } from 'react-native'
4 | import { WebView, WebViewNavigation } from 'react-native-webview'
5 |
6 | interface WebDisplayProps {
7 | destinationUrl: string
8 | visible: boolean
9 | onClose: () => void
10 | exitUrl: string
11 | }
12 |
13 | const WebDisplay = ({ destinationUrl, exitUrl, visible, onClose }: WebDisplayProps) => {
14 | const styles = StyleSheet.create({
15 | container: {
16 | flex: 1,
17 | justifyContent: 'center',
18 | alignItems: 'center',
19 | marginTop: 32,
20 | },
21 | })
22 |
23 | return (
24 |
25 | {
31 | if (exitUrl && nav.url.includes(exitUrl)) {
32 | onClose()
33 | }
34 | }}
35 | />
36 |
37 | )
38 | }
39 |
40 | export default WebDisplay
41 |
--------------------------------------------------------------------------------
/app/__mocks__/custom/react-native-localize.ts:
--------------------------------------------------------------------------------
1 | const getLocales = () => [
2 | { countryCode: 'US', languageTag: 'en-US', languageCode: 'en', isRTL: false },
3 | { countryCode: 'NL', languageTag: 'nl-NL', languageCode: 'nl', isRTL: false },
4 | { countryCode: 'FR', languageTag: 'fr-FR', languageCode: 'fr', isRTL: false },
5 | ]
6 |
7 | const getNumberFormatSettings = () => ({
8 | decimalSeparator: '.',
9 | groupingSeparator: ',',
10 | })
11 |
12 | const getCalendar = () => 'gregorian' // or "japanese", "buddhist"
13 | const getCountry = () => 'US' // the country code you want
14 | const getCurrencies = () => ['USD'] // can be empty array
15 | const getTemperatureUnit = () => 'celsius' // or "fahrenheit"
16 | const getTimeZone = () => 'America/Los_Angeles' // the timezone you want
17 | const uses24HourClock = () => true
18 | const usesMetricSystem = () => true
19 |
20 | const addEventListener = jest.fn()
21 | const removeEventListener = jest.fn()
22 |
23 | export {
24 | addEventListener,
25 | getCalendar,
26 | getCountry,
27 | getCurrencies,
28 | getLocales,
29 | getNumberFormatSettings,
30 | getTemperatureUnit,
31 | getTimeZone,
32 | removeEventListener,
33 | uses24HourClock,
34 | usesMetricSystem,
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/components/LoadingIcon.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useRef } from 'react'
2 | import { Animated } from 'react-native'
3 | import Icon from 'react-native-vector-icons/MaterialIcons'
4 |
5 | interface LoadingIconProps {
6 | size: number
7 | color: string
8 | active: boolean
9 | }
10 |
11 | const timing: Animated.TimingAnimationConfig = {
12 | toValue: 1,
13 | duration: 2000,
14 | useNativeDriver: true,
15 | }
16 |
17 | export default function LoadingIcon({ size, color, active }: Readonly) {
18 | const rotationAnim = useRef(new Animated.Value(0))
19 | const rotation = rotationAnim.current.interpolate({
20 | inputRange: [0, 1],
21 | outputRange: ['0deg', '360deg'],
22 | })
23 |
24 | const animation = Animated.loop(Animated.timing(rotationAnim.current, timing))
25 |
26 | useEffect(() => {
27 | animation.reset()
28 | if (active) {
29 | animation.start()
30 | } else {
31 | animation.stop()
32 | }
33 | }, [animation, active])
34 |
35 | return (
36 | <>
37 |
38 |
39 |
40 | >
41 | )
42 | }
43 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Merge artifacts
6 | *.orig
7 | build/
8 | xbuild/
9 |
10 | # Secrets
11 | *.mobileprovision
12 | *.p12
13 | *.p8
14 | pc-api*.json
15 | api*.json
16 | *secret*
17 | *secrets*
18 | .env
19 | .idea/
20 |
21 | # Other
22 | node_modules
23 | .gradle
24 | lib
25 | local.properties
26 | .jest
27 | .npmrc
28 |
29 | # yarn
30 | .yarn/*
31 | .yarn/cache
32 | !.yarn/patches
33 | !.yarn/plugins
34 | !.yarn/releases
35 | !.yarn/sdks
36 | !.yarn/versions
37 | app/.yarn/*
38 | app/.yarn/cache
39 | !app/.yarn/patches
40 | !app/.yarn/plugins
41 | !app/.yarn/releases
42 | !app/.yarn/sdks
43 | !app/.yarn/versions
44 | yarn-debug.log*
45 | yarn-error.log*
46 | .yarn-integrity
47 |
48 | # aries-bifold should be cloned separately
49 | aries-bifold/
50 | *.code-workspace
51 |
52 | # 3rd-party
53 | app/ios/Pods/*
54 | !app/ios/Pods/Frameworks
55 |
56 | # This patch must be dynamically generated by something
57 | # so its excluded.
58 | app/patches/react-native-gifted-chat*.patch
59 |
60 | # xcode
61 | xcuserdata/
62 | .xcode.env.local
63 |
64 | # gem
65 | app/vendor/bundle/**
66 |
67 | # child packages
68 | bifold/
69 | aries-oca-bundles/
70 | credo-ts/
71 | app/vendor/
72 |
73 | .metro-cache/
74 |
75 | coverage/
76 |
--------------------------------------------------------------------------------
/app/src/hooks/useEventListener.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react'
2 |
3 | type RemoveListenerCallback = () => void
4 |
5 | /**
6 | * Hook to manage attaching and detaching to event listeners.
7 | *
8 | * Note: The eventListener function should return a function that removes the event listener when called.
9 | * This is to prevent memory leaks by ensuring that all event listners are properly cleaned up on component unmount.
10 | *
11 | * @param {() => RemoveListenerCallback} eventListener - Function that attaches the event listener and returns a function to remove it.
12 | * @param {boolean} [canAttach=true] - Flag to determine if the event listener should be attached.
13 | * @returns {*} {void}
14 | */
15 | export const useEventListener = (eventListener: () => RemoveListenerCallback, canAttach = true) => {
16 | // This prevents re-creating the event listener on every render
17 | const eventListenerRef = useRef(eventListener)
18 |
19 | useEffect(() => {
20 | if (!canAttach) {
21 | return
22 | }
23 |
24 | const removeListener = eventListenerRef.current()
25 |
26 | // Cleanup function to remove the event listener on unmount
27 | return removeListener
28 | }, [canAttach]) // only re-run if canAttach changes
29 | }
30 |
--------------------------------------------------------------------------------
/devops/charts/loki-logstack/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v2
2 | name: logstack
3 | description: A Helm chart for Kubernetes
4 |
5 | # A chart can be either an 'application' or a 'library' chart.
6 | #
7 | # Application charts are a collection of templates that can be packaged into versioned archives
8 | # to be deployed.
9 | #
10 | # Library charts provide useful utilities or functions for the chart developer. They're included as
11 | # a dependency of application charts to inject those utilities and functions into the rendering
12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed.
13 | type: application
14 |
15 | # This is the chart version. This version number should be incremented each time you make changes
16 | # to the chart and its templates, including the app version.
17 | # Versions are expected to follow Semantic Versioning (https://semver.org/)
18 | version: 0.0.1
19 |
20 | # This is the version number of the application being deployed. This version number should be
21 | # incremented each time you make changes to the application. Versions are not expected to
22 | # follow Semantic Versioning. They should reflect the version the application is using.
23 | # It is recommended to use it with quotes.
24 | appVersion: "0.0.1"
25 |
--------------------------------------------------------------------------------
/.github/workflows/actions/send-rocketchat-notification/action.yml:
--------------------------------------------------------------------------------
1 | # Makes use of https://github.com/RocketChat/Rocket.Chat.GitHub.Action.Notification
2 | name: Rocketchat Notification
3 | description: Send a rocketchat notification
4 | author: "bryce.j.mcmath@gmail.com"
5 |
6 | inputs:
7 | job_title:
8 | description: The title of the notification
9 | required: true
10 | job_status:
11 | description: The status of the job
12 | required: true
13 | webhook_url:
14 | description: |
15 | The RocketChat Webhook URL as copied from Rocket.Chat.
16 | required: true
17 | github_token:
18 | description: |
19 | The GitHub access token for the action so it can fetch
20 | information from the GitHub API.
21 | required: false
22 |
23 | runs:
24 | using: composite
25 | steps:
26 | - name: Notification
27 | uses: RocketChat/Rocket.Chat.GitHub.Action.Notification@master
28 | with:
29 | type: ${{ inputs.job_status }}
30 | job_name: ${{ inputs.job_title }}
31 | mention: "jason.leach @cvarjao @wade.king @bryce.mcmath"
32 | mention_if: always
33 | channel: "#ditp-digital-wallet-core-team"
34 | commit: true
35 | url: ${{ inputs.webhook_url }}
36 | token: ${{ inputs.github_token }}
37 |
--------------------------------------------------------------------------------
/app/__tests__/components/NavigationContainerContext.test.tsx:
--------------------------------------------------------------------------------
1 | import { NavigationContainerContext, NavigationContainerProvider } from '@/contexts/NavigationContainerContext'
2 | import { renderHook } from '@testing-library/react-native'
3 | import { useContext } from 'react'
4 |
5 | jest.mock('@react-navigation/native', () => ({
6 | NavigationContainer: ({ children }: any) => <>{children}>,
7 | createNavigationContainerRef: jest.fn(() => ({
8 | current: {
9 | getCurrentRoute: jest.fn(() => ({ name: undefined })),
10 | },
11 | })),
12 | }))
13 |
14 | jest.mock('@bifold/core', () => ({
15 | useTheme: jest.fn(() => ({
16 | NavigationTheme: {},
17 | })),
18 | }))
19 |
20 | jest.mock('@/utils/analytics/analytics-singleton', () => ({
21 | Analytics: {
22 | trackScreenEvent: jest.fn(),
23 | },
24 | }))
25 |
26 | describe('NavigationContainerContext', () => {
27 | it('should have isNavigationReady as false by default', () => {
28 | const wrapper = ({ children }: { children: React.ReactNode }) => {
29 | return {children}
30 | }
31 |
32 | const { result } = renderHook(() => useContext(NavigationContainerContext), { wrapper })
33 |
34 | expect(result.current?.isNavigationReady).toBe(false)
35 | })
36 | })
37 |
--------------------------------------------------------------------------------
/app/src/services/version.ts:
--------------------------------------------------------------------------------
1 | import { BifoldLogger, IVersionCheckService, VersionInfo } from '@bifold/core'
2 | import { checkVersion } from 'react-native-check-version'
3 |
4 | export class VersionCheckService implements IVersionCheckService {
5 | private _cachedVersionInfo: VersionInfo | undefined
6 |
7 | constructor(private readonly log: BifoldLogger) {
8 | // Logger is now injected
9 | }
10 |
11 | get lastChecked(): Date | undefined {
12 | return this._cachedVersionInfo?.lastChecked
13 | }
14 |
15 | async checkForUpdate(forceCheck: boolean = false): Promise {
16 | if (forceCheck || !this._cachedVersionInfo) {
17 | try {
18 | const version = await checkVersion()
19 | const now = new Date()
20 |
21 | const versionInfo: VersionInfo = {
22 | version: version.version,
23 | needsUpdate: version.needsUpdate,
24 | lastChecked: now,
25 | }
26 |
27 | this._cachedVersionInfo = versionInfo
28 |
29 | this.log.info('Checked for updates:', { ...version })
30 | return versionInfo
31 | } catch (error) {
32 | this.log.error('Failed to check for updates:', error as Error)
33 | return undefined
34 | }
35 | }
36 |
37 | return this._cachedVersionInfo
38 | }
39 | }
40 |
--------------------------------------------------------------------------------