Skip to content

Commit

Permalink
fix: bounty entity
Browse files Browse the repository at this point in the history
  • Loading branch information
NanezX committed Nov 1, 2023
1 parent 25c5da4 commit 5d265c3
Show file tree
Hide file tree
Showing 4 changed files with 351 additions and 2 deletions.
205 changes: 205 additions & 0 deletions subgraph/tests/entities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2230,6 +2230,211 @@ async fn token_vault_entity_take_order_test() -> anyhow::Result<()> {
Ok(())
}

#[tokio::main]
#[test]
async fn bounty_entity_clear_test() -> anyhow::Result<()> {
let alice = get_wallet(0);
let bob = get_wallet(1);
let bounty_bot = get_wallet(2);

let orderbook = get_orderbook().await?;

// Deploy ExpressionDeployerNP for the config
let expression_deployer = get_expression_deployer().await?;

// Deploy ERC20 token contract (A)
let token_a = deploy_erc20_mock(None).await?;
// Deploy ERC20 token contract (B)
let token_b = deploy_erc20_mock(None).await?;

// Generate vault ids for each account (Input and Output)
let vault_id = generate_random_u256();

// Order Alice Configuration
let order_alice = generate_order_config(
&expression_deployer,
&token_a,
Some(vault_id),
&token_b,
Some(vault_id),
)
.await;

// Order Bob Configuration
let order_bob = generate_order_config(
&expression_deployer,
&token_b,
Some(vault_id),
&token_a,
Some(vault_id),
)
.await;

// Add order alice with Alice connected to the OB
let add_order_alice = orderbook.connect(&alice).await.add_order(order_alice);
let tx = add_order_alice.send().await?;
let add_order_alice_data = get_add_order_event(orderbook, &tx).await?;

// Add order bob with Bob connected to the OB
let add_order_bob = orderbook.connect(&bob).await.add_order(order_bob);
let tx = add_order_bob.send().await?;
let add_order_bob_data = get_add_order_event(orderbook, &tx).await?;

// Make deposit of corresponded output token
let decimal_a = token_a.decimals().call().await?;
let amount_alice = get_amount_tokens(8, decimal_a);

let decimal_b = token_b.decimals().call().await?;
let amount_bob = get_amount_tokens(6, decimal_b);

// Alice has token_b as output
mint_tokens(&amount_alice, &alice.address(), &token_b).await?;

// Approve Alice token_b using to OB
approve_tokens(
// &amount_alice,
&amount_alice,
&orderbook.address(),
&token_b.connect(&alice).await,
)
.await?;

// Deposit using Alice
let deposit_func =
orderbook
.connect(&alice)
.await
.deposit(token_b.address(), vault_id, amount_alice);
let _ = deposit_func.send().await?.await?;

// Bob has token_a as output
mint_tokens(&amount_bob, &bob.address(), &token_a).await?;

// Approve Bob token_a using to OB
approve_tokens(
&amount_bob,
&orderbook.address(),
&token_a.connect(&bob).await,
)
.await?;

// Deposit using Bob
let deposit_func =
orderbook
.connect(&bob)
.await
.deposit(token_a.address(), vault_id, amount_bob);
let _ = deposit_func.send().await?.await?;

// BOUNTY BOT CLEARS THE ORDER
// Clear configuration
let order_alice = &add_order_alice_data.order;
let order_bob = &add_order_bob_data.order;

let a_signed_context: Vec<SignedContextV1> = Vec::new();
let b_signed_context: Vec<SignedContextV1> = Vec::new();

let clear_config_1 = generate_clear_config(&vault_id, &vault_id);
let clear_1 = ClearCall {
alice: order_alice.to_owned(),
bob: order_bob.to_owned(),
clear_config: clear_config_1,
alice_signed_context: a_signed_context.clone(),
bob_signed_context: b_signed_context.clone(),
};

let clear_config_2 = generate_clear_config(&vault_id, &vault_id);
let clear_2 = ClearCall {
alice: order_bob.to_owned(),
bob: order_alice.to_owned(),
clear_config: clear_config_2,
alice_signed_context: b_signed_context,
bob_signed_context: a_signed_context,
};

let clear_configs = vec![clear_1, clear_2];

let multi_clear_bytes = generate_multi_clear(&clear_configs);

let multicall_func = orderbook
.connect(&bounty_bot)
.await
.multicall(multi_clear_bytes);

let tx_multicall = multicall_func.send().await?;

// Tx hash that hold all the logs
let clears_tx_hash = tx_multicall.tx_hash();

let clear_events = get_clear_events(&orderbook, &clears_tx_hash).await?;
let after_clear_events = get_after_clear_events(&orderbook, &clears_tx_hash).await?;

let block_data = get_block_data(&clears_tx_hash).await?;

// It should emit the same amount of events both parts
assert_eq!(clear_events.len(), after_clear_events.len());

// Bounty Vault Entity ID
let bounty_vault = format!("{}-{:?}", vault_id, bounty_bot.address());

// Wait for Subgraph sync
wait().await?;

for (index, clear) in clear_events.iter().enumerate() {
let after_clear = after_clear_events.get(index).unwrap();

let bounty_entity_id = format!("{:?}-{}", clears_tx_hash, index);
let order_clear_id = bounty_entity_id.clone();

let clear_state_change = &after_clear.clear_state_change;

// In these tests, generally only one token is added in the Order, so we pick the "first" in the array
let alice_token_output: &Address = &clear.alice.valid_outputs.first().unwrap().token;
let bob_token_output: &Address = &clear.bob.valid_outputs.first().unwrap().token;

// Bounty Amount from A (alice)
let bounty_amount_a = clear_state_change
.alice_output
.saturating_sub(clear_state_change.bob_input);

let bounty_amount_a_display =
display_number(bounty_amount_a, get_decimals(*alice_token_output).await?);

// Bounty Amount from B (bpb)
let bounty_amount_b = clear_state_change
.bob_output
.saturating_sub(clear_state_change.alice_input);

let bounty_amount_b_display =
display_number(bounty_amount_b, get_decimals(*bob_token_output).await?);

let resp = Query::bounty(&bounty_entity_id).await?;

assert_eq!(resp.clearer, bounty_bot.address());
assert_eq!(resp.order_clear, order_clear_id);

assert_eq!(resp.bounty_vault_a, bounty_vault);
assert_eq!(resp.bounty_vault_b, bounty_vault);

assert_eq!(resp.bounty_token_a, *alice_token_output);
assert_eq!(resp.bounty_token_b, *bob_token_output);

assert_eq!(resp.bounty_amount_a, Some(bounty_amount_a));
assert_eq!(resp.bounty_amount_a_display, Some(bounty_amount_a_display));

assert_eq!(resp.bounty_amount_b, Some(bounty_amount_b));
assert_eq!(resp.bounty_amount_b_display, Some(bounty_amount_b_display));

assert_eq!(resp.transaction, clears_tx_hash);
assert_eq!(resp.emitter, bounty_bot.address());
assert_eq!(resp.timestamp, block_data.timestamp);

// assert_eq!(resp.bounty_amount_b, Some(bounty_amount_b));
// assert_eq!(resp.bounty_token_b, token_b.address());
}
Ok(())
}

#[test]
fn util_cbor_meta_test() -> anyhow::Result<()> {
// Read meta from root repository (output from nix command) and convert to Bytes
Expand Down
34 changes: 34 additions & 0 deletions subgraph/tests/subgraph/query/bounty/bounty.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
query Bounty($id: String) {
bounty(id: $id) {
id
clearer {
id
}
orderClear {
id
}
bountyVaultA {
id
}
bountyVaultB {
id
}
bountyTokenA {
id
}
bountyTokenB {
id
}
bountyAmountA
bountyAmountADisplay
bountyAmountB
bountyAmountBDisplay
transaction {
id
}
emitter {
id
}
timestamp
}
}
104 changes: 104 additions & 0 deletions subgraph/tests/subgraph/query/bounty/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use self::bounty::ResponseData;
use super::SG_URL;
use crate::utils::{bytes_to_h256, hex_string_to_bytes, mn_mpz_to_u256};
use anyhow::{anyhow, Result};
use ethers::types::{Address, Bytes, TxHash, U256};
use graphql_client::{GraphQLQuery, Response};
use rust_bigint::BigInt;
use serde::{Deserialize, Serialize};

// use bigdecimal::BigDecimal;
type BigDecimal = String;

#[derive(GraphQLQuery)]
#[graphql(
schema_path = "tests/subgraph/query/schema.json",
query_path = "tests/subgraph/query/bounty/bounty.graphql",
response_derives = "Debug, Serialize, Deserialize"
)]
#[derive(Serialize, Deserialize, Debug)]
pub struct Bounty;

#[derive(Serialize, Deserialize, Debug)]
pub struct BountyResponse {
pub id: String,
pub clearer: Address,
pub order_clear: String,
pub bounty_vault_a: String,
pub bounty_vault_b: String,
pub bounty_token_a: Address,
pub bounty_token_b: Address,
pub bounty_amount_a: Option<U256>,
pub bounty_amount_a_display: Option<String>,
pub bounty_amount_b: Option<U256>,
pub bounty_amount_b_display: Option<String>,
pub transaction: TxHash,
pub emitter: Address,
pub timestamp: U256,
}

impl BountyResponse {
pub fn from(response: ResponseData) -> BountyResponse {
let data = response.bounty.unwrap();

let clearer = Address::from_slice(&data.clearer.id);

let bounty_token_a =
Address::from_slice(&hex_string_to_bytes(&data.bounty_token_a.id).unwrap());
let bounty_token_b =
Address::from_slice(&hex_string_to_bytes(&data.bounty_token_b.id).unwrap());

let bounty_amount_a = match data.bounty_amount_a {
Some(value) => Some(mn_mpz_to_u256(&value)),
None => None,
};
let bounty_amount_b = match data.bounty_amount_b {
Some(value) => Some(mn_mpz_to_u256(&value)),
None => None,
};

let emitter = Address::from_slice(&data.emitter.id);
let transaction = bytes_to_h256(&hex_string_to_bytes(&data.transaction.id).unwrap());

BountyResponse {
id: data.id,
clearer,
order_clear: data.order_clear.id,
bounty_vault_a: data.bounty_vault_a.id,
bounty_vault_b: data.bounty_vault_b.id,
bounty_token_a,
bounty_token_b,
bounty_amount_a,
bounty_amount_a_display: data.bounty_amount_a_display,
bounty_amount_b,
bounty_amount_b_display: data.bounty_amount_b_display,
transaction,
emitter,
timestamp: mn_mpz_to_u256(&data.timestamp),
}
}
}

pub async fn get_bounty(id: &String) -> Result<BountyResponse> {
let variables = bounty::Variables {
id: id.to_string().into(),
};

let request_body = Bounty::build_query(variables);
let client = reqwest::Client::new();
let res = client
.post((*SG_URL).clone())
.json(&request_body)
.send()
.await?;

let response_body: Response<ResponseData> = res.json().await?;

match response_body.data {
Some(data) => {
let response = BountyResponse::from(data);
Ok(response)
}
None => Err(anyhow!("Failed to get query")),
}
}
10 changes: 8 additions & 2 deletions subgraph/tests/subgraph/query/mod.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
pub(crate) mod bounty;
pub(crate) mod content_meta_v1;
pub(crate) mod erc20;
pub(crate) mod io;
pub(crate) mod order;
pub(crate) mod order_clear;
pub(crate) mod orderbook;
pub(crate) mod rain_meta_v1;
pub(crate) mod token_vault;
pub(crate) mod vault;
pub(crate) mod vault_deposit;
pub(crate) mod vault_withdraw;
pub(crate) mod token_vault;

use anyhow::Result;
use ethers::types::{Address, Bytes};
use once_cell::sync::Lazy;
use reqwest::Url;

use bounty::{get_bounty, BountyResponse};
use content_meta_v1::{get_content_meta_v1, ContentMetaV1Response};
use erc20::{get_erc20, ERC20Response};
use io::{get_i_o, IOResponse};
use order::{get_order, OrderResponse};
use order_clear::{get_order_clear, OrderClearResponse};
use orderbook::{get_orderbook_query, OrderBookResponse};
use rain_meta_v1::{get_rain_meta_v1, RainMetaV1Response};
use token_vault::{get_token_vault, TokenVaultResponse};
use vault::{get_vault, VaultResponse};
use vault_deposit::{get_vault_deposit, VaultDepositResponse};
use vault_withdraw::{get_vault_withdraw, VaultWithdrawResponse};
use token_vault::{get_token_vault, TokenVaultResponse};

pub static SG_URL: Lazy<Url> =
Lazy::new(|| Url::parse("http://localhost:8000/subgraphs/name/test/test").unwrap());
Expand Down Expand Up @@ -76,4 +78,8 @@ impl Query {
pub async fn token_vault(id: &String) -> Result<TokenVaultResponse> {
get_token_vault(id).await
}

pub async fn bounty(id: &String) -> Result<BountyResponse> {
get_bounty(id).await
}
}

0 comments on commit 5d265c3

Please sign in to comment.