diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c2c890..8f149b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [UNRELEASED] +## [1.1.0] + +### Changed + +- `KeyedAccount` to a type alias that uses new pub generic struct `Keyed` so that other crates can use `Keyed`. `Keyed` has blanket implementations for the other traits. ### Fixes diff --git a/Cargo.toml b/Cargo.toml index 08fcea5..4f0650d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "solana-readonly-account" description = "Readonly solana account field getter traits that work for both on-chain AccountInfos and off-chain Accounts" -version = "1.0.0" +version = "1.1.0" edition = "2021" license = "MIT OR Apache-2.0" repository = "https://github.com/igneous-labs/solana-readonly-account.git" diff --git a/README.md b/README.md index f7c6c7c..78de0ca 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,17 @@ The 6 main account fields (key, lamports, data, owner, is_executable, rent_epoch For example, say you had a function that only requires the account's owner and this is a known static pubkey. Instead of having to fetch the full `Account` just to read its already-known owner field, or creating a dummy `Account`, you can simply define a newtype that only needs to implement `ReadonlyAccountOwner`, while still maintaining the ability to use this function with on-chain `AccountInfo`s. -Since [solana_sdk::Account](https://docs.rs/solana-sdk/latest/solana_sdk/account/struct.Account.html) doesn't have its pubkey field, the following [`KeyedAccount`](crate::sdk::KeyedAccount) struct is defined in `crate::sdk` for off-chain use cases: +Since [solana_sdk::Account](https://docs.rs/solana-sdk/latest/solana_sdk/account/struct.Account.html) doesn't have its pubkey field, the following [`Keyed`](crate::keyed::Keyed) struct is defined in `crate::sdk` for off-chain use cases: ```rust ignore -pub struct KeyedAccount { +pub struct Keyed { pub pubkey: Pubkey, - pub account: Account, + pub account: T, } ``` +The type [`KeyedAccount`](crate::sdk::KeyedAccount) is an alias for `Keyed`. + ### ReadonlyAccountPubkey trait ```rust ignore @@ -34,7 +36,7 @@ pub trait ReadonlyAccountPubkey { **impl for:** - [`solana_program::AccountInfo`](https://docs.rs/solana-program/latest/solana_program/account_info/struct.AccountInfo.html) -- [`KeyedAccount`](crate::sdk::KeyedAccount) +- [`Keyed`](crate::keyed::Keyed) - blanket for references ### ReadonlyAccountLamports trait @@ -50,7 +52,7 @@ pub trait ReadonlyAccountLamports { - [`solana_program::AccountInfo`](https://docs.rs/solana-program/latest/solana_program/account_info/struct.AccountInfo.html) - [`solana_sdk::Account`](https://docs.rs/solana-sdk/latest/solana_sdk/account/struct.Account.html) -- [`KeyedAccount`](crate::sdk::KeyedAccount) +- blanket for [`Keyed`](crate::keyed::Keyed) - blanket for references ### ReadonlyAccountData trait @@ -73,7 +75,7 @@ pub trait ReadonlyAccountData { - [`solana_program::AccountInfo`](https://docs.rs/solana-program/latest/solana_program/account_info/struct.AccountInfo.html) - [`solana_sdk::Account`](https://docs.rs/solana-sdk/latest/solana_sdk/account/struct.Account.html) -- [`KeyedAccount`](crate::sdk::KeyedAccount) +- blanket for [`Keyed`](crate::keyed::Keyed) - blanket for references ### ReadonlyAccountOwner trait @@ -89,7 +91,7 @@ pub trait ReadonlyAccountOwner { - [`solana_program::AccountInfo`](https://docs.rs/solana-program/latest/solana_program/account_info/struct.AccountInfo.html) - [`solana_sdk::Account`](https://docs.rs/solana-sdk/latest/solana_sdk/account/struct.Account.html) -- [`KeyedAccount`](crate::sdk::KeyedAccount) +- blanket for [`Keyed`](crate::keyed::Keyed) - blanket for references ### ReadonlyAccountIsExecutable trait @@ -105,7 +107,7 @@ pub trait ReadonlyAccountIsExecutable { - [`solana_program::AccountInfo`](https://docs.rs/solana-program/latest/solana_program/account_info/struct.AccountInfo.html) - [`solana_sdk::Account`](https://docs.rs/solana-sdk/latest/solana_sdk/account/struct.Account.html) -- [`KeyedAccount`](crate::sdk::KeyedAccount) +- blanket for [`Keyed`](crate::keyed::Keyed) - blanket for references ### ReadonlyAccountRentEpoch trait @@ -121,7 +123,7 @@ pub trait ReadonlyAccountRentEpoch { - [`solana_program::AccountInfo`](https://docs.rs/solana-program/latest/solana_program/account_info/struct.AccountInfo.html) - [`solana_sdk::Account`](https://docs.rs/solana-sdk/latest/solana_sdk/account/struct.Account.html) -- [`KeyedAccount`](crate::sdk::KeyedAccount) +- blanket for [`Keyed`](crate::keyed::Keyed) - blanket for references ## Usage diff --git a/src/keyed.rs b/src/keyed.rs new file mode 100644 index 0000000..1ff01bc --- /dev/null +++ b/src/keyed.rs @@ -0,0 +1,56 @@ +use solana_program::pubkey::Pubkey; + +use crate::{ + ReadonlyAccountData, ReadonlyAccountIsExecutable, ReadonlyAccountLamports, + ReadonlyAccountOwner, ReadonlyAccountPubkey, ReadonlyAccountRentEpoch, +}; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +pub struct Keyed { + pub pubkey: Pubkey, + pub account: T, +} + +impl ReadonlyAccountPubkey for Keyed { + fn pubkey(&self) -> &Pubkey { + &self.pubkey + } +} + +impl ReadonlyAccountData for Keyed { + type SliceDeref<'s> = T::SliceDeref<'s> + where + Self: 's; + + type DataDeref<'d> = T::DataDeref<'d> + where + Self: 'd; + + fn data(&self) -> Self::DataDeref<'_> { + self.account.data() + } +} + +impl ReadonlyAccountLamports for Keyed { + fn lamports(&self) -> u64 { + self.account.lamports() + } +} + +impl ReadonlyAccountOwner for Keyed { + fn owner(&self) -> &Pubkey { + self.account.owner() + } +} + +impl ReadonlyAccountIsExecutable for Keyed { + fn executable(&self) -> bool { + self.account.executable() + } +} + +impl ReadonlyAccountRentEpoch for Keyed { + fn rent_epoch(&self) -> solana_program::stake_history::Epoch { + self.account.rent_epoch() + } +} diff --git a/src/lib.rs b/src/lib.rs index e1db467..c6b4abb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,8 @@ use core::ops::Deref; use solana_program::{pubkey::Pubkey, stake_history::Epoch}; +pub mod keyed; + pub mod program; #[cfg(feature = "solana-sdk")] diff --git a/src/sdk.rs b/src/sdk.rs index b9f165d..83b3341 100644 --- a/src/sdk.rs +++ b/src/sdk.rs @@ -3,26 +3,15 @@ use solana_program::{pubkey::Pubkey, stake_history::Epoch}; use solana_sdk::account::Account; use crate::{ - ReadonlyAccountData, ReadonlyAccountIsExecutable, ReadonlyAccountLamports, - ReadonlyAccountOwner, ReadonlyAccountPubkey, ReadonlyAccountRentEpoch, + keyed::Keyed, ReadonlyAccountData, ReadonlyAccountIsExecutable, ReadonlyAccountLamports, + ReadonlyAccountOwner, ReadonlyAccountRentEpoch, }; /// Newtype owning reference to account.data in order to work with trait #[derive(Clone, Copy, Debug, Deref, DerefMut, AsRef, AsMut, From, Into)] pub struct AccountDataRef<'a>(pub &'a [u8]); -/// `solana_sdk::account::Account` with its pubkey -#[derive(Clone, Debug, Default, PartialEq, Eq)] -pub struct KeyedAccount { - pub pubkey: Pubkey, - pub account: Account, -} - -impl ReadonlyAccountPubkey for KeyedAccount { - fn pubkey(&self) -> &Pubkey { - &self.pubkey - } -} +pub type KeyedAccount = Keyed; impl ReadonlyAccountLamports for Account { fn lamports(&self) -> u64 { @@ -30,12 +19,6 @@ impl ReadonlyAccountLamports for Account { } } -impl ReadonlyAccountLamports for KeyedAccount { - fn lamports(&self) -> u64 { - self.account.lamports - } -} - impl ReadonlyAccountData for Account { type SliceDeref<'s> = &'s [u8] where Self: 's; type DataDeref<'d> = AccountDataRef<'d> where Self: 'd; @@ -45,51 +28,24 @@ impl ReadonlyAccountData for Account { } } -impl ReadonlyAccountData for KeyedAccount { - type SliceDeref<'s> = ::SliceDeref<'s>; - type DataDeref<'d> = ::DataDeref<'d>; - - fn data(&self) -> Self::DataDeref<'_> { - self.account.data() - } -} - impl ReadonlyAccountOwner for Account { fn owner(&self) -> &Pubkey { &self.owner } } -impl ReadonlyAccountOwner for KeyedAccount { - fn owner(&self) -> &Pubkey { - self.account.owner() - } -} - impl ReadonlyAccountIsExecutable for Account { fn executable(&self) -> bool { self.executable } } -impl ReadonlyAccountIsExecutable for KeyedAccount { - fn executable(&self) -> bool { - self.account.executable() - } -} - impl ReadonlyAccountRentEpoch for Account { fn rent_epoch(&self) -> Epoch { self.rent_epoch } } -impl ReadonlyAccountRentEpoch for KeyedAccount { - fn rent_epoch(&self) -> Epoch { - self.account.rent_epoch() - } -} - #[cfg(test)] mod tests { use solana_program::program_pack::Pack;