Skip to content
Open
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
1 change: 1 addition & 0 deletions packages/core/src/container-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export const defaultConfig: Config = {
},
showGenericErrors: false,
enableFullScreenErrorModal: false,
trustedCertificatesUrl: ReactConfig.TRUSTED_CERTIFICATES_URL,
}

export const defaultHistoryEventsLogger: HistoryEventsLoggerConfig = {
Expand Down
27 changes: 15 additions & 12 deletions packages/core/src/hooks/useBifoldAgentSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { TOKENS, useServices } from '../container-api'
import { DispatchAction } from '../contexts/reducers/store'
import { useStore } from '../contexts/store'
import { WalletSecret } from '../types/security'
import { createLinkSecretIfRequired, getAgentModules } from '../utils/agent'
import { createLinkSecretIfRequired, getAgentModulesWithCertificates } from '../utils/agent'
import { migrateToAskar } from '../utils/migration'

export type AgentSetupReturnType = {
Expand All @@ -22,13 +22,13 @@ const useBifoldAgentSetup = (): AgentSetupReturnType => {
const [agent, setAgent] = useState<Agent | null>(null)
const agentInstanceRef = useRef<Agent | null>(null)
const [store, dispatch] = useStore()
const [cacheSchemas, cacheCredDefs, logger, indyLedgers, bridge] = useServices([
const [cacheSchemas, cacheCredDefs, logger, indyLedgers, bridge, config] = useServices([
TOKENS.CACHE_SCHEMAS,
TOKENS.CACHE_CRED_DEFS,
TOKENS.UTIL_LOGGER,
TOKENS.UTIL_LEDGERS,
TOKENS.UTIL_AGENT_BRIDGE,
TOKENS.UTIL_REFRESH_ORCHESTRATOR,
TOKENS.CONFIG,
])

const restartExistingAgent = useCallback(
Expand Down Expand Up @@ -64,15 +64,18 @@ const useBifoldAgentSetup = (): AgentSetupReturnType => {
autoUpdateStorageOnStartup: true,
},
dependencies: agentDependencies,
modules: getAgentModules({
indyNetworks: indyLedgers,
mediatorInvitationUrl: mediatorUrl,
txnCache: {
capacity: 1000,
expiryOffsetMs: 1000 * 60 * 60 * 24 * 7,
path: CachesDirectoryPath + '/txn-cache',
modules: await getAgentModulesWithCertificates(
{
indyNetworks: indyLedgers,
mediatorInvitationUrl: mediatorUrl,
txnCache: {
capacity: 1000,
expiryOffsetMs: 1000 * 60 * 60 * 24 * 7,
path: CachesDirectoryPath + '/txn-cache',
},
},
}),
config.trustedCertificatesUrl
),
})
const wsTransport = new WsOutboundTransport()
const httpTransport = new HttpOutboundTransport()
Expand All @@ -82,7 +85,7 @@ const useBifoldAgentSetup = (): AgentSetupReturnType => {

return newAgent
},
[store.preferences.walletName, logger, indyLedgers]
[store.preferences.walletName, logger, indyLedgers, config.trustedCertificatesUrl]
)

const migrateIfRequired = useCallback(
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export * from './types/attestation'
export { BifoldError } from './types/error'
export { Screens, Stacks, TabStacks } from './types/navigators'
export * from './types/version-check'
export { createLinkSecretIfRequired, getAgentModules } from './utils/agent'
export { createLinkSecretIfRequired, getAgentModules, getAgentModulesWithCertificates } from './utils/agent'
export { getCredentialIdentifiers, isValidAnonCredsCredential } from './utils/credential'
export {
connectFromScanOrDeepLink,
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export interface Config {
PINScreensConfig: PINScreensConfig
showGenericErrors?: boolean
enableFullScreenErrorModal?: boolean
trustedCertificatesUrl?: string
}

export interface PINScreensConfig {
Expand Down
56 changes: 55 additions & 1 deletion packages/core/src/utils/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
V2CredentialProtocol,
V2ProofProtocol,
WebDidResolver,
X509Module,
} from '@credo-ts/core'
import { IndyVdrAnonCredsRegistry, IndyVdrModule, IndyVdrPoolConfig } from '@credo-ts/indy-vdr'
import { OpenId4VcHolderModule } from '@credo-ts/openid4vc'
Expand All @@ -40,18 +41,46 @@ interface GetAgentModulesOptions {
indyNetworks: IndyVdrPoolConfig[]
mediatorInvitationUrl?: string
txnCache?: { capacity: number; expiryOffsetMs: number; path?: string }
trustedCertificates?: string[]
}

export type BifoldAgent = Agent<ReturnType<typeof getAgentModules>>

/**
* Fetches trusted certificates from a remote API
* @param url The API endpoint URL
* @returns Array of certificate strings
*/
async function fetchTrustedCertificates(url: string): Promise<string[]> {
try {
const response = await fetch(url)
if (!response.ok) {
return []
}
const certificates = await response.json()
if (!Array.isArray(certificates)) {
return []
}
return certificates.filter((cert) => typeof cert === 'string' && cert.trim().length > 0)
} catch (error) {
return []
}
}

/**
* Constructs the modules to be used in the agent setup
* @param indyNetworks
* @param mediatorInvitationUrl determine which mediator to use
* @param txnCache optional local cache config for indyvdr
* @param trustedCertificates optional array of trusted certificates for X509 module
* @returns modules to be used in agent setup
*/
export function getAgentModules({ indyNetworks, mediatorInvitationUrl, txnCache }: GetAgentModulesOptions) {
export function getAgentModules({
indyNetworks,
mediatorInvitationUrl,
txnCache,
trustedCertificates = [],
}: GetAgentModulesOptions) {
const indyCredentialFormat = new LegacyIndyCredentialFormatService()
const indyProofFormat = new LegacyIndyProofFormatService()

Expand Down Expand Up @@ -120,9 +149,34 @@ export function getAgentModules({ indyNetworks, mediatorInvitationUrl, txnCache
new PeerDidResolver(),
],
}),
...(trustedCertificates.length > 0
? {
x509: new X509Module({
trustedCertificates: trustedCertificates as [string, ...string[]],
}),
}
: {}),
}
}

/**
* Fetches and prepares agent modules with trusted certificates from remote API
* @param options Agent module options including indyNetworks, mediatorInvitationUrl, txnCache
* @param trustedCertificatesUrl Optional URL to fetch trusted certificates from
* @returns Promise resolving to agent modules
*/
export async function getAgentModulesWithCertificates(
options: Omit<GetAgentModulesOptions, 'trustedCertificates'>,
trustedCertificatesUrl?: string
) {
const trustedCertificates = trustedCertificatesUrl ? await fetchTrustedCertificates(trustedCertificatesUrl) : []

return getAgentModules({
...options,
trustedCertificates,
})
}

interface MyAgentContextInterface {
loading: boolean
agent: BifoldAgent
Expand Down
Loading