package transfer import ( "context" "strings" "github.com/tech/sendico/gateway/chain/storage/model" "github.com/tech/sendico/pkg/merrors" chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1" "go.uber.org/zap" ) func resolveDestination(ctx context.Context, deps Deps, dest *chainv1.TransferDestination, source *model.ManagedWallet) (model.TransferDestination, error) { if dest == nil { return model.TransferDestination{}, merrors.InvalidArgument("destination is required") } managedRef := strings.TrimSpace(dest.GetManagedWalletRef()) external := strings.TrimSpace(dest.GetExternalAddress()) if managedRef != "" && external != "" { deps.Logger.Warn("both managed and external destination provided") return model.TransferDestination{}, merrors.InvalidArgument("destination must be managed_wallet_ref or external_address") } if managedRef != "" { wallet, err := deps.Storage.Wallets().Get(ctx, managedRef) if err != nil { deps.Logger.Warn("destination wallet lookup failed", zap.Error(err), zap.String("managed_wallet_ref", managedRef)) return model.TransferDestination{}, err } if !strings.EqualFold(wallet.Network, source.Network) { deps.Logger.Warn("destination wallet network mismatch", zap.String("source_network", source.Network), zap.String("dest_network", wallet.Network)) return model.TransferDestination{}, merrors.InvalidArgument("destination wallet network mismatch") } if strings.TrimSpace(wallet.DepositAddress) == "" { deps.Logger.Warn("destination wallet missing deposit address", zap.String("managed_wallet_ref", managedRef)) return model.TransferDestination{}, merrors.InvalidArgument("destination wallet missing deposit address") } return model.TransferDestination{ ManagedWalletRef: wallet.WalletRef, Memo: strings.TrimSpace(dest.GetMemo()), }, nil } if external == "" { deps.Logger.Warn("destination external address missing") return model.TransferDestination{}, merrors.InvalidArgument("destination is required") } if deps.Drivers == nil { deps.Logger.Warn("chain drivers missing", zap.String("network", source.Network)) return model.TransferDestination{}, merrors.Internal("chain drivers not configured") } chainDriver, err := deps.Drivers.Driver(source.Network) if err != nil { deps.Logger.Warn("unsupported chain driver", zap.String("network", source.Network), zap.Error(err)) return model.TransferDestination{}, merrors.InvalidArgument("unsupported chain for wallet") } normalized, err := chainDriver.NormalizeAddress(external) if err != nil { deps.Logger.Warn("invalid external address", zap.Error(err)) return model.TransferDestination{}, err } return model.TransferDestination{ ExternalAddress: normalized, Memo: strings.TrimSpace(dest.GetMemo()), }, nil }