Skip to content

Commit 874b426

Browse files
authored
Feat/retrieve OFAC trees from api (#769)
* retrieve the ofac trees from the api * remove the ofac trees from the common repo * fix ofac test * yarn nice * yarn nice * yarn nice * refactor ofac fetching
1 parent aee72be commit 874b426

31 files changed

+370
-99625
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ showcase
99
**/.yarn/
1010
output/*
1111
*.tsbuildinfo
12+
.yarnrc.yml

app/ios/Podfile.lock

Lines changed: 64 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,7 +2171,7 @@ SPEC CHECKSUMS:
21712171
GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
21722172
GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15
21732173
lottie-ios: a881093fab623c467d3bce374367755c272bdd59
2174-
lottie-react-native: 3ffec00c889acded6057766c99adf8eaced7790c
2174+
lottie-react-native: db03203d873afcbb6e0cea6a262a88d95e64a98f
21752175
Mixpanel-swift: e9bef28a9648faff384d5ba6f48ecc2787eb24c0
21762176
nanopb: 438bc412db1928dac798aa6fd75726007be04262
21772177
NFCPassportReader: 48873f856f91215dbfa1eaaec20eae639672862e
@@ -2185,81 +2185,81 @@ SPEC CHECKSUMS:
21852185
RCTTypeSafety: 28e24a6e44f5cbf912c66dde6ab7e07d1059a205
21862186
React: c2830fa483b0334bda284e46a8579ebbe0c5447e
21872187
React-callinvoker: 4aecde929540c26b841a4493f70ebf6016691eb8
2188-
React-Core: 65374ea054f3f00eaa3c8bb5e989cb1ba8128844
2189-
React-CoreModules: f53e0674e1747fa41c83bc970e82add97b14ad87
2190-
React-cxxreact: bb77e88b645c5378ecd0c30c94f965a8294001d8
2188+
React-Core: 1e3c04337857fa7fb7559f73f6f29a2a83a84b9c
2189+
React-CoreModules: 9fac2d31803c0ed03e4ddaa17f1481714f8633a5
2190+
React-cxxreact: c72a7a8066fc4323ea85a3137de50c8a10a69794
21912191
React-debug: 7e346b6eeacd2ee1118a0ee7d39f613b428b4be8
2192-
React-defaultsnativemodule: 4f1e9236c048fce31ebaf2c9c59ad7e76fb971a1
2193-
React-domnativemodule: 0d0e04cd8a68f3984b7b15aada7ff531dfc3c3bd
2194-
React-Fabric: fa636eabfe3c8a3af3a9bface586956e90619ebf
2195-
React-FabricComponents: 52382f668a934df9cef21a7893beffbe0e2b2f5e
2196-
React-FabricImage: 69b745c0231d9360180f5e411370c6fb0c3cb546
2192+
React-defaultsnativemodule: e40e760aa97a7183d5f5a8174e44026673c4b995
2193+
React-domnativemodule: 9fef73afd600e7c7d7f540d82532a113830bbdda
2194+
React-Fabric: dcd7ec3ea4da022b6c3f025e2567c9860ff1f760
2195+
React-FabricComponents: 7e67af984cab1d6d1c02aae4a62933abc1baa5d3
2196+
React-FabricImage: 77ca01a0a2bca3e1d39967220d7af7e3de033c9f
21972197
React-featureflags: 4c45b3c06f9a124d2598aff495bfc59470f40597
2198-
React-featureflagsnativemodule: 110c225191b3bca92694d36303385c2c299c12e5
2199-
React-graphics: eb61d404819486a2d9335c043a967a0c4b8ca743
2200-
React-idlecallbacksnativemodule: ca6930a17eaae01591610c87b19dbd90515f54a1
2201-
React-ImageManager: 6652c4cc3de260b5269d58277de383cacd53a234
2198+
React-featureflagsnativemodule: d37e4fe27bd4f541d6d46f05e899345018067314
2199+
React-graphics: a2e6209991a191c94405a234460e05291fa986b9
2200+
React-idlecallbacksnativemodule: fa07e0af59ec6c950b2156b14c73c7fce4d0a663
2201+
React-ImageManager: 17772f78d93539a1a10901b5f537031772fa930c
22022202
React-jsc: 4d3352be620f3fe2272238298aaccc9323b01824
2203-
React-jserrorhandler: 552c5fcd2ee64307c568734b965ea082e1be25cf
2204-
React-jsi: b187c826e5bda25afb36ede4c54c146cd50c9d6c
2205-
React-jsiexecutor: ac8478b6c5f53bcf411a66bf4461e923dafeb0bd
2206-
React-jsinspector: a82cfe0794b831d6e36cf0c8c07da56a0aaa1282
2207-
React-jsitracing: e512a1023a25de831b51be1c773caa6036125a44
2208-
React-logger: 80d87daf2f98bf95ab668b79062c1e0c3f0c2f8a
2209-
React-Mapbuffer: b2642edd9be75d51ead8cda109c986665eae09cf
2210-
React-microtasksnativemodule: 7ebf131e1792a668004d2719a36da0ff8d19c43c
2211-
react-native-app-auth: eb42594042a25455119a8c57194b4fd25b9352f4
2212-
react-native-biometrics: 43ed5b828646a7862dbc7945556446be00798e7d
2213-
react-native-cloud-storage: 47e6649373f429d2f244c904347e9fc4d9ef4ca8
2214-
react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba
2215-
react-native-netinfo: cec9c4e86083cb5b6aba0e0711f563e2fbbff187
2216-
react-native-nfc-manager: a280ef94cd4871a471b052f0dc70381cf1223049
2217-
react-native-quick-crypto: c42da02f2832626ec0b8d8465f2f9b3889a317f6
2218-
react-native-safe-area-context: 827032edf27079702cbd006f11dc79451a2d744b
2219-
react-native-sqlite-storage: 0c84826214baaa498796c7e46a5ccc9a82e114ed
2203+
React-jserrorhandler: 62af5111f6444688182a5850d4b584cbc0c5d6a8
2204+
React-jsi: 490deef195fd3f01d57dc89dda8233a84bd54b83
2205+
React-jsiexecutor: 13bcb5e11822b2a6b69dbb175a24a39e24a02312
2206+
React-jsinspector: 6961a23d4c11b72f3cbeb5083b0b18cc22bc48a1
2207+
React-jsitracing: dab78a74a581f63320604c9de4ab9039209e0501
2208+
React-logger: d79b704bf215af194f5213a6b7deec50ba8e6a9b
2209+
React-Mapbuffer: 42c779748af341935a63ad8831723b8cb1e97830
2210+
React-microtasksnativemodule: 744f7e26200ea3976fef8453101cefcc08756008
2211+
react-native-app-auth: 149f01d2c824758453c9e7815217ded451974683
2212+
react-native-biometrics: 352e5a794bfffc46a0c86725ea7dc62deb085bdc
2213+
react-native-cloud-storage: 63261d420b249d373a0cdef92b4ead37b1539a5c
2214+
react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06
2215+
react-native-netinfo: f0a9899081c185db1de5bb2fdc1c88c202a059ac
2216+
react-native-nfc-manager: 5213321cf6c18d879c8092c0bf56806b771ec5ac
2217+
react-native-quick-crypto: 3a7ac97ed72bb82334ebc89fbc2e452d2bebe365
2218+
react-native-safe-area-context: 657def25b5590dfbde705aec2925b06725f27450
2219+
react-native-sqlite-storage: f6d515e1c446d1e6d026aa5352908a25d4de3261
22202220
React-nativeconfig: 31072ab0146e643594f6959c7f970a04b6c9ddd0
2221-
React-NativeModulesApple: 4ffcab4cdf34002540799bffbedd6466e8023c3a
2221+
React-NativeModulesApple: 5df767d9a2197ac25f4d8dd2d4ae1af3624022e2
22222222
React-perflogger: 59e1a3182dca2cee7b9f1f7aab204018d46d1914
2223-
React-performancetimeline: 2bf8625ff44f482cba84e48e4ab21dee405d68cd
2223+
React-performancetimeline: 3d70a278cc3344def506e97aff3640e658656110
22242224
React-RCTActionSheet: d80e68d3baa163e4012a47c1f42ddd8bcd9672cc
2225-
React-RCTAnimation: 051f0781709c5ed80ba8aa2b421dfb1d72a03162
2226-
React-RCTAppDelegate: 99345256dcceddcacab539ff8f56635de6a2f551
2227-
React-RCTBlob: e949797c162421e363f93bfd8b546b7e632ba847
2228-
React-RCTFabric: 396093d9aeee4bd3a6021ec6df8ed012f78763ef
2229-
React-RCTImage: b73149c0cd54b641dba2d6250aaf168fee784d9f
2230-
React-RCTLinking: 23e519712285427e50372fbc6e0265d422abf462
2231-
React-RCTNetwork: a5d06d122588031989115f293654b13353753630
2232-
React-RCTSettings: 87d03b5d94e6eadd1e8c1d16a62f790751aafb55
2233-
React-RCTText: 75e9dd39684f4bcd1836134ac2348efaca7437b3
2234-
React-RCTVibration: 033c161fe875e6fa096d0d9733c2e2501682e3d4
2225+
React-RCTAnimation: bde981f6bd7f8493696564da9b3bd05721d3b3cc
2226+
React-RCTAppDelegate: bc9c02d6dd4d162e3e1850283aba81bd246fc688
2227+
React-RCTBlob: e492d54533e61a81f2601494a6f393b3e15e33b9
2228+
React-RCTFabric: 4556aa70bd55b48d793cfb87e80d687c164298e2
2229+
React-RCTImage: 90448d2882464af6015ed57c98f463f8748be465
2230+
React-RCTLinking: 1bd95d0a704c271d21d758e0f0388cced768d77d
2231+
React-RCTNetwork: 218af6e63eb9b47935cc5a775b7a1396cf10ff91
2232+
React-RCTSettings: e10b8e42b0fce8a70fbf169de32a2ae03243ef6b
2233+
React-RCTText: e7bf9f4997a1a0b45c052d4ad9a0fe653061cf29
2234+
React-RCTVibration: 5b70b7f11e48d1c57e0d4832c2097478adbabe93
22352235
React-rendererconsistency: 35cef4bc4724194c544b6e5e2bd9b3f7aff52082
2236-
React-rendererdebug: 4e801e9f8d16d21877565dca2845a2e56202b8c6
2236+
React-rendererdebug: 9b1a6a2d4f8086a438f75f28350ccba16b7b706a
22372237
React-rncore: 2c7c94d6e92db0850549223eb2fa8272e0942ac2
2238-
React-RuntimeApple: 0f661760cfcfa5d9464f7e05506874643e88fc2d
2239-
React-RuntimeCore: 1d0fcc0eb13807818e79ccaf48915596f0f5f0e6
2238+
React-RuntimeApple: 22397aca29a0c9be681db02c68416e508a381ef1
2239+
React-RuntimeCore: a6d413611876d8180a5943b80cba3cefdf95ad5f
22402240
React-runtimeexecutor: ea90d8e3a9e0f4326939858dafc6ab17c031a5d3
2241-
React-runtimescheduler: 6b33edee8c830c7926670df4232d51f4f6a82795
2242-
React-utils: 7198bd077f07ce8f9263c05bf610da6e251058ad
2243-
ReactCodegen: fbd3d6af21ba08f12ccd0f542393393d21134ea5
2244-
ReactCommon: b02a50498cb1071cd793044ddbd5d2b5f4db0a34
2245-
RNCAsyncStorage: b44e8a4e798c3e1f56bffccd0f591f674fb9198f
2246-
RNCClipboard: 4abb037e8fe3b98a952564c9e0474f91c492df6d
2247-
RNDeviceInfo: d863506092aef7e7af3a1c350c913d867d795047
2248-
RNFBApp: 4097f75673f8b42a7cd1ba17e6ea85a94b45e4d1
2249-
RNFBMessaging: 92325b0d5619ac90ef023a23cfd16fd3b91d0a88
2250-
RNFBRemoteConfig: a569bacaa410acfcaba769370e53a787f80fd13b
2251-
RNGestureHandler: 9c3877d98d4584891b69d16ebca855ac46507f4d
2252-
RNKeychain: 4990d9be2916c60f9ed4f8c484fcd7ced4828b86
2253-
RNLocalize: 15463c4d79c7da45230064b4adcf5e9bb984667e
2254-
RNReactNativeHapticFeedback: e19b9b2e2ecf5593de8c4ef1496e1e31ae227514
2255-
RNScreens: b7e8d29c6be98f478bc3fb4a97cc770aa9ba7509
2256-
RNSentry: c462461c0a5aaba206265f1f3db01b237cd33239
2257-
RNSVG: e3ad69848b6357587545e0a49628b1148acf082c
2258-
segment-analytics-react-native: 5c3e8a4ee6d7532a011ed862d7c7d4fb5e5303e2
2241+
React-runtimescheduler: e041df0539ad8a8a370e3507c39a9ab0571bb848
2242+
React-utils: 768a7eb396b7df37aa19389201652eac613490cd
2243+
ReactCodegen: 94e0a796b6f35263fe84067a014165616e5b383f
2244+
ReactCommon: 03d2d48fcd1329fe3bc4e428a78a0181b68068c2
2245+
RNCAsyncStorage: 23e56519cc41d3bade3c8d4479f7760cb1c11996
2246+
RNCClipboard: 60fed4b71560d7bfe40e9d35dea9762b024da86d
2247+
RNDeviceInfo: feea80a690d2bde1fe51461cf548039258bd03f2
2248+
RNFBApp: dd35ba8340b89c36e42c4c137915c01d3c792143
2249+
RNFBMessaging: c8d34d9ad44a3258a77e548bba6dc3561af7cf2d
2250+
RNFBRemoteConfig: 7e219246c63c47f56cfe07eee1a044ed298261c8
2251+
RNGestureHandler: 5639cd6112a3aa3bebc3871e3bf4e83940e20f6f
2252+
RNKeychain: a636d163a96e262f578dababac7ec3488d4c636e
2253+
RNLocalize: 06991b9c31e7a898a9fa6ddb204ce0f53a967248
2254+
RNReactNativeHapticFeedback: cba92e59f56506f6058d261dc85986012b2c5032
2255+
RNScreens: d2a8ff4833a42f4eeadaea244f0bd793301b8810
2256+
RNSentry: 3d46e29e54f848539428ce45ae8da496ef117b65
2257+
RNSVG: 28b61fc4856abe8eaea46794419f848986ee7e80
2258+
segment-analytics-react-native: de13f89e52d49c1f4ed33ba86ae24f055722a643
22592259
Sentry: 1ca8405451040482877dcd344dfa3ef80b646631
22602260
SentryPrivate: d651efb234cf385ec9a1cdd3eff94b5e78a0e0fe
22612261
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
2262-
sovran-react-native: a3ad3f8ff90c2002b2aa9790001a78b0b0a38594
2262+
sovran-react-native: eec37f82e4429f0e3661f46aaf4fcd85d1b54f60
22632263
SwiftQRScanner: e85a25f9b843e9231dab89a96e441472fe54a724
22642264
SwiftyTesseract: 1f3d96668ae92dc2208d9842c8a59bea9fad2cbb
22652265
Yoga: b05994d1933f507b0a28ceaa4fdb968dc18da178

app/src/screens/misc/SplashScreen.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ const SplashScreen: React.FC = ({}) => {
9292
setNextScreen('Home');
9393
return;
9494
}
95-
// Currently, we dont check isPassportNullified(passportData);
95+
// Currently, we dont check isDocumentNullified(passportData);
9696
// This could lead to AccountRecoveryChoice just like in LoadingScreen
9797
// But it looks better right now to keep the LaunchScreen flow
9898
// In case user wants to try with another passport.

app/src/stores/protocolStore.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import {
1818
} from '@selfxyz/common';
1919
import { create } from 'zustand';
2020

21+
import { fetchOfacTrees } from '../utils/ofac';
22+
2123
interface ProtocolState {
2224
passport: {
2325
commitment_tree: any;
@@ -26,6 +28,11 @@ interface ProtocolState {
2628
deployed_circuits: any;
2729
circuits_dns_mapping: any;
2830
alternative_csca: Record<string, string>;
31+
ofac_trees: {
32+
passportNoAndNationality: any;
33+
nameAndDob: any;
34+
nameAndYob: any;
35+
} | null;
2936
fetch_deployed_circuits: (environment: 'prod' | 'stg') => Promise<void>;
3037
fetch_circuits_dns_mapping: (environment: 'prod' | 'stg') => Promise<void>;
3138
fetch_csca_tree: (environment: 'prod' | 'stg') => Promise<void>;
@@ -36,6 +43,7 @@ interface ProtocolState {
3643
ski: string,
3744
) => Promise<void>;
3845
fetch_all: (environment: 'prod' | 'stg', ski: string) => Promise<void>;
46+
fetch_ofac_trees: (environment: 'prod' | 'stg') => Promise<void>;
3947
};
4048
id_card: {
4149
commitment_tree: any;
@@ -44,6 +52,11 @@ interface ProtocolState {
4452
deployed_circuits: any;
4553
circuits_dns_mapping: any;
4654
alternative_csca: Record<string, string>;
55+
ofac_trees: {
56+
passportNoAndNationality: any;
57+
nameAndDob: any;
58+
nameAndYob: any;
59+
} | null;
4760
fetch_deployed_circuits: (environment: 'prod' | 'stg') => Promise<void>;
4861
fetch_circuits_dns_mapping: (environment: 'prod' | 'stg') => Promise<void>;
4962
fetch_csca_tree: (environment: 'prod' | 'stg') => Promise<void>;
@@ -54,6 +67,7 @@ interface ProtocolState {
5467
ski: string,
5568
) => Promise<void>;
5669
fetch_all: (environment: 'prod' | 'stg', ski: string) => Promise<void>;
70+
fetch_ofac_trees: (environment: 'prod' | 'stg') => Promise<void>;
5771
};
5872
}
5973

@@ -65,13 +79,15 @@ export const useProtocolStore = create<ProtocolState>((set, get) => ({
6579
deployed_circuits: null,
6680
circuits_dns_mapping: null,
6781
alternative_csca: {},
82+
ofac_trees: null,
6883
fetch_all: async (environment: 'prod' | 'stg', ski: string) => {
6984
await Promise.all([
7085
get().passport.fetch_deployed_circuits(environment),
7186
get().passport.fetch_circuits_dns_mapping(environment),
7287
get().passport.fetch_csca_tree(environment),
7388
get().passport.fetch_dsc_tree(environment),
7489
get().passport.fetch_identity_tree(environment),
90+
get().passport.fetch_ofac_trees(environment),
7591
get().passport.fetch_alternative_csca(environment, ski),
7692
]);
7793
},
@@ -194,7 +210,15 @@ export const useProtocolStore = create<ProtocolState>((set, get) => ({
194210
set({ passport: { ...get().passport, commitment_tree: data.data } });
195211
} catch (error) {
196212
console.error(`Failed fetching identity tree from ${url}:`, error);
197-
// Optionally handle error state
213+
}
214+
},
215+
fetch_ofac_trees: async (environment: 'prod' | 'stg') => {
216+
try {
217+
const trees = await fetchOfacTrees(environment, 'passport');
218+
set({ passport: { ...get().passport, ofac_trees: trees } });
219+
} catch (error) {
220+
console.error('Failed fetching OFAC trees:', error);
221+
set({ passport: { ...get().passport, ofac_trees: null } });
198222
}
199223
},
200224
},
@@ -205,13 +229,15 @@ export const useProtocolStore = create<ProtocolState>((set, get) => ({
205229
deployed_circuits: null,
206230
circuits_dns_mapping: null,
207231
alternative_csca: {},
232+
ofac_trees: null,
208233
fetch_all: async (environment: 'prod' | 'stg', ski: string) => {
209234
await Promise.all([
210235
get().id_card.fetch_deployed_circuits(environment),
211236
get().id_card.fetch_circuits_dns_mapping(environment),
212237
get().id_card.fetch_csca_tree(environment),
213238
get().id_card.fetch_dsc_tree(environment),
214239
get().id_card.fetch_identity_tree(environment),
240+
get().id_card.fetch_ofac_trees(environment),
215241
get().id_card.fetch_alternative_csca(environment, ski),
216242
]);
217243
},
@@ -346,5 +372,14 @@ export const useProtocolStore = create<ProtocolState>((set, get) => ({
346372
set({ id_card: { ...get().id_card, alternative_csca: {} } });
347373
}
348374
},
375+
fetch_ofac_trees: async (environment: 'prod' | 'stg') => {
376+
try {
377+
const trees = await fetchOfacTrees(environment, 'id_card');
378+
set({ id_card: { ...get().id_card, ofac_trees: trees } });
379+
} catch (error) {
380+
console.error('Failed fetching OFAC trees:', error);
381+
set({ id_card: { ...get().id_card, ofac_trees: null } });
382+
}
383+
},
349384
},
350385
}));

app/src/utils/ofac.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// SPDX-License-Identifier: BUSL-1.1; Copyright (c) 2025 Social Connect Labs, Inc.; Licensed under BUSL-1.1 (see LICENSE); Apache-2.0 from 2029-06-11
2+
3+
import { TREE_URL, TREE_URL_STAGING } from '@selfxyz/common';
4+
5+
export type OfacVariant = 'passport' | 'id_card';
6+
7+
export interface OfacTrees {
8+
passportNoAndNationality: any;
9+
nameAndDob: any;
10+
nameAndYob: any;
11+
}
12+
13+
// Generic helper to fetch a single OFAC tree and validate the response shape.
14+
const fetchTree = async (url: string): Promise<any> => {
15+
const res = await fetch(url);
16+
if (!res.ok) {
17+
throw new Error(`HTTP error fetching ${url}! status: ${res.status}`);
18+
}
19+
const responseData = await res.json();
20+
if (responseData.status !== 'success' || !responseData.data) {
21+
throw new Error(
22+
`Failed to fetch tree from ${url}: ${
23+
responseData.message || 'Invalid response format'
24+
}`,
25+
);
26+
}
27+
return responseData.data;
28+
};
29+
30+
// Main public helper that retrieves the three OFAC trees depending on the variant (passport vs id_card).
31+
export const fetchOfacTrees = async (
32+
environment: 'prod' | 'stg',
33+
variant: OfacVariant = 'passport',
34+
): Promise<OfacTrees> => {
35+
const baseUrl = environment === 'prod' ? TREE_URL : TREE_URL_STAGING;
36+
37+
const ppNoNatUrl = `${baseUrl}/ofac/passport-no-nationality`;
38+
const nameDobUrl = `${baseUrl}/ofac/name-dob${
39+
variant === 'id_card' ? '-id' : ''
40+
}`;
41+
const nameYobUrl = `${baseUrl}/ofac/name-yob${
42+
variant === 'id_card' ? '-id' : ''
43+
}`;
44+
45+
// For ID cards, we intentionally skip fetching the (large) passport-number-tree.
46+
if (variant === 'id_card') {
47+
const [nameDobData, nameYobData] = await Promise.all([
48+
fetchTree(nameDobUrl),
49+
fetchTree(nameYobUrl),
50+
]);
51+
52+
return {
53+
passportNoAndNationality: null,
54+
nameAndDob: nameDobData,
55+
nameAndYob: nameYobData,
56+
};
57+
}
58+
59+
// Passport variant → fetch all three.
60+
const [ppNoNatData, nameDobData, nameYobData] = await Promise.all([
61+
fetchTree(ppNoNatUrl),
62+
fetchTree(nameDobUrl),
63+
fetchTree(nameYobUrl),
64+
]);
65+
66+
return {
67+
passportNoAndNationality: ppNoNatData,
68+
nameAndDob: nameDobData,
69+
nameAndYob: nameYobData,
70+
};
71+
};

0 commit comments

Comments
 (0)