Files
assetx/webapp-back/fundmarket/earning.go

94 lines
3.0 KiB
Go
Raw Permalink Normal View History

package fundmarket
import (
"math/big"
"net/http"
"strings"
"github.com/gin-gonic/gin"
db "github.com/gothinkster/golang-gin-realworld-example-app/common"
)
// GetNetDeposited computes the net USDC deposited by a wallet address across all YT vaults.
//
// GET /api/fundmarket/net-deposited?address=0x...&chain_id=97
//
// Net deposited = Σ(amountIn WHERE tokenIn=USDC) - Σ(amountOut WHERE tokenOut=USDC)
// (buy YT: USDC → YT, tokenIn=USDC; sell YT: YT → USDC, tokenOut=USDC)
//
// Returns netDepositedUSD (float64) for the frontend to compute:
// Your Total Earning = currentValue (on-chain) - netDepositedUSD
func GetNetDeposited(c *gin.Context) {
address := strings.ToLower(c.Query("address"))
if address == "" {
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "address required"})
return
}
chainIDStr := c.DefaultQuery("chain_id", "97")
database := db.GetDB()
// Look up USDC address for this chain (token_role = 'stablecoin')
var usdcAddr struct {
ContractAddress string `gorm:"column:contract_address"`
}
if err := database.Table("assets").
Where("token_role = 'stablecoin' AND chain_id = ?", chainIDStr).
Select("contract_address").
First(&usdcAddr).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "USDC address not found"})
return
}
usdcAddress := strings.ToLower(usdcAddr.ContractAddress)
// Sum amountIn where tokenIn = USDC (user bought YT, paid USDC)
type sumResult struct {
Total string
}
var buySum sumResult
database.Raw(`
SELECT COALESCE(SUM(CAST(amount_in AS DECIMAL(65,0))), 0) AS total
FROM yt_swap_records
WHERE account = ? AND chain_id = ? AND LOWER(token_in) = ?
`, address, chainIDStr, usdcAddress).Scan(&buySum)
// Sum amountOut where tokenOut = USDC (user sold YT, received USDC)
var sellSum sumResult
database.Raw(`
SELECT COALESCE(SUM(CAST(amount_out AS DECIMAL(65,0))), 0) AS total
FROM yt_swap_records
WHERE account = ? AND chain_id = ? AND LOWER(token_out) = ?
`, address, chainIDStr, usdcAddress).Scan(&sellSum)
buyWei, _ := new(big.Int).SetString(buySum.Total, 10)
sellWei, _ := new(big.Int).SetString(sellSum.Total, 10)
if buyWei == nil {
buyWei = big.NewInt(0)
}
if sellWei == nil {
sellWei = big.NewInt(0)
}
netWei := new(big.Int).Sub(buyWei, sellWei)
if netWei.Sign() < 0 {
netWei = big.NewInt(0)
}
// Convert from 18-decimal wei to float64 USD
divisor := new(big.Float).SetInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil))
netUSD, _ := new(big.Float).Quo(new(big.Float).SetInt(netWei), divisor).Float64()
c.JSON(http.StatusOK, gin.H{
"success": true,
"data": gin.H{
"address": address,
"chainId": chainIDStr,
"usdcAddress": usdcAddress,
"buyWei": buyWei.String(),
"sellWei": sellWei.String(),
"netDepositedWei": netWei.String(),
"netDepositedUSD": netUSD,
},
})
}