use ai_registry_api::{
consts::{AGENT, MAX_URI_LENGTH},
error::AgentError,
event::IdentityProfileUpdatedEvent,
instruction::UpdateIdentityProfile,
state::Agent,
};
use steel::*;
pub fn process_update_identity_profile(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult {
let args = UpdateIdentityProfile::try_from_bytes(data)?;
let [controller_info, agent_info] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
agent_info.is_writable()?.has_seeds(
&[
AGENT,
agent_info
.as_account::<Agent>(&ai_registry_api::ID)?
.creator
.as_ref(),
],
&ai_registry_api::ID,
)?;
controller_info.is_signer()?;
let agent = agent_info.as_account::<Agent>(&ai_registry_api::ID)?;
if controller_info.key != &agent.controller {
return Err(AgentError::UnauthorizedController.into());
}
let uri_len = args
.identity_profile_uri
.iter()
.position(|&b| b == 0)
.unwrap_or(MAX_URI_LENGTH);
let uri_bytes = &args.identity_profile_uri[..uri_len];
if uri_bytes.is_empty() || uri_bytes.len() > MAX_URI_LENGTH {
return Err(AgentError::InvalidLength.into());
}
let uri_str =
core::str::from_utf8(uri_bytes).map_err(|_| AgentError::InvalidIdentityProfileUri)?;
if !uri_str.starts_with("https://") && !uri_str.starts_with("ipfs://") {
return Err(AgentError::InsecureUri.into());
}
let clock = Clock::get()?;
let agent = agent_info.as_account_mut::<Agent>(&ai_registry_api::ID)?;
agent.identity_profile_uri = args.identity_profile_uri;
agent.identity_profile_uri_len = uri_len as u8;
agent.identity_profile_hash = args.identity_profile_hash;
agent.updated_at = clock.unix_timestamp;
let mut uri_preview = [0u8; 32];
let preview_len = core::cmp::min(32, uri_len);
uri_preview[..preview_len].copy_from_slice(&uri_bytes[..preview_len]);
IdentityProfileUpdatedEvent {
creator: agent.creator,
agent: *agent_info.key,
identity_profile_uri_preview: uri_preview,
identity_profile_hash: args.identity_profile_hash,
timestamp: clock.unix_timestamp,
}
.log();
Ok(())
}