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) }