From 3c94518cce6f0a7dec194ce7eaa983525eb5c10c Mon Sep 17 00:00:00 2001 From: Diyahir <32445955+diyahir@users.noreply.github.com> Date: Mon, 8 Dec 2025 15:38:02 +0100 Subject: [PATCH 1/4] feat adding yeild to magma protocol --- src/adaptors/magma-protocol/index.js | 221 +++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 src/adaptors/magma-protocol/index.js diff --git a/src/adaptors/magma-protocol/index.js b/src/adaptors/magma-protocol/index.js new file mode 100644 index 0000000000..025718c67d --- /dev/null +++ b/src/adaptors/magma-protocol/index.js @@ -0,0 +1,221 @@ +const sdk = require('@defillama/sdk'); +const axios = require('axios'); + +// Time constants +const SECONDS_PER_DAY = 86400; +const DAYS_PER_YEAR = 365; + +// Contract addresses +const MAGMA_ADDRESS = '0x8498312A6B3CbD158bf0c93AbdCF29E6e4F55081'; +const STAKING_PRECOMPILE = '0x0000000000000000000000000000000000001000'; + +// ABI for contract functions +const MAGMA_ABI = { + coreVault: 'address:coreVault', + gVault: 'address:gVault', + getValidators: 'uint64[]:getValidators', + getDelegator: + 'function getDelegator(uint64 validatorId, address delegator) returns (uint256 stake, uint256 accRewardPerToken, uint256 unclaimedRewards, uint256 deltaStake, uint256 nextDeltaStake, uint64 deltaEpoch, uint64 nextDeltaEpoch)', + totalAssets: 'function totalAssets() external view returns (uint256)', + totalSupply: 'erc20:totalSupply', + symbol: 'erc20:symbol', +}; + +const apy = async () => { + // Get current timestamp + const now = Math.floor(Date.now() / 1000); + const timestamp1dayAgo = now - SECONDS_PER_DAY; + + // Fetch block numbers for current and 1 day ago + const [blockNow, block1dayAgo] = await Promise.all([ + axios + .get(`https://coins.llama.fi/block/monad/${now}`) + .then((r) => r.data.height), + axios + .get(`https://coins.llama.fi/block/monad/${timestamp1dayAgo}`) + .then((r) => r.data.height), + ]); + + if (!blockNow || !block1dayAgo) { + throw new Error('RPC issue: Failed to fetch block numbers'); + } + + // Get vault addresses from Magma contract + const [coreVaultAddress, gVaultAddress] = await Promise.all([ + sdk.api.abi.call({ + target: MAGMA_ADDRESS, + abi: MAGMA_ABI.coreVault, + chain: 'monad', + block: blockNow, + }), + sdk.api.abi.call({ + target: MAGMA_ADDRESS, + abi: MAGMA_ABI.gVault, + chain: 'monad', + block: blockNow, + }), + ]); + + const coreVault = coreVaultAddress.output; + const gVault = gVaultAddress.output; + + // Fetch current totalAssets, totalSupply, and symbol for gVault (main liquid staking token) + const [totalAssetsNow, totalSupplyNow, symbol] = await Promise.all([ + sdk.api.abi.call({ + target: MAGMA_ADDRESS, + abi: MAGMA_ABI.totalAssets, + chain: 'monad', + block: blockNow, + }), + sdk.api.abi.call({ + target: MAGMA_ADDRESS, + abi: MAGMA_ABI.totalSupply, + chain: 'monad', + block: blockNow, + }), + sdk.api.abi.call({ + target: MAGMA_ADDRESS, + abi: MAGMA_ABI.symbol, + chain: 'monad', + }), + ]); + + // Fetch 1 day ago totalAssets and totalSupply + const [totalAssets1dayAgo, totalSupply1dayAgo] = await Promise.all([ + sdk.api.abi.call({ + target: MAGMA_ADDRESS, + abi: MAGMA_ABI.totalAssets, + chain: 'monad', + block: block1dayAgo, + }), + sdk.api.abi.call({ + target: MAGMA_ADDRESS, + abi: MAGMA_ABI.totalSupply, + chain: 'monad', + block: block1dayAgo, + }), + ]); + + if ( + !totalAssetsNow.output || + !totalSupplyNow.output || + !totalAssets1dayAgo.output || + !totalSupply1dayAgo.output + ) { + throw new Error('RPC issue: Failed to fetch contract data'); + } + + // Calculate share values (multiply by 1e18 to handle decimals) + const shareValueNow = + (BigInt(totalAssetsNow.output) * BigInt(1e18)) / + BigInt(totalSupplyNow.output); + const shareValue1dayAgo = + (BigInt(totalAssets1dayAgo.output) * BigInt(1e18)) / + BigInt(totalSupply1dayAgo.output); + + if (shareValue1dayAgo === 0n) { + throw new Error('RPC issue: Previous share value is zero'); + } + + // Calculate proportion: shareValueNow / shareValue1dayAgo + // Multiply by 1e18 to maintain precision + const proportion = + Number((shareValueNow * BigInt(1e18)) / shareValue1dayAgo) / 1e18; + + if (proportion <= 0) { + throw new Error('RPC issue: Invalid proportion calculated'); + } + + // Calculate APY using the formula: + // APY = ((1 + ((proportion - 1) / 365)) ** 365 - 1) * 100 + // This is equivalent to: APY = (proportion ** 365 - 1) * 100 + const apyBase = (Math.pow(proportion, DAYS_PER_YEAR) - 1) * 100; + + // Calculate TVL using validator staking info (same as DefiLlama TVL adapter) + const vaults = [coreVault, gVault]; + + // Get validators for each vault + const validatorResults = await Promise.all( + vaults.map((vault) => + sdk.api.abi.call({ + target: vault, + abi: MAGMA_ABI.getValidators, + chain: 'monad', + block: blockNow, + }) + ) + ); + + // Build validator calls for staking precompile + const validatorCalls = []; + validatorResults.forEach((result, vaultIndex) => { + if (result.output) { + result.output.forEach((validatorId) => { + validatorCalls.push({ + target: STAKING_PRECOMPILE, + params: [validatorId, vaults[vaultIndex]], + }); + }); + } + }); + + // Get staking info for all validators + let tvlBigInt = 0n; + if (validatorCalls.length > 0) { + const stakingInfoResults = await sdk.api.abi.multiCall({ + calls: validatorCalls, + abi: MAGMA_ABI.getDelegator, + chain: 'monad', + block: blockNow, + }); + + if (stakingInfoResults.output) { + stakingInfoResults.output.forEach((result) => { + if (result.output) { + const { stake, unclaimedRewards, deltaStake, nextDeltaStake } = + result.output; + tvlBigInt += + BigInt(stake || 0) + + BigInt(unclaimedRewards || 0) + + BigInt(deltaStake || 0) + + BigInt(nextDeltaStake || 0); + } + }); + } + } + + // Convert to number (assuming 18 decimals for MON) + const tvlMon = Number(tvlBigInt) / 1e18; + + // Get MON native token price to convert to USD + let tvlUsd; + try { + const monPriceResponse = await axios.get( + 'https://coins.llama.fi/prices/current/coingecko:monad' + ); + const monPrice = + monPriceResponse.data.coins['coingecko:monad']?.price || 1; + tvlUsd = tvlMon * monPrice; + } catch (error) { + // If price lookup fails, use TVL in MON as-is (assuming 1:1 with USD) + tvlUsd = tvlMon; + } + + return [ + { + pool: gVault.toLowerCase(), + chain: 'monad', + project: 'magma-protocol', + symbol: symbol.output || 'gMON', + tvlUsd: tvlUsd, + apyBase: apyBase, + underlyingTokens: ['0x0000000000000000000000000000000000000000'], // MON + }, + ]; +}; + +module.exports = { + apy, + url: 'https://magmaprotocol.com', +}; + From 46b6174c4a696bab0112f848030299db28438e99 Mon Sep 17 00:00:00 2001 From: Diyahir <32445955+diyahir@users.noreply.github.com> Date: Mon, 8 Dec 2025 15:40:08 +0100 Subject: [PATCH 2/4] Update index.js --- src/adaptors/magma-protocol/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adaptors/magma-protocol/index.js b/src/adaptors/magma-protocol/index.js index 025718c67d..9a45d37e84 100644 --- a/src/adaptors/magma-protocol/index.js +++ b/src/adaptors/magma-protocol/index.js @@ -203,7 +203,7 @@ const apy = async () => { return [ { - pool: gVault.toLowerCase(), + pool: MAGMA_ADDRESS.toLowerCase(), chain: 'monad', project: 'magma-protocol', symbol: symbol.output || 'gMON', From c61d62c52a50e05ac4f80089b8443a72884c13cf Mon Sep 17 00:00:00 2001 From: Diyahir <32445955+diyahir@users.noreply.github.com> Date: Mon, 8 Dec 2025 15:41:56 +0100 Subject: [PATCH 3/4] Update index.js --- src/adaptors/magma-protocol/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adaptors/magma-protocol/index.js b/src/adaptors/magma-protocol/index.js index 9a45d37e84..651f41c18e 100644 --- a/src/adaptors/magma-protocol/index.js +++ b/src/adaptors/magma-protocol/index.js @@ -59,7 +59,7 @@ const apy = async () => { const coreVault = coreVaultAddress.output; const gVault = gVaultAddress.output; - // Fetch current totalAssets, totalSupply, and symbol for gVault (main liquid staking token) + // Fetch current totalAssets, totalSupply, and symbol for Magma protocol const [totalAssetsNow, totalSupplyNow, symbol] = await Promise.all([ sdk.api.abi.call({ target: MAGMA_ADDRESS, From 832a0287f30d46649ec230eb389fdd6ecc95f515 Mon Sep 17 00:00:00 2001 From: Diyahir <32445955+diyahir@users.noreply.github.com> Date: Mon, 8 Dec 2025 15:45:27 +0100 Subject: [PATCH 4/4] =?UTF-8?q?moving=20=C2=B4magma-protocol=C2=B4=20to=20?= =?UTF-8?q?=C2=B4magma-staking=C2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/adaptors/{magma-protocol => magma-staking}/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/adaptors/{magma-protocol => magma-staking}/index.js (98%) diff --git a/src/adaptors/magma-protocol/index.js b/src/adaptors/magma-staking/index.js similarity index 98% rename from src/adaptors/magma-protocol/index.js rename to src/adaptors/magma-staking/index.js index 651f41c18e..241f0d58c8 100644 --- a/src/adaptors/magma-protocol/index.js +++ b/src/adaptors/magma-staking/index.js @@ -205,7 +205,7 @@ const apy = async () => { { pool: MAGMA_ADDRESS.toLowerCase(), chain: 'monad', - project: 'magma-protocol', + project: 'magma-staking', symbol: symbol.output || 'gMON', tvlUsd: tvlUsd, apyBase: apyBase, @@ -216,6 +216,6 @@ const apy = async () => { module.exports = { apy, - url: 'https://magmaprotocol.com', + url: 'https://www.magmastaking.xyz/', };