use crate::cesr::number::Number;
use crate::cesr::tholder::{Tholder, TholderSith};
use crate::cesr::Versionage;
use crate::keri::core::eventing::{ample, is_digest_code, is_prefix_code, MAX_INT_THOLD};
use crate::keri::core::serdering::{SadValue, Sadder, SerderKERI};
use crate::keri::{versify, KERIError};
use num_bigint::BigUint;
use serde_json::Value;
use std::collections::{HashMap, HashSet};
pub struct InceptionEventBuilder {
keys: Vec<String>,
isith: Option<TholderSith>,
ndigs: Vec<String>,
nsith: Option<TholderSith>,
toad: Option<usize>,
wits: Vec<String>,
cnfg: Vec<String>,
data: Vec<SadValue>,
version: String,
kind: String,
code: Option<String>,
intive: bool,
delpre: Option<String>,
}
impl InceptionEventBuilder {
pub fn new(keys: Vec<String>) -> Self {
InceptionEventBuilder {
keys,
isith: None,
ndigs: Vec::new(),
nsith: None,
toad: None,
wits: Vec::new(),
cnfg: Vec::new(),
data: Vec::new(),
version: "KERI10JSON000000_".to_string(), kind: "JSON".to_string(), code: None,
intive: false,
delpre: None,
}
}
pub fn with_isith(mut self, isith: TholderSith) -> Self {
self.isith = Some(isith);
self
}
pub fn with_ndigs(mut self, ndigs: Vec<String>) -> Self {
self.ndigs = ndigs;
self
}
pub fn with_nsith(mut self, nsith: TholderSith) -> Self {
self.nsith = Some(nsith);
self
}
pub fn with_toad(mut self, toad: usize) -> Self {
self.toad = Some(toad);
self
}
pub fn with_wits(mut self, wits: Vec<String>) -> Self {
self.wits = wits;
self
}
pub fn with_cnfg(mut self, cnfg: Vec<String>) -> Self {
self.cnfg = cnfg;
self
}
pub fn with_data(mut self, data: Vec<SadValue>) -> Self {
self.data = data;
self
}
pub fn with_version(mut self, version: String) -> Self {
self.version = version;
self
}
pub fn with_kind(mut self, kind: String) -> Self {
self.kind = kind;
self
}
pub fn with_code(mut self, code: String) -> Self {
self.code = Some(code);
self
}
pub fn with_intive(mut self, intive: bool) -> Self {
self.intive = intive;
self
}
pub fn with_delpre(mut self, delpre: String) -> Self {
self.delpre = Some(delpre);
self
}
pub fn build(self) -> Result<SerderKERI, KERIError> {
let vs = versify("KERI", &Versionage::from(self.version), &self.kind, 0)?;
let ilk = if self.delpre.is_none() { "icp" } else { "dip" };
let sner = Number::from_num(&BigUint::from(0u32))?;
let isith = match self.isith {
Some(sith) => sith,
None => {
let default_threshold =
std::cmp::max(1, (self.keys.len() as f64 / 2.0).ceil() as usize);
TholderSith::Integer(default_threshold)
}
};
let tholder = Tholder::new(None, None, Some(isith.clone()))?;
if let Some(num) = tholder.num() {
if num < 1 {
return Err(KERIError::ValueError(format!(
"Invalid sith = {} less than 1.",
num
)));
}
}
if tholder.size() > self.keys.len() {
return Err(KERIError::ValueError(format!(
"Invalid sith = {:?} for keys = {:?}",
isith, self.keys
)));
}
let nsith = match self.nsith {
Some(sith) => sith,
None => {
let default_threshold =
std::cmp::max(0, (self.ndigs.len() as f64 / 2.0).ceil() as usize);
TholderSith::Integer(default_threshold)
}
};
let ntholder = Tholder::new(None, None, Some(nsith.clone()))?;
if ntholder.size() > self.ndigs.len() {
return Err(KERIError::ValueError(format!(
"Invalid nsith = {:?} for ndigs = {:?}",
nsith, self.ndigs
)));
}
let wits = self.wits;
let wits_set: HashSet<_> = wits.iter().cloned().collect();
if wits_set.len() != wits.len() {
return Err(KERIError::ValueError(format!(
"Invalid wits = {:?}, has duplicates.",
wits
)));
}
let toad = match self.toad {
Some(t) => t,
None => {
if wits.is_empty() {
0
} else {
ample(wits.len())
}
}
};
let toader = Number::from_num(&BigUint::from(toad))?;
if !wits.is_empty() {
if toader.num() < 1 || toader.num() > wits.len() as u128 {
return Err(KERIError::ValueError(format!(
"Invalid toad = {} for wits = {:?}",
toader.num(),
wits
)));
}
} else if toader.num() != 0 {
return Err(KERIError::ValueError(format!(
"Invalid toad = {} for wits = {:?}",
toader.num(),
wits
)));
}
let kt =
if self.intive && tholder.num().is_some() && tholder.num().unwrap() <= MAX_INT_THOLD {
Value::Number(serde_json::Number::from(tholder.num().unwrap() as u64))
} else {
match &tholder.sith() {
TholderSith::Integer(n) => Value::Number(serde_json::Number::from(*n as u64)),
TholderSith::HexString(s) => Value::String(s.clone()),
TholderSith::Json(s) => serde_json::from_str(s).map_err(|e| {
KERIError::ValueError(format!(
"Invalid tholder = {} for keys = {:?}",
s, self.keys
))
})?,
TholderSith::Weights(w) => serde_json::to_value(w).map_err(|e| {
KERIError::ValueError(format!(
"Invalid tholder = {:?} for keys = {:?}",
w, self.keys
))
})?,
}
};
let nt = if self.intive
&& ntholder.num().is_some()
&& ntholder.num().unwrap() <= MAX_INT_THOLD
{
Value::Number(serde_json::Number::from(ntholder.num().unwrap() as u64))
} else {
match &ntholder.sith() {
TholderSith::Integer(n) => Value::Number(serde_json::Number::from(*n as u64)),
TholderSith::HexString(s) => Value::String(s.clone()),
TholderSith::Json(s) => serde_json::from_str(s).map_err(|e| {
KERIError::ValueError(format!(
"Invalid ntholder = {} for keys = {:?}",
s, self.keys
))
})?,
TholderSith::Weights(w) => serde_json::to_value(w).map_err(|e| {
KERIError::ValueError(format!(
"Invalid ntholder = {:?} for keys = {:?}",
w, self.keys
))
})?,
}
};
let bt = if self.intive && toader.num() <= MAX_INT_THOLD as u128 {
Value::Number(serde_json::Number::from(toader.num() as u64))
} else {
Value::String(toader.numh().to_string())
};
let mut ked = Sadder::default();
ked.insert("v".to_string(), SadValue::String(vs));
ked.insert("t".to_string(), SadValue::String(ilk.to_string()));
ked.insert("d".to_string(), SadValue::String(String::new())); ked.insert("i".to_string(), SadValue::String(String::new())); ked.insert("s".to_string(), SadValue::String(sner.numh()));
match kt {
Value::Number(n) => {
if let Some(n_u64) = n.as_u64() {
ked.insert("kt".to_string(), SadValue::Number(n));
}
}
Value::String(s) => {
ked.insert("kt".to_string(), SadValue::String(s.to_string()));
()
}
_ => {
if let Some(num) = tholder.num() {
ked.insert("kt".to_string(), SadValue::String(num.to_string()));
} else {
ked.insert("kt".to_string(), SadValue::String(kt.to_string()));
}
}
};
let key_values = self
.keys
.iter()
.map(|k| SadValue::String(k.clone()))
.collect();
ked.insert("k".to_string(), SadValue::Array(key_values));
match nt {
Value::Number(n) => {
if let Some(n_u64) = n.as_u64() {
ked.insert("nt".to_string(), SadValue::Number(n));
}
}
Value::String(s) => {
ked.insert("nt".to_string(), SadValue::String(s));
()
}
_ => {
if let Some(num) = ntholder.num() {
ked.insert("nt".to_string(), SadValue::String(num.to_string()));
} else {
ked.insert("nt".to_string(), SadValue::String(nt.to_string()));
}
}
};
let ndig_values = self
.ndigs
.iter()
.map(|n| SadValue::String(n.clone()))
.collect();
ked.insert("n".to_string(), SadValue::Array(ndig_values));
match bt {
Value::Number(n) => {
if let Some(n_u64) = n.as_u64() {
ked.insert("bt".to_string(), SadValue::Number(n));
}
}
Value::String(s) => {
ked.insert("bt".to_string(), SadValue::String(s));
()
}
_ => {
ked.insert(
"bt".to_string(),
SadValue::String(toader.numh().to_string()),
);
()
}
};
let wit_values = wits.iter().map(|w| SadValue::String(w.clone())).collect();
ked.insert("b".to_string(), SadValue::Array(wit_values));
let cnfg_values = self
.cnfg
.iter()
.map(|c| SadValue::String(c.clone()))
.collect();
ked.insert("c".to_string(), SadValue::Array(cnfg_values));
if !self.data.is_empty() {
ked.insert("a".to_string(), SadValue::Array(self.data.clone())); }
if let Some(delpre) = self.delpre.clone() {
ked.insert("di".to_string(), SadValue::String(delpre.clone()));
} else {
if (self.code.is_none() || !is_digest_code(&self.code.as_ref().unwrap()))
&& self.keys.len() == 1
{
ked.insert("i".to_string(), SadValue::String(self.keys[0].clone()));
}
}
let mut saids_map = None;
if let Some(ref code) = self.code {
if is_prefix_code(code) {
let mut map = HashMap::new();
map.insert("i", code.clone());
saids_map = Some(map);
}
}
let mut saids = HashMap::new();
if let Some(ref code) = self.code {
if is_prefix_code(code) {
saids.insert("i", code.to_string());
}
}
let serder = SerderKERI::from_sad_and_saids(&ked, Some(saids))?;
Ok(serder)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cesr::diger::Diger;
use crate::cesr::mtr_dex;
use crate::cesr::signing::Signer;
use crate::cesr::tholder::TholderSith;
use crate::keri::core::serdering::Serder;
use crate::keri::Ilks;
use crate::Matter;
use std::error::Error;
#[test]
fn test_inception_event_builder_non_transferable() -> Result<(), KERIError> {
let seed = b"\x9f{\xa8\xa7\xa8C9\x96&\xfa\xb1\x99\xeb\xaa \xc4\x1bG\x11\xc4\xaeSAR\
\xc9\xbd\x04\x9d\x85)~\x93";
let signer0 = Signer::new(Some(&seed[..]), Some(mtr_dex::ED25519_SEED), Some(false))?;
assert_eq!(signer0.code(), mtr_dex::ED25519_SEED);
assert_eq!(signer0.verfer().code(), mtr_dex::ED25519N);
let keys0 = vec![signer0.verfer().qb64()];
let serder = InceptionEventBuilder::new(keys0).build()?;
let ked = serder.ked();
let raw_str = std::str::from_utf8(serder.raw()).expect("Bad raw");
assert_eq!(
ked["i"].as_str(),
Some("BFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH")
);
if let Some(ndigs) = ked["n"].as_array() {
assert!(ndigs.is_empty());
} else {
assert!(true); }
let raw = serder.raw();
assert_eq!(raw, b"{\"v\":\"KERI10JSON0000fd_\",\"t\":\"icp\",\"d\":\"EMW0zK3bagYPO6gx3w7Ua90f-I7x5kGIaI4X\
eq9W8_As\",\"i\":\"BFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH\",\"s\":\"0\",\"kt\":\"1\
\",\"k\":[\"BFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH\"],\"nt\":\"0\",\"n\":[],\"bt\":\
\"0\",\"b\":[],\"c\":[],\"a\":[]}");
Ok(())
}
#[test]
fn test_inception_event_builder_with_thresholds() -> Result<(), Box<dyn Error>> {
let keys = vec![
"DSuhyBcPZEZLK-fcw5tzHn2N46wRCG_ZOoeKtWTOunRA".to_string(),
"DVcuJOOJF1IE8svqEtrSuyQjGTd2HhfAkt9y2QkUtFJI".to_string(),
"DT1iAhBWCkvChxNWsby2J0pJyxBIxbAtbLA0Ljx-Grh8".to_string(),
];
let configs = vec!["EO".to_string()];
let serder = InceptionEventBuilder::new(keys.clone())
.with_isith(TholderSith::Integer(2)) .with_ndigs(vec![
"EGAPkzNZMtX-QiVgbRbyAIZGoXvbGv9IPb0foWTZvI_4".to_string(),
"EIAQI--Q9LC48CM_ZyzjM-w-GfqkFkO-6lJ9klGt1fS8".to_string(),
])
.with_nsith(TholderSith::Integer(1)) .with_wits(vec![
"BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha".to_string(),
"BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM".to_string(),
])
.with_toad(2) .with_cnfg(configs) .build()?;
let ked = serder.ked();
assert_eq!(ked["v"].as_str(), Some("KERI10JSON000219_"));
assert_eq!(ked["t"].as_str(), Some("icp"));
assert_eq!(
ked["d"].as_str(),
Some("EBJ57YenBaTk-SvA5hDVf4KPKmotcKe-8imGK4bSu5xY")
);
assert_eq!(
ked["i"].as_str(),
Some("EBJ57YenBaTk-SvA5hDVf4KPKmotcKe-8imGK4bSu5xY")
);
if let Some(k) = ked["k"].as_array() {
let ks: Vec<String> = k.iter().map(|k| k.as_str().unwrap().to_string()).collect();
assert_eq!(ks, keys);
} else {
panic!("Keys missing in KED");
}
assert_eq!(ked["kt"].as_str(), Some("2"));
assert_eq!(ked["nt"].as_str(), Some("1"));
assert_eq!(ked["bt"].as_str(), Some("2"));
if let Some(wits) = ked["b"].as_array() {
assert_eq!(wits.len(), 2);
assert_eq!(
wits[0],
SadValue::String("BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha".to_string())
);
assert_eq!(
wits[1],
SadValue::String("BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM".to_string())
);
} else {
panic!("Witnesses missing in KED");
}
if let Some(configs) = ked["c"].as_array() {
assert_eq!(configs.len(), 1);
assert_eq!(configs[0], SadValue::String("EO".to_string()));
} else {
panic!("Config missing in KED");
}
Ok(())
}
#[test]
fn test_inception_event_builder_delegation() -> Result<(), Box<dyn Error>> {
let delegator_prefix = "EP1JJCqTdVteCPBqhQ_MqIagD-cplDS_LXoQG-rDd6j4".to_string();
let keys = vec!["DSuhyBcPZEZLK-fcw5tzHn2N46wRCG_ZOoeKtWTOunRA".to_string()];
let serder = InceptionEventBuilder::new(keys)
.with_delpre(delegator_prefix.clone())
.build()?;
let ked = serder.ked();
assert_eq!(ked["t"].as_str(), Some("dip"));
assert_eq!(ked["di"].as_str(), Some(delegator_prefix.as_str()));
Ok(())
}
#[test]
fn test_inception_transferable_case_abandoned() -> Result<(), Box<dyn Error>> {
let seed = b"\x9f{\xa8\xa7\xa8C9\x96&\xfa\xb1\x99\xeb\xaa \xc4\x1bG\x11\xc4\xaeSAR\
\xc9\xbd\x04\x9d\x85)~\x93";
let signer0 = Signer::new(Some(seed), Some(mtr_dex::ED25519_SEED), Some(true))?;
assert_eq!(signer0.code(), mtr_dex::ED25519_SEED);
assert_eq!(signer0.verfer().code(), mtr_dex::ED25519);
let keys0 = vec![signer0.verfer().qb64()];
let serder = InceptionEventBuilder::new(keys0).build()?;
assert_eq!(
serder.ked()["i"].as_str().unwrap(),
"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH"
);
assert!(serder.ked()["n"].as_array().unwrap().is_empty());
assert_eq!(serder.raw(), b"{\"v\":\"KERI10JSON0000fd_\",\"t\":\"icp\",\"d\":\"EPLRRJFe2FHdXKVTkSEX4xb4x-YaPFJ2Xds1\
vhtNTd4n\",\"i\":\"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH\",\"s\":\"0\",\"kt\":\"1\
\",\"k\":[\"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH\"],\"nt\":\"0\",\"n\":[],\"bt\":\
\"0\",\"b\":[],\"c\":[],\"a\":[]}");
Ok(())
}
#[test]
fn test_inception_transferable_not_abandoned_self_addressing() -> Result<(), Box<dyn Error>> {
let seed = b"\x9f{\xa8\xa7\xa8C9\x96&\xfa\xb1\x99\xeb\xaa \xc4\x1bG\x11\xc4\xaeSAR\
\xc9\xbd\x04\x9d\x85)~\x93";
let signer0 = Signer::new(Some(seed), Some(mtr_dex::ED25519_SEED), Some(true))?;
let keys0 = vec![signer0.verfer().qb64()];
let seed1 = b"\x83B~\x04\x94\xe3\xceUQy\x11f\x0c\x93]\x1e\xbf\xacQ\xb5\xd6Y^\xa2E\xfa\x015\
\x98Y\xdd\xe8";
let signer1 = Signer::new(Some(seed1), Some(mtr_dex::ED25519_SEED), Some(true))?;
assert_eq!(signer1.code(), mtr_dex::ED25519_SEED);
assert_eq!(signer1.verfer().code(), mtr_dex::ED25519);
let nxt1 =
vec![Diger::from_ser(&signer1.verfer().qb64b(), Some(mtr_dex::BLAKE3_256))?.qb64()];
assert_eq!(nxt1, vec!["EIf-ENw7PrM52w4H-S7NGU2qVIfraXVIlV9hEAaMHg7W"]);
let serder0 = InceptionEventBuilder::new(keys0.clone())
.with_ndigs(nxt1.clone())
.with_code(mtr_dex::BLAKE3_256.to_string())
.build()?;
let ked = serder0.ked();
let pre = ked["i"].as_str().unwrap();
assert_eq!(ked["t"].as_str().unwrap(), Ilks::ICP);
assert_eq!(ked["d"].as_str().unwrap(), pre);
assert_eq!(pre, "EAKCxMOuoRzREVHsHCkLilBrUXTvyenBiuM2QtV8BB0C");
assert_eq!(ked["s"].as_str().unwrap(), "0");
assert_eq!(ked["kt"].as_str().unwrap(), "1");
assert_eq!(ked["nt"].as_str().unwrap(), "1");
assert_eq!(ked["n"].as_array().unwrap()[0].as_str().unwrap(), nxt1[0]);
assert_eq!(ked["bt"].as_str().unwrap(), "0");
assert_eq!(serder0.raw(), b"{\"v\":\"KERI10JSON00012b_\",\"t\":\"icp\",\"d\":\"EAKCxMOuoRzREVHsHCkLilBrUXTvyenBiuM2\
QtV8BB0C\",\"i\":\"EAKCxMOuoRzREVHsHCkLilBrUXTvyenBiuM2QtV8BB0C\",\"s\":\"0\",\"kt\":\"1\
\",\"k\":[\"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH\"],\"nt\":\"1\",\"n\":[\"EIf-EN\
w7PrM52w4H-S7NGU2qVIfraXVIlV9hEAaMHg7W\"],\"bt\":\"0\",\"b\":[],\"c\":[],\"a\":[]}");
Ok(())
}
#[test]
fn test_inception_transferable_not_abandoned_self_addressing_intive(
) -> Result<(), Box<dyn Error>> {
let seed = b"\x9f{\xa8\xa7\xa8C9\x96&\xfa\xb1\x99\xeb\xaa \xc4\x1bG\x11\xc4\xaeSAR\
\xc9\xbd\x04\x9d\x85)~\x93";
let signer0 = Signer::new(Some(seed), Some(mtr_dex::ED25519_SEED), Some(true))?;
let keys0 = vec![signer0.verfer().qb64()];
let seed1 = b"\x83B~\x04\x94\xe3\xceUQy\x11f\x0c\x93]\x1e\xbf\xacQ\xb5\xd6Y^\xa2E\xfa\x015\
\x98Y\xdd\xe8";
let signer1 = Signer::new(Some(seed1), Some(mtr_dex::ED25519_SEED), Some(true))?;
assert_eq!(signer1.code(), mtr_dex::ED25519_SEED);
assert_eq!(signer1.verfer().code(), mtr_dex::ED25519);
let nxt1 =
vec![Diger::from_ser(&signer1.verfer().qb64b(), Some(mtr_dex::BLAKE3_256))?.qb64()];
assert_eq!(nxt1, vec!["EIf-ENw7PrM52w4H-S7NGU2qVIfraXVIlV9hEAaMHg7W"]);
let serder0 = InceptionEventBuilder::new(keys0.clone())
.with_ndigs(nxt1.clone())
.with_code(mtr_dex::BLAKE3_256.to_string())
.with_intive(true)
.build()?;
let raw_str = std::str::from_utf8(serder0.raw())?;
let ked = serder0.ked();
let pre = ked["i"].as_str().unwrap();
assert_eq!(ked["t"].as_str().unwrap(), Ilks::ICP);
assert_eq!(ked["d"].as_str().unwrap(), pre);
assert_eq!(pre, "EIflL4H4134zYoRM6ls6Q086RLC_BhfNFh5uk-WxvhsL");
assert_eq!(ked["s"].as_str().unwrap(), "0");
assert!(ked["kt"].is_number()); assert!(ked["nt"].is_number()); assert_eq!(ked["n"].as_array().unwrap()[0].as_str().unwrap(), nxt1[0]);
assert!(ked["bt"].is_number());
assert_eq!(serder0.raw(), b"{\"v\":\"KERI10JSON000125_\",\"t\":\"icp\",\"d\":\"EIflL4H4134zYoRM6ls6Q086RLC_BhfNFh5u\
k-WxvhsL\",\"i\":\"EIflL4H4134zYoRM6ls6Q086RLC_BhfNFh5uk-WxvhsL\",\"s\":\"0\",\"kt\":1,\
\"k\":[\"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH\"],\"nt\":1,\"n\":[\"EIf-ENw7Pr\
M52w4H-S7NGU2qVIfraXVIlV9hEAaMHg7W\"],\"bt\":0,\"b\":[],\"c\":[],\"a\":[]}");
Ok(())
}
#[test]
fn test_inception_transferable_not_abandoned_intive_true() -> Result<(), Box<dyn Error>> {
let seed = b"\x9f{\xa8\xa7\xa8C9\x96&\xfa\xb1\x99\xeb\xaa \xc4\x1bG\x11\xc4\xaeSAR\
\xc9\xbd\x04\x9d\x85)~\x93";
let signer0 = Signer::new(Some(seed), Some(mtr_dex::ED25519_SEED), Some(true))?;
let keys0 = vec![signer0.verfer().qb64()];
let seed1 = b"\x83B~\x04\x94\xe3\xceUQy\x11f\x0c\x93]\x1e\xbf\xacQ\xb5\xd6Y^\xa2E\xfa\x015\
\x98Y\xdd\xe8";
let signer1 = Signer::new(Some(seed1), Some(mtr_dex::ED25519_SEED), Some(true))?;
assert_eq!(signer1.code(), mtr_dex::ED25519_SEED);
assert_eq!(signer1.verfer().code(), mtr_dex::ED25519);
let nxt1 =
vec![Diger::from_ser(&signer1.verfer().qb64b(), Some(mtr_dex::BLAKE3_256))?.qb64()];
assert_eq!(nxt1, vec!["EIf-ENw7PrM52w4H-S7NGU2qVIfraXVIlV9hEAaMHg7W"]);
let serder0 = InceptionEventBuilder::new(keys0.clone())
.with_ndigs(nxt1.clone())
.with_intive(true)
.build()?;
let ked = serder0.ked();
assert_eq!(ked["t"].as_str().unwrap(), Ilks::ICP);
assert_eq!(
ked["i"].as_str().unwrap(),
"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH"
);
assert_eq!(ked["s"].as_str().unwrap(), "0");
assert!(ked["kt"].is_number()); assert!(ked["nt"].is_number()); assert_eq!(ked["n"].as_array().unwrap()[0].as_str().unwrap(), nxt1[0]);
assert!(ked["bt"].is_number());
assert_eq!(serder0.raw(), b"{\"v\":\"KERI10JSON000125_\",\"t\":\"icp\",\"d\":\"EFSJqZE0K0WU95dmccrg_8EKSuVSrt4kGIZN\
jqWFA_HL\",\"i\":\"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH\",\"s\":\"0\",\"kt\":1,\
\"k\":[\"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH\"],\"nt\":1,\"n\":[\"EIf-ENw7Pr\
M52w4H-S7NGU2qVIfraXVIlV9hEAaMHg7W\"],\"bt\":0,\"b\":[],\"c\":[],\"a\":[]}");
Ok(())
}
#[test]
fn test_inception_transferable_not_abandoned() -> Result<(), Box<dyn Error>> {
let seed = b"\x9f{\xa8\xa7\xa8C9\x96&\xfa\xb1\x99\xeb\xaa \xc4\x1bG\x11\xc4\xaeSAR\
\xc9\xbd\x04\x9d\x85)~\x93";
let signer0 = Signer::new(Some(seed), Some(mtr_dex::ED25519_SEED), Some(true))?;
let keys0 = vec![signer0.verfer().qb64()];
let seed1 = b"\x83B~\x04\x94\xe3\xceUQy\x11f\x0c\x93]\x1e\xbf\xacQ\xb5\xd6Y^\xa2E\xfa\x015\
\x98Y\xdd\xe8";
let signer1 = Signer::new(Some(seed1), Some(mtr_dex::ED25519_SEED), Some(true))?;
assert_eq!(signer1.code(), mtr_dex::ED25519_SEED);
assert_eq!(signer1.verfer().code(), mtr_dex::ED25519);
let nxt1 =
vec![Diger::from_ser(&signer1.verfer().qb64b(), Some(mtr_dex::BLAKE3_256))?.qb64()];
assert_eq!(nxt1, vec!["EIf-ENw7PrM52w4H-S7NGU2qVIfraXVIlV9hEAaMHg7W"]);
let serder0 = InceptionEventBuilder::new(keys0.clone())
.with_ndigs(nxt1.clone())
.build()?;
let ked = serder0.ked();
assert_eq!(ked["t"].as_str().unwrap(), Ilks::ICP);
assert_eq!(
ked["i"].as_str().unwrap(),
"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH"
);
assert_eq!(ked["s"].as_str().unwrap(), "0");
assert_eq!(ked["kt"].as_str().unwrap(), "1");
assert_eq!(ked["nt"].as_str().unwrap(), "1");
assert_eq!(ked["n"].as_array().unwrap()[0].as_str().unwrap(), nxt1[0]);
assert_eq!(ked["bt"].as_str().unwrap(), "0");
assert_eq!(serder0.raw(), b"{\"v\":\"KERI10JSON00012b_\",\"t\":\"icp\",\"d\":\"EJQUyxnzIAtmZPoq9f4fExeGN0qfJmaFnUEK\
TwIiTBPj\",\"i\":\"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH\",\"s\":\"0\",\"kt\":\"1\
\",\"k\":[\"DFs8BBx86uytIM0D2BhsE5rrqVIT8ef8mflpNceHo4XH\"],\"nt\":\"1\",\"n\":[\"EIf-EN\
w7PrM52w4H-S7NGU2qVIfraXVIlV9hEAaMHg7W\"],\"bt\":\"0\",\"b\":[],\"c\":[],\"a\":[]}");
Ok(())
}
}