Skip to content

Commit

Permalink
Implement positions query which enumerates all positions
Browse files Browse the repository at this point in the history
  • Loading branch information
larry0x committed Mar 3, 2022
1 parent cea1eed commit 7f85e0c
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 4 deletions.
4 changes: 4 additions & 0 deletions contracts/martian-field/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::Config {} => to_binary(&queries::query_config(deps, env)?),
QueryMsg::State {} => to_binary(&queries::query_state(deps, env)?),
QueryMsg::Positions {
start_after,
limit,
} => to_binary(&queries::query_positions(deps, start_after, limit)?),
QueryMsg::Position {
user,
} => to_binary(&queries::query_position(deps, env, user)?),
Expand Down
33 changes: 30 additions & 3 deletions contracts/martian-field/src/queries.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
use cosmwasm_std::{Deps, Env, StdResult};
use cosmwasm_std::{Deps, Env, Order, StdResult};
use cw_storage_plus::Bound;

use fields_of_mars::martian_field::{ConfigUnchecked, Health, PositionUnchecked, State, Snapshot};
use fields_of_mars::martian_field::msg::PositionsResponseItem;
use fields_of_mars::martian_field::{ConfigUnchecked, Health, PositionUnchecked, Snapshot, State};

use crate::health::compute_health;
use crate::state::{CONFIG, POSITION, STATE, SNAPSHOT};
use crate::state::{CONFIG, POSITION, SNAPSHOT, STATE};

// Default settings for pagination
const MAX_LIMIT: u32 = 30;
const DEFAULT_LIMIT: u32 = 10;

pub fn query_config(deps: Deps, _env: Env) -> StdResult<ConfigUnchecked> {
let config = CONFIG.load(deps.storage)?;
Expand All @@ -14,6 +20,27 @@ pub fn query_state(deps: Deps, _env: Env) -> StdResult<State> {
STATE.load(deps.storage)
}

pub fn query_positions(
deps: Deps,
start_after: Option<String>,
limit: Option<u32>,
) -> StdResult<Vec<PositionsResponseItem>> {
let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize;
let start = start_after.map(Bound::exclusive);

POSITION
.range(deps.storage, start, None, Order::Ascending)
.take(limit)
.map(|item| {
let (k, v) = item?;
Ok(PositionsResponseItem {
user: String::from_utf8(k)?,
position: v.into(),
})
})
.collect()
}

pub fn query_position(deps: Deps, _env: Env, user: String) -> StdResult<PositionUnchecked> {
let user_addr = deps.api.addr_validate(&user)?;
let position = POSITION.load(deps.storage, &user_addr).unwrap_or_default();
Expand Down
11 changes: 11 additions & 0 deletions packages/fields-of-mars/src/martian_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,11 @@ pub mod msg {
Config {},
/// Return the global state of the strategy. Response: `StateUnchecked`
State {},
/// Enumerate all user positions. Response: `Vec<PositionsResponseItem>`
Positions {
start_after: Option<String>,
limit: Option<u32>,
},
/// Return data on an individual user's position. Response: `PositionUnchecked`
Position {
user: String,
Expand All @@ -470,6 +475,12 @@ pub mod msg {
},
}

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct PositionsResponseItem {
pub user: String,
pub position: PositionUnchecked,
}

/// We currently don't need any input parameter for migration
pub type MigrateMsg = Empty;
}
26 changes: 25 additions & 1 deletion scripts/tests/4_martian_field.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import chalk from "chalk";
import { expect } from "chai";
import { LocalTerra, MsgExecuteContract, MsgSend } from "@terra-money/terra.js";
import { sendTransaction } from "../helpers/tx";
import { encodeBase64 } from "../helpers/encoding";
Expand All @@ -12,7 +13,7 @@ import {
deployMartianField,
} from "./fixture";
import { Verifier } from "./verifier";
import { Config } from "./types";
import { Config, PositionsResponse } from "./types";

// LocalTerra instance
const terra = new LocalTerra();
Expand Down Expand Up @@ -1015,6 +1016,29 @@ async function testOpenPosition2() {
},
],
});

// Also, make sure the `positions` query works
const response: PositionsResponse = await terra.wasm.contractQuery(field, {
positions: {},
});
expect(response).to.deep.equal([
{
user: user1.key.accAddress,
position: {
bond_units: "170235131000000",
debt_units: "420000000000000",
unlocked_assets: [],
},
},
{
user: user2.key.accAddress,
position: {
bond_units: "84267018084785",
debt_units: "56547629523809",
unlocked_assets: [],
},
},
]);
}

//--------------------------------------------------------------------------------------------------
Expand Down
5 changes: 5 additions & 0 deletions scripts/tests/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ export type StateResponse = {
pending_rewards: Asset[];
};

export type PositionsResponse = {
user: string;
position: PositionResponse;
}[];

export type PositionResponse = {
bond_units: string;
debt_units: string;
Expand Down

0 comments on commit 7f85e0c

Please sign in to comment.