diff --git a/services/spark-matcher-evm/src/config.ts b/services/spark-matcher-evm/src/config.ts index ce424143..b934cdce 100644 --- a/services/spark-matcher-evm/src/config.ts +++ b/services/spark-matcher-evm/src/config.ts @@ -5,7 +5,6 @@ import { loadVar } from "./utils/envUtils"; config({ path: path.join(__dirname, "../.env") }); export const PORT = loadVar("PORT", true); -export const INDEXER_URL = loadVar("INDEXER_URL"); export const PRIVATE_KEY = loadVar("PRIVATE_KEY"); export const CONTRACT_ADDRESS = loadVar("CONTRACT_ADDRESS"); export const NODE_URL = loadVar("NODE_URL"); diff --git a/services/spark-matcher-evm/src/entity/SpotMarketOrder.ts b/services/spark-matcher-evm/src/entity/SpotMarketOrder.ts index 99870728..b1778768 100644 --- a/services/spark-matcher-evm/src/entity/SpotMarketOrder.ts +++ b/services/spark-matcher-evm/src/entity/SpotMarketOrder.ts @@ -22,7 +22,7 @@ export class SpotMarketOrder { readonly baseToken: Token; readonly quoteToken = TOKENS_BY_SYMBOL.USDC; readonly trader: string; - readonly baseSize: BN; + baseSize: BN; readonly baseSizeUnits: BN; readonly quoteSize: BN; readonly quoteSizeUnits: BN; diff --git a/services/spark-matcher-evm/src/server.ts b/services/spark-matcher-evm/src/server.ts index 6338c85e..614ff33a 100644 --- a/services/spark-matcher-evm/src/server.ts +++ b/services/spark-matcher-evm/src/server.ts @@ -24,15 +24,38 @@ class SparkMatcher { public doMatch = async () => { const market = TOKENS_BY_SYMBOL.BTC.assetId; - const [buyOrders, sellOrders]: [SpotMarketOrder[], SpotMarketOrder[]] = await Promise.all([ + let [buyOrders, sellOrders]: [SpotMarketOrder[], SpotMarketOrder[]] = await Promise.all([ this.spotMarket.getOrders({ market, limit: 100, type: "BUY" }), this.spotMarket.getOrders({ market, limit: 100, type: "SELL" }), ]); - for (let sellOrder of sellOrders) { - for (let buyOrder of buyOrders) { - if (sellOrder.baseToken === buyOrder.baseToken && sellOrder.price.lte(buyOrder.price)) { - await this.spotMarket.matchOrders(sellOrder.id, buyOrder.id).catch(console.log); + for (let i = 0; i < sellOrders.length; ++i) { + let sellOrder = sellOrders[i]; + if (sellOrder.baseSize.eq(0)) continue; + for (let j = 0; j < buyOrders.length; ++j) { + let buyOrder = buyOrders[j]; + if (buyOrder.baseSize.eq(0)) continue; + if ( + sellOrder.baseToken === buyOrder.baseToken && + sellOrder.price.lte(buyOrder.price) && + sellOrder.type === "SELL" && + buyOrder.type === "BUY" && + sellOrder.baseSize.gt(0) && + buyOrder.baseSize.gt(0) + ) { + await this.spotMarket + .matchOrders(sellOrder.id, buyOrder.id) + .then(() => { + const amount = + sellOrder.baseSize > buyOrder.baseSize ? buyOrder.baseSize : sellOrder.baseSize; + + sellOrder.baseSize = sellOrder.baseSize.minus(amount); + sellOrders[i].baseSize = sellOrder.baseSize; + + buyOrder.baseSize = buyOrder.baseSize.minus(amount); + buyOrders[i].baseSize = buyOrder.baseSize; + }) + .catch((e) => console.log(e.reason)); } } } diff --git a/services/spark-matcher-evm/src/services/SpotMarketService.ts b/services/spark-matcher-evm/src/services/SpotMarketService.ts index bf8198b1..6604ccaf 100644 --- a/services/spark-matcher-evm/src/services/SpotMarketService.ts +++ b/services/spark-matcher-evm/src/services/SpotMarketService.ts @@ -1,8 +1,9 @@ import axios from "axios"; import { SpotMarketOrder } from "../entity/SpotMarketOrder"; import { ethers } from "ethers"; -import { CONTRACT_ADDRESS, INDEXER_URL, NODE_URL, PRIVATE_KEY } from "../config"; +import { CONTRACT_ADDRESS, NODE_URL, PRIVATE_KEY } from "../config"; import { SPOT_MARKET_ABI } from "../abi"; +import { fetchIndexer } from "../utils/fetchIndexer"; type TOrderType = "BUY" | "SELL"; type TOrderResponse = { @@ -21,6 +22,18 @@ export class SpotMarket { constructor() { const provider = new ethers.JsonRpcProvider(NODE_URL); this.signer = new ethers.Wallet(PRIVATE_KEY, provider); + + this.signer + .getAddress() + .then(async (address) => ({ + balance: await provider.getBalance(address), + address, + })) + .then(({ balance, address }) => + console.log( + `πŸ•Ί Matcher address: ${address}\n Balance: ${ethers.formatUnits(balance)} ETH\n` + ) + ); this.contract = new ethers.Contract(CONTRACT_ADDRESS, SPOT_MARKET_ABI, this.signer); } @@ -46,7 +59,7 @@ export class SpotMarket { } `; try { - const response = await axios.post(INDEXER_URL, { query }); + const response = await fetchIndexer(query); return response.data.data.orders.map((order: TOrderResponse) => new SpotMarketOrder(order)); } catch (error) { console.error("Error during Orders request:", error); @@ -59,9 +72,9 @@ export class SpotMarket { const tx = await this.contract.matchOrders(sellOrder, buyOrder); await tx.wait(); - console.log("βœ… Orders matched:", sellOrder, buyOrder); - } catch (error) { - console.log("❌Error matching orders:", error); + console.log("βœ… Orders matched:", sellOrder, buyOrder, "\n"); + } catch (error: any) { + console.log("❌ Error matching orders:", error.toString(), "\n"); } }; } diff --git a/services/spark-matcher-evm/src/utils/fetchIndexer.ts b/services/spark-matcher-evm/src/utils/fetchIndexer.ts index adae6757..54804147 100644 --- a/services/spark-matcher-evm/src/utils/fetchIndexer.ts +++ b/services/spark-matcher-evm/src/utils/fetchIndexer.ts @@ -1,16 +1,19 @@ -import { INDEXER_URL } from "../config"; import axios from "axios"; -export default async function fetchIndexer(query: string) { - const config = { - method: "POST", - url: INDEXER_URL, - headers: { "Content-Type": "application/json", Accept: "application/json" }, - data: { query }, - }; - const result: T = await axios - .request(config) - .then((result) => result.data.data[0]) - .catch((e) => console.error(`❌ Indexer call: ${e.toString()}\nQuery: ${config.data.query}`)); - return result; -} +export const INDEXER_URLS = [ + "https://api.studio.thegraph.com/query/63182/arbitrum-sepolia-spot-market/version/latest", + "https://api.studio.thegraph.com/query/63182/spark-arbitrum-spor-market/version/latest", +]; + +export const fetchIndexer = async (query: string) => { + for (const i in INDEXER_URLS) { + const indexer = INDEXER_URLS[i]; + try { + return await axios.post(indexer, { query }); + } catch (error: any) { + console.error(`❌ Indexer call: ${error.toString()}\n Indexer: ${indexer}\n`); + /*eslint-disable-next-line */ + } + } + return await axios.post(INDEXER_URLS[0], { query }); +}; diff --git a/services/spark-matcher-evm/src/utils/print.ts b/services/spark-matcher-evm/src/utils/print.ts index 377eff01..e63af34a 100644 --- a/services/spark-matcher-evm/src/utils/print.ts +++ b/services/spark-matcher-evm/src/utils/print.ts @@ -16,4 +16,4 @@ export const print = ` β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ β•šβ•β•β•β•β•β•β•β•šβ•β• β•šβ•β•β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β•β• -${"πŸš€ Server ready at: http://localhost:" + (PORT ?? 5000)} `; +${"πŸš€ Server ready at: http://localhost:" + (PORT ?? 5000)} \n`; diff --git a/spark-frontend/src/screens/TradeScreen/BottomTables/BottomTablesInterfaceSpot/BottomTablesInterfaceSpotImpl.tsx b/spark-frontend/src/screens/TradeScreen/BottomTables/BottomTablesInterfaceSpot/BottomTablesInterfaceSpotImpl.tsx index 0fc52b36..58d01b28 100644 --- a/spark-frontend/src/screens/TradeScreen/BottomTables/BottomTablesInterfaceSpot/BottomTablesInterfaceSpotImpl.tsx +++ b/spark-frontend/src/screens/TradeScreen/BottomTables/BottomTablesInterfaceSpot/BottomTablesInterfaceSpotImpl.tsx @@ -142,7 +142,7 @@ const BottomTablesInterfaceSpotImpl: React.FC = observer(() => { ), price: toCurrency(order.priceUnits.toSignificant(2)), - filled: BN.ZERO, + filled: BN.ZERO.toString(), })); const getBalanceData = () =>