Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/mobile-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ jobs:
- name: Build dependencies (outside emulator)
run: |
echo "Building dependencies..."
yarn workspace @selfxyz/mobile-app run build:deps --silent || { echo "❌ Dependency build failed"; exit 1; }
yarn workspace @selfxyz/mobile-app run build:deps || { echo "❌ Dependency build failed"; exit 1; }
echo "✅ Dependencies built successfully"
- name: Build Android APK
run: |
Expand Down Expand Up @@ -224,7 +224,7 @@ jobs:
- name: Build dependencies (outside main flow)
run: |
echo "Building dependencies..."
yarn workspace @selfxyz/mobile-app run build:deps --silent || { echo "❌ Dependency build failed"; exit 1; }
yarn workspace @selfxyz/mobile-app run build:deps || { echo "❌ Dependency build failed"; exit 1; }
echo "✅ Dependencies built successfully"
- name: Install iOS dependencies
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/mobile-sdk-demo-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
shell: bash
run: |
# Build demo-app and all its transitive workspace deps in the correct order
yarn workspaces foreach -At --from demo-app run build
yarn workspaces foreach -R -t --from demo-app run build
- name: Run demo app tests
run: |
yarn workspace demo-app test
Expand Down
1 change: 1 addition & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
nodeLinker: node-modules
nmHoistingLimits: workspaces
2 changes: 2 additions & 0 deletions app/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ declare module '*.svg' {
const content: React.FC<SvgProps>;
export default content;
}

declare module 'react-native-svg-circle-country-flags';
2 changes: 1 addition & 1 deletion app/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ target "Self" do
pod "lottie-ios"
pod "SwiftQRScanner", :git => "https://github.com/vinodiOS/SwiftQRScanner"
pod "Mixpanel-swift", "~> 5.0.0"
pod "RNReactNativeHapticFeedback", :path => "../../node_modules/react-native-haptic-feedback", :modular_headers => true
pod "RNReactNativeHapticFeedback", :path => "../node_modules/react-native-haptic-feedback", :modular_headers => true

use_react_native!(
:path => config[:reactNativePath],
Expand Down
354 changes: 177 additions & 177 deletions app/ios/Podfile.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions app/ios/Self.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
USE_HERMES = true;
Expand Down Expand Up @@ -882,7 +882,7 @@
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
USE_HERMES = true;
Expand Down
252 changes: 65 additions & 187 deletions app/metro.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,216 +4,94 @@

const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const path = require('node:path');
const findYarnWorkspaceRoot = require('find-yarn-workspace-root');

const defaultConfig = getDefaultConfig(__dirname);
const { assetExts, sourceExts } = defaultConfig.resolver;

const monorepoRoot = path.resolve(__dirname, '../');
const commonPath = path.join(__dirname, '/../common');
const sdkAlphaPath = path.join(__dirname, '/../packages/mobile-sdk-alpha');
const trueMonorepoNodeModules = path.resolve(__dirname, '../node_modules');
const extraNodeModules = {
stream: require.resolve('stream-browserify'),
buffer: require.resolve('buffer'),
util: require.resolve('util'),
assert: require.resolve('assert'),
'@babel/runtime': path.join(trueMonorepoNodeModules, '@babel/runtime'),
// Pin React and React Native to monorepo root
react: path.join(trueMonorepoNodeModules, 'react'),
'react-native': path.join(trueMonorepoNodeModules, 'react-native'),
'@': path.join(__dirname, 'src'),
'@selfxyz/common': path.resolve(commonPath, 'dist'),
'@selfxyz/mobile-sdk-alpha': path.resolve(sdkAlphaPath, 'dist'),
'@selfxyz/mobile-sdk-alpha/constants/analytics': path.resolve(
sdkAlphaPath,
'dist/esm/constants/analytics.js',
),
// Main exports
'@selfxyz/common/utils': path.resolve(
commonPath,
'dist/esm/src/utils/index.js',
),
'@selfxyz/common/types': path.resolve(
commonPath,
'dist/esm/src/types/index.js',
),
'@selfxyz/common/constants': path.resolve(
commonPath,
'dist/esm/src/constants/index.js',
),
// Constants subpaths
'@selfxyz/common/constants/countries': path.resolve(
commonPath,
'dist/esm/src/constants/countries.js',
),
'@selfxyz/common/constants/vkey': path.resolve(
commonPath,
'dist/esm/src/constants/vkey.js',
),
'@selfxyz/common/constants/skiPem': path.resolve(
commonPath,
'dist/esm/src/constants/skiPem.js',
),
'@selfxyz/common/constants/mockCerts': path.resolve(
commonPath,
'dist/esm/src/constants/mockCertificates.js',
),
'@selfxyz/common/constants/hashes': path.resolve(
commonPath,
'dist/esm/src/constants/sampleDataHashes.js',
),
// Utils subpaths
'@selfxyz/common/utils/hash': path.resolve(
commonPath,
'dist/esm/src/utils/hash.js',
),
'@selfxyz/common/utils/attest': path.resolve(
commonPath,
'dist/esm/src/utils/attest.js',
),
'@selfxyz/common/utils/bytes': path.resolve(
commonPath,
'dist/esm/src/utils/bytes.js',
),
'@selfxyz/common/utils/trees': path.resolve(
commonPath,
'dist/esm/src/utils/trees.js',
),
'@selfxyz/common/utils/scope': path.resolve(
commonPath,
'dist/esm/src/utils/scope.js',
),
'@selfxyz/common/utils/proving': path.resolve(
commonPath,
'dist/esm/src/utils/proving.js',
),
'@selfxyz/common/utils/appType': path.resolve(
commonPath,
'dist/esm/src/utils/appType.js',
),
'@selfxyz/common/utils/date': path.resolve(
commonPath,
'dist/esm/src/utils/date.js',
),
'@selfxyz/common/utils/arrays': path.resolve(
commonPath,
'dist/esm/src/utils/arrays.js',
),
'@selfxyz/common/utils/passports': path.resolve(
commonPath,
'dist/esm/src/utils/passports/index.js',
),
'@selfxyz/common/utils/passportFormat': path.resolve(
commonPath,
'dist/esm/src/utils/passports/format.js',
),
'@selfxyz/common/utils/passports/validate': path.resolve(
commonPath,
'dist/esm/src/utils/passports/validate.js',
),
'@selfxyz/common/utils/passportMock': path.resolve(
commonPath,
'dist/esm/src/utils/passports/mock.js',
),
'@selfxyz/common/utils/passportDg1': path.resolve(
commonPath,
'dist/esm/src/utils/passports/dg1.js',
),
'@selfxyz/common/utils/certificates': path.resolve(
commonPath,
'dist/esm/src/utils/certificate_parsing/index.js',
),
'@selfxyz/common/utils/elliptic': path.resolve(
commonPath,
'dist/esm/src/utils/certificate_parsing/elliptic.js',
),
'@selfxyz/common/utils/curves': path.resolve(
commonPath,
'dist/esm/src/utils/certificate_parsing/curves.js',
),
'@selfxyz/common/utils/oids': path.resolve(
commonPath,
'dist/esm/src/utils/certificate_parsing/oids.js',
),
'@selfxyz/common/utils/circuits': path.resolve(
commonPath,
'dist/esm/src/utils/circuits/index.js',
),
'@selfxyz/common/utils/circuitNames': path.resolve(
commonPath,
'dist/esm/src/utils/circuits/circuitsName.js',
),
'@selfxyz/common/utils/circuitFormat': path.resolve(
commonPath,
'dist/esm/src/utils/circuits/formatOutputs.js',
),
'@selfxyz/common/utils/uuid': path.resolve(
commonPath,
'dist/esm/src/utils/circuits/uuid.js',
),
'@selfxyz/common/utils/contracts': path.resolve(
commonPath,
'dist/esm/src/utils/contracts/index.js',
),
'@selfxyz/common/utils/sanctions': path.resolve(
commonPath,
'dist/esm/src/utils/contracts/forbiddenCountries.js',
),
'@selfxyz/common/utils/csca': path.resolve(
commonPath,
'dist/esm/src/utils/csca.js',
),
// Types subpaths
'@selfxyz/common/types/passport': path.resolve(
commonPath,
'dist/esm/src/types/passport.js',
),
'@selfxyz/common/types/app': path.resolve(
commonPath,
'dist/esm/src/types/app.js',
),
'@selfxyz/common/types/certificates': path.resolve(
commonPath,
'dist/esm/src/types/certificates.js',
),
'@selfxyz/common/types/circuits': path.resolve(
commonPath,
'dist/esm/src/types/circuits.js',
),
};
const watchFolders = [
path.resolve(commonPath),
trueMonorepoNodeModules,
path.join(__dirname, 'src'),
path.resolve(sdkAlphaPath),
];
const projectRoot = __dirname;
const workspaceRoot =
findYarnWorkspaceRoot(__dirname) || path.resolve(__dirname, '..');

/**
* Metro configuration
* https://facebook.github.io/metro/docs/configuration
* Modern Metro configuration using native workspace capabilities
* Eliminates need for manual symlink management through:
* - enableGlobalPackages: Automatic workspace package discovery
* - unstable_enablePackageExports: Native subpath import support
* - unstable_enableSymlinks: Optional symlink resolution
*
* @type {import('metro-config').MetroConfig}
*/
const config = {
projectRoot,

watchFolders: [
workspaceRoot, // Watch entire workspace root for changes
path.resolve(workspaceRoot, 'common'),
path.resolve(workspaceRoot, 'packages/mobile-sdk-alpha'),
],

transformer: {
babelTransformerPath: require.resolve(
'react-native-svg-transformer/react-native',
),
disableImportExportTransform: true,
inlineRequires: true,
},

resolver: {
extraNodeModules,
// Prevent Haste module naming collisions from duplicate package.json files
blockList: [
// Ignore built package.json files to prevent Haste collisions
/.*\/dist\/package\.json$/,
/.*\/build\/package\.json$/,
],
// Enable automatic workspace package resolution
enableGlobalPackages: true,

// Handle subpath exports (@selfxyz/common/constants)
unstable_enablePackageExports: true,

// Enable native symlink support (optional, for compatibility)
unstable_enableSymlinks: true,

// Define search order for node modules
nodeModulesPaths: [
path.resolve(__dirname, 'node_modules'), // App's own node_modules
path.resolve(monorepoRoot, 'node_modules'), // Monorepo root node_modules
trueMonorepoNodeModules,
// Add paths to other package workspaces if needed
path.resolve(projectRoot, 'node_modules'), // App's own node_modules
path.resolve(workspaceRoot, 'node_modules'), // Workspace root node_modules
],

// Essential polyfills for React Native
extraNodeModules: {
stream: require.resolve('stream-browserify'),
buffer: require.resolve('buffer'),
util: require.resolve('util'),
assert: require.resolve('assert'),
// App-specific alias
'@': path.join(__dirname, 'src'),
},

// Support package exports with conditions
unstable_conditionNames: ['require', 'react-native'],

// SVG support
assetExts: assetExts.filter(ext => ext !== 'svg'),
sourceExts: [...sourceExts, 'svg'],

// Custom resolver to handle .js imports in TypeScript source files
resolveRequest: (context, moduleName, platform) => {
// For relative imports in common source files that end with .js
if (
context.originModulePath?.includes('/common/src/') &&
moduleName.endsWith('.js')
) {
const tsModuleName = moduleName.replace(/\.js$/, '.ts');
return context.resolveRequest(context, tsModuleName, platform);
}
// Default resolution
return context.resolveRequest(context, moduleName, platform);
},
},
watchFolders,
};

module.exports = mergeConfig(defaultConfig, config);
9 changes: 8 additions & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"clean": "yarn clean:watchman && yarn clean:build && yarn clean:ios && yarn clean:android && yarn clean:xcode && yarn clean:pod-cache && yarn clean:node",
"clean:android": "rm -rf android/app/build android/build",
"clean:build": "rm -rf ios/build android/app/build android/build",
"clean:ios": "rm -rf ios/Pods ios/Podfile.lock Gemfile.lock",
"clean:ios": "rm -rf ios/Pods Gemfile.lock",
"clean:node": "rm -rf ../node_modules app/node_modules",
"clean:pod-cache": "cd ios && pod cache clean --all && cd ..",
"clean:watchman": "watchman watch-del-all",
Expand Down Expand Up @@ -72,8 +72,10 @@
"@babel/runtime": "^7.28.3",
"@ethersproject/shims": "^5.7.0",
"@noble/hashes": "^1.5.0",
"@openpassport/zk-kit-imt": "^0.0.5",
"@openpassport/zk-kit-lean-imt": "^0.0.6",
"@openpassport/zk-kit-smt": "^0.0.1",
"@peculiar/x509": "^1.13.0",
"@react-native-async-storage/async-storage": "^2.2.0",
"@react-native-clipboard/clipboard": "1.16.3",
"@react-native-community/netinfo": "^11.4.1",
Expand All @@ -89,6 +91,7 @@
"@selfxyz/mobile-sdk-alpha": "workspace:^",
"@sentry/react": "^9.32.0",
"@sentry/react-native": "7.0.0-beta.1",
"@stablelib/cbor": "^2.0.1",
"@tamagui/animations-css": "^1.129.3",
"@tamagui/animations-react-native": "^1.129.3",
"@tamagui/config": "1.126.14",
Expand All @@ -103,6 +106,10 @@
"elliptic": "^6.6.1",
"ethers": "^6.11.0",
"expo-modules-core": "^2.2.1",
"hash.js": "^1.1.7",
"i18n-iso-countries": "^7.14.0",
"js-sha1": "^0.7.0",
"js-sha256": "^0.11.1",
"js-sha512": "^0.9.0",
"lottie-react": "^2.4.1",
"lottie-react-native": "7.2.2",
Expand Down
4 changes: 2 additions & 2 deletions app/scripts/bundle-analyze-ci.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ if (!platform || !['android', 'ios'].includes(platform)) {

// Bundle size thresholds in MB - easy to update!
const BUNDLE_THRESHOLDS_MB = {
ios: 36,
android: 36,
ios: 38,
android: 38,
};

function formatBytes(bytes) {
Expand Down
Loading
Loading