diff --git a/projects/vectis/constant.js b/projects/vectis/constant.js new file mode 100644 index 0000000000..bdefdf6975 --- /dev/null +++ b/projects/vectis/constant.js @@ -0,0 +1,11 @@ +const JUP_PERP_PROGRAM_ID = "PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu"; + +const JLP_MINT = "27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4"; + +const BASE_URL = "https://api.vectis.finance"; + +module.exports = { + JUP_PERP_PROGRAM_ID, + JLP_MINT, + BASE_URL, +}; diff --git a/projects/vectis/helpers.js b/projects/vectis/helpers.js index 75ff53ca5d..3809e45f90 100644 --- a/projects/vectis/helpers.js +++ b/projects/vectis/helpers.js @@ -1,6 +1,7 @@ const { PublicKey } = require("@solana/web3.js"); const { getMultipleAccounts } = require('../helper/solana') const axios = require("axios"); +const { BASE_URL } = require("./constant"); function deserializeUserPositions(accountInfo) { if (!accountInfo) { @@ -110,7 +111,7 @@ async function fetchVaultUserAddressesWithOffset(data, offset) { async function fetchVaultAddresses() { try { - const response = await axios.get('https://api.vectis.finance/strategy/fetchAllVaultAddresses'); + const response = await axios.get(`${BASE_URL}/strategy/fetchAllVaultAddresses`); if (response.status !== 200) { throw new Error(`HTTP error! status: ${response.status}`); @@ -123,6 +124,28 @@ async function fetchVaultAddresses() { } } +async function fetchPositionAddresses() { + try { + const response = await axios.get(`${BASE_URL}/voltr/position-addresses`); + + if (response.status !== 200) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return response.data.data; + } catch (error) { + console.error('Error fetching position addresses:', error); + throw error; + } +} + + -module.exports = { readPublicKeyFromBuffer, deserializeUserPositions, fetchVaultUserAddressesWithOffset, fetchVaultAddresses}; +module.exports = { + readPublicKeyFromBuffer, + deserializeUserPositions, + fetchVaultUserAddressesWithOffset, + fetchPositionAddresses, + fetchVaultAddresses +}; diff --git a/projects/vectis/index.js b/projects/vectis/index.js index a95692c710..83a7a251dd 100644 --- a/projects/vectis/index.js +++ b/projects/vectis/index.js @@ -1,14 +1,16 @@ const { getTokenMintFromMarketIndex, processSpotPosition, processPerpPosition, getPerpTokenMintFromMarketIndex, getVaultPublicKey, DRIFT_VAULT_PROGRAM_ID, VOLTR_PROGRAM_ID } = require("./spotMarkets"); -const { deserializeUserPositions, fetchVaultUserAddressesWithOffset, fetchVaultAddresses} = require("./helpers"); +const { deserializeUserPositions, fetchVaultUserAddressesWithOffset, fetchVaultAddresses, fetchPositionAddresses} = require("./helpers"); const { getPerpMarketFundingRates } = require("./spotMarkets"); -const { getMultipleAccounts, getProvider} = require('../helper/solana'); +const { getMultipleAccounts, getProvider, getAssociatedTokenAddress, sumTokens2} = require('../helper/solana'); const { Program } = require("@coral-xyz/anchor"); +const { Program : ProgramSerum } = require("@project-serum/anchor"); const voltrIdl = require("./voltr-idl"); const { PublicKey } = require("@solana/web3.js"); +const { JLP_MINT, JUP_PERP_PROGRAM_ID } = require("./constant"); +const ADDRESSES = require('../helper/coreAssets.json') +const { post } = require('../helper/http'); - - - module.exports = { +module.exports = { timetravel: false, doublecounted: true, methodology: "Calculate sum of spot positions in vaults with unrealized profit and loss", @@ -114,4 +116,33 @@ async function tvl(api) { api.add(mint, balance) }) -} \ No newline at end of file + // HyperLoop Prime A + const positionAddresses = await fetchPositionAddresses(); + + const idl = await ProgramSerum.fetchIdl(JUP_PERP_PROGRAM_ID, provider); + const program = new ProgramSerum(idl, JUP_PERP_PROGRAM_ID, provider); + const jupiterAccounts = await program.account["borrowPosition"].fetchMultiple( + positionAddresses.jupiter + ); + for (const account of jupiterAccounts) { + api.add(JLP_MINT, account.lockedCollateral); + const BORROW_SIZE_PRECISION = 1000; + api.add(ADDRESSES.solana.USDC, -account.borrowSize / BORROW_SIZE_PRECISION); + } + + const tokenAccounts = positionAddresses.solana.map((address) => + getAssociatedTokenAddress(ADDRESSES.solana.USDC, address) + ); + await sumTokens2({ tokenAccounts, api }); + + + for (const address of positionAddresses.hyperliquid) { + let hyperliquidData = await post("https://api.hyperliquid.xyz/info", { + type: "clearinghouseState", + user: address, + }); + hyperliquidData = parseInt(hyperliquidData.marginSummary.accountValue); + api.addCGToken("usd-coin", hyperliquidData); + } +} +