use std::{collections::HashMap, str::FromStr};
use serde::{Deserialize, Serialize};
use solana_clock::Slot;
use solana_pubkey::Pubkey;
use uuid::Uuid;
use crate::Idl;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConstantOption {
pub id: String,
pub label: String,
#[serde(default)]
pub description: Option<String>,
pub value: String,
#[serde(default)]
pub metadata: HashMap<String, serde_json::Value>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConstantDefinition {
pub label: String,
#[serde(default)]
pub description: Option<String>,
pub options: Vec<ConstantOption>,
}
impl ConstantDefinition {
pub fn get_option(&self, id: &str) -> Option<&ConstantOption> {
self.options.iter().find(|o| o.id == id)
}
pub fn get_value(&self, id: &str) -> Option<&str> {
self.get_option(id).map(|o| o.value.as_str())
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
#[doc = "Defines how an account address should be determined"]
pub enum AccountAddress {
#[doc = "A specific public key"]
Pubkey(String),
#[doc = "A Program Derived Address with seeds"]
#[serde(rename_all = "camelCase")]
Pda {
program_id: String,
seeds: Vec<PdaSeed>,
},
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
#[doc = "Seeds used for PDA derivation"]
pub enum PdaSeed {
Pubkey(String),
String(String),
Bytes(Vec<u8>),
PropertyRef(String),
U16Be(u16),
U16BeRef(String),
U16Le(u16),
Bytes32Ref(String),
#[serde(rename_all = "camelCase")]
DerivedPda {
program_id: String,
seeds: Vec<PdaSeed>,
},
}
impl PdaSeed {
pub fn to_bytes(&self, values: Option<&HashMap<String, serde_json::Value>>) -> Option<Vec<u8>> {
match self {
PdaSeed::Pubkey(pk_str) => Pubkey::from_str(pk_str)
.ok()
.map(|pk| pk.to_bytes().to_vec()),
PdaSeed::String(s) => Some(s.as_bytes().to_vec()),
PdaSeed::Bytes(b) => Some(b.clone()),
PdaSeed::PropertyRef(prop) => {
values?.get(prop).and_then(|v| {
if let Some(s) = v.as_str() {
if let Ok(pk) = Pubkey::from_str(s) {
return Some(pk.to_bytes().to_vec());
}
return Some(s.as_bytes().to_vec());
}
if let Some(n) = v.as_u64() {
return Some(n.to_le_bytes().to_vec());
}
None
})
}
PdaSeed::U16Be(n) => Some(n.to_be_bytes().to_vec()),
PdaSeed::U16BeRef(prop) => {
values?.get(prop).and_then(|v| {
if let Some(n) = v.as_u64() {
let n16 = u16::try_from(n).ok()?;
return Some(n16.to_be_bytes().to_vec());
}
None
})
}
PdaSeed::U16Le(n) => Some(n.to_le_bytes().to_vec()),
PdaSeed::Bytes32Ref(prop) => {
values?.get(prop).and_then(|v| {
if let Some(s) = v.as_str() {
let hex_str = s.strip_prefix("0x").unwrap_or(s);
if let Ok(bytes) = hex::decode(hex_str) {
if bytes.len() == 32 {
return Some(bytes);
}
}
}
None
})
}
PdaSeed::DerivedPda { program_id, seeds } => {
let program_pubkey = Pubkey::from_str(program_id).ok()?;
let seed_bytes: Vec<Vec<u8>> = seeds
.iter()
.filter_map(|seed| seed.to_bytes(values))
.collect();
if seed_bytes.len() != seeds.len() {
return None;
}
let seed_slices: Vec<&[u8]> = seed_bytes.iter().map(|s| s.as_slice()).collect();
let (pda, _bump) = Pubkey::find_program_address(&seed_slices, &program_pubkey);
Some(pda.to_bytes().to_vec())
}
}
}
}
impl AccountAddress {
pub fn resolve(&self, values: Option<&HashMap<String, serde_json::Value>>) -> Option<Pubkey> {
match self {
AccountAddress::Pubkey(pubkey_str) => Pubkey::from_str(pubkey_str).ok(),
AccountAddress::Pda { program_id, seeds } => {
let program_pubkey = Pubkey::from_str(program_id).ok()?;
let seed_bytes: Vec<Vec<u8>> = seeds
.iter()
.filter_map(|seed| seed.to_bytes(values))
.collect();
if seed_bytes.len() != seeds.len() {
return None;
}
let seed_slices: Vec<&[u8]> = seed_bytes.iter().map(|s| s.as_slice()).collect();
let (pda, _bump) = Pubkey::find_program_address(&seed_slices, &program_pubkey);
Some(pda)
}
}
}
pub fn resolve_simple(&self) -> Option<Pubkey> {
self.resolve(None)
}
pub fn get_pda_seed_references(&self) -> Vec<String> {
match self {
AccountAddress::Pubkey(_) => vec![],
AccountAddress::Pda { seeds, .. } => {
let mut refs = Vec::new();
Self::collect_seed_references(seeds, &mut refs);
refs
}
}
}
fn collect_seed_references(seeds: &[PdaSeed], refs: &mut Vec<String>) {
for seed in seeds {
match seed {
PdaSeed::PropertyRef(name) => refs.push(name.clone()),
PdaSeed::U16BeRef(name) => refs.push(name.clone()),
PdaSeed::Bytes32Ref(name) => refs.push(name.clone()),
PdaSeed::DerivedPda { seeds: inner, .. } => {
Self::collect_seed_references(inner, refs);
}
_ => {}
}
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Default)]
#[serde(rename_all = "snake_case")]
pub enum PropertyKind {
#[default]
Field,
ConstantRef,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct Property {
pub path: String,
#[serde(default, rename = "type")]
pub kind: PropertyKind,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub constant: Option<String>,
}
impl Property {
pub fn field(path: impl Into<String>) -> Self {
Self {
path: path.into(),
kind: PropertyKind::Field,
label: None,
description: None,
constant: None,
}
}
pub fn constant_ref(path: impl Into<String>, constant: impl Into<String>) -> Self {
Self {
path: path.into(),
kind: PropertyKind::ConstantRef,
label: None,
description: None,
constant: Some(constant.into()),
}
}
pub fn is_constant_ref(&self) -> bool {
matches!(self.kind, PropertyKind::ConstantRef)
}
pub fn constant_name(&self) -> Option<&str> {
self.constant.as_deref()
}
pub fn display_label(&self) -> &str {
self.label.as_deref().unwrap_or(&self.path)
}
}
#[deprecated(
since = "1.5.0",
note = "use Property; PropertyType remains only for legacy tagged JSON compatibility"
)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type")]
pub enum PropertyType {
Field { name: String },
ConstantRef { name: String, constant: String },
}
#[allow(deprecated)]
impl PropertyType {
pub fn name(&self) -> &str {
match self {
PropertyType::Field { name } => name,
PropertyType::ConstantRef { name, .. } => name,
}
}
pub fn is_constant_ref(&self) -> bool {
matches!(self, PropertyType::ConstantRef { .. })
}
pub fn constant_name(&self) -> Option<&str> {
match self {
PropertyType::ConstantRef { constant, .. } => Some(constant),
_ => None,
}
}
}
#[allow(deprecated)]
impl From<PropertyType> for Property {
fn from(pt: PropertyType) -> Self {
match pt {
PropertyType::Field { name } => Property::field(name),
PropertyType::ConstantRef { name, constant } => Property::constant_ref(name, constant),
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OverrideTemplate {
pub id: String,
pub name: String,
pub description: String,
pub protocol: String,
pub idl: Idl,
pub address: AccountAddress,
pub account_type: String,
pub properties: Vec<Property>,
#[serde(default)]
pub constants: HashMap<String, ConstantDefinition>,
pub tags: Vec<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub llm_context: Option<String>,
}
impl OverrideTemplate {
pub fn new(
id: String,
name: String,
description: String,
protocol: String,
idl: Idl,
address: AccountAddress,
properties: Vec<Property>,
account_type: String,
) -> Self {
Self {
id,
name,
description,
protocol,
idl,
address,
account_type,
properties,
constants: HashMap::new(),
tags: Vec::new(),
llm_context: None,
}
}
pub fn get_constant(&self, name: &str) -> Option<&ConstantDefinition> {
self.constants.get(name)
}
pub fn is_property_constant_ref(&self, property_name: &str) -> bool {
self.properties
.iter()
.any(|p| p.path == property_name && p.is_constant_ref())
}
pub fn get_property_constant(&self, property_name: &str) -> Option<&ConstantDefinition> {
self.properties
.iter()
.find(|p| p.path == property_name)
.and_then(|p| p.constant_name())
.and_then(|const_name| self.constants.get(const_name))
}
pub fn get_property(&self, path: &str) -> Option<&Property> {
self.properties.iter().find(|p| p.path == path)
}
pub fn property_paths(&self) -> Vec<&str> {
self.properties.iter().map(|p| p.path.as_str()).collect()
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct OverrideInstance {
#[schemars(description = "Unique identifier for this instance (UUID v4 format)")]
pub id: String,
#[schemars(
description = "Template ID from get_override_templates (e.g., 'raydium-clmm-custom', 'kamino-obligation-health')"
)]
pub template_id: String,
#[schemars(
description = "JSON object mapping property names to values. Keys must be from template.properties. Example: {\"liquidity\": 1000000, \"sqrt_price_x64\": 18446744073709551616}"
)]
pub values: HashMap<String, serde_json::Value>,
#[schemars(
description = "Slot offset from scenario registration (integer, e.g., 1, 2, 3). Each slot is ~400ms."
)]
pub scenario_relative_slot: Slot,
#[schemars(description = "Human-readable label describing what this override does")]
pub label: Option<String>,
#[schemars(description = "Whether this override is active (true/false)")]
pub enabled: bool,
#[schemars(
description = "If true, fetches fresh account data from mainnet before applying override"
)]
#[serde(default)]
pub fetch_before_use: bool,
#[schemars(
description = "Account address: either {\"pubkey\": \"base58_address\"} or {\"pda\": {\"programId\": \"...\", \"seeds\": [...]}}"
)]
pub account: AccountAddress,
}
impl OverrideInstance {
pub fn new(template_id: String, scenario_relative_slot: Slot, account: AccountAddress) -> Self {
Self {
id: Uuid::new_v4().to_string(),
template_id,
values: HashMap::new(),
scenario_relative_slot,
label: None,
enabled: true,
fetch_before_use: false,
account,
}
}
pub fn with_values(mut self, values: HashMap<String, serde_json::Value>) -> Self {
self.values = values;
self
}
pub fn with_label(mut self, label: String) -> Self {
self.label = Some(label);
self
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct Scenario {
#[schemars(
description = "Unique identifier for the scenario (UUID v4 format, e.g., '550e8400-e29b-41d4-a716-446655440000')"
)]
pub id: String,
#[schemars(description = "Human-readable name for the scenario")]
pub name: String,
#[schemars(description = "Description of what this scenario does")]
pub description: String,
#[schemars(
description = "Array of override instances. IMPORTANT: This must be a JSON array [], not a JSON string. Each element is an OverrideInstance object."
)]
pub overrides: Vec<OverrideInstance>,
#[schemars(
description = "Array of string tags for categorization (e.g., ['liquidation', 'arbitrage'])"
)]
pub tags: Vec<String>,
}
impl Scenario {
pub fn new(name: String, description: String) -> Self {
Self {
id: Uuid::new_v4().to_string(),
name,
description,
overrides: Vec::new(),
tags: Vec::new(),
}
}
pub fn add_override(&mut self, override_instance: OverrideInstance) {
self.overrides.push(override_instance);
self.overrides.sort_by_key(|o| o.scenario_relative_slot);
}
pub fn remove_override(&mut self, override_id: &str) {
self.overrides.retain(|o| o.id != override_id);
}
pub fn get_overrides_for_slot(&self, slot: Slot) -> Vec<&OverrideInstance> {
self.overrides
.iter()
.filter(|o| o.enabled && o.scenario_relative_slot == slot)
.collect()
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ScenarioConfig {
pub enabled: bool,
pub active_scenario: Option<String>,
pub auto_save: bool,
}
impl Default for ScenarioConfig {
fn default() -> Self {
Self {
enabled: false,
active_scenario: None,
auto_save: true,
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct YamlOverrideTemplateFile {
pub id: String,
pub name: String,
pub description: String,
pub protocol: String,
pub version: String,
pub account_type: String,
#[serde(default)]
pub properties: Vec<YamlProperty>,
#[serde(default)]
pub constants: HashMap<String, YamlConstantDefinition>,
pub idl_file_path: String,
pub address: YamlAccountAddress,
#[serde(default)]
pub tags: Vec<String>,
#[serde(default)]
pub llm_context: Option<String>,
}
impl YamlOverrideTemplateFile {
pub fn to_override_template(self, idl: Idl) -> OverrideTemplate {
OverrideTemplate {
id: self.id,
name: self.name,
description: self.description,
protocol: self.protocol,
idl,
address: self.address.into(),
account_type: self.account_type,
properties: self.properties.into_iter().map(Into::into).collect(),
constants: self
.constants
.into_iter()
.map(|(k, v)| (k, v.into()))
.collect(),
tags: self.tags,
llm_context: self.llm_context,
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct YamlConstantOption {
pub id: String,
pub label: String,
#[serde(default)]
pub description: Option<String>,
pub value: String,
#[serde(default)]
pub metadata: HashMap<String, serde_json::Value>,
}
impl From<YamlConstantOption> for ConstantOption {
fn from(yaml: YamlConstantOption) -> Self {
ConstantOption {
id: yaml.id,
label: yaml.label,
description: yaml.description,
value: yaml.value,
metadata: yaml.metadata,
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum YamlConstantSource {
Inline { options: Vec<YamlConstantOption> },
TokensRef {
source: String,
#[serde(default)]
filter_tags: Vec<String>,
#[serde(default)]
limit: Option<usize>,
},
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct YamlConstantDefinition {
pub label: String,
#[serde(default)]
pub description: Option<String>,
#[serde(flatten)]
pub source: YamlConstantSource,
}
impl YamlConstantDefinition {
pub fn to_constant_definition(self) -> ConstantDefinition {
let options = match self.source {
YamlConstantSource::Inline { options } => options.into_iter().map(Into::into).collect(),
YamlConstantSource::TokensRef {
source,
filter_tags,
limit,
} => {
if source == "verified_tokens" {
use crate::verified_tokens::VERIFIED_TOKENS_BY_SYMBOL;
let mut tokens: Vec<_> = VERIFIED_TOKENS_BY_SYMBOL
.iter()
.filter(|(_, _token)| {
if filter_tags.is_empty() {
return true;
}
true
})
.map(|(symbol, token)| ConstantOption {
id: symbol.to_lowercase(),
label: format!("{} ({})", token.symbol, token.name),
description: Some(token.name.clone()),
value: token.address.clone(),
metadata: {
let mut meta = HashMap::new();
meta.insert(
"symbol".to_string(),
serde_json::Value::String(token.symbol.clone()),
);
meta.insert(
"decimals".to_string(),
serde_json::Value::Number(token.decimals.into()),
);
if let Some(ref logo) = token.logo_uri {
meta.insert(
"logo_uri".to_string(),
serde_json::Value::String(logo.clone()),
);
}
meta
},
})
.collect();
tokens.sort_by(|a, b| a.id.cmp(&b.id));
if let Some(limit) = limit {
tokens.truncate(limit);
}
tokens
} else {
Vec::new()
}
}
};
ConstantDefinition {
label: self.label,
description: self.description,
options,
}
}
}
impl From<YamlConstantDefinition> for ConstantDefinition {
fn from(yaml: YamlConstantDefinition) -> Self {
yaml.to_constant_definition()
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum YamlProperty {
Simple(String),
Full {
path: String,
#[serde(default, rename = "type")]
kind: Option<String>,
#[serde(default)]
label: Option<String>,
#[serde(default)]
description: Option<String>,
#[serde(default)]
constant: Option<String>,
},
}
impl From<YamlProperty> for Property {
fn from(yaml: YamlProperty) -> Self {
match yaml {
YamlProperty::Simple(path) => Property::field(path),
YamlProperty::Full {
path,
kind,
label,
description,
constant,
} => {
let kind = match kind.as_deref() {
Some("constant_ref") => PropertyKind::ConstantRef,
_ => PropertyKind::Field,
};
Property {
path,
kind,
label,
description,
constant,
}
}
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum YamlPropertyType {
Field { name: String },
ConstantRef { name: String, constant: String },
}
impl From<YamlPropertyType> for Property {
fn from(yaml: YamlPropertyType) -> Self {
match yaml {
YamlPropertyType::Field { name } => Property::field(name),
YamlPropertyType::ConstantRef { name, constant } => {
Property::constant_ref(name, constant)
}
}
}
}
#[allow(deprecated)]
impl From<YamlPropertyType> for PropertyType {
fn from(yaml: YamlPropertyType) -> Self {
match yaml {
YamlPropertyType::Field { name } => PropertyType::Field { name },
YamlPropertyType::ConstantRef { name, constant } => {
PropertyType::ConstantRef { name, constant }
}
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct YamlOverrideTemplateCollection {
pub protocol: String,
pub version: String,
#[serde(default)]
pub account_type: Option<String>,
pub idl_file_path: String,
#[serde(default)]
pub tags: Vec<String>,
#[serde(default)]
pub constants: HashMap<String, YamlConstantDefinition>,
pub templates: Vec<YamlOverrideTemplateEntry>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct YamlOverrideTemplateEntry {
pub id: String,
pub name: String,
pub description: String,
#[serde(default)]
pub idl_account_name: Option<String>,
#[serde(default)]
pub properties: Vec<YamlProperty>,
pub address: YamlAccountAddress,
#[serde(default)]
pub llm_context: Option<String>,
}
impl YamlOverrideTemplateCollection {
pub fn to_override_templates(self, idl: Idl) -> Vec<OverrideTemplate> {
let constants: HashMap<String, ConstantDefinition> = self
.constants
.into_iter()
.map(|(k, v)| (k, v.into()))
.collect();
let default_account_type = self.account_type.clone().unwrap_or_default();
self.templates
.into_iter()
.map(|entry| OverrideTemplate {
id: entry.id,
name: entry.name,
description: entry.description,
protocol: self.protocol.clone(),
idl: idl.clone(),
address: entry.address.into(),
account_type: entry
.idl_account_name
.unwrap_or_else(|| default_account_type.clone()),
properties: entry.properties.into_iter().map(Into::into).collect(),
constants: constants.clone(),
tags: self.tags.clone(),
llm_context: entry.llm_context,
})
.collect()
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct YamlOverrideTemplate {
pub id: String,
pub name: String,
pub description: String,
pub protocol: String,
pub version: String,
pub account_type: String,
pub idl: Idl,
pub address: YamlAccountAddress,
#[serde(default)]
pub properties: Vec<YamlProperty>,
#[serde(default)]
pub constants: HashMap<String, YamlConstantDefinition>,
#[serde(default)]
pub tags: Vec<String>,
#[serde(default)]
pub llm_context: Option<String>,
}
impl YamlOverrideTemplate {
pub fn to_override_template(self) -> OverrideTemplate {
OverrideTemplate {
id: self.id,
name: self.name,
description: self.description,
protocol: self.protocol,
idl: self.idl,
address: self.address.into(),
account_type: self.account_type,
properties: self.properties.into_iter().map(Into::into).collect(),
constants: self
.constants
.into_iter()
.map(|(k, v)| (k, v.into()))
.collect(),
tags: self.tags,
llm_context: self.llm_context,
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "lowercase")]
pub enum YamlAccountAddress {
Pubkey {
#[serde(default)]
value: Option<String>,
},
Pda {
program_id: String,
seeds: Vec<YamlPdaSeed>,
},
}
impl From<YamlAccountAddress> for AccountAddress {
fn from(yaml: YamlAccountAddress) -> Self {
match yaml {
YamlAccountAddress::Pubkey { value } => {
AccountAddress::Pubkey(value.unwrap_or_default())
}
YamlAccountAddress::Pda { program_id, seeds } => AccountAddress::Pda {
program_id,
seeds: seeds.into_iter().map(|s| s.into()).collect(),
},
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum YamlPdaSeed {
String {
value: String,
},
Bytes {
value: Vec<u8>,
},
Pubkey {
value: String,
},
PropertyRef {
value: String,
},
U16Be {
value: u16,
},
U16BeRef {
value: String,
},
U16Le {
value: u16,
},
Bytes32Ref {
value: String,
},
DerivedPda {
program_id: String,
seeds: Vec<YamlPdaSeed>,
},
}
impl From<YamlPdaSeed> for PdaSeed {
fn from(yaml: YamlPdaSeed) -> Self {
match yaml {
YamlPdaSeed::String { value } => PdaSeed::String(value),
YamlPdaSeed::Bytes { value } => PdaSeed::Bytes(value),
YamlPdaSeed::Pubkey { value } => PdaSeed::Pubkey(value),
YamlPdaSeed::PropertyRef { value } => PdaSeed::PropertyRef(value),
YamlPdaSeed::U16Be { value } => PdaSeed::U16Be(value),
YamlPdaSeed::U16BeRef { value } => PdaSeed::U16BeRef(value),
YamlPdaSeed::U16Le { value } => PdaSeed::U16Le(value),
YamlPdaSeed::Bytes32Ref { value } => PdaSeed::Bytes32Ref(value),
YamlPdaSeed::DerivedPda { program_id, seeds } => PdaSeed::DerivedPda {
program_id,
seeds: seeds.into_iter().map(|s| s.into()).collect(),
},
}
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use serde_json::json;
use super::PdaSeed;
#[test]
fn u16_be_ref_rejects_out_of_range_values() {
let seed = PdaSeed::U16BeRef("index".to_string());
let values = HashMap::from([("index".to_string(), json!(70_000))]);
assert_eq!(seed.to_bytes(Some(&values)), None);
}
#[test]
fn u16_be_ref_encodes_in_range_values() {
let seed = PdaSeed::U16BeRef("index".to_string());
let values = HashMap::from([("index".to_string(), json!(513))]);
assert_eq!(seed.to_bytes(Some(&values)), Some(vec![2, 1]));
}
}