2025-07-21 11:48:53 +00:00
|
|
|
package alchemy
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2025-07-21 14:31:44 +00:00
|
|
|
"fmt"
|
2025-07-21 11:48:53 +00:00
|
|
|
"gitea.pena/PenaSide/treasurer/internal/errors"
|
|
|
|
"gitea.pena/PenaSide/treasurer/internal/models"
|
2025-07-21 14:31:44 +00:00
|
|
|
"gitea.pena/PenaSide/treasurer/internal/models/alchemy"
|
2025-07-21 15:03:53 +00:00
|
|
|
"gitea.pena/PenaSide/treasurer/internal/repository"
|
2025-07-21 11:48:53 +00:00
|
|
|
"github.com/gofiber/fiber/v2"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
)
|
|
|
|
|
|
|
|
const ProviderName = "alchemy"
|
|
|
|
|
|
|
|
type Config struct {
|
2025-07-21 14:31:44 +00:00
|
|
|
WalletAddress string `json:"walletAddress"`
|
2025-07-21 11:48:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Provider struct {
|
2025-07-21 15:03:53 +00:00
|
|
|
repository *repository.PaymentRepository
|
|
|
|
logger *zap.Logger
|
|
|
|
config *Config
|
2025-07-21 11:48:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Deps struct {
|
2025-07-21 15:03:53 +00:00
|
|
|
Repository *repository.PaymentMethodRepository
|
|
|
|
Logger *zap.Logger
|
|
|
|
Config *Config
|
2025-07-21 11:48:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func New(deps Deps) *Provider {
|
|
|
|
return &Provider{
|
|
|
|
logger: deps.Logger,
|
|
|
|
config: deps.Config,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Provider) GetName() string {
|
|
|
|
return ProviderName
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Provider) GetSupportedPaymentMethods() []models.PaymentType {
|
|
|
|
return []models.PaymentType{models.PaymentTypeAlchemy}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Provider) CreateInvoice(ctx context.Context, req map[string]string) (string, errors.Error) {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Provider) RegisterWebhookHandlers(router fiber.Router) {
|
|
|
|
router.Post("/webhook/alchemy", p.handleWebhook)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Provider) handleWebhook(ctx *fiber.Ctx) error {
|
2025-07-21 14:31:44 +00:00
|
|
|
var payload alchemy.AlchemyAddressActivityWebhook
|
|
|
|
if err := ctx.BodyParser(&payload); err != nil {
|
|
|
|
return ctx.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("failed to parse Alchemy webhook: %s", err.Error()))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, act := range payload.Event.Activity {
|
|
|
|
if act.ToAddress != p.config.WalletAddress {
|
|
|
|
continue
|
|
|
|
}
|
2025-07-21 15:03:53 +00:00
|
|
|
amountStr := fmt.Sprintf("%v", act.Value)
|
|
|
|
payment, err := p.repository.FindByWalletAddressAndAmount(ctx.Context(), act.FromAddress, amountStr)
|
|
|
|
if err != nil {
|
|
|
|
if err.Type() == errors.ErrNotFound {
|
|
|
|
return ctx.Status(fiber.StatusNotFound).SendString(fmt.Sprintf("payment not found: %s", err.Error()))
|
|
|
|
}
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString(fmt.Sprintf("internal error while searching payment: %s", err.Error()))
|
|
|
|
}
|
|
|
|
_, err = p.repository.SetPaymentComplete(ctx.Context(), payment.PaymentID)
|
|
|
|
if err != nil {
|
|
|
|
return ctx.Status(fiber.StatusInternalServerError).SendString(fmt.Sprintf("failed to set payment complete: %s", err.Error()))
|
|
|
|
}
|
2025-07-21 14:31:44 +00:00
|
|
|
}
|
|
|
|
return ctx.SendStatus(fiber.StatusOK)
|
2025-07-21 11:48:53 +00:00
|
|
|
}
|