use ek_core::{Field, SectionMap};
#[derive(Debug, Clone)]
pub struct AcctSpec {
pub broker_id: String,
pub user: String,
pub td_addr: String,
pub md_addr: String,
pub app_id: String,
pub auth_code: String,
pub classes: String,
pub md_user: String,
pub md_password: Option<String>,
}
pub fn derived_name(spec: &AcctSpec) -> Result<String, String> {
ek_ctp::derived_gateway_name(&spec.broker_id, &spec.user).ok_or_else(|| {
format!(
"派生注册名失败(broker={:?} 账号={:?}):字符不合名纪律",
spec.broker_id, spec.user
)
})
}
pub fn write_account(
store: &ek_cfg::Store,
spec: &AcctSpec,
password: &str,
) -> Result<String, String> {
if spec.broker_id.is_empty()
|| spec.user.is_empty()
|| spec.td_addr.is_empty()
|| spec.app_id.is_empty()
|| spec.auth_code.is_empty()
{
return Err("缺必填要素(broker/user/td 前置/app_id/auth_code)".to_string());
}
if password.trim().is_empty() {
return Err("密码为空:档案不接受无密码账户(受理校验同款)".to_string());
}
let gw = derived_name(spec)?;
let ns = format!("ctp.{gw}");
ek_cfg::secret::set(
&ns,
"gw_td_password",
ek_cfg::SecretValue::from_bytes(password.trim().to_owned()),
)
.map_err(|e| format!("密码登记密库失败: {e:?}"))?;
let mut map = SectionMap::new(1)
.set("broker_id", Field::plain(spec.broker_id.trim()))
.set("td_addr", Field::plain(spec.td_addr.trim()))
.set("td_user", Field::plain(spec.user.trim()))
.set("td_app_id", Field::plain(spec.app_id.trim()))
.set("td_auth_code", Field::plain(spec.auth_code.trim()))
.set("td_password", Field::secret("gw_td_password"));
if !spec.md_addr.trim().is_empty() {
map = map.set("md_addr", Field::plain(spec.md_addr.trim()));
if !spec.md_user.trim().is_empty() {
map = map.set("md_user", Field::plain(spec.md_user.trim()));
}
if let Some(mp) = spec.md_password.as_deref() {
let mp = mp.trim();
if !mp.is_empty() {
ek_cfg::secret::set(&ns, "gw_md_password", ek_cfg::SecretValue::from_bytes(mp))
.map_err(|e| format!("行情密码登记密库失败: {e:?}"))?;
map = map.set("md_password", Field::secret("gw_md_password"));
}
}
}
let classes = spec.classes.trim();
if !classes.is_empty() {
for c in classes.split(',').map(str::trim) {
if c.chars().count() != 1 {
return Err(format!(
"product_classes 项 {c:?} 非单字符 CTP 码(D-PC-FILTER)"
));
}
}
map = map.set("product_classes", Field::plain(classes));
}
store
.store(&ns, &map)
.map_err(|e| format!("档案落盘失败: {e:?}"))?;
Ok(gw)
}