init: 初始化 AssetX 项目仓库
包含 webapp(Next.js 用户端)、webapp-back(Go 后端)、 antdesign(管理后台)、landingpage(营销落地页)、 数据库 SQL 和配置文件。
This commit is contained in:
93
webapp-back/fundmarket/earning.go
Normal file
93
webapp-back/fundmarket/earning.go
Normal file
@@ -0,0 +1,93 @@
|
||||
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,
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user