Skip to content
This repository has been archived by the owner on Aug 3, 2024. It is now read-only.

Commit

Permalink
1.1.0 Keyed<T>
Browse files Browse the repository at this point in the history
  • Loading branch information
billythedummy committed Jan 3, 2024
1 parent ff534a1 commit 327c24e
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 58 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>` so that other crates can use `Keyed<T>`. `Keyed<T>` has blanket implementations for the other traits.

### Fixes

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> {
pub pubkey: Pubkey,
pub account: Account,
pub account: T,
}
```

The type [`KeyedAccount`](crate::sdk::KeyedAccount) is an alias for `Keyed<solana_sdk::account::Account>`.

### ReadonlyAccountPubkey trait

```rust ignore
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
56 changes: 56 additions & 0 deletions src/keyed.rs
Original file line number Diff line number Diff line change
@@ -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<T> {
pub pubkey: Pubkey,
pub account: T,
}

impl<T> ReadonlyAccountPubkey for Keyed<T> {
fn pubkey(&self) -> &Pubkey {
&self.pubkey
}
}

impl<T: ReadonlyAccountData> ReadonlyAccountData for Keyed<T> {
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<T: ReadonlyAccountLamports> ReadonlyAccountLamports for Keyed<T> {
fn lamports(&self) -> u64 {
self.account.lamports()
}
}

impl<T: ReadonlyAccountOwner> ReadonlyAccountOwner for Keyed<T> {
fn owner(&self) -> &Pubkey {
self.account.owner()
}
}

impl<T: ReadonlyAccountIsExecutable> ReadonlyAccountIsExecutable for Keyed<T> {
fn executable(&self) -> bool {
self.account.executable()
}
}

impl<T: ReadonlyAccountRentEpoch> ReadonlyAccountRentEpoch for Keyed<T> {
fn rent_epoch(&self) -> solana_program::stake_history::Epoch {
self.account.rent_epoch()
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down
50 changes: 3 additions & 47 deletions src/sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,22 @@ 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<Account>;

impl ReadonlyAccountLamports for Account {
fn lamports(&self) -> u64 {
self.lamports
}
}

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;
Expand All @@ -45,51 +28,24 @@ impl ReadonlyAccountData for Account {
}
}

impl ReadonlyAccountData for KeyedAccount {
type SliceDeref<'s> = <solana_sdk::account::Account as ReadonlyAccountData>::SliceDeref<'s>;
type DataDeref<'d> = <solana_sdk::account::Account as ReadonlyAccountData>::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;
Expand Down

0 comments on commit 327c24e

Please sign in to comment.