heavy-duty / znap

Performance-first Rust Framework to build APIs compatible with the Solana Actions Spec.
Apache License 2.0
60 stars 1 forks source link

Support Params for Actions #43

Closed danmt closed 2 months ago

danmt commented 2 months ago

We need to provide a way for users to create actions that receive values from the Path. Right now, there's only support for the Query, which works for some cases but there are plenty use cases that are not covered. Jupiter uses a path to specify the pair of the swap, i.e. https://jup.ag/swap/SOL-USDC, https://jup.ag/swap/SOL-PYTH. Our current implementation makes it impossible to achieve such behavior.

Axum has the Params extractor as shown below:

// Path segment labels will be matched with struct field names
#[derive(Deserialize)]
struct Params {
    user_id: Uuid,
    team_id: Uuid,
}

async fn users_teams_show(
    Path(Params { user_id, team_id }): Path<Params>,
) {
    // ...
}

The implementation details involve changing the way the Context works, and introduces a new variant, we need now 8 (2³) combinations of Context to get it to work in the current way. Which, sure, it's still do-able, but makes it harder to maintain, and if we need a new thing, let's say the "headers" or something, it will add even more combinations.

An ideal API would be like:

#[derive(Action)]
#[params(product_id: String)]
#[query(more_data: String)]
struct BuyProductAction;

And it would be used like:

#[collection]
mod my_actions {
  fn post_buy_product(ctx: Context<BuyProductAction>) -> Result<Transaction> {
    // ctx.params.product_id exists
    // ctx.query.more_data exists
    // ...
  }
}