94 lines
3.0 KiB
Go
94 lines
3.0 KiB
Go
|
|
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,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
}
|