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

Funding fee feature #2584

Merged
merged 12 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,10 @@ jobs:
./target/debug/coordinator &> ./data/coordinator/regtest.log &
just wait-for-coordinator-to-be-ready
echo "Coordinator successfully started."
echo "Starting coordinator postgrest server"
just postgrest-coordinator
echo "Started coordinator postgrest server"
- name: Run maker
run: |
just run-maker-detached
Expand Down
56 changes: 56 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions coordinator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ parking_lot = { version = "0.12.1" }
payout_curve = { path = "../crates/payout_curve" }
prometheus = "0.13.3"
rand = "0.8.5"
reqwest = { version = "0.11" }
rust_decimal = { version = "1", features = ["serde-with-float"] }
rust_decimal_macros = "1"
semver = "1.0"
Expand Down
2 changes: 2 additions & 0 deletions coordinator/example-settings/prod-coordinator-settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ close_expired_position_scheduler = "0 0 12 * * *"
close_liquidated_position_scheduler = "0 0 12 * * *"
update_user_bonus_status_scheduler = "0 0 0 * * *"
collect_metrics_scheduler = "0 0 * * * *"
generate_funding_fee_events_scheduler = "* * * * *"
whitelist_enabled = false
whitelisted_makers = []
min_quantity = 1
maintenance_margin_rate = 0.1
order_matching_fee_rate = 0.003
index_price_source = "Bitmex"

[xxi]
off_chain_sync_interval = 5
Expand Down
2 changes: 2 additions & 0 deletions coordinator/example-settings/test-coordinator-settings.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ close_expired_position_scheduler = "0 0 12 * * *"
close_liquidated_position_scheduler = "0 0 12 * * *"
update_user_bonus_status_scheduler = "0 0 0 * * *"
collect_metrics_scheduler = "0 0 * * * *"
generate_funding_fee_events_scheduler = "1/5 * * * * *"
whitelist_enabled = false
# Default testnet maker
whitelisted_makers = ["035eccdd1f05c65b433cf38e3b2597e33715e0392cb14d183e812f1319eb7b6794"]
min_quantity = 1
maintenance_margin_rate = 0.1
order_matching_fee_rate = 0.003
index_price_source = "Test"

[xxi]
off_chain_sync_interval = 5
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS rollover_params;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CREATE TABLE rollover_params
(
id SERIAL PRIMARY KEY NOT NULL,
protocol_id UUID NOT NULL REFERENCES dlc_protocols (protocol_id),
trader_pubkey TEXT NOT NULL,
margin_coordinator_sat BIGINT NOT NULL,
margin_trader_sat BIGINT NOT NULL,
leverage_coordinator REAL NOT NULL,
leverage_trader REAL NOT NULL,
liquidation_price_coordinator REAL NOT NULL,
liquidation_price_trader REAL NOT NULL,
expiry_timestamp TIMESTAMP WITH TIME ZONE NOT NULL
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
drop table if exists funding_rates;
drop table if exists funding_fee_event;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
CREATE TABLE funding_rates
(
id SERIAL PRIMARY KEY NOT NULL,
start_date TIMESTAMP WITH TIME ZONE NOT NULL,
end_date TIMESTAMP WITH TIME ZONE NOT NULL,
rate REAL NOT NULL,
timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE funding_fee_events
(
id SERIAL PRIMARY KEY NOT NULL,
amount_sats BIGINT NOT NULL,
trader_pubkey TEXT NOT NULL,
position_id INTEGER REFERENCES positions (id) NOT NULL,
due_date TIMESTAMP WITH TIME ZONE NOT NULL,
price REAL NOT NULL,
funding_rate REAL NOT NULL,
paid_date TIMESTAMP WITH TIME ZONE,
timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- To prevent generating duplicates for the same position.
UNIQUE (position_id, due_date)
);

CREATE TABLE protocol_funding_fee_events
luckysori marked this conversation as resolved.
Show resolved Hide resolved
(
id SERIAL PRIMARY KEY NOT NULL,
protocol_id UUID REFERENCES dlc_protocols (protocol_id) NOT NULL,
funding_fee_event_id INTEGER REFERENCES funding_fee_events (id) NOT NULL,
timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
);
16 changes: 13 additions & 3 deletions coordinator/src/bin/coordinator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use coordinator::cli::Opts;
use coordinator::db;
use coordinator::dlc_handler;
use coordinator::dlc_handler::DlcHandler;
use coordinator::funding_fee::generate_funding_fee_events_periodically;
use coordinator::logger;
use coordinator::message::spawn_delivering_messages_to_authenticated_users;
use coordinator::message::NewUserMessage;
Expand Down Expand Up @@ -41,6 +42,7 @@ use std::sync::Arc;
use std::time::Duration;
use tokio::sync::broadcast;
use tokio::task::spawn_blocking;
use tokio_cron_scheduler::JobScheduler;
use tracing::metadata::LevelFilter;
use xxi_node::node::event::NodeEventHandler;
use xxi_node::seed::Bip39Seed;
Expand Down Expand Up @@ -319,12 +321,10 @@ async fn main() -> Result<()> {
);

let sender = notification_service.get_sender();
let notification_scheduler = NotificationScheduler::new(sender, settings, network, node);
let scheduler = NotificationScheduler::new(sender, settings.clone(), network, node).await;
tokio::spawn({
let pool = pool.clone();
let scheduler = notification_scheduler;
async move {
let scheduler = scheduler.await;
scheduler
.add_rollover_window_reminder_job(pool.clone())
.await
Expand Down Expand Up @@ -371,6 +371,16 @@ async fn main() -> Result<()> {
tracing::error!("Failed to set expired hodl invoices to canceled. Error: {e:#}");
}

generate_funding_fee_events_periodically(
&JobScheduler::new().await?,
pool.clone(),
auth_users_notifier,
settings.generate_funding_fee_events_scheduler,
settings.index_price_source,
)
.await
.expect("to start task");

tracing::debug!("Listening on http://{}", http_address);

match axum::Server::bind(&http_address)
Expand Down
15 changes: 8 additions & 7 deletions coordinator/src/db/dlc_protocols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ pub(crate) fn get_dlc_protocol(
DlcProtocolType::ForceClose => dlc_protocol::DlcProtocolType::ForceClose {
trader: PublicKey::from_str(&dlc_protocol.trader_pubkey).expect("valid public key"),
},
DlcProtocolType::Rollover => dlc_protocol::DlcProtocolType::Rollover {
trader: PublicKey::from_str(&dlc_protocol.trader_pubkey).expect("valid public key"),
},
DlcProtocolType::Rollover => {
let rollover_params = db::rollover_params::get(conn, protocol_id)?;
dlc_protocol::DlcProtocolType::Rollover { rollover_params }
}
DlcProtocolType::ResizePosition => {
let trade_params = db::trade_params::get(conn, protocol_id)?;
dlc_protocol::DlcProtocolType::ResizePosition { trade_params }
Expand Down Expand Up @@ -173,7 +174,7 @@ pub(crate) fn create(
previous_protocol_id: Option<ProtocolId>,
contract_id: Option<&ContractId>,
channel_id: &DlcChannelId,
protocol_type: dlc_protocol::DlcProtocolType,
protocol_type: impl Into<DlcProtocolType>,
trader: &PublicKey,
) -> QueryResult<()> {
let affected_rows = diesel::insert_into(dlc_protocols::table)
Expand All @@ -185,7 +186,7 @@ pub(crate) fn create(
dlc_protocols::protocol_state.eq(DlcProtocolState::Pending),
dlc_protocols::trader_pubkey.eq(trader.to_string()),
dlc_protocols::timestamp.eq(OffsetDateTime::now_utc()),
dlc_protocols::protocol_type.eq(DlcProtocolType::from(protocol_type)),
dlc_protocols::protocol_type.eq(protocol_type.into()),
))
.execute(conn)?;

Expand Down Expand Up @@ -216,8 +217,8 @@ impl From<DlcProtocolState> for dlc_protocol::DlcProtocolState {
}
}

impl From<dlc_protocol::DlcProtocolType> for DlcProtocolType {
fn from(value: dlc_protocol::DlcProtocolType) -> Self {
impl From<&dlc_protocol::DlcProtocolType> for DlcProtocolType {
fn from(value: &dlc_protocol::DlcProtocolType) -> Self {
match value {
dlc_protocol::DlcProtocolType::OpenChannel { .. } => DlcProtocolType::OpenChannel,
dlc_protocol::DlcProtocolType::OpenPosition { .. } => DlcProtocolType::OpenPosition,
Expand Down
Loading
Loading