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

Perp release #243

Draft
wants to merge 73 commits into
base: main
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
efbaa09
feat: testing env in build
EchoDex Nov 19, 2024
65c1ba1
feat: trying new logic for config handling
EchoDex Nov 19, 2024
fee0c4c
feat: update logo to see current env faster
EchoDex Nov 19, 2024
b2c49cf
Merge pull request #205 from compolabs/feat/testing-build-config
EchoDex Nov 19, 2024
cc26857
chore: update config
EchoDex Nov 19, 2024
60c7b94
fix: bug with min and max price
EchoDex Nov 22, 2024
5556d7c
Merge remote-tracking branch 'origin/main' into develop
EchoDex Dec 3, 2024
511d60e
feat: first iteration of refactoring for perp logic
EchoDex Dec 3, 2024
fb25243
Change path to `helm` in vault-docker-helm.yaml
max5dt Dec 4, 2024
c15f7b2
Merge remote-tracking branch 'origin/main' into develop
EchoDex Dec 5, 2024
59a0fe4
Merge remote-tracking branch 'origin/develop' into feat/perp-config-s…
EchoDex Dec 5, 2024
e1d1e22
feat: update logic related to market selection
EchoDex Dec 5, 2024
0a40f44
feat: update stats info
EchoDex Dec 5, 2024
02bdb9c
[2079] Trading view advance (#208) (#221)
Anton-rock Dec 10, 2024
946352a
feat: done with perp page
EchoDex Dec 10, 2024
765e352
Merge remote-tracking branch 'origin/develop' into feat/perp-config-s…
EchoDex Dec 10, 2024
1308b57
feat: merge develop
EchoDex Dec 10, 2024
8f4d8ef
feat: add deposit modal
EchoDex Dec 10, 2024
e4011ad
Merge remote-tracking branch 'origin/main' into feat/perp-config-setup
EchoDex Dec 23, 2024
0a3eafd
chore: bump version
EchoDex Dec 23, 2024
cfd4f67
Merge remote-tracking branch 'origin/main' into feat/perp-config-setup
EchoDex Dec 25, 2024
5dee69d
fix: rename file
EchoDex Dec 25, 2024
a73ac26
feat: update perp logic related to deposit
EchoDex Dec 25, 2024
c2fc000
Feat: perp table and orderbook (#222)
Anton-rock Dec 25, 2024
6611250
feat: fix pair in order history and fix accordion
Anton-rock Dec 26, 2024
6f5f429
Merge branch 'main' of github-Anton-rock:compolabs/spark-frontend
Anton-rock Dec 26, 2024
27794d7
feat: update logic related to deposit
EchoDex Dec 25, 2024
32348b2
feat: merge hotfix
Anton-rock Dec 26, 2024
c7bcd30
Merge remote-tracking branch 'origin/feat/perp-config-setup' into fea…
Anton-rock Dec 26, 2024
51b44de
feat: add perp store
Anton-rock Dec 27, 2024
c82e634
feat: balances
EchoDex Dec 28, 2024
c44f984
feat: prepare perp stores
EchoDex Dec 29, 2024
2dad7d3
feat: add chart info
EchoDex Dec 29, 2024
abbe863
feat: refactor stores
EchoDex Dec 29, 2024
2b9f507
feat: remove spot logic
EchoDex Dec 29, 2024
d3c7e93
feat: update folder structure
EchoDex Dec 29, 2024
a6b7ff6
fix: remove file ext
EchoDex Dec 29, 2024
8711e7f
feat: update balance logic
EchoDex Dec 29, 2024
e83f4cf
chore: trying to open order
EchoDex Dec 29, 2024
64344e6
feat: add indexer
Anton-rock Dec 29, 2024
55d7b38
feat: add show orderbook
Anton-rock Dec 29, 2024
fca2099
feat: bump version
Anton-rock Dec 29, 2024
8d7a279
feat: rever vite.config
Anton-rock Dec 29, 2024
555826b
feat: update
EchoDex Dec 30, 2024
246bfa2
fix: fix build
EchoDex Dec 30, 2024
61dc771
feat: fix interface
Anton-rock Dec 30, 2024
a73351a
feat: fix interface
Anton-rock Dec 30, 2024
47c6cf6
feat: fix build
Anton-rock Dec 30, 2024
e4dc08b
feat: up version
Anton-rock Dec 30, 2024
c1af023
feat: update version
EchoDex Dec 30, 2024
ddbb6a3
fix: show oracle price for btc
EchoDex Dec 30, 2024
fad0721
Feat: open orders (#244)
Anton-rock Dec 30, 2024
bd90d41
feat: resolve merge request
Anton-rock Jan 6, 2025
99ebb9a
feat: add event trades
Anton-rock Jan 7, 2025
14d4edb
feat: fixed cancel order and price in create order
Anton-rock Jan 13, 2025
9c047fd
Merge branch 'main' of github-Anton-rock:compolabs/spark-frontend
Anton-rock Jan 14, 2025
248b4d6
Merge branch 'main' of github-Anton-rock:compolabs/spark-frontend
Anton-rock Jan 14, 2025
c4a922d
feat: merge from main
Anton-rock Jan 15, 2025
eb5c009
feat: lint
Anton-rock Jan 15, 2025
9e742d4
Merge remote-tracking branch 'origin/main' into perp
EchoDex Jan 20, 2025
aee7f5f
chore: update create order logic
EchoDex Jan 21, 2025
5be47ee
feat: remove many request
Anton-rock Jan 24, 2025
4149ba0
resolve merge conflict
Anton-rock Jan 24, 2025
f7c2146
feat: fix show open order
Anton-rock Jan 24, 2025
827b70e
feat: fix show open position
Anton-rock Jan 27, 2025
004fd47
feat: fix build
Anton-rock Jan 27, 2025
59ac481
feat: show open position
Anton-rock Jan 29, 2025
a9742e9
resolve merge conflict
Anton-rock Jan 29, 2025
9ac6670
feat: fix trading on perps
Anton-rock Jan 29, 2025
5fbc2ce
fix: correct order creation
EchoDex Jan 30, 2025
1b1ecfa
feat: fix decimals
Anton-rock Jan 30, 2025
59017a2
feat: fix decimals
Anton-rock Jan 30, 2025
67219f5
feat: add market and index price and fix bugs
Anton-rock Feb 4, 2025
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
Prev Previous commit
Next Next commit
feat: update perp logic related to deposit
EchoDex committed Dec 25, 2024
commit a73ac265e67c60607db5b83d0e701ec01184509c
12 changes: 9 additions & 3 deletions src/blockchain/FuelNetwork.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,8 @@ import { Account, B256Address } from "fuels";
import { makeObservable } from "mobx";
import { Nullable } from "tsdef";

import SparkOrderBookSdk, { OrderType, WriteTransactionResponse } from "@compolabs/spark-orderbook-ts-sdk";
import SparkOrderbookSdk, { OrderType, WriteTransactionResponse } from "@compolabs/spark-orderbook-ts-sdk";
import SparkPerpetualSdk from "@compolabs/spark-perpetual-ts-sdk";

import BN from "@utils/BN";
import { CONFIG } from "@utils/getConfig";
@@ -16,18 +17,23 @@ export class FuelNetwork {
private static instance: Nullable<FuelNetwork> = null;

private walletManager = new WalletManager();
private orderbookSdk: SparkOrderBookSdk;
private orderbookSdk: SparkOrderbookSdk;
private perpetualSdk: SparkPerpetualSdk;

private constructor() {
makeObservable(this.walletManager);

this.orderbookSdk = new SparkOrderBookSdk({
this.orderbookSdk = new SparkOrderbookSdk({
networkUrl: CONFIG.APP.links.networkUrl,
contractAddresses: {
registry: CONFIG.SPOT.CONTRACTS.registry,
multiAsset: CONFIG.SPOT.CONTRACTS.multiAsset,
},
});

this.perpetualSdk = new SparkPerpetualSdk({
networkUrl: CONFIG.APP.links.networkUrl,
});
}

public static getInstance(): FuelNetwork {
4 changes: 2 additions & 2 deletions src/components/DepositWithdrawModal.tsx
Original file line number Diff line number Diff line change
@@ -23,10 +23,10 @@ export interface IProps extends IDialogPropTypes {}
const tokens = [{ title: "USDC", key: "USDC" }];

const DepositWithdrawModal: React.FC<IProps> = observer(({ ...rest }) => {
const [isDeposit, setIsDeposit] = useState(true);

const theme = useTheme();

const [isDeposit, setIsDeposit] = useState(true);

const [depositAmount, setDepositAmount] = useState(BN.ZERO);
const [withdrawAmount, setWithdrawAmount] = useState(BN.ZERO);

7 changes: 6 additions & 1 deletion src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ import MobileMenu from "./MobileMenu";
import WalletAddressButton from "./WalletAddressButton";

const Header: React.FC = observer(() => {
const { modalStore, quickAssetsStore } = useStores();
const { marketStore, modalStore, quickAssetsStore } = useStores();
const media = useMedia();

const [isMobileMenuOpen, openMobileMenu, closeMobileMenu] = useFlag();
@@ -107,6 +107,11 @@ const Header: React.FC = observer(() => {
</SmartFlex>
</SmartFlex>
<SmartFlex center="y" gap="16px">
{marketStore.perpMarket && (
<Button fitContent onClick={() => modalStore.open(MODAL_TYPE.PERP_DEPOSIT_WITHDRAW_MODAL)}>
Deposit / Withdraw
</Button>
)}
<Button data-onboarding="assets-desktop" fitContent onClick={() => quickAssetsStore.setQuickAssets(true)}>
<SmartFlex center="y" gap="8px">
<DataBase />
44 changes: 20 additions & 24 deletions src/components/MarketSelection/MarketSelection.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef, useState } from "react";
import React, { useLayoutEffect, useRef, useState } from "react";
import styled from "@emotion/styled";
import { observer } from "mobx-react";

@@ -39,42 +39,39 @@ const MarketSelection: React.FC = observer(() => {

const marketsFiltered = marketStore.markets.filter((market) => market.symbol.includes(searchValue)); // TODO: add memo

const renderSpotMarketList = () => {
if (!isSpotMarketType) return;
useLayoutEffect(() => {
if (!marketStore.market) return;

if (!marketsFiltered.length) {
return (
<>
<SizedBox height={16} />
<Row justifyContent="center">
<Text>No spot markets found</Text>
</Row>
</>
);
}
const isCurrentMarketSpot = SpotMarket.isInstance(marketStore.market);

return marketsFiltered
.filter((m) => SpotMarket.isInstance(m))
.map((market) => <MarketRow key={market.symbol} market={market} />);
};
setIsSpotMarketType(isCurrentMarketSpot);
}, [marketStore.market]);

const renderPerpMarketList = () => {
if (isSpotMarketType) return;
const renderMarketList = () => {
const isSpot = isSpotMarketType;
const MarketClass = isSpot ? SpotMarket : PerpMarket;
const noMarketsText = isSpot ? "No spot markets found" : "No perp markets found";

if (!marketsFiltered.length) {
return (
<>
<SizedBox height={16} />
<Row justifyContent="center">
<Text>No perp markets found</Text>
<Text>{noMarketsText}</Text>
</Row>
</>
);
}

return marketsFiltered
.filter((m) => PerpMarket.isInstance(m))
.map((market) => <MarketRow key={market.symbol} market={market} showLeverage showPriceChange />);
.filter((m) => MarketClass.isInstance(m))
.map((market) => (
<MarketRow
key={market.symbol}
market={market}
{...(!isSpot && { showLeverage: true, showPriceChange: true })}
/>
));
};

return (
@@ -98,8 +95,7 @@ const MarketSelection: React.FC = observer(() => {
<Text type={TEXT_TYPES.BODY}>PRICE</Text>
</SmartFlex>
<Divider />
{renderSpotMarketList()}
{renderPerpMarketList()}
{renderMarketList()}
</Root>
</Container>
);
14 changes: 11 additions & 3 deletions src/config-dev.json
Original file line number Diff line number Diff line change
@@ -25,6 +25,14 @@
"assetId": "0x336b7c06352a4b736ff6f688ba6885788b3df16e136e95310ade51aa32dc6f05",
"priceFeed": "0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a",
"precision": 2
},
{
"name": "tUSDC",
"symbol": "tUSDC",
"decimals": 6,
"assetId": "0x22dfb618b9fc621a7d53f0f599dd427fb5688e280062a8de8883a27819d3f276",
"priceFeed": "0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a",
"precision": 2
}
],
"spot": {
@@ -76,11 +84,11 @@
"owner": "0xf47e0ef744ac8c993550e03d17f1c4844494553a12cac11ab8c568c8999fdbbf",
"baseAssetId": "0x38e4ca985b22625fff93205e997bfc5cc8453a953da638ad297ca60a9f2600bc",
"baseAssetDecimals": 8,
"quoteAssetId": "0x336b7c06352a4b736ff6f688ba6885788b3df16e136e95310ade51aa32dc6f05",
"quoteAssetId": "0x22dfb618b9fc621a7d53f0f599dd427fb5688e280062a8de8883a27819d3f276",
"quoteAssetDecimals": 6,
"priceDecimals": 9,
"version": 1539,
"contractId": "0xc5ed0d9b17beedd1c6c10a84bb496f12a5082aa3ce2ad55630bbcac22c64fcf4"
"contractId": "0xc17dd80692a8987fb3d7b310061aaa27c1b9a12cd5d2dfc9e800d7bb01b54cf4"
}
],
"indexers": {
@@ -90,7 +98,7 @@
}
},
"contracts": {
"registry": "0x0c26b7134516773469cd02030a783e43776d1fd26e0698b51af3cef4938e2925",
"vault": "0x0c26b7134516773469cd02030a783e43776d1fd26e0698b51af3cef4938e2925",
"multiAsset": "0xdc527289bdef8ec452f350c9b2d36d464a9ebed88eb389615e512a78e26e3509"
}
},
2 changes: 1 addition & 1 deletion src/screens/Assets/DepositAssets/DepositAssets.tsx
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ const DepositAssets: React.FC<DepositAssetsProps> = observer(({ setStep }) => {
setIsLoading(true);

try {
const response = await balanceStore.depositBalance(
const response = await balanceStore.depositSpotBalance(
currentAsset.asset.assetId,
BN.parseUnits(BN.formatUnits(amount, currentAsset.asset.decimals), currentAsset.asset.decimals).toString(),
);
2 changes: 1 addition & 1 deletion src/screens/Assets/MainAssets/MainAssets.tsx
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ const MainAssets: React.FC<MainAssetsProps> = observer(({ setStep }) => {
);
const handleWithdraw = async () => {
setIsLoading(true);
await balanceStore.withdrawBalanceAll();
await balanceStore.withdrawSpotBalanceAll();
setIsLoading(false);
};

2 changes: 1 addition & 1 deletion src/screens/Assets/WithdrawAssets/WithdrawAssets.tsx
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ const WithdrawAssets = observer(({ setStep }: WithdrawAssets) => {
const handleClick = async () => {
if (!selectAsset || !amount) return;
setIsLoading(true);
const response = await balanceStore.withdrawBalance(
const response = await balanceStore.withdrawSpotBalance(
selectAsset.asset.assetId,
BN.parseUnits(BN.formatUnits(amount, selectAsset.asset.decimals), selectAsset.asset.decimals).toString(),
);
4 changes: 2 additions & 2 deletions src/screens/Dashboard/AssetsDashboard.tsx
Original file line number Diff line number Diff line change
@@ -172,7 +172,7 @@ const AssetsDashboard = observer(() => {

const withdrawalBalance = async (selectAsset: AssetBlockData) => {
setIsLoading(true);
await balanceStore.withdrawBalance(
await balanceStore.withdrawSpotBalance(
selectAsset.asset.assetId,
BN.parseUnits(selectAsset.contractBalance, selectAsset.asset.decimals).toString(),
);
@@ -181,7 +181,7 @@ const AssetsDashboard = observer(() => {

const handleWithdrawAll = async () => {
setIsLoading(true);
await balanceStore.withdrawBalanceAll();
await balanceStore.withdrawSpotBalanceAll();
setIsLoading(false);
};

54 changes: 27 additions & 27 deletions src/stores/BalanceStore.ts
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ const UPDATE_INTERVAL = 5 * 1000;

export class BalanceStore {
public balances: Map<string, BN> = new Map();
public contractBalances: Map<string, BN> = new Map();
public spotContractBalances: Map<string, BN> = new Map();
public initialized = false;

private balancesUpdater: IntervalUpdater;
@@ -38,7 +38,7 @@ export class BalanceStore {
([isConnected]) => {
if (!isConnected) {
this.balances = new Map();
this.contractBalances = new Map();
this.spotContractBalances = new Map();
this.initialized = false;
return;
}
@@ -64,14 +64,14 @@ export class BalanceStore {

return tokens.map((token) => {
const balance = this.getWalletBalance(token.assetId);
const contractBalance = this.getContractBalance(token.assetId);
const totalBalance = balance.plus(contractBalance);
const spotContractBalance = this.getSpotContractBalance(token.assetId);
const totalBalance = balance.plus(spotContractBalance);

return {
assetId: token.assetId,
asset: token,
walletBalance: BN.formatUnits(balance, token.decimals).toString(),
contractBalance: BN.formatUnits(contractBalance, token.decimals).toString(),
contractBalance: BN.formatUnits(spotContractBalance, token.decimals).toString(),
balance: BN.formatUnits(totalBalance, token.decimals).toString(),
price: BN.formatUnits(oracleStore.getTokenIndexPrice(token.priceFeed), DEFAULT_DECIMALS).toString(),
};
@@ -80,7 +80,7 @@ export class BalanceStore {

clearBalance = () => {
this.balances = new Map();
this.contractBalances = new Map();
this.spotContractBalances = new Map();
};

update = async () => {
@@ -92,9 +92,9 @@ export class BalanceStore {

const address = Address.fromB256(accountStore.address);

const [balances, contractBalances] = await Promise.all([
const [balances, spotContractBalances] = await Promise.all([
this.fetchUserBalances(),
this.fetchUserContractBalances(address),
this.fetchUserSpotContractBalances(address),
]);

try {
@@ -108,9 +108,9 @@ export class BalanceStore {
});
}

const aggregatedBalances = CONFIG.SPOT.MARKETS.reduce(
const aggregatedSpotBalances = CONFIG.SPOT.MARKETS.reduce(
(acc, market, index) => {
const marketBalance = contractBalances[index];
const marketBalance = spotContractBalances[index];

const baseAmount = marketBalance ? new BN(marketBalance.liquid.base) : BN.ZERO;
const quoteAmount = marketBalance ? new BN(marketBalance.liquid.quote) : BN.ZERO;
@@ -130,8 +130,8 @@ export class BalanceStore {
{} as Record<string, BN>,
);

Object.entries(aggregatedBalances).forEach(([assetId, balance]) => {
this.contractBalances.set(assetId, balance);
Object.entries(aggregatedSpotBalances).forEach(([assetId, balance]) => {
this.spotContractBalances.set(assetId, balance);
});
} catch (error) {
console.error("Error updating user balances:", error);
@@ -150,27 +150,27 @@ export class BalanceStore {
return this.balances.get(CONFIG.TOKENS_BY_SYMBOL.ETH.assetId) ?? BN.ZERO;
};

getContractBalance = (assetId: string) => {
const amount = this.contractBalances.get(assetId);
return amount ?? BN.ZERO;
};

getFormatContractBalance = (assetId: string, decimals: number) => {
return BN.formatUnits(this.getContractBalance(assetId), decimals).toSignificant(2) ?? "-";
};

getTotalBalance = (assetId: string) => {
const walletBalance = this.balances.get(assetId) ?? BN.ZERO;
const contractBalance = this.contractBalances.get(assetId) ?? BN.ZERO;
const spotContractBalance = this.spotContractBalances.get(assetId) ?? BN.ZERO;

return walletBalance.plus(contractBalance);
return walletBalance.plus(spotContractBalance);
};

getFormatTotalBalance = (assetId: string, decimals: number) => {
return BN.formatUnits(this.getTotalBalance(assetId), decimals).toSignificant(2) ?? "-";
};

depositBalance = async (assetId: string, amount: string) => {
getSpotContractBalance = (assetId: string) => {
const amount = this.spotContractBalances.get(assetId);
return amount ?? BN.ZERO;
};

getFormatSpotContractBalance = (assetId: string, decimals: number) => {
return BN.formatUnits(this.getSpotContractBalance(assetId), decimals).toSignificant(2) ?? "-";
};

depositSpotBalance = async (assetId: string, amount: string) => {
const { notificationStore } = this.rootStore;
const bcNetwork = FuelNetwork.getInstance();

@@ -198,7 +198,7 @@ export class BalanceStore {
}
};

withdrawBalance = async (assetId: string, amount: string) => {
withdrawSpotBalance = async (assetId: string, amount: string) => {
const { notificationStore } = this.rootStore;
const markets = CONFIG.SPOT.MARKETS.filter((el) => el.baseAssetId === assetId || el.quoteAssetId === assetId);

@@ -243,7 +243,7 @@ export class BalanceStore {
}
};

withdrawBalanceAll = async () => {
withdrawSpotBalanceAll = async () => {
const { notificationStore } = this.rootStore;
const bcNetwork = FuelNetwork.getInstance();

@@ -276,7 +276,7 @@ export class BalanceStore {
return bcNetwork.getBalances();
};

private fetchUserContractBalances = async (address: Address): Promise<UserMarketBalance[]> => {
private fetchUserSpotContractBalances = async (address: Address): Promise<UserMarketBalance[]> => {
const bcNetwork = FuelNetwork.getInstance();

return bcNetwork.spotFetchUserMarketBalanceByContracts(
8 changes: 8 additions & 0 deletions src/stores/MarketStore.ts
Original file line number Diff line number Diff line change
@@ -73,6 +73,14 @@ export class MarketStore {
}
}

get perpMarket(): Undefinable<PerpMarket> {
if (!this.market) return;

if (PerpMarket.isInstance(this.market)) {
return this.market;
}
}

get initialized() {
return true;
}
4 changes: 3 additions & 1 deletion src/stores/SpotCreateOrderStore.ts
Original file line number Diff line number Diff line change
@@ -135,8 +135,10 @@ export class SpotCreateOrderStore {
get isSpotInputError(): boolean {
const { balanceStore, marketStore } = this.rootStore;

if (!marketStore.spotMarket) return false;

const amount = this.isSell ? this.inputAmount : this.inputTotal;
const token = this.isSell ? marketStore.spotMarket!.baseToken : marketStore.spotMarket!.quoteToken;
const token = this.isSell ? marketStore.spotMarket.baseToken : marketStore.spotMarket.quoteToken;

const totalBalance = balanceStore.getTotalBalance(token.assetId);

4 changes: 2 additions & 2 deletions src/stores/SpotTableStore.ts
Original file line number Diff line number Diff line change
@@ -152,8 +152,8 @@ export class SpotTableStore {
this.isWithdrawing = true;
this.withdrawingAssetId = assetId;

const amount = balanceStore.getContractBalance(assetId);
await balanceStore.withdrawBalance(assetId, amount.toString());
const amount = balanceStore.getSpotContractBalance(assetId);
await balanceStore.withdrawSpotBalance(assetId, amount.toString());

this.isWithdrawing = false;
this.withdrawingAssetId = null;