use std::sync::LazyLock;
use r402_core::chain::NetworkInfo;
use solana_pubkey::pubkey;
use crate::chain::{
SolanaChainReference, SolanaTokenDeployment, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID,
};
pub static SOLANA_NETWORKS: &[NetworkInfo] = &[
NetworkInfo {
name: "solana",
namespace: "solana",
reference: "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
},
NetworkInfo {
name: "solana-devnet",
namespace: "solana",
reference: "EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
},
NetworkInfo {
name: "solana-testnet",
namespace: "solana",
reference: "4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z",
},
];
static USDC_DEPLOYMENTS: LazyLock<Vec<SolanaTokenDeployment>> = LazyLock::new(|| {
vec![
SolanaTokenDeployment::new(
SolanaChainReference::SOLANA,
pubkey!("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v").into(),
6,
TOKEN_PROGRAM_ID,
),
SolanaTokenDeployment::new(
SolanaChainReference::SOLANA_DEVNET,
pubkey!("4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU").into(),
6,
TOKEN_PROGRAM_ID,
),
SolanaTokenDeployment::new(
SolanaChainReference::SOLANA_TESTNET,
pubkey!("4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU").into(),
6,
TOKEN_PROGRAM_ID,
),
]
});
static USDT_DEPLOYMENTS: LazyLock<Vec<SolanaTokenDeployment>> = LazyLock::new(|| {
vec![
SolanaTokenDeployment::new(
SolanaChainReference::SOLANA,
pubkey!("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB").into(),
6,
TOKEN_PROGRAM_ID,
),
]
});
static USDG_DEPLOYMENTS: LazyLock<Vec<SolanaTokenDeployment>> = LazyLock::new(|| {
vec![
SolanaTokenDeployment::new(
SolanaChainReference::SOLANA,
pubkey!("2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH").into(),
6,
TOKEN_2022_PROGRAM_ID,
),
SolanaTokenDeployment::new(
SolanaChainReference::SOLANA_DEVNET,
pubkey!("4F6PM96JJxngmHnZLBh9n58RH4aTVNWvDs2nuwrT5BP7").into(),
6,
TOKEN_2022_PROGRAM_ID,
),
SolanaTokenDeployment::new(
SolanaChainReference::SOLANA_TESTNET,
pubkey!("4F6PM96JJxngmHnZLBh9n58RH4aTVNWvDs2nuwrT5BP7").into(),
6,
TOKEN_2022_PROGRAM_ID,
),
]
});
static PYUSD_DEPLOYMENTS: LazyLock<Vec<SolanaTokenDeployment>> = LazyLock::new(|| {
vec![
SolanaTokenDeployment::new(
SolanaChainReference::SOLANA,
pubkey!("2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo").into(),
6,
TOKEN_2022_PROGRAM_ID,
),
SolanaTokenDeployment::new(
SolanaChainReference::SOLANA_DEVNET,
pubkey!("CXk2AMBfi3TwaEL2468s6zP8xq9NxTXjp9gjMgzeUynM").into(),
6,
TOKEN_2022_PROGRAM_ID,
),
SolanaTokenDeployment::new(
SolanaChainReference::SOLANA_TESTNET,
pubkey!("CXk2AMBfi3TwaEL2468s6zP8xq9NxTXjp9gjMgzeUynM").into(),
6,
TOKEN_2022_PROGRAM_ID,
),
]
});
static CASH_DEPLOYMENTS: LazyLock<Vec<SolanaTokenDeployment>> = LazyLock::new(|| {
vec![
SolanaTokenDeployment::new(
SolanaChainReference::SOLANA,
pubkey!("CASHx9KJUStyftLFWGvEVf59SGeG9sh5FfcnZMVPCASH").into(),
6,
TOKEN_2022_PROGRAM_ID,
),
]
});
fn deployment_on(
table: &'static [SolanaTokenDeployment],
chain: &SolanaChainReference,
) -> Option<&'static SolanaTokenDeployment> {
table.iter().find(|d| d.chain_reference == *chain)
}
#[must_use]
pub fn usdc_solana_deployments() -> &'static [SolanaTokenDeployment] {
&USDC_DEPLOYMENTS
}
#[must_use]
pub fn usdc_solana_deployment(
chain: &SolanaChainReference,
) -> Option<&'static SolanaTokenDeployment> {
deployment_on(&USDC_DEPLOYMENTS, chain)
}
#[must_use]
pub fn usdt_solana_deployments() -> &'static [SolanaTokenDeployment] {
&USDT_DEPLOYMENTS
}
#[must_use]
pub fn usdt_solana_deployment(
chain: &SolanaChainReference,
) -> Option<&'static SolanaTokenDeployment> {
deployment_on(&USDT_DEPLOYMENTS, chain)
}
#[must_use]
pub fn usdg_solana_deployments() -> &'static [SolanaTokenDeployment] {
&USDG_DEPLOYMENTS
}
#[must_use]
pub fn usdg_solana_deployment(
chain: &SolanaChainReference,
) -> Option<&'static SolanaTokenDeployment> {
deployment_on(&USDG_DEPLOYMENTS, chain)
}
#[must_use]
pub fn pyusd_solana_deployments() -> &'static [SolanaTokenDeployment] {
&PYUSD_DEPLOYMENTS
}
#[must_use]
pub fn pyusd_solana_deployment(
chain: &SolanaChainReference,
) -> Option<&'static SolanaTokenDeployment> {
deployment_on(&PYUSD_DEPLOYMENTS, chain)
}
#[must_use]
pub fn cash_solana_deployments() -> &'static [SolanaTokenDeployment] {
&CASH_DEPLOYMENTS
}
#[must_use]
pub fn cash_solana_deployment(
chain: &SolanaChainReference,
) -> Option<&'static SolanaTokenDeployment> {
deployment_on(&CASH_DEPLOYMENTS, chain)
}
#[derive(Debug, Clone, Copy)]
#[allow(
clippy::upper_case_acronyms,
reason = "USDC is a well-known token ticker"
)]
pub struct USDC;
#[allow(
clippy::doc_markdown,
clippy::missing_panics_doc,
clippy::expect_used,
reason = "static deployment lookups are infallible for built-in data"
)]
impl USDC {
#[must_use]
pub fn on(chain: &SolanaChainReference) -> Option<&'static SolanaTokenDeployment> {
usdc_solana_deployment(chain)
}
#[must_use]
pub fn all() -> &'static [SolanaTokenDeployment] {
usdc_solana_deployments()
}
#[must_use]
pub fn solana() -> &'static SolanaTokenDeployment {
usdc_solana_deployment(&SolanaChainReference::SOLANA)
.expect("built-in USDC deployment for Solana mainnet missing")
}
#[must_use]
pub fn solana_devnet() -> &'static SolanaTokenDeployment {
usdc_solana_deployment(&SolanaChainReference::SOLANA_DEVNET)
.expect("built-in USDC deployment for Solana devnet missing")
}
#[must_use]
pub fn solana_testnet() -> &'static SolanaTokenDeployment {
usdc_solana_deployment(&SolanaChainReference::SOLANA_TESTNET)
.expect("built-in USDC deployment for Solana testnet missing")
}
}
#[derive(Debug, Clone, Copy)]
#[allow(
clippy::upper_case_acronyms,
reason = "USDT is a well-known token ticker"
)]
pub struct USDT;
#[allow(
clippy::doc_markdown,
clippy::missing_panics_doc,
clippy::expect_used,
reason = "static deployment lookups are infallible for built-in data"
)]
impl USDT {
#[must_use]
pub fn on(chain: &SolanaChainReference) -> Option<&'static SolanaTokenDeployment> {
usdt_solana_deployment(chain)
}
#[must_use]
pub fn all() -> &'static [SolanaTokenDeployment] {
usdt_solana_deployments()
}
#[must_use]
pub fn solana() -> &'static SolanaTokenDeployment {
usdt_solana_deployment(&SolanaChainReference::SOLANA)
.expect("built-in USDT deployment for Solana mainnet missing")
}
}
#[derive(Debug, Clone, Copy)]
#[allow(
clippy::upper_case_acronyms,
reason = "USDG is a well-known token ticker"
)]
pub struct USDG;
#[allow(
clippy::doc_markdown,
clippy::missing_panics_doc,
clippy::expect_used,
reason = "static deployment lookups are infallible for built-in data"
)]
impl USDG {
#[must_use]
pub fn on(chain: &SolanaChainReference) -> Option<&'static SolanaTokenDeployment> {
usdg_solana_deployment(chain)
}
#[must_use]
pub fn all() -> &'static [SolanaTokenDeployment] {
usdg_solana_deployments()
}
#[must_use]
pub fn solana() -> &'static SolanaTokenDeployment {
usdg_solana_deployment(&SolanaChainReference::SOLANA)
.expect("built-in USDG deployment for Solana mainnet missing")
}
#[must_use]
pub fn solana_devnet() -> &'static SolanaTokenDeployment {
usdg_solana_deployment(&SolanaChainReference::SOLANA_DEVNET)
.expect("built-in USDG deployment for Solana devnet missing")
}
#[must_use]
pub fn solana_testnet() -> &'static SolanaTokenDeployment {
usdg_solana_deployment(&SolanaChainReference::SOLANA_TESTNET)
.expect("built-in USDG deployment for Solana testnet missing")
}
}
#[derive(Debug, Clone, Copy)]
#[allow(
clippy::upper_case_acronyms,
reason = "PYUSD is a well-known token ticker"
)]
pub struct PYUSD;
#[allow(
clippy::doc_markdown,
clippy::missing_panics_doc,
clippy::expect_used,
reason = "static deployment lookups are infallible for built-in data"
)]
impl PYUSD {
#[must_use]
pub fn on(chain: &SolanaChainReference) -> Option<&'static SolanaTokenDeployment> {
pyusd_solana_deployment(chain)
}
#[must_use]
pub fn all() -> &'static [SolanaTokenDeployment] {
pyusd_solana_deployments()
}
#[must_use]
pub fn solana() -> &'static SolanaTokenDeployment {
pyusd_solana_deployment(&SolanaChainReference::SOLANA)
.expect("built-in PYUSD deployment for Solana mainnet missing")
}
#[must_use]
pub fn solana_devnet() -> &'static SolanaTokenDeployment {
pyusd_solana_deployment(&SolanaChainReference::SOLANA_DEVNET)
.expect("built-in PYUSD deployment for Solana devnet missing")
}
#[must_use]
pub fn solana_testnet() -> &'static SolanaTokenDeployment {
pyusd_solana_deployment(&SolanaChainReference::SOLANA_TESTNET)
.expect("built-in PYUSD deployment for Solana testnet missing")
}
}
#[derive(Debug, Clone, Copy)]
#[allow(
clippy::upper_case_acronyms,
reason = "CASH is a well-known token ticker"
)]
pub struct CASH;
#[allow(
clippy::doc_markdown,
clippy::missing_panics_doc,
clippy::expect_used,
reason = "static deployment lookups are infallible for built-in data"
)]
impl CASH {
#[must_use]
pub fn on(chain: &SolanaChainReference) -> Option<&'static SolanaTokenDeployment> {
cash_solana_deployment(chain)
}
#[must_use]
pub fn all() -> &'static [SolanaTokenDeployment] {
cash_solana_deployments()
}
#[must_use]
pub fn solana() -> &'static SolanaTokenDeployment {
cash_solana_deployment(&SolanaChainReference::SOLANA)
.expect("built-in CASH deployment for Solana mainnet missing")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn solana_networks_include_testnet() {
assert_eq!(SOLANA_NETWORKS.len(), 3);
let testnet = SOLANA_NETWORKS
.iter()
.find(|n| n.name == "solana-testnet")
.expect("solana-testnet row");
assert_eq!(testnet.namespace, "solana");
assert_eq!(testnet.reference, "4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z");
}
#[test]
fn usdc_testnet_mint_equals_devnet() {
assert_eq!(
USDC::solana_testnet().address,
USDC::solana_devnet().address
);
assert_eq!(USDC::solana().token_program, TOKEN_PROGRAM_ID);
assert_eq!(USDC::solana_devnet().token_program, TOKEN_PROGRAM_ID);
assert_eq!(USDC::solana_testnet().token_program, TOKEN_PROGRAM_ID);
assert_eq!(USDC::all().len(), 3);
assert_eq!(USDC::solana().decimals, 6);
}
#[test]
fn usdt_mainnet_only_spl_token() {
assert_eq!(USDT::all().len(), 1);
assert_eq!(USDT::solana().token_program, TOKEN_PROGRAM_ID);
assert_eq!(USDT::solana().decimals, 6);
assert!(USDT::on(&SolanaChainReference::SOLANA_DEVNET).is_none());
assert!(USDT::on(&SolanaChainReference::SOLANA_TESTNET).is_none());
assert_eq!(
USDT::solana().address,
pubkey!("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB").into()
);
}
#[test]
fn usdg_token_2022_on_all_networks() {
assert_eq!(USDG::all().len(), 3);
for deployment in USDG::all() {
assert_eq!(deployment.token_program, TOKEN_2022_PROGRAM_ID);
assert_eq!(deployment.decimals, 6);
}
assert_eq!(
USDG::solana_testnet().address,
USDG::solana_devnet().address
);
assert_eq!(
USDG::solana().address,
pubkey!("2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH").into()
);
}
#[test]
fn pyusd_token_2022_on_all_networks() {
assert_eq!(PYUSD::all().len(), 3);
for deployment in PYUSD::all() {
assert_eq!(deployment.token_program, TOKEN_2022_PROGRAM_ID);
assert_eq!(deployment.decimals, 6);
}
assert_eq!(
PYUSD::solana_testnet().address,
PYUSD::solana_devnet().address
);
assert_eq!(
PYUSD::solana().address,
pubkey!("2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo").into()
);
let parsed = PYUSD::solana().parse("$0.10").unwrap();
assert_eq!(parsed.amount, 100_000);
assert_eq!(parsed.token.token_program, TOKEN_2022_PROGRAM_ID);
}
#[test]
fn cash_mainnet_only_token_2022() {
assert_eq!(CASH::all().len(), 1);
assert_eq!(CASH::solana().token_program, TOKEN_2022_PROGRAM_ID);
assert_eq!(CASH::solana().decimals, 6);
assert!(CASH::on(&SolanaChainReference::SOLANA_DEVNET).is_none());
assert!(CASH::on(&SolanaChainReference::SOLANA_TESTNET).is_none());
assert_eq!(
CASH::solana().address,
pubkey!("CASHx9KJUStyftLFWGvEVf59SGeG9sh5FfcnZMVPCASH").into()
);
}
#[test]
fn chain_reference_testnet_round_trips() {
let parsed: SolanaChainReference = "4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z"
.parse()
.expect("testnet reference");
assert_eq!(parsed, SolanaChainReference::SOLANA_TESTNET);
assert_eq!(parsed.to_string(), "4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z");
}
}