Skip to content
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
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Trivex Web

Frontend of **Trivex**, a next-generation decentralized trading platform built on Starknet Layer 3.
Repository for **Trivex**, a next-generation decentralized strategy analysis and trading platform built on Starknet Layer 3.

## 🌐 What is Trivex?

Expand All @@ -19,7 +19,7 @@ Trivex is designed to onboard both crypto-native users and traditional traders s

---

## Quickstart
## Quickstart for Trivex Frontend

### 1. Clone the Repository

Expand All @@ -42,16 +42,20 @@ npm run start

## Trivex Smart Contracts

Contains all the smart contracts used by Trivex created with Cairo on Starknet

```bash
cd trivex_web
cd trivex_contract
cd src
```

## Trivex Titan Bot

Contains the code for titan bot, a bot used to hedge out the orders from users to external broker

```bash
cd trivex_web
cd trivex titan
cd titan
py titan.py
```

## 🌐 Community & Support
Expand Down
4 changes: 4 additions & 0 deletions trivex_contract/src/interfaces.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ pub trait ITrivexAction<TContractState> {
fn get_total_staked(self: @TContractState) -> Amount;
fn get_fee(self: @TContractState, amount: Amount) -> Amount;
fn get_apy(self: @TContractState) -> Amount;
fn set_used_balance(ref self: TContractState, value: u256);
fn set_available_balance(ref self: TContractState, value: u256);
fn update_external_order_book(ref self: TContractState, symbol: felt252, leverage: u128, total_value: u256, action: felt252);
fn get_external_order_book(self: @TContractState) -> Array<order_book_entry>;
}
73 changes: 68 additions & 5 deletions trivex_contract/src/trivexaction.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,13 @@ mod TrivexAction {
internal_order_book_len: u256,
external_used_balance: u256,
external_available_balance: u256,
external_order_book: LegacyMap<(felt252, u128), Amount>,
external_order_book_keys: LegacyMap<u256, (felt252, u128)>,
external_order_book_len: u256,
lender_interest_rate: u256,
strategy_price: LegacyMap<felt252, u256>,
strategy_creator: LegacyMap<felt252, UserAddress>
strategy_creator: LegacyMap<felt252, UserAddress>,
owner: UserAddress
}

#[constructor]
Expand All @@ -52,6 +56,9 @@ mod TrivexAction {
let key4 = 'coVariance';
self.strategy_price.write(key4, 1_u256);
self.strategy_creator.write(key4, creator);

let owner = contract_address_const::<0x012B099F50C3CbCc82ccF7Ee557c9d60255c35C359eA6615435B761Ec3336EC8>();
self.owner.write(owner);
}

#[abi(embed_v0)]
Expand Down Expand Up @@ -152,7 +159,6 @@ mod TrivexAction {
//removing it from positions
let count = self.user_position_counts.read(caller);
let mut i = id;
let temp = self.positions.read((caller, i));
while i + 1 <= count {
let next_pos = self.positions.read((caller, i + 1));
self.positions.write((caller, i), next_pos);
Expand All @@ -176,11 +182,11 @@ mod TrivexAction {
self.user_transaction_counts.write(caller, count_transactions + 1);

//updating the internal order book
let current_order_book = self.internal_order_book.read((temp.symbol, temp.leverage));
let current_order_book = self.internal_order_book.read((position.symbol, position.leverage));
if action == 'Close Buy' {
self.internal_order_book.write((temp.symbol, temp.leverage), current_order_book - amount);
self.internal_order_book.write((position.symbol, position.leverage), current_order_book - amount);
} else if action == 'Close Sell' {
self.internal_order_book.write((temp.symbol, temp.leverage), current_order_book + amount);
self.internal_order_book.write((position.symbol, position.leverage), current_order_book + amount);
}
}
}
Expand Down Expand Up @@ -338,5 +344,62 @@ mod TrivexAction {
fn get_apy(self: @ContractState) -> Amount {
self.lender_interest_rate.read()
}

fn set_used_balance(ref self: ContractState, value: u256) {
let caller = get_caller_address();
let owner = self.owner.read();
assert(caller == owner, 'NOT_OWNER');
self.external_used_balance.write(value);
}

fn set_available_balance(ref self: ContractState, value: u256) {
let caller = get_caller_address();
let owner = self.owner.read();
assert(caller == owner, 'NOT_OWNER');
self.external_available_balance.write(value);
}

fn update_external_order_book(ref self: ContractState, symbol: felt252, leverage: u128, total_value: u256, action: felt252) {
let current_order_book = self.external_order_book.read((symbol, leverage));
if action == 'Open Buy' {
self.external_order_book.write((symbol, leverage), current_order_book + total_value);
} else if action == 'Open Sell' {
self.external_order_book.write((symbol, leverage), current_order_book - total_value);
}

if current_order_book == 0 {
let idx = self.external_order_book_len.read();
self.external_order_book_keys.write(idx, (symbol, leverage));
self.external_order_book_len.write(idx + 1);
}
}

fn get_external_order_book(self: @ContractState) -> Array<order_book_entry> {
let length = self.external_order_book_len.read();

let mut entries = ArrayTrait::new();
let mut i = 0;

loop {
if i == length {
break;
}

let key = self.external_order_book_keys.read(i);
let (symbol, leverage) = key;
let amount = self.external_order_book.read(key);

let entry = order_book_entry {
symbol: symbol,
leverage: leverage,
amount: amount
};

entries.append(entry);
i = i + 1;
};

entries
}
}
}
5 changes: 3 additions & 2 deletions trivex_frontend/src/components/AppContract.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Contract, Provider, cairo, CallData, shortString } from 'starknet';

const hash_provider = new Provider({ network: 'sepolia' });

const classHash = '0x00464f2ddef3ea45129244440b3c21789f38d56b680f0a4d01526a09b0ae3fe8';
const contractAddress = '0x05083aa7aba0aa78514ac84d70a7c969360a6095189d2fdfaafcb689b4734d38';
const classHash = '0x044bdb1b55aa0c3e7f1437434e205bfd697405b805e654a68a3fa3adb82e1eeb';
const contractAddress = '0x031015bf30be2b3e1241bd44b65d6c21fe32255cca3f68b59b5c8a9a0fca3b9b';
const usdcTokenAddress = '0x53b40a647cedfca6ca84f542a0fe36736031905a9639a7f19a3c1e66bfd5080';
const strkTokenAddress = '0x4718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d';

Expand Down Expand Up @@ -178,6 +178,7 @@ export class AppContract {
datetime: new Date(Number(item.datetime) * 1000)
}));

console.log(positions);
return positions;
}

Expand Down
2 changes: 1 addition & 1 deletion trivex_frontend/src/components/TradingViewWidget.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useRef, memo } from "react";
import { Box } from "@mui/material";

const TradingViewWidget = ({ symbol = "BTCUSDC"}) => {
const TradingViewWidget = ({ symbol = "BTCUSDT"}) => {
const container = useRef(null);

useEffect(() => {
Expand Down
30 changes: 28 additions & 2 deletions trivex_frontend/src/pages/StrategyPage.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useContext} from 'react';
import React, { useState, useContext, useEffect} from 'react';
import { Box, Typography, TextField, MenuItem, Button, Switch, List, ListItem, ListItemText} from '@mui/material';
import axios from 'axios';
import {AppContext} from '../components/AppProvider';
Expand All @@ -25,6 +25,7 @@ const StrategyPage = () => {
const [endDate, setEndDate] = useState('');

const [loading, setLoading] = useState(false)
const [strategyPrice, setStrategyPrice] = useState(0);

const host = "trivex-strategy-etbga3bramfwgfe9.canadacentral-01.azurewebsites.net";

Expand Down Expand Up @@ -55,6 +56,15 @@ const StrategyPage = () => {
}
};

const handleStrategyPrice = async (strategy) => {
try {
const amount = await contract.getStrategyPrice(strategy);
setStrategyPrice(amount);
} catch (error) {
alert("An unexpected error occurred. Please try again.");
}
};

const handleStartAlgo = async () => {
if (!strategy) {
alert('Please select both a strategy.');
Expand Down Expand Up @@ -159,6 +169,11 @@ const StrategyPage = () => {
}
};

useEffect(() => {
if (strategy) {
handleStrategyPrice(strategy);
}
}, [strategy]);

if(info.walletAddress != null){
return (
Expand Down Expand Up @@ -347,6 +362,17 @@ const StrategyPage = () => {
</>
)}

<Box
sx={{
backgroundColor: '#D7CCE8', // Lighter shade
padding: '15px',
borderRadius: '8px',
marginBottom: '10px',
color: '#000'
}}
>
<Typography variant="body1">Cost: {strategyPrice} STRK</Typography>
</Box>
<Button
variant="contained"
sx={{ backgroundColor: '#7E57C2' }}
Expand All @@ -358,7 +384,7 @@ const StrategyPage = () => {
</Box>

{results && (
<Box sx={{ maxWidth: '600px', marginTop: '30px', padding: '20px', backgroundColor: '#f1f1f1', borderRadius: '8px', margin: '20px auto'}}>
<Box sx={{ maxWidth: '70%', marginTop: '30px', padding: '20px', backgroundColor: '#f1f1f1', borderRadius: '8px', margin: '20px auto'}}>
<Typography variant="h5" sx={{ marginBottom: '10px' }}>
Results
</Typography>
Expand Down
17 changes: 10 additions & 7 deletions trivex_frontend/src/pages/TradePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const TradePage = () => {
const [position, setPosition] = useState([]);
const [transaction, setTransaction] = useState([]);
const [price, setPrice] = useState(0);
const [tradingSymbol, setTradingSymbol] = useState('BTCUSDC');
const [tradingSymbol, setTradingSymbol] = useState('BTCUSDT');
const [fee, setFee] = useState(0);

const host = "https://trivex-trade-faekh0awhkdphxhq.canadacentral-01.azurewebsites.net";
Expand Down Expand Up @@ -95,9 +95,9 @@ const TradePage = () => {
}
};

const fetchFee = async (address, symbol, size) => {
const fetchFee = async (address, symbol, amount) => {
try {
console.log(`Fetching fee for ${address} for order ${symbol} with size ${size}`);
console.log(`Fetching fee for ${address} for order ${symbol} with size ${amount}`);
const estimate_fee = await contract.getFee(amount);
setFee(estimate_fee);
if (isNaN(estimate_fee)) {
Expand Down Expand Up @@ -137,12 +137,12 @@ const TradePage = () => {
const amountChange = async (value) => {
setAmount(value);
setSize(value/price);
fetchFee(info.walletAddress, symbol+"-"+sector, size);
await fetchFee(info.walletAddress, symbol+"-"+sector, value);
};

const symbolChange = (e) => {
setSymbol(e);
setTradingSymbol(e+"USDC");
setTradingSymbol(e+"USDT");
handlePrice(e+"-"+sector);
};

Expand All @@ -165,9 +165,10 @@ const TradePage = () => {
alert('Please fill in all fields before proceeding.');
return;
}
await fetchFee(info.walletAddress, symbol+"-"+sector, size);

try {
const totalValue = size * price;
const totalValue = size * price + fee;
const orderAction = "Open " + action;

const result = await contract.open_order(
Expand Down Expand Up @@ -200,7 +201,9 @@ const TradePage = () => {

let response = await axios.get(`${host}/price/${position.symbol + "-Crypto"}`);
const current_price = parseFloat(response.data.price);
const amount = position.quantity * current_price;
let amount = position.quantity * current_price;
const estimate_fee = await contract.getFee(amount);
amount = amount - estimate_fee;
const action = "Close " + position.action.split(" ")[1];

const result = await contract.close_order(
Expand Down