Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3977b491b7 | ||
|
|
77ca101781 | ||
|
|
d238c37d0c | ||
|
|
79feb485f6 | ||
|
|
6aa5c3b6e3 | ||
|
|
82abc13fda |
@@ -54,3 +54,5 @@ To run the UI automation tests with a mocked API, run:
|
||||
```bash
|
||||
yarn nx run trading-e2e:e2e
|
||||
```
|
||||
|
||||
To run tests with market sim please read [the readme](e2e/README.md).
|
||||
|
||||
@@ -18,7 +18,7 @@ def setup_simple_market(
|
||||
custom_market_name=market_name,
|
||||
custom_asset_name="tDAI",
|
||||
custom_asset_symbol="tDAI",
|
||||
custom_quantum=1
|
||||
custom_quantum=1,
|
||||
):
|
||||
for wallet in wallets:
|
||||
vega.create_key(wallet.name)
|
||||
@@ -117,18 +117,30 @@ def setup_simple_successor_market(
|
||||
return market_id
|
||||
|
||||
|
||||
def setup_opening_auction_market(vega: VegaService, market_id: str = None, buy_orders=default_buy_orders, sell_orders=default_sell_orders, add_liquidity=True, **kwargs):
|
||||
def setup_opening_auction_market(
|
||||
vega: VegaService,
|
||||
market_id: str = None,
|
||||
buy_orders=default_buy_orders,
|
||||
sell_orders=default_sell_orders,
|
||||
add_liquidity=True,
|
||||
custom_market_name="BTC:DAI_2023",
|
||||
custom_asset_name="tDAI",
|
||||
custom_asset_symbol="tDAI",
|
||||
**kwargs,
|
||||
):
|
||||
if not market_exists(vega, market_id):
|
||||
market_id = setup_simple_market(vega, **kwargs)
|
||||
market_id = setup_simple_market(
|
||||
vega,
|
||||
custom_market_name=custom_market_name,
|
||||
custom_asset_name=custom_asset_name,
|
||||
custom_asset_symbol=custom_asset_symbol,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
if add_liquidity:
|
||||
submit_liquidity(vega, MM_WALLET.name, market_id)
|
||||
submit_multiple_orders(
|
||||
vega, MM_WALLET.name, market_id, "SIDE_SELL", sell_orders
|
||||
)
|
||||
submit_multiple_orders(
|
||||
vega, MM_WALLET2.name, market_id, "SIDE_BUY", buy_orders
|
||||
)
|
||||
submit_multiple_orders(vega, MM_WALLET.name, market_id, "SIDE_SELL", sell_orders)
|
||||
submit_multiple_orders(vega, MM_WALLET2.name, market_id, "SIDE_BUY", buy_orders)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
@@ -146,13 +158,37 @@ def market_exists(vega: VegaService, market_id: str):
|
||||
|
||||
|
||||
# Add sell orders and buy orders to put on the book
|
||||
def setup_continuous_market(vega: VegaService, market_id: str = None, buy_orders=default_buy_orders, sell_orders=default_sell_orders, add_liquidity=True, **kwargs):
|
||||
if not market_exists(vega, market_id) or buy_orders != default_buy_orders or sell_orders != default_sell_orders:
|
||||
def setup_continuous_market(
|
||||
vega: VegaService,
|
||||
market_id: str = None,
|
||||
buy_orders=default_buy_orders,
|
||||
sell_orders=default_sell_orders,
|
||||
add_liquidity=True,
|
||||
custom_market_name="BTC:DAI_2023",
|
||||
custom_asset_name="tDAI",
|
||||
custom_asset_symbol="tDAI",
|
||||
**kwargs,
|
||||
):
|
||||
if (
|
||||
not market_exists(vega, market_id)
|
||||
or buy_orders != default_buy_orders
|
||||
or sell_orders != default_sell_orders
|
||||
):
|
||||
market_id = setup_opening_auction_market(
|
||||
vega, market_id, buy_orders, sell_orders, add_liquidity, **kwargs)
|
||||
vega,
|
||||
market_id,
|
||||
buy_orders,
|
||||
sell_orders,
|
||||
add_liquidity,
|
||||
custom_market_name=custom_market_name,
|
||||
custom_asset_name=custom_asset_name,
|
||||
custom_asset_symbol=custom_asset_symbol,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
submit_order(vega, "Key 1", market_id, "SIDE_BUY",
|
||||
sell_orders[0][0], sell_orders[0][1])
|
||||
submit_order(
|
||||
vega, "Key 1", market_id, "SIDE_BUY", sell_orders[0][0], sell_orders[0][1]
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
@@ -250,6 +286,8 @@ def setup_perps_market(
|
||||
def market_exists(vega: VegaService, market_id: str):
|
||||
if market_id is None:
|
||||
return False
|
||||
all_markets = vega.all_markets()
|
||||
all_markets = vega.all_markets()
|
||||
market_ids = [market.id for market in all_markets]
|
||||
return market_id in market_ids
|
||||
print("Checking for market ID:", market_id)
|
||||
print("Available market IDs:", market_ids)
|
||||
return market_id in market_ids
|
||||
@@ -70,7 +70,6 @@ def test_iceberg_open_order(continuous_market, vega: VegaServiceNull, page: Page
|
||||
expect(
|
||||
page.locator(".ag-center-cols-container .ag-row [col-id='size']").first
|
||||
).to_have_text("-102")
|
||||
page.pause()
|
||||
expect(
|
||||
page.locator(".ag-center-cols-container .ag-row [col-id='type'] ").first
|
||||
).to_have_text("Limit (Iceberg)")
|
||||
|
||||
@@ -16,7 +16,6 @@ def vega(request):
|
||||
def continuous_market(vega):
|
||||
return setup_continuous_market(vega)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_liquidity_provision_amendment(continuous_market, vega: VegaServiceNull, page: Page):
|
||||
# TODO Refactor asserting the grid
|
||||
|
||||
@@ -1,13 +1,34 @@
|
||||
import pytest
|
||||
import logging
|
||||
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from typing import Tuple, Any
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup
|
||||
from fixtures.market import setup_continuous_market, market_exists
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET, PARTY_A, PARTY_B, PARTY_C, PARTY_D
|
||||
from vega_sim.service import VegaService
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
# region Constants
|
||||
ACTIVITY = "activity"
|
||||
HOARDER = "hoarder"
|
||||
COMBO = "combo"
|
||||
|
||||
REWARDS_URL = "/#/rewards"
|
||||
|
||||
# test IDs
|
||||
COMBINED_MULTIPLIERS = "combined-multipliers"
|
||||
TOTAL_REWARDS = "total-rewards"
|
||||
PRICE_TAKING_COL_ID = '[col-id="priceTaking"]'
|
||||
TOTAL_COL_ID = '[col-id="total"]'
|
||||
ROW = "row"
|
||||
STREAK_REWARD_MULTIPLIER_VALUE = "streak-reward-multiplier-value"
|
||||
HOARDER_REWARD_MULTIPLIER_VALUE = "hoarder-reward-multiplier-value"
|
||||
HOARDER_BONUS_TOTAL_HOARDED = "hoarder-bonus-total-hoarded"
|
||||
EARNED_BY_ME_BUTTON = "earned-by-me-button"
|
||||
TRANSFER_AMOUNT = "transfer-amount"
|
||||
EPOCH_STREAK = "epoch-streak"
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
@@ -24,19 +45,19 @@ def market_ids():
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_activity_tier_0(request):
|
||||
# with init_vega(request) as vega_activity_tier_0:
|
||||
with init_vega(request) as vega_activity_tier_0:
|
||||
yield vega_activity_tier_0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_hoarder_tier_0(request):
|
||||
# with init_vega(request) as vega_hoarder_tier_0:
|
||||
with init_vega(request) as vega_hoarder_tier_0:
|
||||
yield vega_hoarder_tier_0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_combo_tier_0(request):
|
||||
# with init_vega(request) as vega_combo_tier_0:
|
||||
with init_vega(request) as vega_combo_tier_0:
|
||||
yield vega_combo_tier_0
|
||||
|
||||
|
||||
@@ -48,79 +69,48 @@ def vega_activity_tier_1(request):
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_hoarder_tier_1(request):
|
||||
#with init_vega(request) as vega_hoarder_tier_1:
|
||||
with init_vega(request) as vega_hoarder_tier_1:
|
||||
yield vega_hoarder_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_combo_tier_1(request):
|
||||
# with init_vega(request) as vega_combo_tier_1:
|
||||
with init_vega(request) as vega_combo_tier_1:
|
||||
yield vega_combo_tier_1
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def auth(vega_instance, page):
|
||||
vega, _, _ = vega_instance
|
||||
return auth_setup(vega, page)
|
||||
return auth_setup(vega_instance, page)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def page(vega_instance, browser, request):
|
||||
vega, _, _ = vega_instance
|
||||
with init_page(vega, browser, request) as page_instance:
|
||||
with init_page(vega_instance, browser, request) as page_instance:
|
||||
yield page_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vega_instance(
|
||||
reward_program: str,
|
||||
vega_activity_tier_0: Any,
|
||||
vega_hoarder_tier_0: Any,
|
||||
vega_combo_tier_0: Any,
|
||||
vega_activity_tier_1: Any,
|
||||
vega_hoarder_tier_1: Any,
|
||||
vega_combo_tier_1: Any,
|
||||
market_ids: list,
|
||||
tier: int,
|
||||
) -> Tuple[Any, Any, Any]:
|
||||
"""
|
||||
Create a Vega instance based on the reward program and tier.
|
||||
|
||||
:param reward_program: The reward program type.
|
||||
:param vega_activity_tier_0: The Vega instance for activity tier 0.
|
||||
:param vega_hoarder_tier_0: The Vega instance for hoarder tier 0.
|
||||
:param vega_combo_tier_0: The Vega instance for combo tier 0.
|
||||
:param vega_activity_tier_1: The Vega instance for activity tier 1.
|
||||
:param vega_hoarder_tier_1: The Vega instance for hoarder tier 1.
|
||||
:param vega_combo_tier_1: The Vega instance for combo tier 1.
|
||||
:param market_ids: List of market IDs.
|
||||
:param tier: The tier level.
|
||||
:return: Tuple containing the Vega instance, market ID, and tDAI asset ID.
|
||||
"""
|
||||
|
||||
vega_tiers = {
|
||||
"activity": (vega_activity_tier_0, vega_activity_tier_1),
|
||||
"hoarder": (vega_hoarder_tier_0, vega_hoarder_tier_1),
|
||||
"combo": (vega_combo_tier_0, vega_combo_tier_1),
|
||||
}
|
||||
|
||||
if reward_program not in vega_tiers or tier not in (0, 1):
|
||||
logging.error(f"Invalid reward_program '{reward_program}' or tier '{tier}'")
|
||||
raise ValueError(f"Invalid reward_program '{reward_program}' or tier '{tier}'")
|
||||
|
||||
vega = vega_tiers[reward_program][tier]
|
||||
|
||||
# Set up market with the reward program
|
||||
logging.info("Setting up Vega Instance")
|
||||
market_id, tDAI_asset_id = set_market_reward_program(
|
||||
vega, reward_program, market_ids, tier
|
||||
)
|
||||
|
||||
return vega, market_id, tDAI_asset_id
|
||||
reward_program,
|
||||
vega_activity_tier_0,
|
||||
vega_hoarder_tier_0,
|
||||
vega_combo_tier_0,
|
||||
vega_activity_tier_1,
|
||||
vega_hoarder_tier_1,
|
||||
vega_combo_tier_1,
|
||||
tier,
|
||||
):
|
||||
if reward_program == "activity":
|
||||
return vega_activity_tier_0 if tier == 1 else vega_activity_tier_1
|
||||
elif reward_program == "hoarder":
|
||||
return vega_hoarder_tier_0 if tier == 1 else vega_hoarder_tier_1
|
||||
elif reward_program == "combo":
|
||||
return vega_combo_tier_0 if tier == 1 else vega_combo_tier_1
|
||||
|
||||
|
||||
def setup_market_with_reward_program(vega: VegaService, reward_programs, tier):
|
||||
print("Started setup_market_with_reward_program")
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull, reward_programs, tier):
|
||||
print(f"Started setup_market_with_{reward_programs}_{tier}")
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
@@ -128,7 +118,7 @@ def setup_market_with_reward_program(vega: VegaService, reward_programs, tier):
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
if "activity" in reward_programs:
|
||||
if ACTIVITY in reward_programs:
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.activityStreak.benefitTiers",
|
||||
@@ -137,7 +127,7 @@ def setup_market_with_reward_program(vega: VegaService, reward_programs, tier):
|
||||
print("update_network_parameter activity done")
|
||||
next_epoch(vega=vega)
|
||||
|
||||
if "hoarder" in reward_programs:
|
||||
if HOARDER in reward_programs:
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.vesting.benefitTiers",
|
||||
@@ -160,6 +150,7 @@ def setup_market_with_reward_program(vega: VegaService, reward_programs, tier):
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
# lock_period= 5,
|
||||
# TODO test lock period
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
@@ -181,7 +172,17 @@ def setup_market_with_reward_program(vega: VegaService, reward_programs, tier):
|
||||
)
|
||||
|
||||
vega.wait_for_total_catchup()
|
||||
""" if tier == 1:
|
||||
if tier == 1:
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_LIMIT",
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
side="SIDE_BUY",
|
||||
price=1,
|
||||
volume=1,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
@@ -199,46 +200,62 @@ def setup_market_with_reward_program(vega: VegaService, reward_programs, tier):
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_for_total_catchup() """
|
||||
|
||||
#next_epoch(vega=vega)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
if HOARDER in reward_programs:
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
def set_market_reward_program(vega, reward_program, market_ids, tier):
|
||||
market_id_key = f"vega_{reward_program}"
|
||||
if reward_program == "combo":
|
||||
market_id_key = "combo"
|
||||
|
||||
market_id_key = f"vega_{reward_program}_tier_{tier}"
|
||||
if reward_program == COMBO:
|
||||
market_id_key = COMBO
|
||||
market_id = market_ids.get(market_id_key, "default_id")
|
||||
|
||||
print(f"Checking if market exists: {market_id}")
|
||||
if not market_exists(vega, market_id):
|
||||
print(f"Market doesn't exist for {reward_program}. Setting up new market.")
|
||||
print(
|
||||
f"Market doesn't exist for {reward_program} {tier}. Setting up new market."
|
||||
)
|
||||
|
||||
reward_programs = [reward_program]
|
||||
if reward_program == "combo":
|
||||
reward_programs = ["activity", "hoarder"]
|
||||
if reward_program == COMBO:
|
||||
reward_programs = [ACTIVITY, HOARDER]
|
||||
|
||||
market_id = setup_market_with_reward_program(vega, reward_programs, tier)
|
||||
market_id, _ = setup_market_with_reward_program(vega, reward_programs, tier)
|
||||
market_ids[market_id_key] = market_id
|
||||
|
||||
print(f"Using market ID: {market_id}")
|
||||
return market_id
|
||||
return market_id, market_ids
|
||||
|
||||
|
||||
ACTIVITY_STREAKS = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_activity_streak": 1,
|
||||
"minimum_activity_streak": 2,
|
||||
"reward_multiplier": "2.0",
|
||||
"vesting_multiplier": "1.1"
|
||||
},
|
||||
{
|
||||
"minimum_activity_streak": 5,
|
||||
"reward_multiplier": "3.0",
|
||||
"vesting_multiplier": "1.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -247,12 +264,8 @@ VESTING = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_quantum_balance": "5000000",
|
||||
"minimum_quantum_balance": "10000000",
|
||||
"reward_multiplier": "2"
|
||||
},
|
||||
{
|
||||
"minimum_quantum_balance": "11666668",
|
||||
"reward_multiplier": "3"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -262,134 +275,195 @@ VESTING = """
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, total_rewards",
|
||||
[
|
||||
#("activity", 0, "50.00 tDAI"),
|
||||
#("hoarder", 0, "50.00 tDAI"),
|
||||
#("combo", 0, "50.00 tDAI"),
|
||||
("activity", 1, "110.00 tDAI"),
|
||||
#("hoarder", 1, "116.66666 tDAI"),
|
||||
#("combo", 1, "125.00 tDAI"),
|
||||
(ACTIVITY, 0, "50.00 tDAI"),
|
||||
(HOARDER, 0, "50.00 tDAI"),
|
||||
(COMBO, 0, "50.00 tDAI"),
|
||||
(ACTIVITY, 1, "116.66666 tDAI"),
|
||||
(HOARDER, 1, "166.66666 tDAI "),
|
||||
(COMBO, 1, "183.33333 tDAI"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.skip("tbd")
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_network_reward_pot(
|
||||
reward_program, vega_instance: VegaService, page: Page, total_rewards, tier
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
total_rewards,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
vega, market_id, tDAI_asset_id = vega_instance
|
||||
next_epoch(vega=vega)
|
||||
|
||||
page.goto(f"/#/rewards")
|
||||
if tier == 1:
|
||||
page.pause()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=market_id,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=market_id,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_for_total_catchup()
|
||||
page.pause()
|
||||
next_epoch(vega=vega)
|
||||
page.pause()
|
||||
next_epoch(vega=vega)
|
||||
change_keys(page, vega, PARTY_B.name)
|
||||
page.pause()
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
|
||||
expect(page.get_by_test_id("total-rewards")).to_have_text(total_rewards)
|
||||
# TODO Add test ID and Assert for locked,
|
||||
|
||||
|
||||
|
||||
""" @pytest.mark.parametrize(
|
||||
"reward_program",
|
||||
[
|
||||
("activity"),
|
||||
# ("hoarder"),
|
||||
# ("combo"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_vesting(vega_setup, vega: VegaService, page: Page):
|
||||
expect() """
|
||||
|
||||
@pytest.mark.skip("tbd")
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, reward_multiplier",
|
||||
[
|
||||
("activity", 0, "1x"),
|
||||
("hoarder", 0, "1x"),
|
||||
("combo", 0, "1x"),
|
||||
("activity", 1, "2x"),
|
||||
("hoarder", 1, "2x"),
|
||||
("combo", 1, "4x"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_reward_multiplier(reward_program, vega_instance: VegaService, page: Page, reward_multiplier, tier):
|
||||
vega, market_id, tDAI_asset_id = vega_instance
|
||||
page.goto(f"/#/rewards")
|
||||
change_keys(page, vega, PARTY_B.name)
|
||||
expect(page.get_by_test_id("combined-multipliers")).to_have_text(reward_multiplier)
|
||||
#TODO add test ids and assert for individual multipliers
|
||||
|
||||
"""
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program",
|
||||
[
|
||||
("activity"),
|
||||
# ("hoarder"),
|
||||
# ("combo"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_activity_streak(vega_setup, vega: VegaService, page: Page):
|
||||
expect()
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text(total_rewards)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program",
|
||||
"reward_program, tier, reward_multiplier, streak_multiplier, hoarder_multiplier",
|
||||
[
|
||||
("activity"),
|
||||
# ("hoarder"),
|
||||
# ("combo"),
|
||||
(ACTIVITY, 0, "1x", "1x", "1x"),
|
||||
(HOARDER, 0, "1x", "1x", "1x"),
|
||||
(COMBO, 0, "1x", "1x", "1x"),
|
||||
(ACTIVITY, 1, "2x", "2x", "1x"),
|
||||
(HOARDER, 1, "2x", "1x", "2x"),
|
||||
(COMBO, 1, "4x", "2x", "2x"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_hoarder_Bonus(vega_setup, vega: VegaService, page: Page):
|
||||
expect()
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_reward_multiplier(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
reward_multiplier,
|
||||
streak_multiplier,
|
||||
hoarder_multiplier,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text(reward_multiplier)
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text(
|
||||
streak_multiplier
|
||||
)
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text(
|
||||
hoarder_multiplier
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program",
|
||||
"reward_program, tier, epoch_streak",
|
||||
[
|
||||
("activity"),
|
||||
# ("hoarder"),
|
||||
# ("combo"),
|
||||
(ACTIVITY, 0, "1"),
|
||||
(ACTIVITY, 1, "7"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_Rewards_history(vega_setup, vega: VegaService, page: Page):
|
||||
expect()
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_activity_streak(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
epoch_streak,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
if tier == 1:
|
||||
expect(page.get_by_test_id(EPOCH_STREAK)).to_have_text(
|
||||
"Active trader: " + epoch_streak + " epochs so far (Tier 1 as of last epoch)"
|
||||
)
|
||||
else:
|
||||
expect(page.get_by_test_id(EPOCH_STREAK)).to_have_text(
|
||||
"Active trader: " + epoch_streak + " epochs so far "
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_redeem(vega_setup, vega: VegaService, page: Page):
|
||||
expect()
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, rewards_hoarded",
|
||||
[
|
||||
(HOARDER, 0, "5,000,000"),
|
||||
(HOARDER, 1, "16,666,666"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_hoarder_bonus(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
rewards_hoarded,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
expect(page.get_by_test_id(HOARDER_BONUS_TOTAL_HOARDED)).to_contain_text(
|
||||
rewards_hoarded
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_redeem(vega_setup, vega: VegaService, page: Page):
|
||||
expect()
|
||||
"""
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, price_taking, total, earned_by_me",
|
||||
[
|
||||
(ACTIVITY, 0, "100.00100.00%", "100.00", "50.00"),
|
||||
(HOARDER, 0, "100.00100.00%", "100.00", "50.00"),
|
||||
(COMBO, 0, "100.00100.00%", "100.00", "50.00"),
|
||||
(ACTIVITY, 1, "300.00100.00%", "300.00", "116.66666"),
|
||||
(HOARDER, 1, "299.99999100.00%", "299.99999", "166.66666"),
|
||||
(COMBO, 1, "299.99999100.00%", "299.99999", "183.33333"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_reward_history(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
price_taking,
|
||||
total,
|
||||
earned_by_me,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
price_taking
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(total)
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||
earned_by_me
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier",
|
||||
[
|
||||
(ACTIVITY, 1),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_redeem(
|
||||
reward_program, vega_instance: VegaServiceNull, page: Page, tier, market_ids
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
page.get_by_test_id("redeem-rewards-button").click()
|
||||
available_to_withdraw = page.get_by_test_id(
|
||||
"available-to-withdraw-value"
|
||||
).text_content()
|
||||
option_value = page.locator(
|
||||
'[data-testid="transfer-form"] [name="fromAccount"] option[value^="ACCOUNT_TYPE_VESTED_REWARDS"]'
|
||||
).first.get_attribute("value")
|
||||
|
||||
page.select_option(
|
||||
'[data-testid="transfer-form"] [name="fromAccount"]', option_value
|
||||
)
|
||||
|
||||
page.get_by_test_id("use-max-button").first.click()
|
||||
expect(page.get_by_test_id(TRANSFER_AMOUNT)).to_have_text(available_to_withdraw)
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import pytest
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET, PARTY_A, PARTY_B
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth")
|
||||
def test_vesting(continuous_market, vega: VegaServiceNull, page: Page):
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
lock_period=5,
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=continuous_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=continuous_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.goto("/#/rewards")
|
||||
change_keys(page, vega, PARTY_B.name)
|
||||
next_epoch(vega=vega)
|
||||
page.reload()
|
||||
|
||||
expect(page.get_by_test_id("locked-value")).to_have_text("50.00")
|
||||
|
||||
# Proceed through the 5 epoch lock period
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
page.reload()
|
||||
|
||||
expect(page.get_by_test_id("locked-value")).to_have_text("0.00")
|
||||
expect(page.get_by_test_id("vesting-value")).to_have_text("37.50")
|
||||
expect(page.get_by_test_id("available-to-withdraw-value")).to_have_text("12.50")
|
||||
@@ -146,7 +146,7 @@ def test_transfer_vesting_below_minimum(
|
||||
vega.wait_fn(10)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.get_by_text("Use max").first.click()
|
||||
page.get_by_test_id("use-max-button").first.click()
|
||||
page.locator('[data-testid=transfer-form] [type="submit"]').click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
|
||||
@@ -438,6 +438,7 @@ export const TransferForm = ({
|
||||
shouldValidate: true,
|
||||
})
|
||||
}
|
||||
data-testid="use-max-button"
|
||||
>
|
||||
{t('Use max')}
|
||||
</button>
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
"MoreMarketsInfo": "To see Explorer data on existing markets visit",
|
||||
"MoreNetParamsInfo": "To see Explorer data on network params visit",
|
||||
"MoreProposalsInfo": "To see Explorer data on proposals visit",
|
||||
"multisigContractIncorrect": "is incorrectly configured. Validator and delegator rewards will be penalised until this is resolved.",
|
||||
"multisigContractIncorrect": "was incorrectly configured as at the end of the last epoch so rewards were penalised. Validator and delegator rewards will continue to be penalised until this is resolved.",
|
||||
"multisigContractLink": "Ethereum Multisig Contract",
|
||||
"multisigPenalty": "Multisig penalty",
|
||||
"myPendingStake": "My pending stake",
|
||||
|
||||
@@ -83,11 +83,6 @@ describe('LiquidityTable', () => {
|
||||
h.querySelector('[ref="eText"]')?.textContent?.trim()
|
||||
);
|
||||
const expectedHeaders = [
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
'Party',
|
||||
'Status',
|
||||
'Commitment ()',
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
truncateMiddle,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import type {
|
||||
ColGroupDef,
|
||||
ColDef,
|
||||
ITooltipParams,
|
||||
ValueFormatterParams,
|
||||
} from 'ag-grid-community';
|
||||
@@ -60,10 +60,11 @@ const dateValueFormatter = ({ value }: { value?: string | null }) => {
|
||||
return getDateTimeFormat().format(new Date(value));
|
||||
};
|
||||
|
||||
const defaultColDef = {
|
||||
const defaultColDef: ColDef = {
|
||||
resizable: true,
|
||||
sortable: true,
|
||||
tooltipComponent: TooltipCellComponent,
|
||||
minWidth: 120,
|
||||
};
|
||||
|
||||
export interface LiquidityTableProps
|
||||
@@ -168,333 +169,300 @@ export const LiquidityTable = ({
|
||||
)}`;
|
||||
};
|
||||
|
||||
const defs: ColGroupDef[] = [
|
||||
const defs: ColDef[] = [
|
||||
{
|
||||
headerName: '',
|
||||
children: [
|
||||
{
|
||||
headerName: t('Party'),
|
||||
field: 'partyId',
|
||||
headerTooltip: t(
|
||||
'The public key of the party making this commitment.'
|
||||
),
|
||||
cellRenderer: copyCellRenderer,
|
||||
},
|
||||
],
|
||||
headerName: t('Party'),
|
||||
field: 'partyId',
|
||||
headerTooltip: t('The public key of the party making this commitment.'),
|
||||
cellRenderer: copyCellRenderer,
|
||||
pinned: 'left',
|
||||
},
|
||||
{
|
||||
headerName: t('Commitment details'),
|
||||
marryChildren: true,
|
||||
children: [
|
||||
{
|
||||
headerName: t('Status'),
|
||||
headerTooltip: t('The current status of this liquidity provision.'),
|
||||
field: 'status',
|
||||
cellRenderer: ({
|
||||
data,
|
||||
value,
|
||||
}: VegaICellRendererParams<LiquidityProvisionData, 'status'>) => {
|
||||
if (!value) return value;
|
||||
if (
|
||||
data?.status === LiquidityProvisionStatus.STATUS_PENDING &&
|
||||
(data?.currentCommitmentAmount || data?.currentFee)
|
||||
) {
|
||||
return (
|
||||
<span className="text-warning">
|
||||
{t('Updating next epoch')}
|
||||
</span>
|
||||
);
|
||||
headerName: t('Status'),
|
||||
headerTooltip: t('The current status of this liquidity provision.'),
|
||||
field: 'status',
|
||||
cellRenderer: ({
|
||||
data,
|
||||
value,
|
||||
}: VegaICellRendererParams<LiquidityProvisionData, 'status'>) => {
|
||||
if (!value) return value;
|
||||
if (
|
||||
data?.status === LiquidityProvisionStatus.STATUS_PENDING &&
|
||||
(data?.currentCommitmentAmount || data?.currentFee)
|
||||
) {
|
||||
return (
|
||||
<span className="text-warning">{t('Updating next epoch')}</span>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<span>
|
||||
{
|
||||
LiquidityProvisionStatusMapping[
|
||||
value as LiquidityProvisionStatus
|
||||
]
|
||||
}
|
||||
return (
|
||||
<span>
|
||||
{
|
||||
LiquidityProvisionStatusMapping[
|
||||
value as LiquidityProvisionStatus
|
||||
]
|
||||
}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
headerName: t(`Commitment ({{symbol}})`, { symbol }),
|
||||
field: 'commitmentAmount',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The amount committed to the market by this liquidity provider.'
|
||||
),
|
||||
cellRenderer: ({
|
||||
data,
|
||||
value,
|
||||
}: VegaICellRendererParams<
|
||||
LiquidityProvisionData,
|
||||
'commitmentAmount'
|
||||
>) => {
|
||||
if (!value) return '-';
|
||||
const currentCommitmentAmount = data?.currentCommitmentAmount;
|
||||
const pendingCommitmentAmount = value;
|
||||
|
||||
const formattedPendingCommitmentAmount =
|
||||
addDecimalsFormatNumberQuantum(
|
||||
pendingCommitmentAmount,
|
||||
assetDecimalPlaces ?? 0,
|
||||
quantum ?? 0
|
||||
);
|
||||
|
||||
if (
|
||||
currentCommitmentAmount &&
|
||||
currentCommitmentAmount !== pendingCommitmentAmount
|
||||
) {
|
||||
const formattedCurrentCommitmentAmount =
|
||||
addDecimalsFormatNumberQuantum(
|
||||
currentCommitmentAmount,
|
||||
assetDecimalPlaces ?? 0,
|
||||
quantum ?? 0
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
headerName: t(`Commitment ({{symbol}})`, { symbol }),
|
||||
field: 'commitmentAmount',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The amount committed to the market by this liquidity provider.'
|
||||
),
|
||||
cellRenderer: ({
|
||||
data,
|
||||
value,
|
||||
}: VegaICellRendererParams<
|
||||
LiquidityProvisionData,
|
||||
'commitmentAmount'
|
||||
>) => {
|
||||
if (!value) return '-';
|
||||
const currentCommitmentAmount = data?.currentCommitmentAmount;
|
||||
const pendingCommitmentAmount = value;
|
||||
|
||||
const formattedPendingCommitmentAmount =
|
||||
addDecimalsFormatNumberQuantum(
|
||||
pendingCommitmentAmount,
|
||||
assetDecimalPlaces ?? 0,
|
||||
quantum ?? 0
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<span>{formattedCurrentCommitmentAmount}</span> (
|
||||
<span className="text-warning">
|
||||
{formattedPendingCommitmentAmount}
|
||||
</span>
|
||||
)
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return formattedPendingCommitmentAmount;
|
||||
}
|
||||
},
|
||||
tooltipValueGetter: assetDecimalsFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Obligation'),
|
||||
field: 'commitmentAmount',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`The liquidity provider's obligation to the market, calculated as the liquidity commitment amount multiplied by the value of the stake_to_ccy_volume network parameter to convert into units of liquidity volume.`
|
||||
),
|
||||
cellRenderer: ({
|
||||
data,
|
||||
value,
|
||||
}: VegaICellRendererParams<
|
||||
LiquidityProvisionData,
|
||||
'commitmentAmount'
|
||||
>) => {
|
||||
if (!value) return '-';
|
||||
|
||||
if (
|
||||
currentCommitmentAmount &&
|
||||
currentCommitmentAmount !== pendingCommitmentAmount
|
||||
) {
|
||||
const formattedCurrentCommitmentAmount =
|
||||
addDecimalsFormatNumberQuantum(
|
||||
currentCommitmentAmount,
|
||||
assetDecimalPlaces ?? 0,
|
||||
quantum ?? 0
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<span>{formattedCurrentCommitmentAmount}</span> (
|
||||
<span className="text-warning">
|
||||
{formattedPendingCommitmentAmount}
|
||||
</span>
|
||||
)
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return formattedPendingCommitmentAmount;
|
||||
}
|
||||
},
|
||||
tooltipValueGetter: assetDecimalsFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Obligation'),
|
||||
field: 'commitmentAmount',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`The liquidity provider's obligation to the market, calculated as the liquidity commitment amount multiplied by the value of the stake_to_ccy_volume network parameter to convert into units of liquidity volume.`
|
||||
),
|
||||
cellRenderer: ({
|
||||
data,
|
||||
value,
|
||||
}: VegaICellRendererParams<
|
||||
LiquidityProvisionData,
|
||||
'commitmentAmount'
|
||||
>) => {
|
||||
if (!value) return '-';
|
||||
|
||||
const currentCommitmentAmount = data?.currentCommitmentAmount
|
||||
? new BigNumber(data?.currentCommitmentAmount)
|
||||
.times(Number(stakeToCcyVolume) || 1)
|
||||
.toString()
|
||||
: undefined;
|
||||
|
||||
const pendingCommitmentAmount = new BigNumber(value)
|
||||
const currentCommitmentAmount = data?.currentCommitmentAmount
|
||||
? new BigNumber(data?.currentCommitmentAmount)
|
||||
.times(Number(stakeToCcyVolume) || 1)
|
||||
.toString();
|
||||
.toString()
|
||||
: undefined;
|
||||
|
||||
const formattedPendingCommitmentAmount =
|
||||
addDecimalsFormatNumberQuantum(
|
||||
pendingCommitmentAmount,
|
||||
assetDecimalPlaces ?? 0,
|
||||
quantum ?? 0
|
||||
);
|
||||
const pendingCommitmentAmount = new BigNumber(value)
|
||||
.times(Number(stakeToCcyVolume) || 1)
|
||||
.toString();
|
||||
|
||||
if (
|
||||
currentCommitmentAmount &&
|
||||
currentCommitmentAmount !== pendingCommitmentAmount
|
||||
) {
|
||||
const formattedCurrentCommitmentAmount =
|
||||
addDecimalsFormatNumberQuantum(
|
||||
currentCommitmentAmount,
|
||||
assetDecimalPlaces ?? 0,
|
||||
quantum ?? 0
|
||||
);
|
||||
const formattedPendingCommitmentAmount =
|
||||
addDecimalsFormatNumberQuantum(
|
||||
pendingCommitmentAmount,
|
||||
assetDecimalPlaces ?? 0,
|
||||
quantum ?? 0
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<span>{formattedCurrentCommitmentAmount}</span> (
|
||||
<span className="text-warning">
|
||||
{formattedPendingCommitmentAmount}
|
||||
</span>
|
||||
)
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return formattedPendingCommitmentAmount;
|
||||
}
|
||||
},
|
||||
tooltipValueGetter: stakeToCcyVolumeFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Fee'),
|
||||
headerTooltip: t(
|
||||
'The fee percentage (per trade) proposed by each liquidity provider.'
|
||||
),
|
||||
field: 'fee',
|
||||
type: 'rightAligned',
|
||||
cellRenderer: ({
|
||||
data,
|
||||
value,
|
||||
}: VegaICellRendererParams<LiquidityProvisionData, 'fee'>) => {
|
||||
if (!value) return '-';
|
||||
const formattedPendingFee =
|
||||
formatNumberPercentage(new BigNumber(value).times(100), 2) ||
|
||||
'-';
|
||||
if (data?.currentFee && data?.currentFee !== value) {
|
||||
const formattedCurrentFee = formatNumberPercentage(
|
||||
new BigNumber(data.currentFee).times(100),
|
||||
2
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<span>{formattedCurrentFee}</span> (
|
||||
<span className="text-warning">{formattedPendingFee}</span>)
|
||||
</>
|
||||
);
|
||||
}
|
||||
return formattedPendingFee;
|
||||
},
|
||||
},
|
||||
{
|
||||
headerName: t('Adjusted stake'),
|
||||
field: 'feeShare.virtualStake',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The effective stake of the liquidity provider, adjusted for length of commitment and impact on equity like share.'
|
||||
),
|
||||
if (
|
||||
currentCommitmentAmount &&
|
||||
currentCommitmentAmount !== pendingCommitmentAmount
|
||||
) {
|
||||
const formattedCurrentCommitmentAmount =
|
||||
addDecimalsFormatNumberQuantum(
|
||||
currentCommitmentAmount,
|
||||
assetDecimalPlaces ?? 0,
|
||||
quantum ?? 0
|
||||
);
|
||||
|
||||
valueFormatter: assetDecimalsQuantumFormatter,
|
||||
tooltipValueGetter: assetDecimalsFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t(`Share`),
|
||||
field: 'feeShare.equityLikeShare',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The equity-like share of liquidity of the market used to determine allocation of LP fees. Calculated based on share of total liquidity, with a premium added for length of commitment.'
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
],
|
||||
return (
|
||||
<>
|
||||
<span>{formattedCurrentCommitmentAmount}</span> (
|
||||
<span className="text-warning">
|
||||
{formattedPendingCommitmentAmount}
|
||||
</span>
|
||||
)
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return formattedPendingCommitmentAmount;
|
||||
}
|
||||
},
|
||||
tooltipValueGetter: stakeToCcyVolumeFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Live liquidity data'),
|
||||
marryChildren: true,
|
||||
children: [
|
||||
{
|
||||
headerName: t('Live supplied liquidity'),
|
||||
field: 'balance',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`The amount of liquidity volume supplied by the LP order in order to meet the obligation. If the obligation is already met in full by other limit orders from the same Vega key the LP order is not required and this value will be zero. Also note if the target stake for the market is less than the obligation the full value of the obligation may not be required.`
|
||||
),
|
||||
valueFormatter: stakeToCcyVolumeQuantumFormatter,
|
||||
tooltipValueGetter: stakeToCcyVolumeFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Fees accrued this epoch'),
|
||||
field: 'earmarkedFees',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`The liquidity fees accrued by each provider, which will be distributed at the end of the epoch after applying any penalties.`
|
||||
),
|
||||
valueFormatter: assetDecimalsQuantumFormatter,
|
||||
tooltipValueGetter: feesAccruedTooltip,
|
||||
cellClassRules: {
|
||||
'text-warning': ({ data }: { data: LiquidityProvisionData }) => {
|
||||
if (!data.sla) return false;
|
||||
return (
|
||||
new BigNumber(
|
||||
data.sla.currentEpochFractionOfTimeOnBook
|
||||
).isLessThan(1) &&
|
||||
new BigNumber(
|
||||
data.sla.currentEpochFractionOfTimeOnBook
|
||||
).isGreaterThan(data.commitmentMinTimeFraction)
|
||||
);
|
||||
},
|
||||
'text-red-500': ({ data }: { data: LiquidityProvisionData }) => {
|
||||
if (!data.sla) return false;
|
||||
return new BigNumber(
|
||||
data.sla.currentEpochFractionOfTimeOnBook
|
||||
).isLessThan(data.commitmentMinTimeFraction);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
headerName: t(`Live time on book`),
|
||||
field: 'sla.currentEpochFractionOfTimeOnBook',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t('Current epoch fraction of time on the book.'),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Live liquidity score (%)'),
|
||||
field: 'feeShare.averageScore',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The liquidity score of the provider, used to determine allocation of fees to the best performing LPs. Posting volume closer to the mid on both sides of the book will improve this score.'
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
],
|
||||
headerName: t('Fee'),
|
||||
headerTooltip: t(
|
||||
'The fee percentage (per trade) proposed by each liquidity provider.'
|
||||
),
|
||||
field: 'fee',
|
||||
type: 'rightAligned',
|
||||
cellRenderer: ({
|
||||
data,
|
||||
value,
|
||||
}: VegaICellRendererParams<LiquidityProvisionData, 'fee'>) => {
|
||||
if (!value) return '-';
|
||||
const formattedPendingFee =
|
||||
formatNumberPercentage(new BigNumber(value).times(100), 2) || '-';
|
||||
if (data?.currentFee && data?.currentFee !== value) {
|
||||
const formattedCurrentFee = formatNumberPercentage(
|
||||
new BigNumber(data.currentFee).times(100),
|
||||
2
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<span>{formattedCurrentFee}</span> (
|
||||
<span className="text-warning">{formattedPendingFee}</span>)
|
||||
</>
|
||||
);
|
||||
}
|
||||
return formattedPendingFee;
|
||||
},
|
||||
},
|
||||
{
|
||||
headerName: t('Last epoch SLA details'),
|
||||
marryChildren: true,
|
||||
children: [
|
||||
{
|
||||
headerName: t(`Last time on book`),
|
||||
field: 'sla.lastEpochFractionOfTimeOnBook',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'Fraction of time on the book at the end of the last epoch.'
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t(`Last fee penalty`),
|
||||
field: 'sla.lastEpochFeePenalty',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'Penalty applied on the fees a liquidity provider collected in the last epoch. This percentage increased if an LP did not meet the SLA, or if they met it but other LPs outscored them in the previous epoch.'
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t(`Last bond penalty`),
|
||||
field: 'sla.lastEpochBondPenalty',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`Penalty applied on a provider's bond penalty at the end of the last epoch. This percentage increased if an LP: had a shortfall and their bond needed to be used to cover it, did not meet the SLA, and/or reduced their commitment to the point that the market was below its target stake.`
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
],
|
||||
headerName: t('Adjusted stake'),
|
||||
field: 'feeShare.virtualStake',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The effective stake of the liquidity provider, adjusted for length of commitment and impact on equity like share.'
|
||||
),
|
||||
|
||||
valueFormatter: assetDecimalsQuantumFormatter,
|
||||
tooltipValueGetter: assetDecimalsFormatter,
|
||||
},
|
||||
{
|
||||
headerName: '',
|
||||
marryChildren: true,
|
||||
children: [
|
||||
{
|
||||
headerName: t('Created'),
|
||||
headerTooltip: t(
|
||||
'The date and time this liquidity provision was created.'
|
||||
),
|
||||
field: 'createdAt',
|
||||
type: 'rightAligned',
|
||||
valueFormatter: dateValueFormatter,
|
||||
headerName: t(`Share`),
|
||||
field: 'feeShare.equityLikeShare',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The equity-like share of liquidity of the market used to determine allocation of LP fees. Calculated based on share of total liquidity, with a premium added for length of commitment.'
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Live supplied liquidity'),
|
||||
field: 'balance',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`The amount of liquidity volume supplied by the LP order in order to meet the obligation. If the obligation is already met in full by other limit orders from the same Vega key the LP order is not required and this value will be zero. Also note if the target stake for the market is less than the obligation the full value of the obligation may not be required.`
|
||||
),
|
||||
valueFormatter: stakeToCcyVolumeQuantumFormatter,
|
||||
tooltipValueGetter: stakeToCcyVolumeFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Fees accrued this epoch'),
|
||||
field: 'earmarkedFees',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`The liquidity fees accrued by each provider, which will be distributed at the end of the epoch after applying any penalties.`
|
||||
),
|
||||
valueFormatter: assetDecimalsQuantumFormatter,
|
||||
tooltipValueGetter: feesAccruedTooltip,
|
||||
cellClassRules: {
|
||||
'text-warning': ({ data }: { data: LiquidityProvisionData }) => {
|
||||
if (!data.sla) return false;
|
||||
return (
|
||||
new BigNumber(
|
||||
data.sla.currentEpochFractionOfTimeOnBook
|
||||
).isLessThan(1) &&
|
||||
new BigNumber(
|
||||
data.sla.currentEpochFractionOfTimeOnBook
|
||||
).isGreaterThan(data.commitmentMinTimeFraction)
|
||||
);
|
||||
},
|
||||
{
|
||||
headerName: t('Updated'),
|
||||
headerTooltip: t(
|
||||
'The date and time this liquidity provision was last updated.'
|
||||
),
|
||||
field: 'updatedAt',
|
||||
type: 'rightAligned',
|
||||
valueFormatter: dateValueFormatter,
|
||||
'text-red-500': ({ data }: { data: LiquidityProvisionData }) => {
|
||||
if (!data.sla) return false;
|
||||
return new BigNumber(
|
||||
data.sla.currentEpochFractionOfTimeOnBook
|
||||
).isLessThan(data.commitmentMinTimeFraction);
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
headerName: t(`Live time on book`),
|
||||
field: 'sla.currentEpochFractionOfTimeOnBook',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t('Current epoch fraction of time on the book.'),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Live liquidity score (%)'),
|
||||
field: 'feeShare.averageScore',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The liquidity score of the provider, used to determine allocation of fees to the best performing LPs. Posting volume closer to the mid on both sides of the book will improve this score.'
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t(`Last time on book`),
|
||||
field: 'sla.lastEpochFractionOfTimeOnBook',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'Fraction of time on the book at the end of the last epoch.'
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t(`Last fee penalty`),
|
||||
field: 'sla.lastEpochFeePenalty',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'Penalty applied on the fees a liquidity provider collected in the last epoch. This percentage increased if an LP did not meet the SLA, or if they met it but other LPs outscored them in the previous epoch.'
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t(`Last bond penalty`),
|
||||
field: 'sla.lastEpochBondPenalty',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`Penalty applied on a provider's bond penalty at the end of the last epoch. This percentage increased if an LP: had a shortfall and their bond needed to be used to cover it, did not meet the SLA, and/or reduced their commitment to the point that the market was below its target stake.`
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Created'),
|
||||
headerTooltip: t(
|
||||
'The date and time this liquidity provision was created.'
|
||||
),
|
||||
field: 'createdAt',
|
||||
type: 'rightAligned',
|
||||
valueFormatter: dateValueFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Updated'),
|
||||
headerTooltip: t(
|
||||
'The date and time this liquidity provision was last updated.'
|
||||
),
|
||||
field: 'updatedAt',
|
||||
type: 'rightAligned',
|
||||
valueFormatter: dateValueFormatter,
|
||||
},
|
||||
];
|
||||
return defs;
|
||||
|
||||
@@ -262,6 +262,7 @@ export const MarketInfoAccordion = ({
|
||||
<PriceMonitoringBoundsInfoPanel
|
||||
market={market}
|
||||
triggerIndex={triggerIndex}
|
||||
key={id}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -698,17 +698,13 @@ export const PriceMonitoringBoundsInfoPanel = ({
|
||||
|
||||
const quoteUnit = getQuoteName(market);
|
||||
|
||||
const trigger =
|
||||
market.priceMonitoringSettings?.parameters?.triggers?.[triggerIndex];
|
||||
|
||||
const bounds = data?.priceMonitoringBounds?.[triggerIndex];
|
||||
const trigger = bounds?.trigger;
|
||||
|
||||
if (!trigger) {
|
||||
console.error(
|
||||
`Could not find data for trigger ${triggerIndex} (market id: ${market.id})`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-2 grid grid-cols-2 text-sm">
|
||||
|
||||
Reference in New Issue
Block a user