Files
sendico/api/server/interface/api/sresponse/wallet.go
2025-12-24 18:17:35 +01:00

156 lines
4.5 KiB
Go

package sresponse
import (
"net/http"
"strings"
"time"
"github.com/tech/sendico/pkg/api/http/response"
"github.com/tech/sendico/pkg/mlogger"
"github.com/tech/sendico/pkg/model"
paginationv1 "github.com/tech/sendico/pkg/proto/common/pagination/v1"
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
"google.golang.org/protobuf/types/known/timestamppb"
)
type walletAsset struct {
Chain string `json:"chain"`
TokenSymbol string `json:"tokenSymbol"`
ContractAddress string `json:"contractAddress"`
}
type wallet struct {
WalletRef string `json:"walletRef"`
OrganizationRef string `json:"organizationRef"`
OwnerRef string `json:"ownerRef"`
Asset walletAsset `json:"asset"`
DepositAddress string `json:"depositAddress"`
Status string `json:"status"`
Metadata map[string]string `json:"metadata,omitempty"`
Name string `json:"name"`
Description *string `json:"description,omitempty"`
CreatedAt string `json:"createdAt,omitempty"`
UpdatedAt string `json:"updatedAt,omitempty"`
}
type walletsResponse struct {
authResponse `json:",inline"`
Wallets []wallet `json:"wallets"`
Page *paginationv1.CursorPageResponse `json:"page,omitempty"`
}
type walletBalance struct {
Available *model.Money `json:"available,omitempty"`
PendingInbound *model.Money `json:"pendingInbound,omitempty"`
PendingOutbound *model.Money `json:"pendingOutbound,omitempty"`
CalculatedAt string `json:"calculatedAt,omitempty"`
}
type walletBalanceResponse struct {
authResponse `json:",inline"`
Balance walletBalance `json:"balance"`
}
func Wallets(logger mlogger.Logger, resp *chainv1.ListManagedWalletsResponse, accessToken *TokenData) http.HandlerFunc {
dto := walletsResponse{
Page: resp.GetPage(),
authResponse: authResponse{AccessToken: *accessToken},
}
dto.Wallets = make([]wallet, 0, len(resp.GetWallets()))
for _, w := range resp.GetWallets() {
dto.Wallets = append(dto.Wallets, toWallet(w))
}
return response.Ok(logger, dto)
}
func WalletBalance(logger mlogger.Logger, bal *chainv1.WalletBalance, accessToken *TokenData) http.HandlerFunc {
return response.Ok(logger, walletBalanceResponse{
Balance: toWalletBalance(bal),
authResponse: authResponse{AccessToken: *accessToken},
})
}
func toWallet(w *chainv1.ManagedWallet) wallet {
if w == nil {
return wallet{}
}
asset := w.GetAsset()
chain := ""
token := ""
contract := ""
if asset != nil {
chain = chainNetworkValue(asset.GetChain())
token = asset.GetTokenSymbol()
contract = asset.GetContractAddress()
}
name := ""
if d := w.GetDescribable(); d != nil {
name = strings.TrimSpace(d.GetName())
}
if name == "" {
name = strings.TrimSpace(w.GetMetadata()["name"])
}
if name == "" {
name = w.GetWalletRef()
}
var description *string
if d := w.GetDescribable(); d != nil && d.Description != nil {
if trimmed := strings.TrimSpace(d.GetDescription()); trimmed != "" {
description = &trimmed
}
}
if description == nil {
if trimmed := strings.TrimSpace(w.GetMetadata()["description"]); trimmed != "" {
description = &trimmed
}
}
return wallet{
WalletRef: w.GetWalletRef(),
OrganizationRef: w.GetOrganizationRef(),
OwnerRef: w.GetOwnerRef(),
Asset: walletAsset{
Chain: chain,
TokenSymbol: token,
ContractAddress: contract,
},
DepositAddress: w.GetDepositAddress(),
Status: w.GetStatus().String(),
Metadata: w.GetMetadata(),
Name: name,
Description: description,
CreatedAt: tsToString(w.GetCreatedAt()),
UpdatedAt: tsToString(w.GetUpdatedAt()),
}
}
func toWalletBalance(b *chainv1.WalletBalance) walletBalance {
if b == nil {
return walletBalance{}
}
return walletBalance{
Available: toMoney(b.GetAvailable()),
PendingInbound: toMoney(b.GetPendingInbound()),
PendingOutbound: toMoney(b.GetPendingOutbound()),
CalculatedAt: tsToString(b.GetCalculatedAt()),
}
}
func tsToString(ts *timestamppb.Timestamp) string {
if ts == nil {
return ""
}
return ts.AsTime().UTC().Format(time.RFC3339)
}
func chainNetworkValue(chain chainv1.ChainNetwork) string {
name := chain.String()
if !strings.HasPrefix(name, "CHAIN_NETWORK_") {
return "unspecified"
}
trimmed := strings.TrimPrefix(name, "CHAIN_NETWORK_")
if trimmed == "" {
return "unspecified"
}
return strings.ToLower(trimmed)
}