Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added map method to query builders #45

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

akorchyn
Copy link
Collaborator

@akorchyn akorchyn commented Jan 30, 2025

  • added map method to change the query result type if you want to construct it some other way around. These methods help to simplify mapping internally (more clean) and provide a big improvement in dev UX on fetching data.

  • Bug-fixed Delegation::view_balance method that returned staked balance instead of unstaked.

@race-of-sloths

@race-of-sloths
Copy link

race-of-sloths commented Jan 30, 2025

@akorchyn Thank you for your contribution! Your pull request is now a part of the Race of Sloths!
We are launching a survey "Who is faster? You vs SpaceX"

Shows inviting banner with latest news.

Shows profile picture for the author of the PR

Current status: waiting for merge
Reviewer Score
@dj8yfo 8

Your contribution is much appreciated with a final score of 8!
You have received 80 Sloth points for this contribution

@dj8yfo received 25 Sloth Points for reviewing and scoring this pull request.

What is the Race of Sloths

Race of Sloths is a friendly competition where you can participate in challenges and compete with other open-source contributors within your normal workflow

For contributors:

  • Tag @race-of-sloths inside your pull requests
  • Wait for the maintainer to review and score your pull request
  • Check out your position in the Leaderboard
  • Keep weekly and monthly streaks to reach higher positions
  • Boast your contributions with a dynamic picture of your Profile

For maintainers:

  • Score pull requests that participate in the Race of Sloths and receive a reward
  • Engage contributors with fair scoring and fast responses so they keep their streaks
  • Promote the Race to the point where the Race starts promoting you
  • Grow the community of your contributors

Feel free to check our website for additional details!

Bot commands
  • For contributors
    • Include a PR: @race-of-sloths include to enter the Race with your PR
  • For maintainers:
    • Invite contributor @race-of-sloths invite to invite the contributor to participate in a race or include it, if it's already a runner.
    • Assign points: @race-of-sloths score [1/2/3/5/8/13] to award points based on your assessment.
    • Reject this PR: @race-of-sloths exclude to send this PR back to the drawing board.
    • Exclude repo: @race-of-sloths pause to stop bot activity in this repo until @race-of-sloths unpause command is called

@akorchyn akorchyn changed the title feat: added read_only_with_postprocess method to simplify contract interaction feat: added map method to query builders Feb 3, 2025
Copy link
Collaborator

@dj8yfo dj8yfo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this thingy here has to test the same thing that will be published
RUSTDOCFLAGS="-D warnings" cargo doc --all-features --document-private-items

https://github.com/near/near-api-rs/blob/main/.github/workflows/test.yml#L43

@akorchyn
Copy link
Collaborator Author

this thingy here has to test the same thing that will be published RUSTDOCFLAGS="-D warnings" cargo doc --all-features --document-private-items

https://github.com/near/near-api-rs/blob/main/.github/workflows/test.yml#L43

Don't think it related to this PR, though

@dj8yfo
Copy link
Collaborator

dj8yfo commented Feb 12, 2025

Don't think it related to this PR, though

actually , i went to workflows in the target branch to copy an up-to-date command to a local justfile to build documentation with, to look at doc comments added in target branch, and noticed it's out of sync with docs.rs directives in manifest,
so i think it's pretty much related to this pr, despite the referenced line being nowhere close to modified ones

besides, the commented structs/methods (e.g. in src/common/query.rs) reside in a private module, so their addition won't be checked for consistency in ci with cargo doc before attempting to publish

Copy link
Collaborator

@dj8yfo dj8yfo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@race-of-sloths score 8
this looks great

left some comments

Comment on lines +156 to +157
/// - [Tokens::ft_balance](crate::tokens::Tokens::ft_balance)
/// - [StakingPool::staking_pool_info](crate::stake::Staking::staking_pool_info)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should hint that implementations are meant, or better be replaced with compilable example (without map logic, to showcase stock MultiRpcBuilder)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this MultiRpcBuilder as well as its alias near_api::common::query::MultiQueryBuilder can be considered to be made public (they don't appear to be public atm), as i see no reason why lib user cannot try to combine something like https://docs.rs/near-api/latest/src/near_api/tokens.rs.html#179-217 on his/her own, if he wants to try something custom

@@ -173,6 +181,22 @@ where
}
}

/// Map response of the queries to another type. The `map` function is executed after the queries are fetched.
///
/// The response is a tuple of the responses of the queries.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line can be made more specific, by replacing response -> with Handler:Response ,
replacing the queries -> the querires added by [Self::add_query] ,

and also the statement about a tuple of responses can specify, that for a tuple of the responses
a MultiQueryHandler<(H1, ... Hn)> has to be used to initialize the Handler of this MultiRpcBuilder.

       let postprocess = MultiQueryHandler::new((
            CallResultHandler(PhantomData::<Response1>),
            CallResultHandler(PhantomData::<Response2>),
        ));

It's also worth mentioning that currently MultiQueryHandler supports tupples with sizes in the range 1..=3 (not absolutely sure about that, but that was my impression)

a compilable example to showcase this api in isolation from other api (ft_balance) in the lib would be beneficial too

Comment on lines +282 to +283
CallResultHandler(PhantomData::<FungibleTokenMetadata>),
CallResultHandler(PhantomData::<U128>),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only field of tuple struct could be made non-pub, as formally using a PhantomData<T> is an implementation detail

impl<Response: Send + Sync> CallResultHandler<Response> {
    pub fn new() -> Self {
        Self(PhantomData::<Response>)
    }
}
        let postprocess = MultiQueryHandler::new((
            CallResultHandler::<FungibleTokenMetadata>::new(),
            CallResultHandler::<U128>::new(),
            // CallResultHandler(PhantomData::<FungibleTokenMetadata>),
            // CallResultHandler(PhantomData::<U128>),
        ));

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this could be streamlined further to only require

 let postprocess = MultiQueryHandler::new(Default::default());

but this remains unclear, whether it's a good idea, specifying types upfront looks readable,
though maybe a tad redundant

Comment on lines +91 to +92
block_height: storage.block_height,
block_hash: storage.block_hash,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be a map or map_inner_data method on https://docs.rs/near-api/latest/near_api/types/struct.Data.html itself

}),
)?
.read_only()
.map(near_data_to_near_token))
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these 3 could be further dedup-ed, as they only differ in called function method_name

Comment on lines 174 to 176
let staked = near_data_to_near_token(staked);
let unstaked = near_data_to_near_token(unstaked);
let total = near_data_to_near_token(total);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

frankly speaking, this looks strange. not sure why this compiles.
One would expect that 3 queries returned by add_query_builder already resolve to NearToken,
as they all have .map(near_data_to_near_token)) in their implementation bodies and have NearToken return type somewhere in their method signatures.

first impression that it should be just composing fields into output type

                UserStakeBalance {
                    staked,
                    unstaked,
                    total,
                }

without the need for an extra round of near_data_to_near_token type conversions

@@ -147,6 +147,14 @@ pub type MultiQueryBuilder<T> = MultiRpcBuilder<T, RpcQueryRequest, BlockReferen
pub type ValidatorQueryBuilder<T> = RpcBuilder<T, RpcValidatorRequest, EpochReference>;
pub type BlockQueryBuilder<T> = RpcBuilder<T, RpcBlockRequest, BlockReference>;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't know, this module could be split into some smaller sub-modules, maybe defined by some core trait that all items within a sub-module implement, maybe by some other categories (maybe by a few layers of categories) ,
but the names are all a bit lookalike , QueryBuilder, RpcBuilder, RpcHandler, RpcRequest, RpcRequestHandler, ...

idk, if e.g. RpcBuilder resided in near_api::common::query::<module_name>, and QueryBuilder resided in
near_api::common::query::<module_name>::aliases, maybe these would be easier to separate from MultiRpcBuilder and its alias

it's not large though, only 800 lines

.add_query_builder(Self::staking_pool_reward_fee(pool.clone()))
.add_query_builder(Self::staking_pool_delegators(pool.clone()))
.add_query_builder(Self::staking_pool_total_stake(pool))
.map(move |(reward_fee, delegators, total_stake)| {
let total = near_data_to_near_token(total_stake);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same thing here abount apparently repeated near_data_to_near_token

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants