moves ofac and protocol store (#1012)

* move ofact tree fetch to common

* move protocol store to the msdk, fix some dependencies on msdk
This commit is contained in:
Aaron DeRuvo
2025-09-09 13:31:43 +02:00
committed by GitHub
parent 75dee90e41
commit 3aabfc984a
24 changed files with 91 additions and 127 deletions

View File

@@ -9,6 +9,7 @@ import { useNavigation } from '@react-navigation/native';
import { isUserRegisteredWithAlternativeCSCA } from '@selfxyz/common/utils/passports/validate';
import { useSelfClient } from '@selfxyz/mobile-sdk-alpha';
import { BackupEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
import { useProtocolStore } from '@selfxyz/mobile-sdk-alpha/stores';
import { PrimaryButton } from '@/components/buttons/PrimaryButton';
import { SecondaryButton } from '@/components/buttons/SecondaryButton';
@@ -24,7 +25,6 @@ import {
loadPassportDataAndSecret,
reStorePassportDataWithRightCSCA,
} from '@/providers/passportDataProvider';
import { useProtocolStore } from '@/stores/protocolStore';
import { useSettingStore } from '@/stores/settingStore';
import { STORAGE_NAME, useBackupMnemonic } from '@/utils/cloudBackup';
import { black, slate500, slate600, white } from '@/utils/colors';

View File

@@ -12,6 +12,7 @@ import { useNavigation } from '@react-navigation/native';
import { isUserRegisteredWithAlternativeCSCA } from '@selfxyz/common/utils/passports/validate';
import { useSelfClient } from '@selfxyz/mobile-sdk-alpha';
import { BackupEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
import { useProtocolStore } from '@selfxyz/mobile-sdk-alpha/stores';
import { SecondaryButton } from '@/components/buttons/SecondaryButton';
import Description from '@/components/typography/Description';
@@ -21,7 +22,6 @@ import {
loadPassportDataAndSecret,
reStorePassportDataWithRightCSCA,
} from '@/providers/passportDataProvider';
import { useProtocolStore } from '@/stores/protocolStore';
import {
black,
slate300,

View File

@@ -1,381 +0,0 @@
// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
import { create } from 'zustand';
import {
API_URL,
API_URL_STAGING,
CSCA_TREE_URL,
CSCA_TREE_URL_ID_CARD,
CSCA_TREE_URL_STAGING,
CSCA_TREE_URL_STAGING_ID_CARD,
DSC_TREE_URL,
DSC_TREE_URL_ID_CARD,
DSC_TREE_URL_STAGING,
DSC_TREE_URL_STAGING_ID_CARD,
IDENTITY_TREE_URL,
IDENTITY_TREE_URL_ID_CARD,
IDENTITY_TREE_URL_STAGING,
IDENTITY_TREE_URL_STAGING_ID_CARD,
} from '@selfxyz/common/constants';
import type { DeployedCircuits, OfacTree } from '@selfxyz/common/utils/types';
import { fetchOfacTrees } from '@/utils/ofac';
interface ProtocolState {
passport: {
commitment_tree: any;
dsc_tree: any;
csca_tree: string[][] | null;
deployed_circuits: DeployedCircuits | null;
circuits_dns_mapping: any;
alternative_csca: Record<string, string>;
ofac_trees: OfacTree | null;
fetch_deployed_circuits: (environment: 'prod' | 'stg') => Promise<void>;
fetch_circuits_dns_mapping: (environment: 'prod' | 'stg') => Promise<void>;
fetch_csca_tree: (environment: 'prod' | 'stg') => Promise<void>;
fetch_dsc_tree: (environment: 'prod' | 'stg') => Promise<void>;
fetch_identity_tree: (environment: 'prod' | 'stg') => Promise<void>;
fetch_alternative_csca: (
environment: 'prod' | 'stg',
ski: string,
) => Promise<void>;
fetch_all: (environment: 'prod' | 'stg', ski: string) => Promise<void>;
fetch_ofac_trees: (environment: 'prod' | 'stg') => Promise<void>;
};
id_card: {
commitment_tree: any;
dsc_tree: any;
csca_tree: string[][] | null;
deployed_circuits: DeployedCircuits | null;
circuits_dns_mapping: any;
alternative_csca: Record<string, string>;
ofac_trees: OfacTree | null;
fetch_deployed_circuits: (environment: 'prod' | 'stg') => Promise<void>;
fetch_circuits_dns_mapping: (environment: 'prod' | 'stg') => Promise<void>;
fetch_csca_tree: (environment: 'prod' | 'stg') => Promise<void>;
fetch_dsc_tree: (environment: 'prod' | 'stg') => Promise<void>;
fetch_identity_tree: (environment: 'prod' | 'stg') => Promise<void>;
fetch_alternative_csca: (
environment: 'prod' | 'stg',
ski: string,
) => Promise<void>;
fetch_all: (environment: 'prod' | 'stg', ski: string) => Promise<void>;
fetch_ofac_trees: (environment: 'prod' | 'stg') => Promise<void>;
};
}
export const useProtocolStore = create<ProtocolState>((set, get) => ({
passport: {
commitment_tree: null,
dsc_tree: null,
csca_tree: null,
deployed_circuits: null,
circuits_dns_mapping: null,
alternative_csca: {},
ofac_trees: null,
fetch_all: async (environment: 'prod' | 'stg', ski: string) => {
await Promise.all([
get().passport.fetch_deployed_circuits(environment),
get().passport.fetch_circuits_dns_mapping(environment),
get().passport.fetch_csca_tree(environment),
get().passport.fetch_dsc_tree(environment),
get().passport.fetch_identity_tree(environment),
get().passport.fetch_ofac_trees(environment),
get().passport.fetch_alternative_csca(environment, ski),
]);
},
fetch_alternative_csca: async (
environment: 'prod' | 'stg',
ski: string,
) => {
const url = `${environment === 'prod' ? API_URL : API_URL_STAGING}/ski-pems/${ski.toLowerCase()}`; // TODO: remove false once we have the endpoint in production
try {
const response = await fetch(url, {
method: 'GET',
});
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const data = JSON.parse(responseText);
set({ passport: { ...get().passport, alternative_csca: data.data } });
} catch (error) {
console.error(`Failed fetching alternative CSCA from ${url}:`, error);
set({ passport: { ...get().passport, alternative_csca: {} } });
}
},
fetch_deployed_circuits: async (environment: 'prod' | 'stg') => {
const url = `${environment === 'prod' ? API_URL : API_URL_STAGING}/deployed-circuits`;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const data = JSON.parse(responseText);
set({ passport: { ...get().passport, deployed_circuits: data.data } });
} catch (error) {
console.error(`Failed fetching deployed circuits from ${url}:`, error);
}
},
fetch_circuits_dns_mapping: async (environment: 'prod' | 'stg') => {
const url = `${environment === 'prod' ? API_URL : API_URL_STAGING}/circuit-dns-mapping`;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const data = JSON.parse(responseText);
set({
passport: { ...get().passport, circuits_dns_mapping: data.data },
});
} catch (error) {
console.error(
`Failed fetching circuit DNS mapping from ${url}:`,
error,
);
}
},
fetch_csca_tree: async (environment: 'prod' | 'stg') => {
const url =
environment === 'prod' ? CSCA_TREE_URL : CSCA_TREE_URL_STAGING;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const rawData = JSON.parse(responseText);
let treeData: any;
if (rawData && rawData.data) {
treeData =
typeof rawData.data === 'string'
? JSON.parse(rawData.data)
: rawData.data;
} else {
treeData = rawData; // Assume rawData is the tree if no .data field
}
set({ passport: { ...get().passport, csca_tree: treeData } });
} catch (error) {
console.error(`Failed fetching CSCA tree from ${url}:`, error);
set({ passport: { ...get().passport, csca_tree: null } }); // Reset on error
}
},
fetch_dsc_tree: async (environment: 'prod' | 'stg') => {
const url = environment === 'prod' ? DSC_TREE_URL : DSC_TREE_URL_STAGING;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const data = JSON.parse(responseText);
set({ passport: { ...get().passport, dsc_tree: data.data } });
} catch (error) {
console.error(`Failed fetching DSC tree from ${url}:`, error);
// Optionally handle error state
}
},
fetch_identity_tree: async (environment: 'prod' | 'stg') => {
const url =
environment === 'prod' ? IDENTITY_TREE_URL : IDENTITY_TREE_URL_STAGING;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const data = JSON.parse(responseText);
set({ passport: { ...get().passport, commitment_tree: data.data } });
} catch (error) {
console.error(`Failed fetching identity tree from ${url}:`, error);
}
},
fetch_ofac_trees: async (environment: 'prod' | 'stg') => {
try {
const trees = await fetchOfacTrees(environment, 'passport');
set({ passport: { ...get().passport, ofac_trees: trees } });
} catch (error) {
console.error('Failed fetching OFAC trees:', error);
set({ passport: { ...get().passport, ofac_trees: null } });
}
},
},
id_card: {
commitment_tree: null,
dsc_tree: null,
csca_tree: null,
deployed_circuits: null,
circuits_dns_mapping: null,
alternative_csca: {},
ofac_trees: null,
fetch_all: async (environment: 'prod' | 'stg', ski: string) => {
await Promise.all([
get().id_card.fetch_deployed_circuits(environment),
get().id_card.fetch_circuits_dns_mapping(environment),
get().id_card.fetch_csca_tree(environment),
get().id_card.fetch_dsc_tree(environment),
get().id_card.fetch_identity_tree(environment),
get().id_card.fetch_ofac_trees(environment),
get().id_card.fetch_alternative_csca(environment, ski),
]);
},
fetch_deployed_circuits: async (environment: 'prod' | 'stg') => {
const url = `${environment === 'prod' ? API_URL : API_URL_STAGING}/deployed-circuits`;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const data = JSON.parse(responseText);
set({ id_card: { ...get().id_card, deployed_circuits: data.data } });
} catch (error) {
console.error(`Failed fetching deployed circuits from ${url}:`, error);
// Optionally handle error state
}
},
fetch_circuits_dns_mapping: async (environment: 'prod' | 'stg') => {
const url = `${environment === 'prod' ? API_URL : API_URL_STAGING}/circuit-dns-mapping`;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const data = JSON.parse(responseText);
set({
id_card: { ...get().id_card, circuits_dns_mapping: data.data },
});
} catch (error) {
console.error(
`Failed fetching circuit DNS mapping from ${url}:`,
error,
);
// Optionally handle error state
}
},
fetch_csca_tree: async (environment: 'prod' | 'stg') => {
const url =
environment === 'prod'
? CSCA_TREE_URL_ID_CARD
: CSCA_TREE_URL_STAGING_ID_CARD;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const rawData = JSON.parse(responseText);
let treeData: any;
if (rawData && rawData.data) {
treeData =
typeof rawData.data === 'string'
? JSON.parse(rawData.data)
: rawData.data;
} else {
treeData = rawData; // Assume rawData is the tree if no .data field
}
set({ id_card: { ...get().id_card, csca_tree: treeData } });
} catch (error) {
console.error(`Failed fetching CSCA tree from ${url}:`, error);
set({ id_card: { ...get().id_card, csca_tree: null } }); // Reset on error
}
},
fetch_dsc_tree: async (environment: 'prod' | 'stg') => {
const url =
environment === 'prod'
? DSC_TREE_URL_ID_CARD
: DSC_TREE_URL_STAGING_ID_CARD;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const data = JSON.parse(responseText);
set({ id_card: { ...get().id_card, dsc_tree: data.data } });
} catch (error) {
console.error(`Failed fetching DSC tree from ${url}:`, error);
// Optionally handle error state
}
},
fetch_identity_tree: async (environment: 'prod' | 'stg') => {
const url =
environment === 'prod'
? IDENTITY_TREE_URL_ID_CARD
: IDENTITY_TREE_URL_STAGING_ID_CARD;
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const data = JSON.parse(responseText);
set({ id_card: { ...get().id_card, commitment_tree: data.data } });
} catch (error) {
console.error(`Failed fetching identity tree from ${url}:`, error);
// Optionally handle error state
}
},
fetch_alternative_csca: async (
environment: 'prod' | 'stg',
ski: string,
) => {
const url = `${environment === 'prod' ? API_URL : API_URL_STAGING}/ski-pems/${ski.toLowerCase()}`; // TODO: remove false once we have the endpoint in production
try {
const response = await fetch(url, {
method: 'GET',
});
if (!response.ok) {
throw new Error(
`HTTP error fetching ${url}! status: ${response.status}`,
);
}
const responseText = await response.text();
const data = JSON.parse(responseText);
set({ id_card: { ...get().id_card, alternative_csca: data.data } });
} catch (error) {
console.error(`Failed fetching alternative CSCA from ${url}:`, error);
set({ id_card: { ...get().id_card, alternative_csca: {} } });
}
},
fetch_ofac_trees: async (environment: 'prod' | 'stg') => {
try {
const trees = await fetchOfacTrees(environment, 'id_card');
set({ id_card: { ...get().id_card, ofac_trees: trees } });
} catch (error) {
console.error('Failed fetching OFAC trees:', error);
set({ id_card: { ...get().id_card, ofac_trees: null } });
}
},
},
}));

View File

@@ -1,68 +0,0 @@
// SPDX-FileCopyrightText: 2025 Social Connect Labs, Inc.
// SPDX-License-Identifier: BUSL-1.1
// NOTE: Converts to Apache-2.0 on 2029-06-11 per LICENSE.
import { TREE_URL, TREE_URL_STAGING } from '@selfxyz/common/constants';
import type { OfacTree } from '@selfxyz/common/utils/types';
export type OfacVariant = 'passport' | 'id_card';
// Generic helper to fetch a single OFAC tree and validate the response shape.
const fetchTree = async (url: string): Promise<any> => {
const res = await fetch(url);
if (!res.ok) {
throw new Error(`HTTP error fetching ${url}! status: ${res.status}`);
}
const responseData = await res.json();
if (responseData.status !== 'success' || !responseData.data) {
throw new Error(
`Failed to fetch tree from ${url}: ${
responseData.message || 'Invalid response format'
}`,
);
}
return responseData.data;
};
// Main public helper that retrieves the three OFAC trees depending on the variant (passport vs id_card).
export const fetchOfacTrees = async (
environment: 'prod' | 'stg',
variant: OfacVariant = 'passport',
): Promise<OfacTree> => {
const baseUrl = environment === 'prod' ? TREE_URL : TREE_URL_STAGING;
const ppNoNatUrl = `${baseUrl}/ofac/passport-no-nationality`;
const nameDobUrl = `${baseUrl}/ofac/name-dob${
variant === 'id_card' ? '-id' : ''
}`;
const nameYobUrl = `${baseUrl}/ofac/name-yob${
variant === 'id_card' ? '-id' : ''
}`;
// For ID cards, we intentionally skip fetching the (large) passport-number-tree.
if (variant === 'id_card') {
const [nameDobData, nameYobData] = await Promise.all([
fetchTree(nameDobUrl),
fetchTree(nameYobUrl),
]);
return {
passportNoAndNationality: null,
nameAndDob: nameDobData,
nameAndYob: nameYobData,
};
}
// Passport variant → fetch all three.
const [ppNoNatData, nameDobData, nameYobData] = await Promise.all([
fetchTree(ppNoNatUrl),
fetchTree(nameDobUrl),
fetchTree(nameYobUrl),
]);
return {
passportNoAndNationality: ppNoNatData,
nameAndDob: nameDobData,
nameAndYob: nameYobData,
};
};

View File

@@ -4,20 +4,9 @@
import type { DocumentCategory, PassportData } from '@selfxyz/common/types';
import type { SelfApp } from '@selfxyz/common/utils';
import {
generateCircuitInputsRegister,
generateTEEInputsDiscloseStateless,
generateTEEInputsDSC,
generateTEEInputsRegister,
} from '@selfxyz/common/utils/circuits/registerInputs';
import { generateTEEInputsDiscloseStateless } from '@selfxyz/common/utils/circuits/registerInputs';
import { useProtocolStore } from '@selfxyz/mobile-sdk-alpha/stores';
import { useProtocolStore } from '@/stores/protocolStore';
export {
generateCircuitInputsRegister,
generateTEEInputsDSC,
generateTEEInputsRegister,
};
export function generateTEEInputsDisclose(
secret: string,
passportData: PassportData,

View File

@@ -17,6 +17,10 @@ import {
getSolidityPackedUserContextData,
} from '@selfxyz/common/utils';
import { getPublicKey, verifyAttestation } from '@selfxyz/common/utils/attest';
import {
generateTEEInputsDSC,
generateTEEInputsRegister,
} from '@selfxyz/common/utils/circuits/registerInputs';
import {
checkDocumentSupported,
checkIfPassportDscIsInTree,
@@ -41,6 +45,7 @@ import {
PassportEvents,
ProofEvents,
} from '@selfxyz/mobile-sdk-alpha/constants/analytics';
import { useProtocolStore } from '@selfxyz/mobile-sdk-alpha/stores';
import { navigationRef } from '@/navigation';
// will need to be passed in from selfClient
@@ -49,14 +54,9 @@ import {
markCurrentDocumentAsRegistered,
reStorePassportDataWithRightCSCA,
} from '@/providers/passportDataProvider';
import { useProtocolStore } from '@/stores/protocolStore';
import { useSelfAppStore } from '@/stores/selfAppStore';
import analytics from '@/utils/analytics';
import {
generateTEEInputsDisclose,
generateTEEInputsDSC,
generateTEEInputsRegister,
} from '@/utils/proving/provingInputs';
import { generateTEEInputsDisclose } from '@/utils/proving/provingInputs';
const { trackEvent } = analytics();

View File

@@ -7,6 +7,7 @@ import { isUserRegistered } from '@selfxyz/common/utils/passports/validate';
import type { PassportValidationCallbacks } from '@selfxyz/mobile-sdk-alpha';
import { isPassportDataValid } from '@selfxyz/mobile-sdk-alpha';
import { DocumentEvents } from '@selfxyz/mobile-sdk-alpha/constants/analytics';
import { useProtocolStore } from '@selfxyz/mobile-sdk-alpha/stores';
import {
getAllDocumentsDirectlyFromKeychain,
@@ -16,7 +17,6 @@ import {
storePassportData,
updateDocumentRegistrationState,
} from '@/providers/passportDataProvider';
import { useProtocolStore } from '@/stores/protocolStore';
import analytics from '@/utils/analytics';
const { trackEvent } = analytics();