Compare commits
104 Commits
SEND041
...
e767436f33
| Author | SHA1 | Date | |
|---|---|---|---|
| e767436f33 | |||
|
|
57914c0754 | ||
| b894f92e50 | |||
|
|
76548032b3 | ||
| d121f4172e | |||
|
|
e717cabd0f | ||
| 8fead967d1 | |||
|
|
a09fd550ba | ||
| 8eae9270f2 | |||
|
|
dc6a4224a0 | ||
| a99a3c851c | |||
|
|
9bca523caa | ||
| 27de7a9655 | |||
|
|
7cbcbb4b3c | ||
| fee10afbb8 | |||
|
|
97395acd8f | ||
| f4b43f7218 | |||
|
|
3c0d709a82 | ||
| b787cc4d9e | |||
|
|
7b53ca6cef | ||
| fab07fdc8e | |||
|
|
e116535926 | ||
| 9b8f59e05a | |||
|
|
6844d1e587 | ||
| 3225babeca | |||
|
|
0a1e04d0d6 | ||
| 648ace709a | |||
|
|
274035ed6d | ||
| 0aab5cceb0 | |||
|
|
9b97ebfa6c | ||
| b02df379a7 | |||
|
|
f5052f6cf8 | ||
|
|
edb43f9909 | ||
| 7524852533 | |||
|
|
cfb219e206 | ||
| 66989ea36c | |||
|
|
296cc7b86a | ||
| 6745bc0f6f | |||
|
|
c962ac7cbd | ||
| 817d4357cf | |||
|
|
2711d601b0 | ||
| 74b0976cb7 | |||
|
|
3c82afbd43 | ||
| 32688a2de7 | |||
|
|
f2938daddd | ||
| 7c26698f0d | |||
|
|
461a340b08 | ||
| dadf9e2485 | |||
|
|
f59789ab7a | ||
| 5e92d7b9ff | |||
|
|
3578ddd54f | ||
| 9463c7ce1f | |||
|
|
7c182afd23 | ||
|
|
7f540671c1 | ||
|
|
76c3bfdea9 | ||
|
|
eda6b75f74 | ||
| 5caf46ffe1 | |||
|
|
c8b8b1183b | ||
| 17bc2a2a62 | |||
|
|
706861af5f | ||
|
|
f8a3bef2e6 | ||
| 4639b2c610 | |||
|
|
b9748b8ab2 | ||
| 8034847e46 | |||
|
|
49b0b63f55 | ||
| 5984f2c2f7 | |||
|
|
bc50391fe7 | ||
| 67598449e6 | |||
|
|
761dda9377 | ||
| 42da0260b0 | |||
|
|
5df02baa80 | ||
| 7417b33de3 | |||
|
|
217542ec14 | ||
| e394770eb1 | |||
|
|
611bde214f | ||
|
|
d3e69bcd62 | ||
| fb9def8c19 | |||
|
|
6e3115e7fa | ||
| 0675978bd1 | |||
|
|
04391cbd8d | ||
| 87f320802d | |||
|
|
3a4f1c7e3f | ||
| 542d88750d | |||
|
|
b27eed31b7 | ||
|
|
69ed9f25cb | ||
|
|
e4fb270390 | ||
|
|
81ffdd4291 | ||
|
|
0ce90eef21 | ||
| 509af9bc5c | |||
|
|
bc0fd6ab2f | ||
| ca0e45ee5f | |||
| 3cf6b10ea7 | |||
|
|
1bdbbf65a4 | ||
|
|
fe9133c206 | ||
| b722d61c4f | |||
|
|
f56a3d4611 | ||
| afa842ba65 | |||
|
|
ccc9737d1b | ||
| a569757b7f | |||
|
|
43b252859e | ||
| e1c439fb85 | |||
|
|
571cea3b37 | ||
| 6198ceb9a4 | |||
|
|
f02f28d53f |
@@ -9,6 +9,12 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/server/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/billing/documents/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/billing/fees/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
exclude: ['**']
|
||||||
|
ignore_message: '[infra]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/discovery/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/server/**
|
||||||
|
- api/pkg/**
|
||||||
|
- api/proto/**
|
||||||
|
- frontend/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -11,6 +11,13 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/fx/ingestor/**
|
||||||
|
- api/fx/storage/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -11,6 +11,14 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/fx/oracle/**
|
||||||
|
- api/fx/storage/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/gateway/chain/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/gateway/mntx/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/gateway/tgsettle/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/gateway/tron/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/ledger/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
exclude: ['**']
|
||||||
|
ignore_message: '[infra]'
|
||||||
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/notification/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ matrix:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/payments/orchestrator/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: version
|
- name: version
|
||||||
|
|||||||
81
.woodpecker/payments_quotation.yml
Normal file
81
.woodpecker/payments_quotation.yml
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- PAYMENTS_QUOTATION_IMAGE_PATH: payments/quotation
|
||||||
|
PAYMENTS_QUOTATION_DOCKERFILE: ci/prod/compose/payments_quotation.dockerfile
|
||||||
|
PAYMENTS_QUOTATION_MONGO_SECRET_PATH: sendico/db
|
||||||
|
PAYMENTS_QUOTATION_ENV: prod
|
||||||
|
|
||||||
|
when:
|
||||||
|
- event: push
|
||||||
|
branch: main
|
||||||
|
path:
|
||||||
|
include:
|
||||||
|
- api/payments/quotation/**
|
||||||
|
- api/payments/storage/**
|
||||||
|
- api/payments/orchestrator/**
|
||||||
|
- api/proto/**
|
||||||
|
- api/pkg/**
|
||||||
|
ignore_message: '[rebuild]'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: version
|
||||||
|
image: alpine:latest
|
||||||
|
commands:
|
||||||
|
- set -euo pipefail 2>/dev/null || set -eu
|
||||||
|
- apk add --no-cache git
|
||||||
|
- GIT_REV="$(git rev-parse --short HEAD)"
|
||||||
|
- BUILD_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
||||||
|
- APP_V="$(cat version)"
|
||||||
|
- BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||||
|
- BUILD_USER="${WOODPECKER_MACHINE:-woodpecker}"
|
||||||
|
- printf "GIT_REV=%s\nBUILD_BRANCH=%s\nAPP_V=%s\nBUILD_DATE=%s\nBUILD_USER=%s\n" \
|
||||||
|
"$GIT_REV" "$BUILD_BRANCH" "$APP_V" "$BUILD_DATE" "$BUILD_USER" | tee .env.version
|
||||||
|
|
||||||
|
- name: proto
|
||||||
|
image: golang:alpine
|
||||||
|
depends_on: [ version ]
|
||||||
|
commands:
|
||||||
|
- set -eu
|
||||||
|
- apk add --no-cache bash git build-base protoc protobuf-dev
|
||||||
|
- go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||||
|
- go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
||||||
|
- export PATH="$(go env GOPATH)/bin:$PATH"
|
||||||
|
- bash ci/scripts/proto/generate.sh
|
||||||
|
|
||||||
|
- name: secrets
|
||||||
|
image: alpine:latest
|
||||||
|
depends_on: [ version ]
|
||||||
|
environment:
|
||||||
|
VAULT_ADDR: { from_secret: VAULT_ADDR }
|
||||||
|
VAULT_ROLE_ID: { from_secret: VAULT_APP_ROLE }
|
||||||
|
VAULT_SECRET_ID: { from_secret: VAULT_SECRET_ID }
|
||||||
|
commands:
|
||||||
|
- set -euo pipefail
|
||||||
|
- apk add --no-cache bash coreutils openssh-keygen curl sed python3
|
||||||
|
- mkdir -p secrets
|
||||||
|
- ./ci/vlt kv_to_file kv ops/deploy/ssh_key private_b64 secrets/SSH_KEY.b64 600
|
||||||
|
- base64 -d secrets/SSH_KEY.b64 > secrets/SSH_KEY
|
||||||
|
- chmod 600 secrets/SSH_KEY
|
||||||
|
- ssh-keygen -y -f secrets/SSH_KEY >/dev/null
|
||||||
|
- ./ci/vlt kv_get kv registry user > secrets/REGISTRY_USER
|
||||||
|
- ./ci/vlt kv_get kv registry password > secrets/REGISTRY_PASSWORD
|
||||||
|
|
||||||
|
- name: build-image
|
||||||
|
image: gcr.io/kaniko-project/executor:debug
|
||||||
|
depends_on: [ proto, secrets ]
|
||||||
|
commands:
|
||||||
|
- sh ci/scripts/payments_quotation/build-image.sh
|
||||||
|
|
||||||
|
- name: deploy
|
||||||
|
image: alpine:latest
|
||||||
|
depends_on: [ secrets, build-image ]
|
||||||
|
environment:
|
||||||
|
VAULT_ADDR: { from_secret: VAULT_ADDR }
|
||||||
|
VAULT_ROLE_ID: { from_secret: VAULT_APP_ROLE }
|
||||||
|
VAULT_SECRET_ID: { from_secret: VAULT_SECRET_ID }
|
||||||
|
commands:
|
||||||
|
- set -euo pipefail
|
||||||
|
- apk add --no-cache bash openssh-client rsync coreutils curl sed python3
|
||||||
|
- mkdir -p /root/.ssh
|
||||||
|
- install -m 600 secrets/SSH_KEY /root/.ssh/id_rsa
|
||||||
|
- sh ci/scripts/payments_quotation/deploy.sh
|
||||||
69
Makefile
69
Makefile
@@ -1,7 +1,7 @@
|
|||||||
# Sendico Development Environment - Makefile
|
# Sendico Development Environment - Makefile
|
||||||
# Docker Compose + Makefile build system
|
# Docker Compose + Makefile build system
|
||||||
|
|
||||||
.PHONY: help init build up down restart logs rebuild clean vault-init proto
|
.PHONY: help init build up down restart logs rebuild clean vault-init proto generate generate-api generate-frontend update update-api update-frontend test test-api test-frontend
|
||||||
|
|
||||||
COMPOSE := docker compose -f docker-compose.dev.yml --env-file .env.dev
|
COMPOSE := docker compose -f docker-compose.dev.yml --env-file .env.dev
|
||||||
SERVICE ?=
|
SERVICE ?=
|
||||||
@@ -43,6 +43,15 @@ help:
|
|||||||
@echo ""
|
@echo ""
|
||||||
@echo "$(YELLOW)Development:$(NC)"
|
@echo "$(YELLOW)Development:$(NC)"
|
||||||
@echo " make proto Generate protobuf code"
|
@echo " make proto Generate protobuf code"
|
||||||
|
@echo " make generate Generate all code (protobuf + Flutter)"
|
||||||
|
@echo " make generate-api Generate protobuf code only"
|
||||||
|
@echo " make generate-frontend Generate Flutter code only"
|
||||||
|
@echo " make update Update all dependencies (Go + Flutter)"
|
||||||
|
@echo " make update-api Update Go dependencies only"
|
||||||
|
@echo " make update-frontend Update Flutter dependencies only"
|
||||||
|
@echo " make test Run all tests (API + frontend)"
|
||||||
|
@echo " make test-api Run Go API tests only"
|
||||||
|
@echo " make test-frontend Run Flutter tests only"
|
||||||
@echo " make health Check service health"
|
@echo " make health Check service health"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Examples:"
|
@echo "Examples:"
|
||||||
@@ -136,12 +145,25 @@ endif
|
|||||||
@echo "$(GREEN)✅ $(SERVICE) rebuilt$(NC)"
|
@echo "$(GREEN)✅ $(SERVICE) rebuilt$(NC)"
|
||||||
@echo "View logs: make logs SERVICE=$(SERVICE)"
|
@echo "View logs: make logs SERVICE=$(SERVICE)"
|
||||||
|
|
||||||
|
# Generate protobuf code (alias)
|
||||||
|
proto: generate-api
|
||||||
|
|
||||||
|
# Generate all code
|
||||||
|
generate: generate-api generate-frontend
|
||||||
|
|
||||||
# Generate protobuf code
|
# Generate protobuf code
|
||||||
proto:
|
generate-api:
|
||||||
@echo "$(GREEN)Generating protobuf code...$(NC)"
|
@echo "$(GREEN)Generating protobuf code...$(NC)"
|
||||||
@./generate_protos.sh
|
@./generate_protos.sh
|
||||||
@echo "$(GREEN)✅ Protobuf generation complete$(NC)"
|
@echo "$(GREEN)✅ Protobuf generation complete$(NC)"
|
||||||
|
|
||||||
|
# Generate Flutter code (json_serializable, etc.)
|
||||||
|
generate-frontend:
|
||||||
|
@echo "$(GREEN)Generating Flutter code...$(NC)"
|
||||||
|
@cd frontend/pshared && flutter pub run build_runner build --delete-conflicting-outputs
|
||||||
|
@cd frontend/pweb && flutter pub run build_runner build --delete-conflicting-outputs
|
||||||
|
@echo "$(GREEN)✅ Flutter code generation complete$(NC)"
|
||||||
|
|
||||||
# Clean everything
|
# Clean everything
|
||||||
clean:
|
clean:
|
||||||
@echo "$(YELLOW)WARNING: This will remove all containers and volumes!$(NC)"
|
@echo "$(YELLOW)WARNING: This will remove all containers and volumes!$(NC)"
|
||||||
@@ -264,3 +286,46 @@ build-api:
|
|||||||
build-frontend:
|
build-frontend:
|
||||||
@echo "$(GREEN)Building frontend...$(NC)"
|
@echo "$(GREEN)Building frontend...$(NC)"
|
||||||
@$(COMPOSE) build dev-frontend
|
@$(COMPOSE) build dev-frontend
|
||||||
|
|
||||||
|
# Update all dependencies
|
||||||
|
update: update-api update-frontend
|
||||||
|
|
||||||
|
# Update Go API dependencies
|
||||||
|
update-api:
|
||||||
|
@echo "$(GREEN)Updating Go dependencies...$(NC)"
|
||||||
|
@for dir in $$(find api -name go.mod -exec dirname {} \;); do \
|
||||||
|
echo "Updating $$dir..."; \
|
||||||
|
(cd "$$dir" && go get -u ./... && go mod tidy); \
|
||||||
|
done
|
||||||
|
@echo "$(GREEN)✅ Go dependencies updated$(NC)"
|
||||||
|
|
||||||
|
# Update Flutter dependencies
|
||||||
|
update-frontend:
|
||||||
|
@echo "$(GREEN)Updating Flutter dependencies...$(NC)"
|
||||||
|
@cd frontend/pshared && flutter pub upgrade --major-versions
|
||||||
|
@cd frontend/pweb && flutter pub upgrade --major-versions
|
||||||
|
@echo "$(GREEN)✅ Flutter dependencies updated$(NC)"
|
||||||
|
|
||||||
|
# Run all tests
|
||||||
|
test: test-api test-frontend
|
||||||
|
|
||||||
|
# Run Go API tests
|
||||||
|
test-api:
|
||||||
|
@echo "$(GREEN)Running API tests...$(NC)"
|
||||||
|
@failed=""; \
|
||||||
|
for dir in $$(find api -name go.mod -exec dirname {} \;); do \
|
||||||
|
echo "Testing $$dir..."; \
|
||||||
|
(cd "$$dir" && go test ./...) || failed="$$failed $$dir"; \
|
||||||
|
done; \
|
||||||
|
if [ -n "$$failed" ]; then \
|
||||||
|
echo "$(YELLOW)Failed:$$failed$(NC)"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
@echo "$(GREEN)✅ All API tests passed$(NC)"
|
||||||
|
|
||||||
|
# Run Flutter tests
|
||||||
|
test-frontend:
|
||||||
|
@echo "$(GREEN)Running frontend tests...$(NC)"
|
||||||
|
@cd frontend/pshared && flutter test
|
||||||
|
@cd frontend/pweb && flutter test
|
||||||
|
@echo "$(GREEN)✅ All frontend tests passed$(NC)"
|
||||||
|
|||||||
99
README.md
Normal file
99
README.md
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# Sendico [](https://ci.sendico.io/repos/1)
|
||||||
|
|
||||||
|
|
||||||
|
Financial services platform providing payment orchestration, ledger accounting, FX conversion, and multi-rail payment processing.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
- **Backend**: Go microservices with gRPC inter-service communication
|
||||||
|
- **Frontend**: Flutter/Dart web application
|
||||||
|
- **Infrastructure**: Woodpecker CI/CD, Docker, MongoDB, NATS, Vault
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
| Service | Path | Description |
|
||||||
|
|---------|------|-------------|
|
||||||
|
| Discovery | `api/discovery/` | Service registry |
|
||||||
|
| Ledger | `api/ledger/` | Double-entry accounting |
|
||||||
|
| Orchestrator | `api/payments/orchestrator/` | Payment orchestration |
|
||||||
|
| Quotation | `api/payments/quotation/` | Payment quotation |
|
||||||
|
| Billing Fees | `api/billing/fees/` | Fee calculation |
|
||||||
|
| Billing Documents | `api/billing/documents/` | Billing documents |
|
||||||
|
| FX Oracle | `api/fx/oracle/` | FX quote provider |
|
||||||
|
| FX Ingestor | `api/fx/ingestor/` | FX rate ingestion |
|
||||||
|
| Gateway Chain | `api/gateway/chain/` | EVM blockchain gateway |
|
||||||
|
| Gateway TRON | `api/gateway/tron/` | TRON blockchain gateway |
|
||||||
|
| Gateway MNTX | `api/gateway/mntx/` | Card payouts |
|
||||||
|
| Gateway TGSettle | `api/gateway/tgsettle/` | Settlements |
|
||||||
|
| Notification | `api/notification/` | Notifications |
|
||||||
|
| BFF | `api/server/` | Backend for frontend |
|
||||||
|
| Frontend | `frontend/pweb/` | Flutter web UI |
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
Development uses Docker Compose via the Makefile. Run `make help` for all available commands.
|
||||||
|
|
||||||
|
### Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make init # First-time setup (generates keys, .env.dev, builds images)
|
||||||
|
make up # Start all services
|
||||||
|
make vault-init # Initialize Vault (if needed)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make build # Build all service images
|
||||||
|
make up # Start all services
|
||||||
|
make down # Stop all services
|
||||||
|
make restart # Restart all services
|
||||||
|
make status # Show service status
|
||||||
|
make logs # View all logs
|
||||||
|
make logs SERVICE=dev-ledger # View logs for a specific service
|
||||||
|
make rebuild SERVICE=dev-ledger # Rebuild and restart a specific service
|
||||||
|
make clean # Remove all containers and volumes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Selective Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make infra-up # Start infrastructure only (MongoDB, NATS, Vault)
|
||||||
|
make services-up # Start application services only (assumes infra is running)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build Groups
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make build-core # discovery, ledger, fees, documents
|
||||||
|
make build-fx # oracle, ingestor
|
||||||
|
make build-payments # orchestrator
|
||||||
|
make build-gateways # chain, tron, mntx, tgsettle
|
||||||
|
make build-api # notification, bff
|
||||||
|
make build-frontend # Flutter web UI
|
||||||
|
```
|
||||||
|
|
||||||
|
### Code Generation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make generate # Generate all code (protobuf + Flutter)
|
||||||
|
make generate-api # Generate protobuf code only
|
||||||
|
make generate-frontend # Generate Flutter code only (build_runner)
|
||||||
|
make proto # Alias for generate-api
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make test # Run all tests (API + frontend)
|
||||||
|
make test-api # Run Go API tests only
|
||||||
|
make test-frontend # Run Flutter tests only
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update Dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make update # Update all Go and Flutter dependencies
|
||||||
|
make update-api # Update Go dependencies only
|
||||||
|
make update-frontend # Update Flutter dependencies only
|
||||||
|
```
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/tech/sendico/billing/documents
|
module github.com/tech/sendico/billing/documents
|
||||||
|
|
||||||
go 1.25.6
|
go 1.25.7
|
||||||
|
|
||||||
replace github.com/tech/sendico/pkg => ../../pkg
|
replace github.com/tech/sendico/pkg => ../../pkg
|
||||||
|
|
||||||
@@ -41,9 +41,9 @@ require (
|
|||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/go-chi/chi/v5 v5.2.4 // indirect
|
github.com/go-chi/chi/v5 v5.2.5 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.3 // indirect
|
github.com/klauspost/compress v1.18.4 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
@@ -60,11 +60,11 @@ require (
|
|||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/crypto v0.47.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/net v0.49.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||||
google.golang.org/protobuf v1.36.11 // indirect
|
google.golang.org/protobuf v1.36.11 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
|
|||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
|
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||||
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
@@ -100,8 +100,8 @@ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
|||||||
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||||
github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc=
|
github.com/jung-kurt/gofpdf v1.16.2 h1:jgbatWHfRlPYiK85qgevsZTHviWXKwB1TTiKdz5PtRc=
|
||||||
github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0=
|
github.com/jung-kurt/gofpdf v1.16.2/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0=
|
||||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@@ -221,16 +221,16 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
|||||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
@@ -241,16 +241,16 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@@ -258,8 +258,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b h1:GZxXGdFaHX27ZSMHudWc4FokdD+xl8BC2UJm1OVIEzs=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/tech/sendico/billing/fees
|
module github.com/tech/sendico/billing/fees
|
||||||
|
|
||||||
go 1.25.6
|
go 1.25.7
|
||||||
|
|
||||||
replace github.com/tech/sendico/pkg => ../../pkg
|
replace github.com/tech/sendico/pkg => ../../pkg
|
||||||
|
|
||||||
@@ -25,9 +25,9 @@ require (
|
|||||||
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
github.com/casbin/casbin/v2 v2.135.0 // indirect
|
||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/go-chi/chi/v5 v5.2.4 // indirect
|
github.com/go-chi/chi/v5 v5.2.5 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.3 // indirect
|
github.com/klauspost/compress v1.18.4 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
@@ -45,11 +45,11 @@ require (
|
|||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/crypto v0.47.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/net v0.49.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||||
google.golang.org/protobuf v1.36.11
|
google.golang.org/protobuf v1.36.11
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
|
|||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
|
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||||
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
@@ -57,8 +57,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@@ -172,15 +172,15 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
|||||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
@@ -191,16 +191,16 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@@ -208,8 +208,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b h1:GZxXGdFaHX27ZSMHudWc4FokdD+xl8BC2UJm1OVIEzs=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
|||||||
195
api/discovery/.golangci.yml
Normal file
195
api/discovery/.golangci.yml
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
# See the dedicated "version" documentation section.
|
||||||
|
version: "2"
|
||||||
|
linters:
|
||||||
|
# Default set of linters.
|
||||||
|
# The value can be:
|
||||||
|
# - `standard`: https://golangci-lint.run/docs/linters/#enabled-by-default
|
||||||
|
# - `all`: enables all linters by default.
|
||||||
|
# - `none`: disables all linters by default.
|
||||||
|
# - `fast`: enables only linters considered as "fast" (`golangci-lint help linters --json | jq '[ .[] | select(.fast==true) ] | map(.name)'`).
|
||||||
|
# Default: standard
|
||||||
|
default: all
|
||||||
|
# Enable specific linter.
|
||||||
|
enable:
|
||||||
|
- arangolint
|
||||||
|
- asasalint
|
||||||
|
- asciicheck
|
||||||
|
- bidichk
|
||||||
|
- bodyclose
|
||||||
|
- canonicalheader
|
||||||
|
- containedctx
|
||||||
|
- contextcheck
|
||||||
|
- copyloopvar
|
||||||
|
- cyclop
|
||||||
|
- decorder
|
||||||
|
- dogsled
|
||||||
|
- dupl
|
||||||
|
- dupword
|
||||||
|
- durationcheck
|
||||||
|
- embeddedstructfieldcheck
|
||||||
|
- err113
|
||||||
|
- errcheck
|
||||||
|
- errchkjson
|
||||||
|
- errname
|
||||||
|
- errorlint
|
||||||
|
- exhaustive
|
||||||
|
- exptostd
|
||||||
|
- fatcontext
|
||||||
|
- forbidigo
|
||||||
|
- forcetypeassert
|
||||||
|
- funcorder
|
||||||
|
- funlen
|
||||||
|
- ginkgolinter
|
||||||
|
- gocheckcompilerdirectives
|
||||||
|
- gochecknoglobals
|
||||||
|
- gochecknoinits
|
||||||
|
- gochecksumtype
|
||||||
|
- gocognit
|
||||||
|
- goconst
|
||||||
|
- gocritic
|
||||||
|
- gocyclo
|
||||||
|
- godoclint
|
||||||
|
- godot
|
||||||
|
- godox
|
||||||
|
- goheader
|
||||||
|
- gomodguard
|
||||||
|
- goprintffuncname
|
||||||
|
- gosec
|
||||||
|
- gosmopolitan
|
||||||
|
- govet
|
||||||
|
- grouper
|
||||||
|
- iface
|
||||||
|
- importas
|
||||||
|
- inamedparam
|
||||||
|
- ineffassign
|
||||||
|
- interfacebloat
|
||||||
|
- intrange
|
||||||
|
- iotamixing
|
||||||
|
- ireturn
|
||||||
|
- lll
|
||||||
|
- loggercheck
|
||||||
|
- maintidx
|
||||||
|
- makezero
|
||||||
|
- mirror
|
||||||
|
- misspell
|
||||||
|
- mnd
|
||||||
|
- modernize
|
||||||
|
- musttag
|
||||||
|
- nakedret
|
||||||
|
- nestif
|
||||||
|
- nilerr
|
||||||
|
- nilnesserr
|
||||||
|
- nilnil
|
||||||
|
- nlreturn
|
||||||
|
- noctx
|
||||||
|
- noinlineerr
|
||||||
|
- nolintlint
|
||||||
|
- nonamedreturns
|
||||||
|
- nosprintfhostport
|
||||||
|
- paralleltest
|
||||||
|
- perfsprint
|
||||||
|
- prealloc
|
||||||
|
- predeclared
|
||||||
|
- promlinter
|
||||||
|
- protogetter
|
||||||
|
- reassign
|
||||||
|
- recvcheck
|
||||||
|
- revive
|
||||||
|
- rowserrcheck
|
||||||
|
- sloglint
|
||||||
|
- spancheck
|
||||||
|
- sqlclosecheck
|
||||||
|
- staticcheck
|
||||||
|
- tagalign
|
||||||
|
- tagliatelle
|
||||||
|
- testableexamples
|
||||||
|
- testifylint
|
||||||
|
- testpackage
|
||||||
|
- thelper
|
||||||
|
- tparallel
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- unqueryvet
|
||||||
|
- unused
|
||||||
|
- usestdlibvars
|
||||||
|
- usetesting
|
||||||
|
- varnamelen
|
||||||
|
- wastedassign
|
||||||
|
- whitespace
|
||||||
|
- wsl_v5
|
||||||
|
- zerologlint
|
||||||
|
# Disable specific linters.
|
||||||
|
disable:
|
||||||
|
- depguard
|
||||||
|
- exhaustruct
|
||||||
|
- gochecknoglobals
|
||||||
|
- gomoddirectives
|
||||||
|
- wsl
|
||||||
|
- wrapcheck
|
||||||
|
# All available settings of specific linters.
|
||||||
|
# See the dedicated "linters.settings" documentation section.
|
||||||
|
settings:
|
||||||
|
wsl_v5:
|
||||||
|
allow-first-in-block: true
|
||||||
|
allow-whole-block: false
|
||||||
|
branch-max-lines: 2
|
||||||
|
|
||||||
|
# Defines a set of rules to ignore issues.
|
||||||
|
# It does not skip the analysis, and so does not ignore "typecheck" errors.
|
||||||
|
exclusions:
|
||||||
|
# Mode of the generated files analysis.
|
||||||
|
#
|
||||||
|
# - `strict`: sources are excluded by strictly following the Go generated file convention.
|
||||||
|
# Source files that have lines matching only the following regular expression will be excluded: `^// Code generated .* DO NOT EDIT\.$`
|
||||||
|
# This line must appear before the first non-comment, non-blank text in the file.
|
||||||
|
# https://go.dev/s/generatedcode
|
||||||
|
# - `lax`: sources are excluded if they contain lines like `autogenerated file`, `code generated`, `do not edit`, etc.
|
||||||
|
# - `disable`: disable the generated files exclusion.
|
||||||
|
#
|
||||||
|
# Default: strict
|
||||||
|
generated: lax
|
||||||
|
# Log a warning if an exclusion rule is unused.
|
||||||
|
# Default: false
|
||||||
|
warn-unused: true
|
||||||
|
# Predefined exclusion rules.
|
||||||
|
# Default: []
|
||||||
|
presets:
|
||||||
|
- comments
|
||||||
|
- std-error-handling
|
||||||
|
- common-false-positives
|
||||||
|
- legacy
|
||||||
|
# Excluding configuration per-path, per-linter, per-text and per-source.
|
||||||
|
rules:
|
||||||
|
# Exclude some linters from running on tests files.
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- gocyclo
|
||||||
|
- errcheck
|
||||||
|
- dupl
|
||||||
|
- gosec
|
||||||
|
# Run some linter only for test files by excluding its issues for everything else.
|
||||||
|
- path-except: _test\.go
|
||||||
|
linters:
|
||||||
|
- forbidigo
|
||||||
|
# Exclude known linters from partially hard-vendored code,
|
||||||
|
# which is impossible to exclude via `nolint` comments.
|
||||||
|
# `/` will be replaced by the current OS file path separator to properly work on Windows.
|
||||||
|
- path: internal/hmac/
|
||||||
|
text: "weak cryptographic primitive"
|
||||||
|
linters:
|
||||||
|
- gosec
|
||||||
|
# Exclude some `staticcheck` messages.
|
||||||
|
- linters:
|
||||||
|
- staticcheck
|
||||||
|
text: "SA9003:"
|
||||||
|
# Exclude `lll` issues for long lines with `go:generate`.
|
||||||
|
- linters:
|
||||||
|
- lll
|
||||||
|
source: "^//go:generate "
|
||||||
|
# Which file paths to exclude: they will be analyzed, but issues from them won't be reported.
|
||||||
|
# "/" will be replaced by the current OS file path separator to properly work on Windows.
|
||||||
|
# Default: []
|
||||||
|
paths: []
|
||||||
|
# Which file paths to not exclude.
|
||||||
|
# Default: []
|
||||||
|
paths-except: []
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
module github.com/tech/sendico/discovery
|
module github.com/tech/sendico/discovery
|
||||||
|
|
||||||
go 1.25.6
|
go 1.25.7
|
||||||
|
|
||||||
replace github.com/tech/sendico/pkg => ../pkg
|
replace github.com/tech/sendico/pkg => ../pkg
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-chi/chi/v5 v5.2.4
|
github.com/go-chi/chi/v5 v5.2.5
|
||||||
github.com/prometheus/client_golang v1.23.2
|
github.com/prometheus/client_golang v1.23.2
|
||||||
github.com/tech/sendico/pkg v0.1.0
|
github.com/tech/sendico/pkg v0.1.0
|
||||||
go.uber.org/zap v1.27.1
|
go.uber.org/zap v1.27.1
|
||||||
@@ -20,7 +20,7 @@ require (
|
|||||||
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.3 // indirect
|
github.com/klauspost/compress v1.18.4 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
@@ -38,12 +38,12 @@ require (
|
|||||||
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/crypto v0.47.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/net v0.49.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||||
google.golang.org/grpc v1.78.0 // indirect
|
google.golang.org/grpc v1.78.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.11 // indirect
|
google.golang.org/protobuf v1.36.11 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
|
|||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
|
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||||
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
@@ -57,8 +57,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@@ -172,15 +172,15 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
|||||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
@@ -191,16 +191,16 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@@ -208,8 +208,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b h1:GZxXGdFaHX27ZSMHudWc4FokdD+xl8BC2UJm1OVIEzs=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ var (
|
|||||||
BuildDate string
|
BuildDate string
|
||||||
)
|
)
|
||||||
|
|
||||||
func Create() version.Printer {
|
func Create() version.Printer { //nolint:ireturn // factory returns interface by design
|
||||||
vi := version.Info{
|
info := version.Info{
|
||||||
Program: "Sendico Discovery Service",
|
Program: "Sendico Discovery Service",
|
||||||
Revision: Revision,
|
Revision: Revision,
|
||||||
Branch: Branch,
|
Branch: Branch,
|
||||||
@@ -23,5 +23,6 @@ func Create() version.Printer {
|
|||||||
BuildDate: BuildDate,
|
BuildDate: BuildDate,
|
||||||
Version: Version,
|
Version: Version,
|
||||||
}
|
}
|
||||||
return vf.Create(&vi)
|
|
||||||
|
return vf.Create(&info)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ import (
|
|||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultMetricsAddress = ":9405"
|
const (
|
||||||
|
defaultMetricsAddress = ":9405"
|
||||||
|
defaultShutdownTimeoutSeconds = 15
|
||||||
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
Runtime *grpcapp.RuntimeConfig `yaml:"runtime"`
|
Runtime *grpcapp.RuntimeConfig `yaml:"runtime"`
|
||||||
@@ -24,24 +27,28 @@ type metricsConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type registryConfig struct {
|
type registryConfig struct {
|
||||||
KVTTLSeconds *int `yaml:"kv_ttl_seconds"`
|
KVTTLSeconds *int `yaml:"kv_ttl_seconds"` //nolint:tagliatelle // matches config file format
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Imp) loadConfig() (*config, error) {
|
func (i *Imp) loadConfig() (*config, error) {
|
||||||
data, err := os.ReadFile(i.file)
|
data, err := os.ReadFile(i.file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
i.logger.Error("Could not read configuration file", zap.String("config_file", i.file), zap.Error(err))
|
i.logger.Error("Could not read configuration file", zap.String("config_file", i.file), zap.Error(err))
|
||||||
return nil, err
|
|
||||||
|
return nil, err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := &config{}
|
cfg := &config{}
|
||||||
if err := yaml.Unmarshal(data, cfg); err != nil {
|
|
||||||
|
err = yaml.Unmarshal(data, cfg)
|
||||||
|
if err != nil {
|
||||||
i.logger.Error("Failed to parse configuration", zap.Error(err))
|
i.logger.Error("Failed to parse configuration", zap.Error(err))
|
||||||
return nil, err
|
|
||||||
|
return nil, err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Runtime == nil {
|
if cfg.Runtime == nil {
|
||||||
cfg.Runtime = &grpcapp.RuntimeConfig{ShutdownTimeoutSeconds: 15}
|
cfg.Runtime = &grpcapp.RuntimeConfig{ShutdownTimeoutSeconds: defaultShutdownTimeoutSeconds}
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Metrics != nil && strings.TrimSpace(cfg.Metrics.Address) == "" {
|
if cfg.Metrics != nil && strings.TrimSpace(cfg.Metrics.Address) == "" {
|
||||||
|
|||||||
@@ -14,30 +14,37 @@ import (
|
|||||||
|
|
||||||
func (i *Imp) startDiscovery(cfg *config) error {
|
func (i *Imp) startDiscovery(cfg *config) error {
|
||||||
if cfg == nil || cfg.Messaging == nil || cfg.Messaging.Driver == "" {
|
if cfg == nil || cfg.Messaging == nil || cfg.Messaging.Driver == "" {
|
||||||
|
//nolint:wrapcheck
|
||||||
return merrors.InvalidArgument("discovery service: messaging configuration is required", "messaging")
|
return merrors.InvalidArgument("discovery service: messaging configuration is required", "messaging")
|
||||||
}
|
}
|
||||||
|
|
||||||
broker, err := msg.CreateMessagingBroker(i.logger.Named("discovery_bus"), cfg.Messaging)
|
broker, err := msg.CreateMessagingBroker(i.logger.Named("discovery_bus"), cfg.Messaging)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
i.logger.Info("Discovery messaging broker ready", zap.String("messaging_driver", string(cfg.Messaging.Driver)))
|
i.logger.Info("Discovery messaging broker ready", zap.String("messaging_driver", string(cfg.Messaging.Driver)))
|
||||||
producer := msgproducer.NewProducer(i.logger.Named("discovery_producer"), broker)
|
producer := msgproducer.NewProducer(i.logger.Named("discovery_producer"), broker)
|
||||||
|
|
||||||
registry := discovery.NewRegistry()
|
registry := discovery.NewRegistry()
|
||||||
|
|
||||||
var registryOpts []discovery.RegistryOption
|
var registryOpts []discovery.RegistryOption
|
||||||
|
|
||||||
if cfg.Registry != nil && cfg.Registry.KVTTLSeconds != nil {
|
if cfg.Registry != nil && cfg.Registry.KVTTLSeconds != nil {
|
||||||
ttlSeconds := *cfg.Registry.KVTTLSeconds
|
ttlSeconds := *cfg.Registry.KVTTLSeconds
|
||||||
if ttlSeconds < 0 {
|
if ttlSeconds < 0 {
|
||||||
i.logger.Warn("Discovery registry TTL is negative, disabling TTL", zap.Int("ttl_seconds", ttlSeconds))
|
i.logger.Warn("Discovery registry TTL is negative, disabling TTL", zap.Int("ttl_seconds", ttlSeconds))
|
||||||
ttlSeconds = 0
|
ttlSeconds = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
registryOpts = append(registryOpts, discovery.WithRegistryKVTTL(time.Duration(ttlSeconds)*time.Second))
|
registryOpts = append(registryOpts, discovery.WithRegistryKVTTL(time.Duration(ttlSeconds)*time.Second))
|
||||||
}
|
}
|
||||||
svc, err := discovery.NewRegistryService(i.logger, broker, producer, registry, string(mservice.Discovery), registryOpts...)
|
|
||||||
|
svc, err := discovery.NewRegistryService(i.logger, broker, producer, registry, mservice.Discovery, registryOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
svc.Start()
|
svc.Start()
|
||||||
i.registrySvc = svc
|
i.registrySvc = svc
|
||||||
|
|
||||||
@@ -47,10 +54,11 @@ func (i *Imp) startDiscovery(cfg *config) error {
|
|||||||
Operations: []string{"discovery.lookup"},
|
Operations: []string{"discovery.lookup"},
|
||||||
Version: appversion.Create().Short(),
|
Version: appversion.Create().Short(),
|
||||||
}
|
}
|
||||||
i.announcer = discovery.NewAnnouncer(i.logger, producer, string(mservice.Discovery), announce)
|
i.announcer = discovery.NewAnnouncer(i.logger, producer, mservice.Discovery, announce)
|
||||||
i.announcer.Start()
|
i.announcer.Start()
|
||||||
|
|
||||||
i.logger.Info("Discovery registry service started", zap.String("messaging_driver", string(cfg.Messaging.Driver)))
|
i.logger.Info("Discovery registry service started", zap.String("messaging_driver", string(cfg.Messaging.Driver)))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,10 +66,12 @@ func (i *Imp) stopDiscovery() {
|
|||||||
if i == nil {
|
if i == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.announcer != nil {
|
if i.announcer != nil {
|
||||||
i.announcer.Stop()
|
i.announcer.Stop()
|
||||||
i.announcer = nil
|
i.announcer = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.registrySvc != nil {
|
if i.registrySvc != nil {
|
||||||
i.registrySvc.Stop()
|
i.registrySvc.Stop()
|
||||||
i.registrySvc = nil
|
i.registrySvc = nil
|
||||||
|
|||||||
@@ -15,22 +15,30 @@ import (
|
|||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const readHeaderTimeout = 5 * time.Second
|
||||||
|
|
||||||
func (i *Imp) startMetrics(cfg *metricsConfig) {
|
func (i *Imp) startMetrics(cfg *metricsConfig) {
|
||||||
if i == nil {
|
if i == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
address := ""
|
address := ""
|
||||||
if cfg != nil {
|
if cfg != nil {
|
||||||
address = strings.TrimSpace(cfg.Address)
|
address = strings.TrimSpace(cfg.Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
if address == "" {
|
if address == "" {
|
||||||
i.logger.Info("Metrics endpoint disabled")
|
i.logger.Info("Metrics endpoint disabled")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
listener, err := net.Listen("tcp", address)
|
lc := net.ListenConfig{}
|
||||||
|
|
||||||
|
listener, err := lc.Listen(context.Background(), "tcp", address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
i.logger.Error("Failed to bind metrics listener", zap.String("address", address), zap.Error(err))
|
i.logger.Error("Failed to bind metrics listener", zap.String("address", address), zap.Error(err))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +46,9 @@ func (i *Imp) startMetrics(cfg *metricsConfig) {
|
|||||||
router.Handle("/metrics", promhttp.Handler())
|
router.Handle("/metrics", promhttp.Handler())
|
||||||
|
|
||||||
var healthRouter routers.Health
|
var healthRouter routers.Health
|
||||||
if hr, err := routers.NewHealthRouter(i.logger.Named("metrics"), router, ""); err != nil {
|
|
||||||
|
hr, err := routers.NewHealthRouter(i.logger.Named("metrics"), router, "")
|
||||||
|
if err != nil {
|
||||||
i.logger.Warn("Failed to initialise health router", zap.Error(err))
|
i.logger.Warn("Failed to initialise health router", zap.Error(err))
|
||||||
} else {
|
} else {
|
||||||
hr.SetStatus(health.SSStarting)
|
hr.SetStatus(health.SSStarting)
|
||||||
@@ -49,13 +59,16 @@ func (i *Imp) startMetrics(cfg *metricsConfig) {
|
|||||||
i.metricsSrv = &http.Server{
|
i.metricsSrv = &http.Server{
|
||||||
Addr: address,
|
Addr: address,
|
||||||
Handler: router,
|
Handler: router,
|
||||||
ReadHeaderTimeout: 5 * time.Second,
|
ReadHeaderTimeout: readHeaderTimeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
i.logger.Info("Prometheus endpoint listening", zap.String("address", address))
|
i.logger.Info("Prometheus endpoint listening", zap.String("address", address))
|
||||||
if err := i.metricsSrv.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
||||||
i.logger.Error("Prometheus endpoint stopped unexpectedly", zap.Error(err))
|
serveErr := i.metricsSrv.Serve(listener)
|
||||||
|
if serveErr != nil && !errors.Is(serveErr, http.ErrServerClosed) {
|
||||||
|
i.logger.Error("Prometheus endpoint stopped unexpectedly", zap.Error(serveErr))
|
||||||
|
|
||||||
if healthRouter != nil {
|
if healthRouter != nil {
|
||||||
healthRouter.SetStatus(health.SSTerminating)
|
healthRouter.SetStatus(health.SSTerminating)
|
||||||
}
|
}
|
||||||
@@ -69,14 +82,18 @@ func (i *Imp) shutdownMetrics(ctx context.Context) {
|
|||||||
i.metricsHealth.Finish()
|
i.metricsHealth.Finish()
|
||||||
i.metricsHealth = nil
|
i.metricsHealth = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.metricsSrv == nil {
|
if i.metricsSrv == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := i.metricsSrv.Shutdown(ctx); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
||||||
|
err := i.metricsSrv.Shutdown(ctx)
|
||||||
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
i.logger.Warn("Failed to stop metrics server", zap.Error(err))
|
i.logger.Warn("Failed to stop metrics server", zap.Error(err))
|
||||||
} else {
|
} else {
|
||||||
i.logger.Info("Metrics server stopped")
|
i.logger.Info("Metrics server stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
i.metricsSrv = nil
|
i.metricsSrv = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,5 +101,6 @@ func (i *Imp) setMetricsStatus(status health.ServiceStatus) {
|
|||||||
if i == nil || i.metricsHealth == nil {
|
if i == nil || i.metricsHealth == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
i.metricsHealth.SetStatus(status)
|
i.metricsHealth.SetStatus(status)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const defaultShutdownTimeout = 15 * time.Second
|
||||||
|
|
||||||
func Create(logger mlogger.Logger, file string, debug bool) (*Imp, error) {
|
func Create(logger mlogger.Logger, file string, debug bool) (*Imp, error) {
|
||||||
return &Imp{
|
return &Imp{
|
||||||
logger: logger.Named("server"),
|
logger: logger.Named("server"),
|
||||||
@@ -28,29 +30,37 @@ func (i *Imp) Start() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
i.config = cfg
|
i.config = cfg
|
||||||
|
|
||||||
messagingDriver := "none"
|
messagingDriver := "none"
|
||||||
if cfg.Messaging != nil {
|
if cfg.Messaging != nil {
|
||||||
messagingDriver = string(cfg.Messaging.Driver)
|
messagingDriver = string(cfg.Messaging.Driver)
|
||||||
}
|
}
|
||||||
|
|
||||||
metricsAddress := ""
|
metricsAddress := ""
|
||||||
if cfg.Metrics != nil {
|
if cfg.Metrics != nil {
|
||||||
metricsAddress = strings.TrimSpace(cfg.Metrics.Address)
|
metricsAddress = strings.TrimSpace(cfg.Metrics.Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
if metricsAddress == "" {
|
if metricsAddress == "" {
|
||||||
metricsAddress = "disabled"
|
metricsAddress = "disabled"
|
||||||
}
|
}
|
||||||
i.logger.Info("Discovery config loaded", zap.String("messaging_driver", messagingDriver), zap.String("metrics_address", metricsAddress))
|
|
||||||
|
i.logger.Info("Discovery config loaded",
|
||||||
|
zap.String("messaging_driver", messagingDriver),
|
||||||
|
zap.String("metrics_address", metricsAddress))
|
||||||
|
|
||||||
i.startMetrics(cfg.Metrics)
|
i.startMetrics(cfg.Metrics)
|
||||||
|
|
||||||
if err := i.startDiscovery(cfg); err != nil {
|
err = i.startDiscovery(cfg)
|
||||||
|
if err != nil {
|
||||||
i.stopDiscovery()
|
i.stopDiscovery()
|
||||||
i.setMetricsStatus(health.SSTerminating)
|
i.setMetricsStatus(health.SSTerminating)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), i.shutdownTimeout())
|
ctx, cancel := context.WithTimeout(context.Background(), i.shutdownTimeout())
|
||||||
i.shutdownMetrics(ctx)
|
i.shutdownMetrics(ctx)
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +69,7 @@ func (i *Imp) Start() error {
|
|||||||
|
|
||||||
<-i.stopCh
|
<-i.stopCh
|
||||||
i.logger.Info("Discovery service stop signal received")
|
i.logger.Info("Discovery service stop signal received")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +83,7 @@ func (i *Imp) Shutdown() {
|
|||||||
if i.doneCh != nil {
|
if i.doneCh != nil {
|
||||||
<-i.doneCh
|
<-i.doneCh
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
i.shutdownMetrics(ctx)
|
i.shutdownMetrics(ctx)
|
||||||
cancel()
|
cancel()
|
||||||
@@ -83,6 +95,7 @@ func (i *Imp) initStopChannels() {
|
|||||||
if i.stopCh == nil {
|
if i.stopCh == nil {
|
||||||
i.stopCh = make(chan struct{})
|
i.stopCh = make(chan struct{})
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.doneCh == nil {
|
if i.doneCh == nil {
|
||||||
i.doneCh = make(chan struct{})
|
i.doneCh = make(chan struct{})
|
||||||
}
|
}
|
||||||
@@ -108,5 +121,6 @@ func (i *Imp) shutdownTimeout() time.Duration {
|
|||||||
if i.config != nil && i.config.Runtime != nil {
|
if i.config != nil && i.config.Runtime != nil {
|
||||||
return i.config.Runtime.ShutdownTimeout()
|
return i.config.Runtime.ShutdownTimeout()
|
||||||
}
|
}
|
||||||
return 15 * time.Second
|
|
||||||
|
return defaultShutdownTimeout
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/tech/sendico/pkg/server"
|
"github.com/tech/sendico/pkg/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//nolint:ireturn // factory returns interface by design
|
||||||
func Create(logger mlogger.Logger, file string, debug bool) (server.Application, error) {
|
func Create(logger mlogger.Logger, file string, debug bool) (server.Application, error) {
|
||||||
return serverimp.Create(logger, file, debug)
|
return serverimp.Create(logger, file, debug) //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ import (
|
|||||||
smain "github.com/tech/sendico/pkg/server/main"
|
smain "github.com/tech/sendico/pkg/server/main"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//nolint:ireturn // factory returns interface by design
|
||||||
func factory(logger mlogger.Logger, file string, debug bool) (server.Application, error) {
|
func factory(logger mlogger.Logger, file string, debug bool) (server.Application, error) {
|
||||||
return si.Create(logger, file, debug)
|
return si.Create(logger, file, debug) //nolint:wrapcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
195
api/fx/ingestor/.golangci.yml
Normal file
195
api/fx/ingestor/.golangci.yml
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
# See the dedicated "version" documentation section.
|
||||||
|
version: "2"
|
||||||
|
linters:
|
||||||
|
# Default set of linters.
|
||||||
|
# The value can be:
|
||||||
|
# - `standard`: https://golangci-lint.run/docs/linters/#enabled-by-default
|
||||||
|
# - `all`: enables all linters by default.
|
||||||
|
# - `none`: disables all linters by default.
|
||||||
|
# - `fast`: enables only linters considered as "fast" (`golangci-lint help linters --json | jq '[ .[] | select(.fast==true) ] | map(.name)'`).
|
||||||
|
# Default: standard
|
||||||
|
default: all
|
||||||
|
# Enable specific linter.
|
||||||
|
enable:
|
||||||
|
- arangolint
|
||||||
|
- asasalint
|
||||||
|
- asciicheck
|
||||||
|
- bidichk
|
||||||
|
- bodyclose
|
||||||
|
- canonicalheader
|
||||||
|
- containedctx
|
||||||
|
- contextcheck
|
||||||
|
- copyloopvar
|
||||||
|
- cyclop
|
||||||
|
- decorder
|
||||||
|
- dogsled
|
||||||
|
- dupl
|
||||||
|
- dupword
|
||||||
|
- durationcheck
|
||||||
|
- embeddedstructfieldcheck
|
||||||
|
- err113
|
||||||
|
- errcheck
|
||||||
|
- errchkjson
|
||||||
|
- errname
|
||||||
|
- errorlint
|
||||||
|
- exhaustive
|
||||||
|
- exptostd
|
||||||
|
- fatcontext
|
||||||
|
- forbidigo
|
||||||
|
- forcetypeassert
|
||||||
|
- funcorder
|
||||||
|
- funlen
|
||||||
|
- ginkgolinter
|
||||||
|
- gocheckcompilerdirectives
|
||||||
|
- gochecknoglobals
|
||||||
|
- gochecknoinits
|
||||||
|
- gochecksumtype
|
||||||
|
- gocognit
|
||||||
|
- goconst
|
||||||
|
- gocritic
|
||||||
|
- gocyclo
|
||||||
|
- godoclint
|
||||||
|
- godot
|
||||||
|
- godox
|
||||||
|
- goheader
|
||||||
|
- gomodguard
|
||||||
|
- goprintffuncname
|
||||||
|
- gosec
|
||||||
|
- gosmopolitan
|
||||||
|
- govet
|
||||||
|
- grouper
|
||||||
|
- iface
|
||||||
|
- importas
|
||||||
|
- inamedparam
|
||||||
|
- ineffassign
|
||||||
|
- interfacebloat
|
||||||
|
- intrange
|
||||||
|
- iotamixing
|
||||||
|
- ireturn
|
||||||
|
- lll
|
||||||
|
- loggercheck
|
||||||
|
- maintidx
|
||||||
|
- makezero
|
||||||
|
- mirror
|
||||||
|
- misspell
|
||||||
|
- mnd
|
||||||
|
- modernize
|
||||||
|
- musttag
|
||||||
|
- nakedret
|
||||||
|
- nestif
|
||||||
|
- nilerr
|
||||||
|
- nilnesserr
|
||||||
|
- nilnil
|
||||||
|
- nlreturn
|
||||||
|
- noctx
|
||||||
|
- noinlineerr
|
||||||
|
- nolintlint
|
||||||
|
- nonamedreturns
|
||||||
|
- nosprintfhostport
|
||||||
|
- paralleltest
|
||||||
|
- perfsprint
|
||||||
|
- prealloc
|
||||||
|
- predeclared
|
||||||
|
- promlinter
|
||||||
|
- protogetter
|
||||||
|
- reassign
|
||||||
|
- recvcheck
|
||||||
|
- revive
|
||||||
|
- rowserrcheck
|
||||||
|
- sloglint
|
||||||
|
- spancheck
|
||||||
|
- sqlclosecheck
|
||||||
|
- staticcheck
|
||||||
|
- tagalign
|
||||||
|
- tagliatelle
|
||||||
|
- testableexamples
|
||||||
|
- testifylint
|
||||||
|
- testpackage
|
||||||
|
- thelper
|
||||||
|
- tparallel
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- unqueryvet
|
||||||
|
- unused
|
||||||
|
- usestdlibvars
|
||||||
|
- usetesting
|
||||||
|
- varnamelen
|
||||||
|
- wastedassign
|
||||||
|
- whitespace
|
||||||
|
- wsl_v5
|
||||||
|
- zerologlint
|
||||||
|
# Disable specific linters.
|
||||||
|
disable:
|
||||||
|
- depguard
|
||||||
|
- exhaustruct
|
||||||
|
- gochecknoglobals
|
||||||
|
- gomoddirectives
|
||||||
|
- wrapcheck
|
||||||
|
- wsl
|
||||||
|
# All available settings of specific linters.
|
||||||
|
# See the dedicated "linters.settings" documentation section.
|
||||||
|
settings:
|
||||||
|
wsl_v5:
|
||||||
|
allow-first-in-block: true
|
||||||
|
allow-whole-block: false
|
||||||
|
branch-max-lines: 2
|
||||||
|
|
||||||
|
# Defines a set of rules to ignore issues.
|
||||||
|
# It does not skip the analysis, and so does not ignore "typecheck" errors.
|
||||||
|
exclusions:
|
||||||
|
# Mode of the generated files analysis.
|
||||||
|
#
|
||||||
|
# - `strict`: sources are excluded by strictly following the Go generated file convention.
|
||||||
|
# Source files that have lines matching only the following regular expression will be excluded: `^// Code generated .* DO NOT EDIT\.$`
|
||||||
|
# This line must appear before the first non-comment, non-blank text in the file.
|
||||||
|
# https://go.dev/s/generatedcode
|
||||||
|
# - `lax`: sources are excluded if they contain lines like `autogenerated file`, `code generated`, `do not edit`, etc.
|
||||||
|
# - `disable`: disable the generated files exclusion.
|
||||||
|
#
|
||||||
|
# Default: strict
|
||||||
|
generated: lax
|
||||||
|
# Log a warning if an exclusion rule is unused.
|
||||||
|
# Default: false
|
||||||
|
warn-unused: true
|
||||||
|
# Predefined exclusion rules.
|
||||||
|
# Default: []
|
||||||
|
presets:
|
||||||
|
- comments
|
||||||
|
- std-error-handling
|
||||||
|
- common-false-positives
|
||||||
|
- legacy
|
||||||
|
# Excluding configuration per-path, per-linter, per-text and per-source.
|
||||||
|
rules:
|
||||||
|
# Exclude some linters from running on tests files.
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- gocyclo
|
||||||
|
- errcheck
|
||||||
|
- dupl
|
||||||
|
- gosec
|
||||||
|
# Run some linter only for test files by excluding its issues for everything else.
|
||||||
|
- path-except: _test\.go
|
||||||
|
linters:
|
||||||
|
- forbidigo
|
||||||
|
# Exclude known linters from partially hard-vendored code,
|
||||||
|
# which is impossible to exclude via `nolint` comments.
|
||||||
|
# `/` will be replaced by the current OS file path separator to properly work on Windows.
|
||||||
|
- path: internal/hmac/
|
||||||
|
text: "weak cryptographic primitive"
|
||||||
|
linters:
|
||||||
|
- gosec
|
||||||
|
# Exclude some `staticcheck` messages.
|
||||||
|
- linters:
|
||||||
|
- staticcheck
|
||||||
|
text: "SA9003:"
|
||||||
|
# Exclude `lll` issues for long lines with `go:generate`.
|
||||||
|
- linters:
|
||||||
|
- lll
|
||||||
|
source: "^//go:generate "
|
||||||
|
# Which file paths to exclude: they will be analyzed, but issues from them won't be reported.
|
||||||
|
# "/" will be replaced by the current OS file path separator to properly work on Windows.
|
||||||
|
# Default: []
|
||||||
|
paths: []
|
||||||
|
# Which file paths to not exclude.
|
||||||
|
# Default: []
|
||||||
|
paths-except: []
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
module github.com/tech/sendico/fx/ingestor
|
module github.com/tech/sendico/fx/ingestor
|
||||||
|
|
||||||
go 1.25.6
|
go 1.25.7
|
||||||
|
|
||||||
replace github.com/tech/sendico/pkg => ../../pkg
|
replace github.com/tech/sendico/pkg => ../../pkg
|
||||||
|
|
||||||
replace github.com/tech/sendico/fx/storage => ../storage
|
replace github.com/tech/sendico/fx/storage => ../storage
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-chi/chi/v5 v5.2.4
|
github.com/go-chi/chi/v5 v5.2.5
|
||||||
github.com/google/go-cmp v0.7.0
|
github.com/google/go-cmp v0.7.0
|
||||||
github.com/prometheus/client_golang v1.23.2
|
github.com/prometheus/client_golang v1.23.2
|
||||||
github.com/tech/sendico/fx/storage v0.0.0
|
github.com/tech/sendico/fx/storage v0.0.0
|
||||||
github.com/tech/sendico/pkg v0.1.0
|
github.com/tech/sendico/pkg v0.1.0
|
||||||
go.uber.org/zap v1.27.1
|
go.uber.org/zap v1.27.1
|
||||||
golang.org/x/net v0.49.0
|
golang.org/x/net v0.50.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ require (
|
|||||||
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.3 // indirect
|
github.com/klauspost/compress v1.18.4 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
@@ -43,11 +43,11 @@ require (
|
|||||||
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/crypto v0.47.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||||
google.golang.org/grpc v1.78.0 // indirect
|
google.golang.org/grpc v1.78.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.11 // indirect
|
google.golang.org/protobuf v1.36.11 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
|
|||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
|
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||||
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
@@ -57,8 +57,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@@ -172,15 +172,15 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
|||||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
@@ -191,16 +191,16 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@@ -208,8 +208,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b h1:GZxXGdFaHX27ZSMHudWc4FokdD+xl8BC2UJm1OVIEzs=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
|||||||
@@ -51,16 +51,17 @@ func (a *App) Run(ctx context.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
a.logger.Debug("Metrics server initialised")
|
a.logger.Debug("Metrics server initialised")
|
||||||
defer metricsSrv.Close(context.Background())
|
defer metricsSrv.Close(context.Background()) //nolint:contextcheck
|
||||||
|
|
||||||
conn, err := db.ConnectMongo(a.logger, a.cfg.Database)
|
conn, err := db.ConnectMongo(a.logger, a.cfg.Database) //nolint:contextcheck
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer conn.Disconnect(context.Background())
|
defer conn.Disconnect(context.Background()) //nolint:errcheck,contextcheck
|
||||||
|
|
||||||
a.logger.Debug("MongoDB connection established")
|
a.logger.Debug("MongoDB connection established")
|
||||||
|
|
||||||
repo, err := mongostorage.New(a.logger, conn)
|
repo, err := mongostorage.New(a.logger, conn) //nolint:contextcheck
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -72,6 +73,7 @@ func (a *App) Run(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var announcer *discovery.Announcer
|
var announcer *discovery.Announcer
|
||||||
|
|
||||||
if cfg := a.cfg.Messaging; cfg != nil && cfg.Driver != "" {
|
if cfg := a.cfg.Messaging; cfg != nil && cfg.Driver != "" {
|
||||||
broker, err := msg.CreateMessagingBroker(a.logger.Named("discovery_bus"), cfg)
|
broker, err := msg.CreateMessagingBroker(a.logger.Named("discovery_bus"), cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -84,6 +86,7 @@ func (a *App) Run(ctx context.Context) error {
|
|||||||
Version: appversion.Create().Short(),
|
Version: appversion.Create().Short(),
|
||||||
}
|
}
|
||||||
announcer = discovery.NewAnnouncer(a.logger, producer, "fx_ingestor", announce)
|
announcer = discovery.NewAnnouncer(a.logger, producer, "fx_ingestor", announce)
|
||||||
|
|
||||||
announcer.Start()
|
announcer.Start()
|
||||||
defer announcer.Stop()
|
defer announcer.Stop()
|
||||||
}
|
}
|
||||||
@@ -98,6 +101,8 @@ func (a *App) Run(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
a.logger.Info("Ingestor service stopped")
|
a.logger.Info("Ingestor service stopped")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ var (
|
|||||||
BuildDate string
|
BuildDate string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//nolint:ireturn
|
||||||
func Create() version.Printer {
|
func Create() version.Printer {
|
||||||
vi := version.Info{
|
info := version.Info{
|
||||||
Program: "Sendico FX Ingestor Service",
|
Program: "Sendico FX Ingestor Service",
|
||||||
Revision: Revision,
|
Revision: Revision,
|
||||||
Branch: Branch,
|
Branch: Branch,
|
||||||
@@ -23,5 +24,6 @@ func Create() version.Printer {
|
|||||||
BuildDate: BuildDate,
|
BuildDate: BuildDate,
|
||||||
Version: Version,
|
Version: Version,
|
||||||
}
|
}
|
||||||
return vf.Create(&vi)
|
|
||||||
|
return vf.Create(&info)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ type Config struct {
|
|||||||
pairsBySource map[mmodel.Driver][]PairConfig
|
pairsBySource map[mmodel.Driver][]PairConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:cyclop
|
||||||
func Load(path string) (*Config, error) {
|
func Load(path string) (*Config, error) {
|
||||||
if path == "" {
|
if path == "" {
|
||||||
return nil, merrors.InvalidArgument("config: path is empty")
|
return nil, merrors.InvalidArgument("config: path is empty")
|
||||||
@@ -36,19 +37,23 @@ func Load(path string) (*Config, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfg := &Config{}
|
cfg := &Config{}
|
||||||
if err := yaml.Unmarshal(data, cfg); err != nil {
|
|
||||||
|
err = yaml.Unmarshal(data, cfg)
|
||||||
|
if err != nil {
|
||||||
return nil, merrors.InternalWrap(err, "config: failed to parse yaml")
|
return nil, merrors.InternalWrap(err, "config: failed to parse yaml")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(cfg.Market.Sources) == 0 {
|
if len(cfg.Market.Sources) == 0 {
|
||||||
return nil, merrors.InvalidArgument("config: no market sources configured")
|
return nil, merrors.InvalidArgument("config: no market sources configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSet := make(map[mmodel.Driver]struct{}, len(cfg.Market.Sources))
|
sourceSet := make(map[mmodel.Driver]struct{}, len(cfg.Market.Sources))
|
||||||
for idx := range cfg.Market.Sources {
|
for idx := range cfg.Market.Sources {
|
||||||
src := &cfg.Market.Sources[idx]
|
src := &cfg.Market.Sources[idx]
|
||||||
if src.Driver.IsEmpty() {
|
if src.Driver.IsEmpty() {
|
||||||
return nil, merrors.InvalidArgument("config: market source driver is empty")
|
return nil, merrors.InvalidArgument("config: market source driver is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSet[src.Driver] = struct{}{}
|
sourceSet[src.Driver] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +70,7 @@ func Load(path string) (*Config, error) {
|
|||||||
if driver.IsEmpty() {
|
if driver.IsEmpty() {
|
||||||
return nil, merrors.InvalidArgument("config: pair source is empty")
|
return nil, merrors.InvalidArgument("config: pair source is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := sourceSet[driver]; !ok {
|
if _, ok := sourceSet[driver]; !ok {
|
||||||
return nil, merrors.InvalidArgument("config: pair references unknown source: "+driver.String(), "pairs."+driver.String())
|
return nil, merrors.InvalidArgument("config: pair references unknown source: "+driver.String(), "pairs."+driver.String())
|
||||||
}
|
}
|
||||||
@@ -74,10 +80,12 @@ func Load(path string) (*Config, error) {
|
|||||||
pair := pairList[idx]
|
pair := pairList[idx]
|
||||||
pair.Base = strings.ToUpper(strings.TrimSpace(pair.Base))
|
pair.Base = strings.ToUpper(strings.TrimSpace(pair.Base))
|
||||||
pair.Quote = strings.ToUpper(strings.TrimSpace(pair.Quote))
|
pair.Quote = strings.ToUpper(strings.TrimSpace(pair.Quote))
|
||||||
|
|
||||||
pair.Symbol = strings.TrimSpace(pair.Symbol)
|
pair.Symbol = strings.TrimSpace(pair.Symbol)
|
||||||
if pair.Base == "" || pair.Quote == "" || pair.Symbol == "" {
|
if pair.Base == "" || pair.Quote == "" || pair.Symbol == "" {
|
||||||
return nil, merrors.InvalidArgument("config: pair entries must define base, quote, and symbol", "pairs."+driver.String())
|
return nil, merrors.InvalidArgument("config: pair entries must define base, quote, and symbol", "pairs."+driver.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.TrimSpace(pair.Provider) == "" {
|
if strings.TrimSpace(pair.Provider) == "" {
|
||||||
pair.Provider = strings.ToLower(driver.String())
|
pair.Provider = strings.ToLower(driver.String())
|
||||||
}
|
}
|
||||||
@@ -87,6 +95,7 @@ func Load(path string) (*Config, error) {
|
|||||||
Source: driver,
|
Source: driver,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pairsBySource[driver] = processed
|
pairsBySource[driver] = processed
|
||||||
normalizedPairs[driver.String()] = processed
|
normalizedPairs[driver.String()] = processed
|
||||||
}
|
}
|
||||||
@@ -94,6 +103,7 @@ func Load(path string) (*Config, error) {
|
|||||||
cfg.Market.Pairs = normalizedPairs
|
cfg.Market.Pairs = normalizedPairs
|
||||||
cfg.pairsBySource = pairsBySource
|
cfg.pairsBySource = pairsBySource
|
||||||
cfg.pairs = flattened
|
cfg.pairs = flattened
|
||||||
|
|
||||||
if cfg.Database == nil {
|
if cfg.Database == nil {
|
||||||
return nil, merrors.InvalidArgument("config: database configuration is required")
|
return nil, merrors.InvalidArgument("config: database configuration is required")
|
||||||
}
|
}
|
||||||
@@ -101,7 +111,7 @@ func Load(path string) (*Config, error) {
|
|||||||
if cfg.Metrics != nil && cfg.Metrics.Enabled {
|
if cfg.Metrics != nil && cfg.Metrics.Enabled {
|
||||||
cfg.Metrics.Address = strings.TrimSpace(cfg.Metrics.Address)
|
cfg.Metrics.Address = strings.TrimSpace(cfg.Metrics.Address)
|
||||||
if cfg.Metrics.Address == "" {
|
if cfg.Metrics.Address == "" {
|
||||||
cfg.Metrics.Address = ":9102"
|
cfg.Metrics.Address = ":9102" //nolint:mnd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,9 +122,11 @@ func (c *Config) PollInterval() time.Duration {
|
|||||||
if c == nil {
|
if c == nil {
|
||||||
return defaultPollInterval
|
return defaultPollInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.PollIntervalSeconds <= 0 {
|
if c.PollIntervalSeconds <= 0 {
|
||||||
return defaultPollInterval
|
return defaultPollInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
return time.Duration(c.PollIntervalSeconds) * time.Second
|
return time.Duration(c.PollIntervalSeconds) * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,8 +134,10 @@ func (c *Config) Pairs() []Pair {
|
|||||||
if c == nil {
|
if c == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
out := make([]Pair, len(c.pairs))
|
out := make([]Pair, len(c.pairs))
|
||||||
copy(out, c.pairs)
|
copy(out, c.pairs)
|
||||||
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,12 +145,14 @@ func (c *Config) PairsBySource() map[mmodel.Driver][]PairConfig {
|
|||||||
if c == nil {
|
if c == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
out := make(map[mmodel.Driver][]PairConfig, len(c.pairsBySource))
|
out := make(map[mmodel.Driver][]PairConfig, len(c.pairsBySource))
|
||||||
for driver, pairs := range c.pairsBySource {
|
for driver, pairs := range c.pairsBySource {
|
||||||
cp := make([]PairConfig, len(pairs))
|
cp := make([]PairConfig, len(pairs))
|
||||||
copy(cp, pairs)
|
copy(cp, pairs)
|
||||||
out[driver] = cp
|
out[driver] = cp
|
||||||
}
|
}
|
||||||
|
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +160,8 @@ func (c *Config) MetricsConfig() *MetricsConfig {
|
|||||||
if c == nil || c.Metrics == nil {
|
if c == nil || c.Metrics == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cp := *c.Metrics
|
cp := *c.Metrics
|
||||||
|
|
||||||
return &cp
|
return &cp
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ type PairConfig struct {
|
|||||||
|
|
||||||
type Pair struct {
|
type Pair struct {
|
||||||
PairConfig `yaml:",inline"`
|
PairConfig `yaml:",inline"`
|
||||||
Source mmodel.Driver `yaml:"-"`
|
|
||||||
|
Source mmodel.Driver `yaml:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MarketConfig struct {
|
type MarketConfig struct {
|
||||||
|
|||||||
@@ -28,9 +28,11 @@ func New(logger mlogger.Logger, cfg *config.Config, repo storage.Repository) (*S
|
|||||||
if logger == nil {
|
if logger == nil {
|
||||||
return nil, merrors.InvalidArgument("ingestor: nil logger")
|
return nil, merrors.InvalidArgument("ingestor: nil logger")
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
return nil, merrors.InvalidArgument("ingestor: nil config")
|
return nil, merrors.InvalidArgument("ingestor: nil config")
|
||||||
}
|
}
|
||||||
|
|
||||||
if repo == nil {
|
if repo == nil {
|
||||||
return nil, merrors.InvalidArgument("ingestor: nil repository")
|
return nil, merrors.InvalidArgument("ingestor: nil repository")
|
||||||
}
|
}
|
||||||
@@ -52,6 +54,7 @@ func New(logger mlogger.Logger, cfg *config.Config, repo storage.Repository) (*S
|
|||||||
|
|
||||||
func (s *Service) Run(ctx context.Context) error {
|
func (s *Service) Run(ctx context.Context) error {
|
||||||
interval := s.cfg.PollInterval()
|
interval := s.cfg.PollInterval()
|
||||||
|
|
||||||
ticker := time.NewTicker(interval)
|
ticker := time.NewTicker(interval)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
@@ -65,6 +68,7 @@ func (s *Service) Run(ctx context.Context) error {
|
|||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
s.logger.Info("Context cancelled, stopping ingestor")
|
s.logger.Info("Context cancelled, stopping ingestor")
|
||||||
|
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
if err := s.executePoll(ctx); err != nil {
|
if err := s.executePoll(ctx); err != nil {
|
||||||
@@ -77,27 +81,34 @@ func (s *Service) Run(ctx context.Context) error {
|
|||||||
func (s *Service) executePoll(ctx context.Context) error {
|
func (s *Service) executePoll(ctx context.Context) error {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
err := s.pollOnce(ctx)
|
err := s.pollOnce(ctx)
|
||||||
|
|
||||||
if s.metrics != nil {
|
if s.metrics != nil {
|
||||||
s.metrics.observePoll(time.Since(start), err)
|
s.metrics.observePoll(time.Since(start), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) pollOnce(ctx context.Context) error {
|
func (s *Service) pollOnce(ctx context.Context) error {
|
||||||
var firstErr error
|
var firstErr error
|
||||||
failures := 0
|
failures := 0
|
||||||
|
|
||||||
for _, pair := range s.pairs {
|
for _, pair := range s.pairs {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
err := s.upsertPair(ctx, pair)
|
err := s.upsertPair(ctx, pair)
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
|
|
||||||
if s.metrics != nil {
|
if s.metrics != nil {
|
||||||
s.metrics.observePair(pair, elapsed, err)
|
s.metrics.observePair(pair, elapsed, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if firstErr == nil {
|
if firstErr == nil {
|
||||||
firstErr = err
|
firstErr = err
|
||||||
}
|
}
|
||||||
|
|
||||||
failures++
|
failures++
|
||||||
|
|
||||||
s.logger.Warn("Failed to ingest pair",
|
s.logger.Warn("Failed to ingest pair",
|
||||||
zap.String("symbol", pair.Symbol),
|
zap.String("symbol", pair.Symbol),
|
||||||
zap.String("source", pair.Source.String()),
|
zap.String("source", pair.Source.String()),
|
||||||
@@ -110,14 +121,17 @@ func (s *Service) pollOnce(ctx context.Context) error {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if failures > 0 {
|
if failures > 0 {
|
||||||
s.logger.Warn("Ingestion poll completed with failures", zap.Int("failures", failures), zap.Int("total", len(s.pairs)))
|
s.logger.Warn("Ingestion poll completed with failures", zap.Int("failures", failures), zap.Int("total", len(s.pairs)))
|
||||||
} else {
|
} else {
|
||||||
s.logger.Debug("Ingestion poll completed", zap.Int("total", len(s.pairs)))
|
s.logger.Debug("Ingestion poll completed", zap.Int("total", len(s.pairs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstErr
|
return firstErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:funlen
|
||||||
func (s *Service) upsertPair(ctx context.Context, pair config.Pair) error {
|
func (s *Service) upsertPair(ctx context.Context, pair config.Pair) error {
|
||||||
connector, ok := s.connectors[pair.Source]
|
connector, ok := s.connectors[pair.Source]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -133,6 +147,7 @@ func (s *Service) upsertPair(ctx context.Context, pair config.Pair) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return merrors.InvalidArgumentWrap(err, "parse bid price", "bid")
|
return merrors.InvalidArgumentWrap(err, "parse bid price", "bid")
|
||||||
}
|
}
|
||||||
|
|
||||||
ask, err := parseDecimal(ticker.AskPrice)
|
ask, err := parseDecimal(ticker.AskPrice)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return merrors.InvalidArgumentWrap(err, "parse ask price", "ask")
|
return merrors.InvalidArgumentWrap(err, "parse ask price", "ask")
|
||||||
@@ -148,16 +163,18 @@ func (s *Service) upsertPair(ctx context.Context, pair config.Pair) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mid := new(big.Rat).Add(bid, ask)
|
mid := new(big.Rat).Add(bid, ask)
|
||||||
mid.Quo(mid, big.NewRat(2, 1))
|
mid.Quo(mid, big.NewRat(2, 1)) //nolint:mnd
|
||||||
|
|
||||||
spread := big.NewRat(0, 1)
|
spread := big.NewRat(0, 1)
|
||||||
if mid.Sign() != 0 {
|
if mid.Sign() != 0 {
|
||||||
spread.Sub(ask, bid)
|
spread.Sub(ask, bid)
|
||||||
|
|
||||||
if spread.Sign() < 0 {
|
if spread.Sign() < 0 {
|
||||||
spread.Neg(spread)
|
spread.Neg(spread)
|
||||||
}
|
}
|
||||||
|
|
||||||
spread.Quo(spread, mid)
|
spread.Quo(spread, mid)
|
||||||
spread.Mul(spread, big.NewRat(10000, 1)) // basis points
|
spread.Mul(spread, big.NewRat(10000, 1)) //nolint:mnd // basis points
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
@@ -201,6 +218,7 @@ func parseDecimal(value string) (*big.Rat, error) {
|
|||||||
if _, ok := r.SetString(value); !ok {
|
if _, ok := r.SetString(value); !ok {
|
||||||
return nil, merrors.InvalidArgument("invalid decimal \""+value+"\"", "value")
|
return nil, merrors.InvalidArgument("invalid decimal \""+value+"\"", "value")
|
||||||
}
|
}
|
||||||
|
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,9 +226,11 @@ func invertPrices(bid, ask *big.Rat) (*big.Rat, *big.Rat) {
|
|||||||
if bid.Sign() == 0 || ask.Sign() == 0 {
|
if bid.Sign() == 0 || ask.Sign() == 0 {
|
||||||
return bid, ask
|
return bid, ask
|
||||||
}
|
}
|
||||||
|
|
||||||
one := big.NewRat(1, 1)
|
one := big.NewRat(1, 1)
|
||||||
invBid := new(big.Rat).Quo(one, ask) // invert ask to get bid
|
invBid := new(big.Rat).Quo(one, ask) // invert ask to get bid
|
||||||
invAsk := new(big.Rat).Quo(one, bid) // invert bid to get ask
|
invAsk := new(big.Rat).Quo(one, bid) // invert bid to get ask
|
||||||
|
|
||||||
return invBid, invAsk
|
return invBid, invAsk
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,6 +238,7 @@ func formatDecimal(r *big.Rat) string {
|
|||||||
if r == nil {
|
if r == nil {
|
||||||
return "0"
|
return "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format with 8 decimal places, trimming trailing zeros.
|
// Format with 8 decimal places, trimming trailing zeros.
|
||||||
return r.FloatString(8)
|
return r.FloatString(8)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,30 +27,33 @@ type binanceConnector struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const defaultBinanceBaseURL = "https://api.binance.com"
|
const defaultBinanceBaseURL = "https://api.binance.com"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultDialTimeoutSeconds = 5 * time.Second
|
defaultDialTimeout = 5 * time.Second
|
||||||
defaultDialKeepAliveSeconds = 30 * time.Second
|
defaultDialKeepAlive = 30 * time.Second
|
||||||
defaultTLSHandshakeTimeoutSeconds = 5 * time.Second
|
defaultTLSHandshakeTimeout = 5 * time.Second
|
||||||
defaultResponseHeaderTimeoutSeconds = 10 * time.Second
|
defaultResponseHeaderTimeout = 10 * time.Second
|
||||||
defaultRequestTimeoutSeconds = 10 * time.Second
|
defaultRequestTimeout = 10 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewConnector(logger mlogger.Logger, settings model.SettingsT) (mmodel.Connector, error) {
|
func NewConnector(logger mlogger.Logger, settings model.SettingsT) (mmodel.Connector, error) { //nolint:ireturn
|
||||||
baseURL := defaultBinanceBaseURL
|
baseURL := defaultBinanceBaseURL
|
||||||
provider := strings.ToLower(mmodel.DriverBinance.String())
|
provider := strings.ToLower(mmodel.DriverBinance.String())
|
||||||
dialTimeout := defaultDialTimeoutSeconds
|
dialTimeout := defaultDialTimeout
|
||||||
dialKeepAlive := defaultDialKeepAliveSeconds
|
dialKeepAlive := defaultDialKeepAlive
|
||||||
tlsHandshakeTimeout := defaultTLSHandshakeTimeoutSeconds
|
tlsHandshakeTimeout := defaultTLSHandshakeTimeout
|
||||||
responseHeaderTimeout := defaultResponseHeaderTimeoutSeconds
|
responseHeaderTimeout := defaultResponseHeaderTimeout
|
||||||
requestTimeout := defaultRequestTimeoutSeconds
|
requestTimeout := defaultRequestTimeout
|
||||||
|
|
||||||
if settings != nil {
|
if settings != nil {
|
||||||
if value, ok := settings["base_url"].(string); ok && strings.TrimSpace(value) != "" {
|
if value, ok := settings["base_url"].(string); ok && strings.TrimSpace(value) != "" {
|
||||||
baseURL = strings.TrimSpace(value)
|
baseURL = strings.TrimSpace(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if value, ok := settings["provider"].(string); ok && strings.TrimSpace(value) != "" {
|
if value, ok := settings["provider"].(string); ok && strings.TrimSpace(value) != "" {
|
||||||
provider = strings.TrimSpace(value)
|
provider = strings.TrimSpace(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
dialTimeout = common.DurationSetting(settings, "dial_timeout_seconds", dialTimeout)
|
dialTimeout = common.DurationSetting(settings, "dial_timeout_seconds", dialTimeout)
|
||||||
dialKeepAlive = common.DurationSetting(settings, "dial_keep_alive_seconds", dialKeepAlive)
|
dialKeepAlive = common.DurationSetting(settings, "dial_keep_alive_seconds", dialKeepAlive)
|
||||||
tlsHandshakeTimeout = common.DurationSetting(settings, "tls_handshake_timeout_seconds", tlsHandshakeTimeout)
|
tlsHandshakeTimeout = common.DurationSetting(settings, "tls_handshake_timeout_seconds", tlsHandshakeTimeout)
|
||||||
@@ -96,6 +99,7 @@ func (c *binanceConnector) FetchTicker(ctx context.Context, symbol string) (*mmo
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, merrors.InternalWrap(err, "binance: parse base url")
|
return nil, merrors.InternalWrap(err, "binance: parse base url")
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint.Path = "/api/v3/ticker/bookTicker"
|
endpoint.Path = "/api/v3/ticker/bookTicker"
|
||||||
query := endpoint.Query()
|
query := endpoint.Query()
|
||||||
query.Set("symbol", strings.ToUpper(strings.TrimSpace(symbol)))
|
query.Set("symbol", strings.ToUpper(strings.TrimSpace(symbol)))
|
||||||
@@ -109,12 +113,14 @@ func (c *binanceConnector) FetchTicker(ctx context.Context, symbol string) (*mmo
|
|||||||
resp, err := c.client.Do(req)
|
resp, err := c.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Warn("Binance request failed", zap.String("symbol", symbol), zap.Error(err))
|
c.logger.Warn("Binance request failed", zap.String("symbol", symbol), zap.Error(err))
|
||||||
|
|
||||||
return nil, merrors.InternalWrap(err, "binance: request failed")
|
return nil, merrors.InternalWrap(err, "binance: request failed")
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
c.logger.Warn("Binance returned non-OK status", zap.String("symbol", symbol), zap.Int("status", resp.StatusCode))
|
c.logger.Warn("Binance returned non-OK status", zap.String("symbol", symbol), zap.Int("status", resp.StatusCode))
|
||||||
|
|
||||||
return nil, merrors.Internal("binance: unexpected status " + strconv.Itoa(resp.StatusCode))
|
return nil, merrors.Internal("binance: unexpected status " + strconv.Itoa(resp.StatusCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,9 +130,11 @@ func (c *binanceConnector) FetchTicker(ctx context.Context, symbol string) (*mmo
|
|||||||
AskPrice string `json:"askPrice"`
|
AskPrice string `json:"askPrice"`
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&payload); err != nil {
|
decodeErr := json.NewDecoder(resp.Body).Decode(&payload)
|
||||||
c.logger.Warn("Binance decode failed", zap.String("symbol", symbol), zap.Error(err))
|
if decodeErr != nil {
|
||||||
return nil, merrors.InternalWrap(err, "binance: decode response")
|
c.logger.Warn("Binance decode failed", zap.String("symbol", symbol), zap.Error(decodeErr))
|
||||||
|
|
||||||
|
return nil, merrors.InternalWrap(decodeErr, "binance: decode response")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &mmodel.Ticker{
|
return &mmodel.Ticker{
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const (
|
|||||||
defaultRequestTimeoutSeconds = 10 * time.Second
|
defaultRequestTimeoutSeconds = 10 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewConnector(logger mlogger.Logger, settings model.SettingsT) (mmodel.Connector, error) {
|
func NewConnector(logger mlogger.Logger, settings model.SettingsT) (mmodel.Connector, error) { //nolint:cyclop,ireturn
|
||||||
baseURL := defaultCBRBaseURL
|
baseURL := defaultCBRBaseURL
|
||||||
provider := strings.ToLower(mmodel.DriverCBR.String())
|
provider := strings.ToLower(mmodel.DriverCBR.String())
|
||||||
dialTimeout := defaultDialTimeoutSeconds
|
dialTimeout := defaultDialTimeoutSeconds
|
||||||
@@ -284,7 +284,7 @@ func (c *cbrConnector) fetchDailyRate(ctx context.Context, valute valuteInfo) (s
|
|||||||
return computePrice(entry.Value, entry.Nominal)
|
return computePrice(entry.Value, entry.Nominal)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cbrConnector) fetchHistoricalRate(ctx context.Context, valute valuteInfo, date time.Time) (string, error) {
|
func (c *cbrConnector) fetchHistoricalRate(ctx context.Context, valute valuteInfo, date time.Time) (string, error) { //nolint:funlen
|
||||||
query := map[string]string{
|
query := map[string]string{
|
||||||
"date_req1": date.Format("02/01/2006"),
|
"date_req1": date.Format("02/01/2006"),
|
||||||
"date_req2": date.Format("02/01/2006"),
|
"date_req2": date.Format("02/01/2006"),
|
||||||
@@ -366,6 +366,7 @@ func (c *cbrConnector) buildURL(path string, query map[string]string) (string, e
|
|||||||
return "", merrors.InternalWrap(err, "cbr: parse base url")
|
return "", merrors.InternalWrap(err, "cbr: parse base url")
|
||||||
}
|
}
|
||||||
base.Path = strings.TrimRight(base.Path, "/") + path
|
base.Path = strings.TrimRight(base.Path, "/") + path
|
||||||
|
|
||||||
q := base.Query()
|
q := base.Query()
|
||||||
for key, value := range query {
|
for key, value := range query {
|
||||||
q.Set(key, value)
|
q.Set(key, value)
|
||||||
@@ -401,7 +402,7 @@ type valuteMapping struct {
|
|||||||
byID map[string]valuteInfo
|
byID map[string]valuteInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildValuteMapping(logger *zap.Logger, items []valuteItem) (*valuteMapping, error) {
|
func buildValuteMapping(logger *zap.Logger, items []valuteItem) (*valuteMapping, error) { //nolint:gocognit,nestif
|
||||||
byISO := make(map[string]valuteInfo, len(items))
|
byISO := make(map[string]valuteInfo, len(items))
|
||||||
byID := make(map[string]valuteInfo, len(items))
|
byID := make(map[string]valuteInfo, len(items))
|
||||||
byNum := make(map[string]string, len(items))
|
byNum := make(map[string]string, len(items))
|
||||||
@@ -453,11 +454,12 @@ func buildValuteMapping(logger *zap.Logger, items []valuteItem) (*valuteMapping,
|
|||||||
// 2) Otherwise prefer smaller nominal
|
// 2) Otherwise prefer smaller nominal
|
||||||
keepExisting := true
|
keepExisting := true
|
||||||
|
|
||||||
if existing.Nominal != 1 && info.Nominal == 1 {
|
switch {
|
||||||
|
case existing.Nominal != 1 && info.Nominal == 1:
|
||||||
keepExisting = false
|
keepExisting = false
|
||||||
} else if existing.Nominal == 1 && info.Nominal != 1 {
|
case existing.Nominal == 1 && info.Nominal != 1:
|
||||||
keepExisting = true
|
keepExisting = true
|
||||||
} else if info.Nominal < existing.Nominal {
|
case info.Nominal < existing.Nominal:
|
||||||
keepExisting = false
|
keepExisting = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,7 +515,9 @@ func buildValuteMapping(logger *zap.Logger, items []valuteItem) (*valuteMapping,
|
|||||||
byNum[isoNum] = id
|
byNum[isoNum] = id
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Installing currency code", zap.String("iso_code", isoChar), zap.String("id", id), zap.Int64("nominal", nominal))
|
logger.Info("Installing currency code",
|
||||||
|
zap.String("iso_code", isoChar), zap.String("id", id), zap.Int64("nominal", nominal),
|
||||||
|
)
|
||||||
|
|
||||||
byISO[isoChar] = info
|
byISO[isoChar] = info
|
||||||
byID[id] = info
|
byID[id] = info
|
||||||
@@ -546,6 +550,7 @@ func (d *dailyRates) find(id string) *dailyValute {
|
|||||||
if d == nil {
|
if d == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx := range d.Valutes {
|
for idx := range d.Valutes {
|
||||||
if strings.EqualFold(strings.TrimSpace(d.Valutes[idx].ID), id) {
|
if strings.EqualFold(strings.TrimSpace(d.Valutes[idx].ID), id) {
|
||||||
return &d.Valutes[idx]
|
return &d.Valutes[idx]
|
||||||
@@ -569,7 +574,9 @@ func (d *dynamicRates) find(id string, date time.Time) *dynamicRecord {
|
|||||||
if d == nil {
|
if d == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
target := date.Format("02.01.2006")
|
target := date.Format("02.01.2006")
|
||||||
|
|
||||||
for idx := range d.Records {
|
for idx := range d.Records {
|
||||||
rec := &d.Records[idx]
|
rec := &d.Records[idx]
|
||||||
if !strings.EqualFold(strings.TrimSpace(rec.ID), id) {
|
if !strings.EqualFold(strings.TrimSpace(rec.ID), id) {
|
||||||
@@ -663,7 +670,7 @@ func computePrice(value string, nominalStr string) (string, error) {
|
|||||||
|
|
||||||
den := big.NewRat(nominal, 1)
|
den := big.NewRat(nominal, 1)
|
||||||
price := new(big.Rat).Quo(r, den)
|
price := new(big.Rat).Quo(r, den)
|
||||||
return price.FloatString(8), nil
|
return price.FloatString(8), nil //nolint:mnd
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatSymbol(iso string, asOf *time.Time) string {
|
func formatSymbol(iso string, asOf *time.Time) string {
|
||||||
|
|||||||
@@ -29,29 +29,36 @@ type coingeckoConnector struct {
|
|||||||
const defaultCoinGeckoBaseURL = "https://api.coingecko.com/api/v3"
|
const defaultCoinGeckoBaseURL = "https://api.coingecko.com/api/v3"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultDialTimeoutSeconds = 5 * time.Second
|
defaultDialTimeout = 5 * time.Second
|
||||||
defaultDialKeepAliveSeconds = 30 * time.Second
|
defaultDialKeepAlive = 30 * time.Second
|
||||||
defaultTLSHandshakeTimeoutSeconds = 5 * time.Second
|
defaultTLSHandshakeTimeout = 5 * time.Second
|
||||||
defaultResponseHeaderTimeoutSeconds = 10 * time.Second
|
defaultResponseHeaderTimeout = 10 * time.Second
|
||||||
defaultRequestTimeoutSeconds = 10 * time.Second
|
defaultRequestTimeout = 10 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewConnector(logger mlogger.Logger, settings model.SettingsT) (mmodel.Connector, error) {
|
const (
|
||||||
|
expectedSymbolParts = 2
|
||||||
|
tsToMillis = 1000
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewConnector(logger mlogger.Logger, settings model.SettingsT) (mmodel.Connector, error) { //nolint:ireturn
|
||||||
baseURL := defaultCoinGeckoBaseURL
|
baseURL := defaultCoinGeckoBaseURL
|
||||||
provider := strings.ToLower(mmodel.DriverCoinGecko.String())
|
provider := strings.ToLower(mmodel.DriverCoinGecko.String())
|
||||||
dialTimeout := defaultDialTimeoutSeconds
|
dialTimeout := defaultDialTimeout
|
||||||
dialKeepAlive := defaultDialKeepAliveSeconds
|
dialKeepAlive := defaultDialKeepAlive
|
||||||
tlsHandshakeTimeout := defaultTLSHandshakeTimeoutSeconds
|
tlsHandshakeTimeout := defaultTLSHandshakeTimeout
|
||||||
responseHeaderTimeout := defaultResponseHeaderTimeoutSeconds
|
responseHeaderTimeout := defaultResponseHeaderTimeout
|
||||||
requestTimeout := defaultRequestTimeoutSeconds
|
requestTimeout := defaultRequestTimeout
|
||||||
|
|
||||||
if settings != nil {
|
if settings != nil {
|
||||||
if value, ok := settings["base_url"].(string); ok && strings.TrimSpace(value) != "" {
|
if value, ok := settings["base_url"].(string); ok && strings.TrimSpace(value) != "" {
|
||||||
baseURL = strings.TrimSpace(value)
|
baseURL = strings.TrimSpace(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if value, ok := settings["provider"].(string); ok && strings.TrimSpace(value) != "" {
|
if value, ok := settings["provider"].(string); ok && strings.TrimSpace(value) != "" {
|
||||||
provider = strings.TrimSpace(value)
|
provider = strings.TrimSpace(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
dialTimeout = common.DurationSetting(settings, "dial_timeout_seconds", dialTimeout)
|
dialTimeout = common.DurationSetting(settings, "dial_timeout_seconds", dialTimeout)
|
||||||
dialKeepAlive = common.DurationSetting(settings, "dial_keep_alive_seconds", dialKeepAlive)
|
dialKeepAlive = common.DurationSetting(settings, "dial_keep_alive_seconds", dialKeepAlive)
|
||||||
tlsHandshakeTimeout = common.DurationSetting(settings, "tls_handshake_timeout_seconds", tlsHandshakeTimeout)
|
tlsHandshakeTimeout = common.DurationSetting(settings, "tls_handshake_timeout_seconds", tlsHandshakeTimeout)
|
||||||
@@ -88,6 +95,7 @@ func (c *coingeckoConnector) ID() mmodel.Driver {
|
|||||||
return c.id
|
return c.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:cyclop,funlen
|
||||||
func (c *coingeckoConnector) FetchTicker(ctx context.Context, symbol string) (*mmodel.Ticker, error) {
|
func (c *coingeckoConnector) FetchTicker(ctx context.Context, symbol string) (*mmodel.Ticker, error) {
|
||||||
coinID, vsCurrency, err := parseSymbol(symbol)
|
coinID, vsCurrency, err := parseSymbol(symbol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -98,6 +106,7 @@ func (c *coingeckoConnector) FetchTicker(ctx context.Context, symbol string) (*m
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, merrors.InternalWrap(err, "coingecko: parse base url")
|
return nil, merrors.InternalWrap(err, "coingecko: parse base url")
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint.Path = strings.TrimRight(endpoint.Path, "/") + "/simple/price"
|
endpoint.Path = strings.TrimRight(endpoint.Path, "/") + "/simple/price"
|
||||||
query := endpoint.Query()
|
query := endpoint.Query()
|
||||||
query.Set("ids", coinID)
|
query.Set("ids", coinID)
|
||||||
@@ -113,44 +122,51 @@ func (c *coingeckoConnector) FetchTicker(ctx context.Context, symbol string) (*m
|
|||||||
resp, err := c.client.Do(req)
|
resp, err := c.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Warn("CoinGecko request failed", zap.String("symbol", symbol), zap.Error(err))
|
c.logger.Warn("CoinGecko request failed", zap.String("symbol", symbol), zap.Error(err))
|
||||||
|
|
||||||
return nil, merrors.InternalWrap(err, "coingecko: request failed")
|
return nil, merrors.InternalWrap(err, "coingecko: request failed")
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
c.logger.Warn("CoinGecko returned non-OK status", zap.String("symbol", symbol), zap.Int("status", resp.StatusCode))
|
c.logger.Warn("CoinGecko returned non-OK status", zap.String("symbol", symbol), zap.Int("status", resp.StatusCode))
|
||||||
|
|
||||||
return nil, merrors.Internal("coingecko: unexpected status " + strconv.Itoa(resp.StatusCode))
|
return nil, merrors.Internal("coingecko: unexpected status " + strconv.Itoa(resp.StatusCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
decoder := json.NewDecoder(resp.Body)
|
decoder := json.NewDecoder(resp.Body)
|
||||||
decoder.UseNumber()
|
decoder.UseNumber()
|
||||||
|
|
||||||
var payload map[string]map[string]interface{}
|
var payload map[string]map[string]any
|
||||||
if err := decoder.Decode(&payload); err != nil {
|
|
||||||
c.logger.Warn("CoinGecko decode failed", zap.String("symbol", symbol), zap.Error(err))
|
decodeErr := decoder.Decode(&payload)
|
||||||
return nil, merrors.InternalWrap(err, "coingecko: decode response")
|
if decodeErr != nil {
|
||||||
|
c.logger.Warn("CoinGecko decode failed", zap.String("symbol", symbol), zap.Error(decodeErr))
|
||||||
|
|
||||||
|
return nil, merrors.InternalWrap(decodeErr, "coingecko: decode response")
|
||||||
}
|
}
|
||||||
|
|
||||||
coinData, ok := payload[coinID]
|
coinData, coinFound := payload[coinID]
|
||||||
if !ok {
|
if !coinFound {
|
||||||
return nil, merrors.Internal("coingecko: coin id not found in response")
|
return nil, merrors.Internal("coingecko: coin id not found in response")
|
||||||
}
|
}
|
||||||
priceValue, ok := coinData[vsCurrency]
|
|
||||||
if !ok {
|
priceValue, priceFound := coinData[vsCurrency]
|
||||||
|
if !priceFound {
|
||||||
return nil, merrors.Internal("coingecko: vs currency not found in response")
|
return nil, merrors.Internal("coingecko: vs currency not found in response")
|
||||||
}
|
}
|
||||||
|
|
||||||
price, ok := toFloat(priceValue)
|
price, priceOk := toFloat(priceValue)
|
||||||
if !ok || price <= 0 {
|
if !priceOk || price <= 0 {
|
||||||
return nil, merrors.Internal("coingecko: invalid price value in response")
|
return nil, merrors.Internal("coingecko: invalid price value in response")
|
||||||
}
|
}
|
||||||
|
|
||||||
priceStr := strconv.FormatFloat(price, 'f', -1, 64)
|
priceStr := strconv.FormatFloat(price, 'f', -1, 64)
|
||||||
|
|
||||||
timestamp := time.Now().UnixMilli()
|
timestamp := time.Now().UnixMilli()
|
||||||
if tsValue, ok := coinData["last_updated_at"]; ok {
|
|
||||||
if tsFloat, ok := toFloat(tsValue); ok && tsFloat > 0 {
|
if tsValue, tsFound := coinData["last_updated_at"]; tsFound {
|
||||||
tsMillis := int64(tsFloat * 1000)
|
if tsFloat, tsOk := toFloat(tsValue); tsOk && tsFloat > 0 {
|
||||||
|
tsMillis := int64(tsFloat * tsToMillis)
|
||||||
if tsMillis > 0 {
|
if tsMillis > 0 {
|
||||||
timestamp = tsMillis
|
timestamp = tsMillis
|
||||||
}
|
}
|
||||||
@@ -179,14 +195,16 @@ func parseSymbol(symbol string) (string, string, error) {
|
|||||||
case ':', '/', '-', '_':
|
case ':', '/', '-', '_':
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(parts) != 2 {
|
if len(parts) != expectedSymbolParts {
|
||||||
return "", "", merrors.InvalidArgument("coingecko: symbol must be <coin_id>/<vs_currency>", "symbol")
|
return "", "", merrors.InvalidArgument("coingecko: symbol must be <coin_id>/<vs_currency>", "symbol")
|
||||||
}
|
}
|
||||||
|
|
||||||
coinID := strings.TrimSpace(parts[0])
|
coinID := strings.TrimSpace(parts[0])
|
||||||
|
|
||||||
vsCurrency := strings.TrimSpace(parts[1])
|
vsCurrency := strings.TrimSpace(parts[1])
|
||||||
if coinID == "" || vsCurrency == "" {
|
if coinID == "" || vsCurrency == "" {
|
||||||
return "", "", merrors.InvalidArgument("coingecko: symbol contains empty segments", "symbol")
|
return "", "", merrors.InvalidArgument("coingecko: symbol contains empty segments", "symbol")
|
||||||
@@ -195,28 +213,31 @@ func parseSymbol(symbol string) (string, string, error) {
|
|||||||
return coinID, vsCurrency, nil
|
return coinID, vsCurrency, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toFloat(value interface{}) (float64, bool) {
|
func toFloat(value any) (float64, bool) {
|
||||||
switch v := value.(type) {
|
switch val := value.(type) {
|
||||||
case json.Number:
|
case json.Number:
|
||||||
f, err := v.Float64()
|
f, err := val.Float64()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return f, true
|
return f, true
|
||||||
case float64:
|
case float64:
|
||||||
return v, true
|
return val, true
|
||||||
case float32:
|
case float32:
|
||||||
return float64(v), true
|
return float64(val), true
|
||||||
case int:
|
case int:
|
||||||
return float64(v), true
|
return float64(val), true
|
||||||
case int64:
|
case int64:
|
||||||
return float64(v), true
|
return float64(val), true
|
||||||
case uint64:
|
case uint64:
|
||||||
return float64(v), true
|
return float64(val), true
|
||||||
case string:
|
case string:
|
||||||
if parsed, err := strconv.ParseFloat(v, 64); err == nil {
|
parsed, parseErr := strconv.ParseFloat(val, 64)
|
||||||
|
if parseErr == nil {
|
||||||
return parsed, true
|
return parsed, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package common
|
package common //nolint:revive // package provides shared market connector utilities
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -8,39 +8,46 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// DurationSetting reads a positive duration override from settings or returns def when the value is missing or invalid.
|
// DurationSetting reads a positive duration override from settings or returns def when the value is missing or invalid.
|
||||||
|
//
|
||||||
|
//nolint:cyclop
|
||||||
func DurationSetting(settings model.SettingsT, key string, def time.Duration) time.Duration {
|
func DurationSetting(settings model.SettingsT, key string, def time.Duration) time.Duration {
|
||||||
if settings == nil {
|
if settings == nil {
|
||||||
return def
|
return def
|
||||||
}
|
}
|
||||||
|
|
||||||
value, ok := settings[key]
|
value, ok := settings[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
return def
|
return def
|
||||||
}
|
}
|
||||||
|
|
||||||
switch v := value.(type) {
|
switch val := value.(type) {
|
||||||
case time.Duration:
|
case time.Duration:
|
||||||
if v > 0 {
|
if val > 0 {
|
||||||
return v
|
return val
|
||||||
}
|
}
|
||||||
case int:
|
case int:
|
||||||
if v > 0 {
|
if val > 0 {
|
||||||
return time.Duration(v) * time.Second
|
return time.Duration(val) * time.Second
|
||||||
}
|
}
|
||||||
case int64:
|
case int64:
|
||||||
if v > 0 {
|
if val > 0 {
|
||||||
return time.Duration(v) * time.Second
|
return time.Duration(val) * time.Second
|
||||||
}
|
}
|
||||||
case float64:
|
case float64:
|
||||||
if v > 0 {
|
if val > 0 {
|
||||||
return time.Duration(v * float64(time.Second))
|
return time.Duration(val * float64(time.Second))
|
||||||
}
|
}
|
||||||
case string:
|
case string:
|
||||||
if parsed, err := time.ParseDuration(v); err == nil && parsed > 0 {
|
parsed, parseErr := time.ParseDuration(val)
|
||||||
|
if parseErr == nil && parsed > 0 {
|
||||||
return parsed
|
return parsed
|
||||||
}
|
}
|
||||||
if seconds, err := strconv.ParseFloat(v, 64); err == nil && seconds > 0 {
|
|
||||||
|
seconds, floatErr := strconv.ParseFloat(val, 64)
|
||||||
|
if floatErr == nil && seconds > 0 {
|
||||||
return time.Duration(seconds * float64(time.Second))
|
return time.Duration(seconds * float64(time.Second))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return def
|
return def
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,16 +24,19 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Server interface {
|
type Server interface {
|
||||||
SetStatus(health.ServiceStatus)
|
SetStatus(status health.ServiceStatus)
|
||||||
Close(context.Context)
|
Close(ctx context.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:ireturn
|
||||||
func NewServer(logger mlogger.Logger, cfg *config.MetricsConfig) (Server, error) {
|
func NewServer(logger mlogger.Logger, cfg *config.MetricsConfig) (Server, error) {
|
||||||
if logger == nil {
|
if logger == nil {
|
||||||
return nil, merrors.InvalidArgument("metrics: logger is nil")
|
return nil, merrors.InvalidArgument("metrics: logger is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg == nil || !cfg.Enabled {
|
if cfg == nil || !cfg.Enabled {
|
||||||
logger.Debug("Metrics disabled; using noop server")
|
logger.Debug("Metrics disabled; using noop server")
|
||||||
|
|
||||||
return noopServer{}, nil
|
return noopServer{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +50,9 @@ func NewServer(logger mlogger.Logger, cfg *config.MetricsConfig) (Server, error)
|
|||||||
router.Handle("/metrics", promhttp.Handler())
|
router.Handle("/metrics", promhttp.Handler())
|
||||||
|
|
||||||
var healthRouter routers.Health
|
var healthRouter routers.Health
|
||||||
if hr, err := routers.NewHealthRouter(metricsLogger, router, ""); err != nil {
|
|
||||||
|
hr, err := routers.NewHealthRouter(metricsLogger, router, "")
|
||||||
|
if err != nil {
|
||||||
metricsLogger.Warn("Failed to initialise health router", zap.Error(err))
|
metricsLogger.Warn("Failed to initialise health router", zap.Error(err))
|
||||||
} else {
|
} else {
|
||||||
hr.SetStatus(health.SSStarting)
|
hr.SetStatus(health.SSStarting)
|
||||||
@@ -60,7 +65,7 @@ func NewServer(logger mlogger.Logger, cfg *config.MetricsConfig) (Server, error)
|
|||||||
ReadHeaderTimeout: readHeaderTimeout,
|
ReadHeaderTimeout: readHeaderTimeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
ms := &httpServerWrapper{
|
wrapper := &httpServerWrapper{
|
||||||
logger: metricsLogger,
|
logger: metricsLogger,
|
||||||
server: httpServer,
|
server: httpServer,
|
||||||
health: healthRouter,
|
health: healthRouter,
|
||||||
@@ -69,7 +74,9 @@ func NewServer(logger mlogger.Logger, cfg *config.MetricsConfig) (Server, error)
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
metricsLogger.Info("Prometheus endpoint listening", zap.String("address", address))
|
metricsLogger.Info("Prometheus endpoint listening", zap.String("address", address))
|
||||||
if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
|
||||||
|
err := httpServer.ListenAndServe()
|
||||||
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
metricsLogger.Error("Prometheus endpoint stopped unexpectedly", zap.Error(err))
|
metricsLogger.Error("Prometheus endpoint stopped unexpectedly", zap.Error(err))
|
||||||
if healthRouter != nil {
|
if healthRouter != nil {
|
||||||
healthRouter.SetStatus(health.SSTerminating)
|
healthRouter.SetStatus(health.SSTerminating)
|
||||||
@@ -77,7 +84,7 @@ func NewServer(logger mlogger.Logger, cfg *config.MetricsConfig) (Server, error)
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return ms, nil
|
return wrapper, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpServerWrapper struct {
|
type httpServerWrapper struct {
|
||||||
@@ -91,6 +98,7 @@ func (s *httpServerWrapper) SetStatus(status health.ServiceStatus) {
|
|||||||
if s == nil || s.health == nil {
|
if s == nil || s.health == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.logger.Debug("Updating metrics health status", zap.String("status", string(status)))
|
s.logger.Debug("Updating metrics health status", zap.String("status", string(status)))
|
||||||
s.health.SetStatus(status)
|
s.health.SetStatus(status)
|
||||||
}
|
}
|
||||||
@@ -110,10 +118,12 @@ func (s *httpServerWrapper) Close(ctx context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:contextcheck
|
||||||
shutdownCtx := ctx
|
shutdownCtx := ctx
|
||||||
if shutdownCtx == nil {
|
if shutdownCtx == nil {
|
||||||
shutdownCtx = context.Background()
|
shutdownCtx = context.Background()
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.timeout > 0 {
|
if s.timeout > 0 {
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
shutdownCtx, cancel = context.WithTimeout(shutdownCtx, s.timeout)
|
shutdownCtx, cancel = context.WithTimeout(shutdownCtx, s.timeout)
|
||||||
@@ -129,6 +139,6 @@ func (s *httpServerWrapper) Close(ctx context.Context) {
|
|||||||
|
|
||||||
type noopServer struct{}
|
type noopServer struct{}
|
||||||
|
|
||||||
func (noopServer) SetStatus(health.ServiceStatus) {}
|
func (noopServer) SetStatus(_ health.ServiceStatus) {}
|
||||||
|
|
||||||
func (noopServer) Close(context.Context) {}
|
func (noopServer) Close(_ context.Context) {}
|
||||||
|
|||||||
@@ -26,16 +26,18 @@ func main() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
logger := lf.NewLogger(*debugFlag).Named("fx_ingestor")
|
logger := lf.NewLogger(*debugFlag).Named("fx_ingestor")
|
||||||
logger = logger.With(zap.String("instance_id", discovery.InstanceID()))
|
|
||||||
defer logger.Sync()
|
|
||||||
|
|
||||||
av := appversion.Create()
|
logger = logger.With(zap.String("instance_id", discovery.InstanceID()))
|
||||||
|
defer logger.Sync() //nolint:errcheck
|
||||||
|
|
||||||
|
appVersion := appversion.Create()
|
||||||
if *versionFlag {
|
if *versionFlag {
|
||||||
fmt.Fprintln(os.Stdout, av.Print())
|
fmt.Fprintln(os.Stdout, appVersion.Print())
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info(fmt.Sprintf("Starting %s", av.Program()), zap.String("version", av.Info()))
|
logger.Info("Starting "+appVersion.Program(), zap.String("version", appVersion.Info()))
|
||||||
|
|
||||||
ctx, cancel := signalctx.WithSignals(context.Background(), os.Interrupt, syscall.SIGTERM)
|
ctx, cancel := signalctx.WithSignals(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -47,8 +49,10 @@ func main() {
|
|||||||
if err := application.Run(ctx); err != nil {
|
if err := application.Run(ctx); err != nil {
|
||||||
if errors.Is(err, context.Canceled) {
|
if errors.Is(err, context.Canceled) {
|
||||||
logger.Info("FX ingestor stopped")
|
logger.Info("FX ingestor stopped")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Error("Ingestor terminated with error", zap.Error(err))
|
logger.Error("Ingestor terminated with error", zap.Error(err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/tech/sendico/fx/oracle
|
module github.com/tech/sendico/fx/oracle
|
||||||
|
|
||||||
go 1.25.6
|
go 1.25.7
|
||||||
|
|
||||||
replace github.com/tech/sendico/pkg => ../../pkg
|
replace github.com/tech/sendico/pkg => ../../pkg
|
||||||
|
|
||||||
@@ -25,8 +25,8 @@ require (
|
|||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/go-chi/chi/v5 v5.2.4 // indirect
|
github.com/go-chi/chi/v5 v5.2.5 // indirect
|
||||||
github.com/klauspost/compress v1.18.3 // indirect
|
github.com/klauspost/compress v1.18.4 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
@@ -43,10 +43,10 @@ require (
|
|||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/crypto v0.47.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/net v0.49.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
|
|||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
|
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||||
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
@@ -57,8 +57,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@@ -172,15 +172,15 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
|||||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
@@ -191,16 +191,16 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@@ -208,8 +208,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b h1:GZxXGdFaHX27ZSMHudWc4FokdD+xl8BC2UJm1OVIEzs=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/tech/sendico/fx/storage
|
module github.com/tech/sendico/fx/storage
|
||||||
|
|
||||||
go 1.25.6
|
go 1.25.7
|
||||||
|
|
||||||
replace github.com/tech/sendico/pkg => ../../pkg
|
replace github.com/tech/sendico/pkg => ../../pkg
|
||||||
|
|
||||||
@@ -16,15 +16,15 @@ require (
|
|||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.3 // indirect
|
github.com/klauspost/compress v1.18.4 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
github.com/xdg-go/scram v1.2.0 // indirect
|
github.com/xdg-go/scram v1.2.0 // indirect
|
||||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/crypto v0.47.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.11 // indirect
|
google.golang.org/protobuf v1.36.11 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54 h1:mFWunSatvkQQDhpdyuFAYwyAan3hzCuma+Pz8sqvOfg=
|
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54 h1:mFWunSatvkQQDhpdyuFAYwyAan3hzCuma+Pz8sqvOfg=
|
||||||
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
||||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||||
@@ -134,8 +134,8 @@ go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
|||||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
@@ -150,16 +150,16 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/tech/sendico/gateway/chain
|
module github.com/tech/sendico/gateway/chain
|
||||||
|
|
||||||
go 1.25.6
|
go 1.25.7
|
||||||
|
|
||||||
replace github.com/tech/sendico/pkg => ../../pkg
|
replace github.com/tech/sendico/pkg => ../../pkg
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260201044653-ee82dce4af02 // indirect
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260212005555-3a7e5700f354 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
||||||
@@ -32,13 +32,13 @@ require (
|
|||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/consensys/gnark-crypto v0.19.2 // indirect
|
github.com/consensys/gnark-crypto v0.19.2 // indirect
|
||||||
github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect
|
github.com/crate-crypto/go-eth-kzg v1.5.0 // indirect
|
||||||
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
|
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/deckarep/golang-set/v2 v2.8.0 // indirect
|
github.com/deckarep/golang-set/v2 v2.8.0 // indirect
|
||||||
github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect
|
github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect
|
||||||
github.com/ethereum/go-verkle v0.2.2 // indirect
|
github.com/ethereum/go-verkle v0.2.2 // indirect
|
||||||
github.com/go-chi/chi/v5 v5.2.4 // indirect
|
github.com/go-chi/chi/v5 v5.2.5 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
@@ -53,7 +53,7 @@ require (
|
|||||||
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
|
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.1-vault-7 // indirect
|
github.com/hashicorp/hcl v1.0.1-vault-7 // indirect
|
||||||
github.com/holiman/uint256 v1.3.2 // indirect
|
github.com/holiman/uint256 v1.3.2 // indirect
|
||||||
github.com/klauspost/compress v1.18.3 // indirect
|
github.com/klauspost/compress v1.18.4 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
@@ -77,12 +77,12 @@ require (
|
|||||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/crypto v0.47.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
||||||
golang.org/x/net v0.49.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
golang.org/x/time v0.14.0 // indirect
|
golang.org/x/time v0.14.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
|
|||||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260201044653-ee82dce4af02 h1:0uY5Ooun4eqGmP0IrQhiKVqeeEXoeEcL8KVRtug8+r8=
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260212005555-3a7e5700f354 h1:BgaMXBpcqcW74afzqI3iKo07K3tC+VuyWU3/FIvLlNI=
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260201044653-ee82dce4af02/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260212005555-3a7e5700f354/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
|
||||||
github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0=
|
github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0=
|
||||||
github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU=
|
github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
@@ -50,8 +50,8 @@ github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GK
|
|||||||
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
|
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/crate-crypto/go-eth-kzg v1.4.0 h1:WzDGjHk4gFg6YzV0rJOAsTK4z3Qkz5jd4RE3DAvPFkg=
|
github.com/crate-crypto/go-eth-kzg v1.5.0 h1:FYRiJMJG2iv+2Dy3fi14SVGjcPteZ5HAAUe4YWlJygc=
|
||||||
github.com/crate-crypto/go-eth-kzg v1.4.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI=
|
github.com/crate-crypto/go-eth-kzg v1.5.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI=
|
||||||
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg=
|
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg=
|
||||||
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM=
|
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
@@ -90,8 +90,8 @@ github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeD
|
|||||||
github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg=
|
github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg=
|
||||||
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
|
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
|
||||||
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||||
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
|
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||||
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
|
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
@@ -159,8 +159,8 @@ github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
|
|||||||
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
@@ -318,8 +318,8 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
|||||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
@@ -327,8 +327,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
@@ -341,16 +341,16 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||||
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@@ -360,8 +360,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b h1:GZxXGdFaHX27ZSMHudWc4FokdD+xl8BC2UJm1OVIEzs=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ func WithNetworks(networks []shared.Network) Option {
|
|||||||
clone.TokenConfigs[i].Symbol = strings.ToUpper(strings.TrimSpace(clone.TokenConfigs[i].Symbol))
|
clone.TokenConfigs[i].Symbol = strings.ToUpper(strings.TrimSpace(clone.TokenConfigs[i].Symbol))
|
||||||
clone.TokenConfigs[i].ContractAddress = strings.ToLower(strings.TrimSpace(clone.TokenConfigs[i].ContractAddress))
|
clone.TokenConfigs[i].ContractAddress = strings.ToLower(strings.TrimSpace(clone.TokenConfigs[i].ContractAddress))
|
||||||
}
|
}
|
||||||
clone.Name = clone.Name
|
clone.Name = network.Name
|
||||||
s.networks[clone.Name] = clone
|
s.networks[clone.Name] = clone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,16 +199,22 @@ func (s *Service) startDiscoveryAnnouncers() {
|
|||||||
}
|
}
|
||||||
version := appversion.Create().Short()
|
version := appversion.Create().Short()
|
||||||
for _, network := range s.networks {
|
for _, network := range s.networks {
|
||||||
currencies := []string{shared.NativeCurrency(network)}
|
currencies := []discovery.CurrencyAnnouncement{{
|
||||||
|
Currency: shared.NativeCurrency(network),
|
||||||
|
Network: string(network.Name),
|
||||||
|
}}
|
||||||
for _, token := range network.TokenConfigs {
|
for _, token := range network.TokenConfigs {
|
||||||
if token.Symbol != "" {
|
if token.Symbol != "" {
|
||||||
currencies = append(currencies, token.Symbol)
|
currencies = append(currencies, discovery.CurrencyAnnouncement{
|
||||||
|
Currency: token.Symbol,
|
||||||
|
Network: string(network.Name),
|
||||||
|
ContractAddress: token.ContractAddress,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
announce := discovery.Announcement{
|
announce := discovery.Announcement{
|
||||||
Service: "CRYPTO_RAIL_GATEWAY",
|
Service: "CRYPTO_RAIL_GATEWAY",
|
||||||
Rail: "CRYPTO",
|
Rail: "CRYPTO",
|
||||||
Network: string(network.Name),
|
|
||||||
Operations: []string{"balance.read", "payin.crypto", "payout.crypto", "fee.send", "observe.confirm"},
|
Operations: []string{"balance.read", "payin.crypto", "payout.crypto", "fee.send", "observe.confirm"},
|
||||||
Currencies: currencies,
|
Currencies: currencies,
|
||||||
InvokeURI: s.invokeURI,
|
InvokeURI: s.invokeURI,
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ func (w *inMemoryWallets) List(ctx context.Context, filter model.ManagedWalletFi
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if wallet.Network != filter.Network {
|
if filter.Network != "" && wallet.Network != filter.Network {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if filter.TokenSymbol != "" && !strings.EqualFold(wallet.TokenSymbol, filter.TokenSymbol) {
|
if filter.TokenSymbol != "" && !strings.EqualFold(wallet.TokenSymbol, filter.TokenSymbol) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ This service now supports Monetix “payout by card”.
|
|||||||
- `MONETIX_PROJECT_ID` – integer project ID
|
- `MONETIX_PROJECT_ID` – integer project ID
|
||||||
- `MONETIX_SECRET_KEY` – signature secret
|
- `MONETIX_SECRET_KEY` – signature secret
|
||||||
- Optional: `allowed_currencies`, `require_customer_address`, `request_timeout_seconds`
|
- Optional: `allowed_currencies`, `require_customer_address`, `request_timeout_seconds`
|
||||||
- Gateway descriptor: `gateway.id`, optional `gateway.currencies`, `gateway.limits`
|
- Gateway descriptor: `gateway.id`, optional `gateway.currencies`, `gateway.limits` (for per-payout minimum use `gateway.limits.per_tx_min_amount`)
|
||||||
- Callback server: `MNTX_GATEWAY_HTTP_PORT` (exposed as 8084), `http.callback.path`, optional `allowed_cidrs`
|
- Callback server: `MNTX_GATEWAY_HTTP_PORT` (exposed as 8084), `http.callback.path`, optional `allowed_cidrs`
|
||||||
|
|
||||||
## Outbound request (CreateCardPayout)
|
## Outbound request (CreateCardPayout)
|
||||||
|
|||||||
@@ -151,7 +151,9 @@ func operationFromCardPayout(req *mntxv1.CardPayoutRequest) (*connectorv1.Operat
|
|||||||
money := moneyFromMinor(req.GetAmountMinor(), req.GetCurrency())
|
money := moneyFromMinor(req.GetAmountMinor(), req.GetCurrency())
|
||||||
op := &connectorv1.Operation{
|
op := &connectorv1.Operation{
|
||||||
Type: connectorv1.OperationType_PAYOUT,
|
Type: connectorv1.OperationType_PAYOUT,
|
||||||
IdempotencyKey: strings.TrimSpace(req.GetPayoutId()),
|
IdempotencyKey: strings.TrimSpace(req.GetIdempotencyKey()),
|
||||||
|
OperationRef: strings.TrimSpace(req.GetOperationRef()),
|
||||||
|
IntentRef: strings.TrimSpace(req.GetIntentRef()),
|
||||||
Money: money,
|
Money: money,
|
||||||
Params: structFromMap(params),
|
Params: structFromMap(params),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ monetix:
|
|||||||
gateway:
|
gateway:
|
||||||
id: "monetix"
|
id: "monetix"
|
||||||
is_enabled: true
|
is_enabled: true
|
||||||
network: "VISA_DIRECT"
|
network: "MIR"
|
||||||
currencies: ["RUB"]
|
currencies: ["RUB"]
|
||||||
limits:
|
limits:
|
||||||
min_amount: "0"
|
per_tx_min_amount: "0"
|
||||||
|
|
||||||
http:
|
http:
|
||||||
callback:
|
callback:
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ monetix:
|
|||||||
gateway:
|
gateway:
|
||||||
id: "monetix"
|
id: "monetix"
|
||||||
is_enabled: true
|
is_enabled: true
|
||||||
network: "VISA_DIRECT"
|
network: "MIR"
|
||||||
currencies: ["RUB"]
|
currencies: ["RUB"]
|
||||||
limits:
|
limits:
|
||||||
min_amount: "0"
|
per_tx_min_amount: "100.00"
|
||||||
|
|
||||||
http:
|
http:
|
||||||
callback:
|
callback:
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
module github.com/tech/sendico/gateway/mntx
|
module github.com/tech/sendico/gateway/mntx
|
||||||
|
|
||||||
go 1.25.6
|
go 1.25.7
|
||||||
|
|
||||||
replace github.com/tech/sendico/pkg => ../../pkg
|
replace github.com/tech/sendico/pkg => ../../pkg
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-chi/chi/v5 v5.2.4
|
github.com/go-chi/chi/v5 v5.2.5
|
||||||
github.com/prometheus/client_golang v1.23.2
|
github.com/prometheus/client_golang v1.23.2
|
||||||
github.com/shopspring/decimal v1.4.0
|
github.com/shopspring/decimal v1.4.0
|
||||||
github.com/tech/sendico/pkg v0.1.0
|
github.com/tech/sendico/pkg v0.1.0
|
||||||
@@ -24,7 +24,7 @@ require (
|
|||||||
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.3 // indirect
|
github.com/klauspost/compress v1.18.4 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
@@ -43,10 +43,10 @@ require (
|
|||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/crypto v0.47.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/net v0.49.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
|
|||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
|
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||||
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
@@ -57,8 +57,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@@ -174,15 +174,15 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
|||||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
@@ -193,16 +193,16 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@@ -210,8 +210,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b h1:GZxXGdFaHX27ZSMHudWc4FokdD+xl8BC2UJm1OVIEzs=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
|||||||
@@ -51,13 +51,13 @@ func (s *cardPayoutStore) FindByPaymentID(_ context.Context, id string) (*model.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *cardPayoutStore) Upsert(_ context.Context, record *model.CardPayout) error {
|
func (s *cardPayoutStore) Upsert(_ context.Context, record *model.CardPayout) error {
|
||||||
s.data[record.PayoutID] = record
|
s.data[record.PaymentRef] = record
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save is a helper for tests to pre-populate data.
|
// Save is a helper for tests to pre-populate data.
|
||||||
func (s *cardPayoutStore) Save(state *model.CardPayout) {
|
func (s *cardPayoutStore) Save(state *model.CardPayout) {
|
||||||
s.data[state.PayoutID] = state
|
s.data[state.PaymentRef] = state
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get is a helper for tests to retrieve data.
|
// Get is a helper for tests to retrieve data.
|
||||||
|
|||||||
@@ -4,17 +4,22 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
"github.com/tech/sendico/gateway/mntx/internal/service/monetix"
|
"github.com/tech/sendico/gateway/mntx/internal/service/monetix"
|
||||||
"github.com/tech/sendico/gateway/mntx/storage"
|
"github.com/tech/sendico/gateway/mntx/storage"
|
||||||
"github.com/tech/sendico/gateway/mntx/storage/model"
|
"github.com/tech/sendico/gateway/mntx/storage/model"
|
||||||
clockpkg "github.com/tech/sendico/pkg/clock"
|
clockpkg "github.com/tech/sendico/pkg/clock"
|
||||||
|
"github.com/tech/sendico/pkg/db/storable"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
msg "github.com/tech/sendico/pkg/messaging"
|
msg "github.com/tech/sendico/pkg/messaging"
|
||||||
"github.com/tech/sendico/pkg/mlogger"
|
"github.com/tech/sendico/pkg/mlogger"
|
||||||
|
gatewayv1 "github.com/tech/sendico/pkg/proto/common/gateway/v1"
|
||||||
mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1"
|
mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,6 +30,80 @@ type cardPayoutProcessor struct {
|
|||||||
store storage.Repository
|
store storage.Repository
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
producer msg.Producer
|
producer msg.Producer
|
||||||
|
|
||||||
|
perTxMinAmountMinor int64
|
||||||
|
perTxMinAmountMinorByCurrency map[string]int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergePayoutStateWithExisting(state, existing *model.CardPayout) {
|
||||||
|
if state == nil || existing == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
state.ID = existing.ID // preserve ID for upsert
|
||||||
|
if !existing.CreatedAt.IsZero() {
|
||||||
|
state.CreatedAt = existing.CreatedAt
|
||||||
|
}
|
||||||
|
if state.OperationRef == "" {
|
||||||
|
state.OperationRef = existing.OperationRef
|
||||||
|
}
|
||||||
|
if state.IdempotencyKey == "" {
|
||||||
|
state.IdempotencyKey = existing.IdempotencyKey
|
||||||
|
}
|
||||||
|
if state.IntentRef == "" {
|
||||||
|
state.IntentRef = existing.IntentRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *cardPayoutProcessor) findAndMergePayoutState(ctx context.Context, state *model.CardPayout) (*model.CardPayout, error) {
|
||||||
|
if p == nil || state == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
existing, err := p.store.Payouts().FindByPaymentID(ctx, state.PaymentRef)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
mergePayoutStateWithExisting(state, existing)
|
||||||
|
return existing, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *cardPayoutProcessor) resolveProjectID(requestProjectID int64, logFieldKey, logFieldValue string) (int64, error) {
|
||||||
|
projectID := requestProjectID
|
||||||
|
if projectID == 0 {
|
||||||
|
projectID = p.config.ProjectID
|
||||||
|
}
|
||||||
|
if projectID == 0 {
|
||||||
|
p.logger.Warn("Monetix project_id is not configured", zap.String(logFieldKey, logFieldValue))
|
||||||
|
return 0, merrors.Internal("monetix project_id is not configured")
|
||||||
|
}
|
||||||
|
return projectID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyCardPayoutSendResult(state *model.CardPayout, result *monetix.CardPayoutSendResult) {
|
||||||
|
if state == nil || result == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.ProviderPaymentID = strings.TrimSpace(result.ProviderRequestID)
|
||||||
|
if result.Accepted {
|
||||||
|
state.Status = model.PayoutStatusWaiting
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.Status = model.PayoutStatusFailed
|
||||||
|
state.ProviderCode = strings.TrimSpace(result.ErrorCode)
|
||||||
|
state.ProviderMessage = strings.TrimSpace(result.ErrorMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func payoutStateLogFields(state *model.CardPayout) []zap.Field {
|
||||||
|
if state == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return []zap.Field{
|
||||||
|
zap.String("payment_ref", state.PaymentRef),
|
||||||
|
zap.String("customer_id", state.CustomerID),
|
||||||
|
zap.String("operation_ref", state.OperationRef),
|
||||||
|
zap.String("idempotency_key", state.IdempotencyKey),
|
||||||
|
zap.String("intent_ref", state.IntentRef),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCardPayoutProcessor(
|
func newCardPayoutProcessor(
|
||||||
@@ -45,6 +124,90 @@ func newCardPayoutProcessor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *cardPayoutProcessor) applyGatewayDescriptor(descriptor *gatewayv1.GatewayInstanceDescriptor) {
|
||||||
|
if p == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
minAmountMinor, perCurrency := perTxMinAmountPolicy(descriptor)
|
||||||
|
p.perTxMinAmountMinor = minAmountMinor
|
||||||
|
p.perTxMinAmountMinorByCurrency = perCurrency
|
||||||
|
}
|
||||||
|
|
||||||
|
func perTxMinAmountPolicy(descriptor *gatewayv1.GatewayInstanceDescriptor) (int64, map[string]int64) {
|
||||||
|
if descriptor == nil || descriptor.GetLimits() == nil {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
limits := descriptor.GetLimits()
|
||||||
|
globalMin, _ := decimalAmountToMinor(firstNonEmpty(limits.GetPerTxMinAmount(), limits.GetMinAmount()))
|
||||||
|
perCurrency := map[string]int64{}
|
||||||
|
for currency, override := range limits.GetCurrencyLimits() {
|
||||||
|
if override == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
minor, ok := decimalAmountToMinor(override.GetMinAmount())
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
code := strings.ToUpper(strings.TrimSpace(currency))
|
||||||
|
if code == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
perCurrency[code] = minor
|
||||||
|
}
|
||||||
|
if len(perCurrency) == 0 {
|
||||||
|
perCurrency = nil
|
||||||
|
}
|
||||||
|
return globalMin, perCurrency
|
||||||
|
}
|
||||||
|
|
||||||
|
func decimalAmountToMinor(raw string) (int64, bool) {
|
||||||
|
raw = strings.TrimSpace(raw)
|
||||||
|
if raw == "" {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
value, err := decimal.NewFromString(raw)
|
||||||
|
if err != nil || !value.IsPositive() {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
minor := value.Mul(decimal.NewFromInt(100)).Ceil().IntPart()
|
||||||
|
if minor <= 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return minor, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *cardPayoutProcessor) validatePerTxMinimum(amountMinor int64, currency string) error {
|
||||||
|
if p == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
minAmountMinor := p.perTxMinimum(currency)
|
||||||
|
if minAmountMinor <= 0 || amountMinor >= minAmountMinor {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return newPayoutError("amount_below_minimum", merrors.InvalidArgument(
|
||||||
|
fmt.Sprintf("amount_minor must be at least %d", minAmountMinor),
|
||||||
|
"amount_minor",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *cardPayoutProcessor) perTxMinimum(currency string) int64 {
|
||||||
|
if p == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
minAmountMinor := p.perTxMinAmountMinor
|
||||||
|
if len(p.perTxMinAmountMinorByCurrency) == 0 {
|
||||||
|
return minAmountMinor
|
||||||
|
}
|
||||||
|
code := strings.ToUpper(strings.TrimSpace(currency))
|
||||||
|
if code == "" {
|
||||||
|
return minAmountMinor
|
||||||
|
}
|
||||||
|
if override, ok := p.perTxMinAmountMinorByCurrency[code]; ok && override > 0 {
|
||||||
|
return override
|
||||||
|
}
|
||||||
|
return minAmountMinor
|
||||||
|
}
|
||||||
|
|
||||||
func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayoutRequest) (*mntxv1.CardPayoutResponse, error) {
|
func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayoutRequest) (*mntxv1.CardPayoutResponse, error) {
|
||||||
if p == nil {
|
if p == nil {
|
||||||
return nil, merrors.Internal("card payout processor not initialised")
|
return nil, merrors.Internal("card payout processor not initialised")
|
||||||
@@ -74,20 +237,30 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout
|
|||||||
)
|
)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := p.validatePerTxMinimum(req.GetAmountMinor(), req.GetCurrency()); err != nil {
|
||||||
projectID := req.GetProjectId()
|
p.logger.Warn("Card payout amount below configured minimum",
|
||||||
if projectID == 0 {
|
zap.String("payout_id", req.GetPayoutId()),
|
||||||
projectID = p.config.ProjectID
|
zap.String("customer_id", req.GetCustomerId()),
|
||||||
|
zap.Int64("amount_minor", req.GetAmountMinor()),
|
||||||
|
zap.String("currency", strings.ToUpper(strings.TrimSpace(req.GetCurrency()))),
|
||||||
|
zap.Int64("configured_min_amount_minor", p.perTxMinimum(req.GetCurrency())),
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
if projectID == 0 {
|
|
||||||
p.logger.Warn("Monetix project_id is not configured", zap.String("payout_id", req.GetPayoutId()))
|
projectID, err := p.resolveProjectID(req.GetProjectId(), "payout_id", req.GetPayoutId())
|
||||||
return nil, merrors.Internal("monetix project_id is not configured")
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
now := p.clock.Now()
|
now := p.clock.Now()
|
||||||
|
|
||||||
state := &model.CardPayout{
|
state := &model.CardPayout{
|
||||||
PayoutID: strings.TrimSpace(req.GetPayoutId()),
|
Base: storable.Base{
|
||||||
|
ID: bson.NilObjectID,
|
||||||
|
},
|
||||||
|
PaymentRef: strings.TrimSpace(req.GetPayoutId()),
|
||||||
OperationRef: strings.TrimSpace(req.GetOperationRef()),
|
OperationRef: strings.TrimSpace(req.GetOperationRef()),
|
||||||
IdempotencyKey: strings.TrimSpace(req.GetIdempotencyKey()),
|
IdempotencyKey: strings.TrimSpace(req.GetIdempotencyKey()),
|
||||||
IntentRef: strings.TrimSpace(req.GetIntentRef()),
|
IntentRef: strings.TrimSpace(req.GetIntentRef()),
|
||||||
@@ -101,17 +274,7 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Keep CreatedAt/refs if record already exists.
|
// Keep CreatedAt/refs if record already exists.
|
||||||
if existing, err := p.store.Payouts().FindByPaymentID(ctx, state.PayoutID); err == nil && existing != nil {
|
_, _ = p.findAndMergePayoutState(ctx, state)
|
||||||
if !existing.CreatedAt.IsZero() {
|
|
||||||
state.CreatedAt = existing.CreatedAt
|
|
||||||
}
|
|
||||||
if state.OperationRef == "" {
|
|
||||||
state.OperationRef = existing.OperationRef
|
|
||||||
}
|
|
||||||
if state.IdempotencyKey == "" {
|
|
||||||
state.IdempotencyKey = existing.IdempotencyKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client := monetix.NewClient(p.config, p.httpClient, p.logger)
|
client := monetix.NewClient(p.config, p.httpClient, p.logger)
|
||||||
apiReq := buildCardPayoutRequest(projectID, req)
|
apiReq := buildCardPayoutRequest(projectID, req)
|
||||||
@@ -123,41 +286,24 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout
|
|||||||
state.UpdatedAt = p.clock.Now()
|
state.UpdatedAt = p.clock.Now()
|
||||||
|
|
||||||
if e := p.updatePayoutStatus(ctx, state); e != nil {
|
if e := p.updatePayoutStatus(ctx, state); e != nil {
|
||||||
p.logger.Warn("Failed to update payout status",
|
fields := append([]zap.Field{zap.Error(e)}, payoutStateLogFields(state)...)
|
||||||
zap.Error(e),
|
p.logger.Warn("Failed to update payout status", fields...)
|
||||||
zap.String("payout_id", state.PayoutID),
|
|
||||||
zap.String("customer_id", state.CustomerID),
|
|
||||||
zap.String("operation_ref", state.OperationRef),
|
|
||||||
zap.String("idempotency_key", state.IdempotencyKey),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.logger.Warn("Monetix payout submission failed",
|
fields := append([]zap.Field{zap.Error(err)}, payoutStateLogFields(state)...)
|
||||||
zap.Error(err),
|
p.logger.Warn("Monetix payout submission failed", fields...)
|
||||||
zap.String("payout_id", state.PayoutID),
|
|
||||||
zap.String("customer_id", state.CustomerID),
|
|
||||||
zap.String("operation_ref", state.OperationRef),
|
|
||||||
zap.String("idempotency_key", state.IdempotencyKey),
|
|
||||||
)
|
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provider request id is the provider-side payment id in your model.
|
// Provider request id is the provider-side payment id in your model.
|
||||||
state.ProviderPaymentID = strings.TrimSpace(result.ProviderRequestID)
|
applyCardPayoutSendResult(state, result)
|
||||||
if result.Accepted {
|
|
||||||
state.Status = model.PayoutStatusWaiting
|
|
||||||
} else {
|
|
||||||
state.Status = model.PayoutStatusFailed
|
|
||||||
state.ProviderCode = strings.TrimSpace(result.ErrorCode)
|
|
||||||
state.ProviderMessage = strings.TrimSpace(result.ErrorMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
state.UpdatedAt = p.clock.Now()
|
state.UpdatedAt = p.clock.Now()
|
||||||
if err := p.updatePayoutStatus(ctx, state); err != nil {
|
if err := p.updatePayoutStatus(ctx, state); err != nil {
|
||||||
p.logger.Warn("Failed to store payout",
|
p.logger.Warn("Failed to store payout",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.String("payout_id", state.PayoutID),
|
zap.String("payment_ref", state.PaymentRef),
|
||||||
zap.String("customer_id", state.CustomerID),
|
zap.String("customer_id", state.CustomerID),
|
||||||
zap.String("operation_ref", state.OperationRef),
|
zap.String("operation_ref", state.OperationRef),
|
||||||
zap.String("idempotency_key", state.IdempotencyKey),
|
zap.String("idempotency_key", state.IdempotencyKey),
|
||||||
@@ -174,7 +320,7 @@ func (p *cardPayoutProcessor) Submit(ctx context.Context, req *mntxv1.CardPayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.logger.Info("Card payout submission stored",
|
p.logger.Info("Card payout submission stored",
|
||||||
zap.String("payout_id", state.PayoutID),
|
zap.String("payment_ref", state.PaymentRef),
|
||||||
zap.String("status", string(state.Status)),
|
zap.String("status", string(state.Status)),
|
||||||
zap.Bool("accepted", result.Accepted),
|
zap.Bool("accepted", result.Accepted),
|
||||||
zap.String("provider_request_id", result.ProviderRequestID),
|
zap.String("provider_request_id", result.ProviderRequestID),
|
||||||
@@ -212,19 +358,26 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT
|
|||||||
)
|
)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := p.validatePerTxMinimum(req.GetAmountMinor(), req.GetCurrency()); err != nil {
|
||||||
projectID := req.GetProjectId()
|
p.logger.Warn("Card token payout amount below configured minimum",
|
||||||
if projectID == 0 {
|
zap.String("payout_id", req.GetPayoutId()),
|
||||||
projectID = p.config.ProjectID
|
zap.String("customer_id", req.GetCustomerId()),
|
||||||
|
zap.Int64("amount_minor", req.GetAmountMinor()),
|
||||||
|
zap.String("currency", strings.ToUpper(strings.TrimSpace(req.GetCurrency()))),
|
||||||
|
zap.Int64("configured_min_amount_minor", p.perTxMinimum(req.GetCurrency())),
|
||||||
|
zap.Error(err),
|
||||||
|
)
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
if projectID == 0 {
|
|
||||||
p.logger.Warn("Monetix project_id is not configured", zap.String("payout_id", req.GetPayoutId()))
|
projectID, err := p.resolveProjectID(req.GetProjectId(), "payout_id", req.GetPayoutId())
|
||||||
return nil, merrors.Internal("monetix project_id is not configured")
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
now := p.clock.Now()
|
now := p.clock.Now()
|
||||||
state := &model.CardPayout{
|
state := &model.CardPayout{
|
||||||
PayoutID: strings.TrimSpace(req.GetPayoutId()),
|
PaymentRef: strings.TrimSpace(req.GetPayoutId()),
|
||||||
OperationRef: strings.TrimSpace(req.GetOperationRef()),
|
OperationRef: strings.TrimSpace(req.GetOperationRef()),
|
||||||
IdempotencyKey: strings.TrimSpace(req.GetIdempotencyKey()),
|
IdempotencyKey: strings.TrimSpace(req.GetIdempotencyKey()),
|
||||||
ProjectID: projectID,
|
ProjectID: projectID,
|
||||||
@@ -236,17 +389,7 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT
|
|||||||
UpdatedAt: now,
|
UpdatedAt: now,
|
||||||
}
|
}
|
||||||
|
|
||||||
if existing, err := p.store.Payouts().FindByPaymentID(ctx, state.PayoutID); err == nil && existing != nil {
|
_, _ = p.findAndMergePayoutState(ctx, state)
|
||||||
if !existing.CreatedAt.IsZero() {
|
|
||||||
state.CreatedAt = existing.CreatedAt
|
|
||||||
}
|
|
||||||
if state.OperationRef == "" {
|
|
||||||
state.OperationRef = existing.OperationRef
|
|
||||||
}
|
|
||||||
if state.IdempotencyKey == "" {
|
|
||||||
state.IdempotencyKey = existing.IdempotencyKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client := monetix.NewClient(p.config, p.httpClient, p.logger)
|
client := monetix.NewClient(p.config, p.httpClient, p.logger)
|
||||||
apiReq := buildCardTokenPayoutRequest(projectID, req)
|
apiReq := buildCardTokenPayoutRequest(projectID, req)
|
||||||
@@ -260,7 +403,7 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT
|
|||||||
_ = p.updatePayoutStatus(ctx, state)
|
_ = p.updatePayoutStatus(ctx, state)
|
||||||
|
|
||||||
p.logger.Warn("Monetix token payout submission failed",
|
p.logger.Warn("Monetix token payout submission failed",
|
||||||
zap.String("payout_id", state.PayoutID),
|
zap.String("payment_ref", state.PaymentRef),
|
||||||
zap.String("customer_id", state.CustomerID),
|
zap.String("customer_id", state.CustomerID),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
@@ -268,14 +411,7 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
state.ProviderPaymentID = strings.TrimSpace(result.ProviderRequestID)
|
applyCardPayoutSendResult(state, result)
|
||||||
if result.Accepted {
|
|
||||||
state.Status = model.PayoutStatusWaiting
|
|
||||||
} else {
|
|
||||||
state.Status = model.PayoutStatusFailed
|
|
||||||
state.ProviderCode = strings.TrimSpace(result.ErrorCode)
|
|
||||||
state.ProviderMessage = strings.TrimSpace(result.ErrorMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
state.UpdatedAt = p.clock.Now()
|
state.UpdatedAt = p.clock.Now()
|
||||||
if err := p.updatePayoutStatus(ctx, state); err != nil {
|
if err := p.updatePayoutStatus(ctx, state); err != nil {
|
||||||
@@ -292,7 +428,7 @@ func (p *cardPayoutProcessor) SubmitToken(ctx context.Context, req *mntxv1.CardT
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.logger.Info("Card token payout submission stored",
|
p.logger.Info("Card token payout submission stored",
|
||||||
zap.String("payout_id", state.PayoutID),
|
zap.String("payment_ref", state.PaymentRef),
|
||||||
zap.String("status", string(state.Status)),
|
zap.String("status", string(state.Status)),
|
||||||
zap.Bool("accepted", result.Accepted),
|
zap.Bool("accepted", result.Accepted),
|
||||||
zap.String("provider_request_id", result.ProviderRequestID),
|
zap.String("provider_request_id", result.ProviderRequestID),
|
||||||
@@ -321,13 +457,9 @@ func (p *cardPayoutProcessor) Tokenize(ctx context.Context, req *mntxv1.CardToke
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
projectID := req.GetProjectId()
|
projectID, err := p.resolveProjectID(req.GetProjectId(), "request_id", req.GetRequestId())
|
||||||
if projectID == 0 {
|
if err != nil {
|
||||||
projectID = p.config.ProjectID
|
return nil, err
|
||||||
}
|
|
||||||
if projectID == 0 {
|
|
||||||
p.logger.Warn("Monetix project_id is not configured", zap.String("request_id", req.GetRequestId()))
|
|
||||||
return nil, merrors.Internal("monetix project_id is not configured")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
req = sanitizeCardTokenizeRequest(req)
|
req = sanitizeCardTokenizeRequest(req)
|
||||||
@@ -387,7 +519,7 @@ func (p *cardPayoutProcessor) Status(ctx context.Context, payoutID string) (*mnt
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.logger.Info("Card payout status resolved",
|
p.logger.Info("Card payout status resolved",
|
||||||
zap.String("payout_id", state.PayoutID),
|
zap.String("payment_ref", state.PaymentRef),
|
||||||
zap.String("status", string(state.Status)),
|
zap.String("status", string(state.Status)),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -440,22 +572,15 @@ func (p *cardPayoutProcessor) ProcessCallback(ctx context.Context, payload []byt
|
|||||||
state := CardPayoutStateFromProto(p.clock, pbState)
|
state := CardPayoutStateFromProto(p.clock, pbState)
|
||||||
|
|
||||||
// Preserve CreatedAt + internal keys from existing record if present.
|
// Preserve CreatedAt + internal keys from existing record if present.
|
||||||
if existing, err := p.store.Payouts().FindByPaymentID(ctx, state.PayoutID); err != nil {
|
existing, err := p.findAndMergePayoutState(ctx, state)
|
||||||
|
if err != nil {
|
||||||
p.logger.Warn("Failed to fetch payout state while processing callback",
|
p.logger.Warn("Failed to fetch payout state while processing callback",
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
zap.String("payout_id", state.PayoutID),
|
zap.String("payment_ref", state.PaymentRef),
|
||||||
)
|
)
|
||||||
return http.StatusInternalServerError, err
|
return http.StatusInternalServerError, err
|
||||||
} else if existing != nil {
|
}
|
||||||
if !existing.CreatedAt.IsZero() {
|
if existing != nil {
|
||||||
state.CreatedAt = existing.CreatedAt
|
|
||||||
}
|
|
||||||
if state.OperationRef == "" {
|
|
||||||
state.OperationRef = existing.OperationRef
|
|
||||||
}
|
|
||||||
if state.IdempotencyKey == "" {
|
|
||||||
state.IdempotencyKey = existing.IdempotencyKey
|
|
||||||
}
|
|
||||||
// keep failure reason if you want, or override depending on callback semantics
|
// keep failure reason if you want, or override depending on callback semantics
|
||||||
if state.FailureReason == "" {
|
if state.FailureReason == "" {
|
||||||
state.FailureReason = existing.FailureReason
|
state.FailureReason = existing.FailureReason
|
||||||
@@ -468,7 +593,7 @@ func (p *cardPayoutProcessor) ProcessCallback(ctx context.Context, payload []byt
|
|||||||
monetix.ObserveCallback(statusLabel)
|
monetix.ObserveCallback(statusLabel)
|
||||||
|
|
||||||
p.logger.Info("Monetix payout callback processed",
|
p.logger.Info("Monetix payout callback processed",
|
||||||
zap.String("payout_id", state.PayoutID),
|
zap.String("payment_ref", state.PaymentRef),
|
||||||
zap.String("status", statusLabel),
|
zap.String("status", statusLabel),
|
||||||
zap.String("provider_code", state.ProviderCode),
|
zap.String("provider_code", state.ProviderCode),
|
||||||
zap.String("provider_message", state.ProviderMessage),
|
zap.String("provider_message", state.ProviderMessage),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/tech/sendico/gateway/mntx/storage/model"
|
"github.com/tech/sendico/gateway/mntx/storage/model"
|
||||||
clockpkg "github.com/tech/sendico/pkg/clock"
|
clockpkg "github.com/tech/sendico/pkg/clock"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
|
gatewayv1 "github.com/tech/sendico/pkg/proto/common/gateway/v1"
|
||||||
mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1"
|
mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@@ -44,8 +45,8 @@ func TestCardPayoutProcessor_Submit_Success(t *testing.T) {
|
|||||||
|
|
||||||
repo := newMockRepository()
|
repo := newMockRepository()
|
||||||
repo.payouts.Save(&model.CardPayout{
|
repo.payouts.Save(&model.CardPayout{
|
||||||
PayoutID: "payout-1",
|
PaymentRef: "payout-1",
|
||||||
CreatedAt: existingCreated,
|
CreatedAt: existingCreated,
|
||||||
})
|
})
|
||||||
|
|
||||||
httpClient := &http.Client{
|
httpClient := &http.Client{
|
||||||
@@ -119,6 +120,63 @@ func TestCardPayoutProcessor_Submit_MissingConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCardPayoutProcessor_Submit_RejectsAmountBelowConfiguredMinimum(t *testing.T) {
|
||||||
|
cfg := monetix.Config{
|
||||||
|
BaseURL: "https://monetix.test",
|
||||||
|
SecretKey: "secret",
|
||||||
|
AllowedCurrencies: []string{"RUB"},
|
||||||
|
}
|
||||||
|
|
||||||
|
repo := newMockRepository()
|
||||||
|
processor := newCardPayoutProcessor(
|
||||||
|
zap.NewNop(),
|
||||||
|
cfg,
|
||||||
|
staticClock{now: time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)},
|
||||||
|
repo,
|
||||||
|
&http.Client{},
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
processor.applyGatewayDescriptor(&gatewayv1.GatewayInstanceDescriptor{
|
||||||
|
Limits: &gatewayv1.Limits{
|
||||||
|
PerTxMinAmount: "20.00",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
req := validCardPayoutRequest() // 15.00 RUB
|
||||||
|
_, err := processor.Submit(context.Background(), req)
|
||||||
|
requireReason(t, err, "amount_below_minimum")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCardPayoutProcessor_SubmitToken_RejectsAmountBelowCurrencyMinimum(t *testing.T) {
|
||||||
|
cfg := monetix.Config{
|
||||||
|
BaseURL: "https://monetix.test",
|
||||||
|
SecretKey: "secret",
|
||||||
|
AllowedCurrencies: []string{"USD"},
|
||||||
|
}
|
||||||
|
|
||||||
|
repo := newMockRepository()
|
||||||
|
processor := newCardPayoutProcessor(
|
||||||
|
zap.NewNop(),
|
||||||
|
cfg,
|
||||||
|
staticClock{now: time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)},
|
||||||
|
repo,
|
||||||
|
&http.Client{},
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
processor.applyGatewayDescriptor(&gatewayv1.GatewayInstanceDescriptor{
|
||||||
|
Limits: &gatewayv1.Limits{
|
||||||
|
PerTxMinAmount: "20.00",
|
||||||
|
CurrencyLimits: map[string]*gatewayv1.LimitsOverride{
|
||||||
|
"USD": {MinAmount: "30.00"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
req := validCardTokenPayoutRequest() // 25.00 USD
|
||||||
|
_, err := processor.SubmitToken(context.Background(), req)
|
||||||
|
requireReason(t, err, "amount_below_minimum")
|
||||||
|
}
|
||||||
|
|
||||||
func TestCardPayoutProcessor_ProcessCallback(t *testing.T) {
|
func TestCardPayoutProcessor_ProcessCallback(t *testing.T) {
|
||||||
cfg := monetix.Config{
|
cfg := monetix.Config{
|
||||||
SecretKey: "secret",
|
SecretKey: "secret",
|
||||||
|
|||||||
@@ -49,9 +49,18 @@ func (s *Service) SubmitOperation(ctx context.Context, req *connectorv1.SubmitOp
|
|||||||
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(connectorv1.ErrorCode_INVALID_PARAMS, "submit_operation: operation is required", nil, "")}}, nil
|
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(connectorv1.ErrorCode_INVALID_PARAMS, "submit_operation: operation is required", nil, "")}}, nil
|
||||||
}
|
}
|
||||||
op := req.GetOperation()
|
op := req.GetOperation()
|
||||||
if strings.TrimSpace(op.GetIdempotencyKey()) == "" {
|
idempotencyKey := strings.TrimSpace(op.GetIdempotencyKey())
|
||||||
|
if idempotencyKey == "" {
|
||||||
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(connectorv1.ErrorCode_INVALID_PARAMS, "submit_operation: idempotency_key is required", op, "")}}, nil
|
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(connectorv1.ErrorCode_INVALID_PARAMS, "submit_operation: idempotency_key is required", op, "")}}, nil
|
||||||
}
|
}
|
||||||
|
operationRef := strings.TrimSpace(op.GetOperationRef())
|
||||||
|
if operationRef == "" {
|
||||||
|
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(connectorv1.ErrorCode_INVALID_PARAMS, "submit_operation: operation_ref is required", op, "")}}, nil
|
||||||
|
}
|
||||||
|
intentRef := strings.TrimSpace(op.GetIntentRef())
|
||||||
|
if intentRef == "" {
|
||||||
|
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(connectorv1.ErrorCode_INVALID_PARAMS, "submit_operation: intent_ref is required", op, "")}}, nil
|
||||||
|
}
|
||||||
if op.GetType() != connectorv1.OperationType_PAYOUT {
|
if op.GetType() != connectorv1.OperationType_PAYOUT {
|
||||||
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(connectorv1.ErrorCode_UNSUPPORTED_OPERATION, "submit_operation: unsupported operation type", op, "")}}, nil
|
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(connectorv1.ErrorCode_UNSUPPORTED_OPERATION, "submit_operation: unsupported operation type", op, "")}}, nil
|
||||||
}
|
}
|
||||||
@@ -73,7 +82,8 @@ func (s *Service) SubmitOperation(ctx context.Context, req *connectorv1.SubmitOp
|
|||||||
}
|
}
|
||||||
return &connectorv1.SubmitOperationResponse{Receipt: payoutReceipt(resp.GetPayout())}, nil
|
return &connectorv1.SubmitOperationResponse{Receipt: payoutReceipt(resp.GetPayout())}, nil
|
||||||
}
|
}
|
||||||
resp, err := s.CreateCardPayout(ctx, buildCardPayoutRequestFromParams(reader, payoutID, amountMinor, currency))
|
cr := buildCardPayoutRequestFromParams(reader, payoutID, idempotencyKey, operationRef, intentRef, amountMinor, currency)
|
||||||
|
resp, err := s.CreateCardPayout(ctx, cr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(mapErrorCode(err), err.Error(), op, "")}}, nil
|
return &connectorv1.SubmitOperationResponse{Receipt: &connectorv1.OperationReceipt{Error: connectorError(mapErrorCode(err), err.Error(), op, "")}}, nil
|
||||||
}
|
}
|
||||||
@@ -183,7 +193,9 @@ func buildCardTokenPayoutRequestFromParams(reader params.Reader, payoutID string
|
|||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildCardPayoutRequestFromParams(reader params.Reader, payoutID string, amountMinor int64, currency string) *mntxv1.CardPayoutRequest {
|
func buildCardPayoutRequestFromParams(reader params.Reader,
|
||||||
|
payoutID, idempotencyKey, operationRef, intentRef string,
|
||||||
|
amountMinor int64, currency string) *mntxv1.CardPayoutRequest {
|
||||||
return &mntxv1.CardPayoutRequest{
|
return &mntxv1.CardPayoutRequest{
|
||||||
PayoutId: payoutID,
|
PayoutId: payoutID,
|
||||||
ProjectId: readerInt64(reader, "project_id"),
|
ProjectId: readerInt64(reader, "project_id"),
|
||||||
@@ -204,6 +216,9 @@ func buildCardPayoutRequestFromParams(reader params.Reader, payoutID string, amo
|
|||||||
CardExpMonth: uint32(readerInt64(reader, "card_exp_month")),
|
CardExpMonth: uint32(readerInt64(reader, "card_exp_month")),
|
||||||
CardHolder: strings.TrimSpace(reader.String("card_holder")),
|
CardHolder: strings.TrimSpace(reader.String("card_holder")),
|
||||||
Metadata: reader.StringMap("metadata"),
|
Metadata: reader.StringMap("metadata"),
|
||||||
|
OperationRef: operationRef,
|
||||||
|
IdempotencyKey: idempotencyKey,
|
||||||
|
IntentRef: intentRef,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func CardPayoutStateFromProto(clock clockpkg.Clock, p *mntxv1.CardPayoutState) *
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &model.CardPayout{
|
return &model.CardPayout{
|
||||||
PayoutID: p.PayoutId,
|
PaymentRef: p.PayoutId,
|
||||||
OperationRef: p.GetOperationRef(),
|
OperationRef: p.GetOperationRef(),
|
||||||
IntentRef: p.GetIntentRef(),
|
IntentRef: p.GetIntentRef(),
|
||||||
IdempotencyKey: p.GetIdempotencyKey(),
|
IdempotencyKey: p.GetIdempotencyKey(),
|
||||||
@@ -41,7 +41,7 @@ func CardPayoutStateFromProto(clock clockpkg.Clock, p *mntxv1.CardPayoutState) *
|
|||||||
|
|
||||||
func StateToProto(m *model.CardPayout) *mntxv1.CardPayoutState {
|
func StateToProto(m *model.CardPayout) *mntxv1.CardPayoutState {
|
||||||
return &mntxv1.CardPayoutState{
|
return &mntxv1.CardPayoutState{
|
||||||
PayoutId: m.PayoutID,
|
PayoutId: m.PaymentRef,
|
||||||
ProjectId: m.ProjectID,
|
ProjectId: m.ProjectID,
|
||||||
CustomerId: m.CustomerID,
|
CustomerId: m.CustomerID,
|
||||||
AmountMinor: m.AmountMinor,
|
AmountMinor: m.AmountMinor,
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ func NewService(logger mlogger.Logger, opts ...Option) *Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
svc.card = newCardPayoutProcessor(svc.logger, svc.config, svc.clock, svc.storage, svc.httpClient, svc.producer)
|
svc.card = newCardPayoutProcessor(svc.logger, svc.config, svc.clock, svc.storage, svc.httpClient, svc.producer)
|
||||||
|
svc.card.applyGatewayDescriptor(svc.gatewayDescriptor)
|
||||||
svc.startDiscoveryAnnouncer()
|
svc.startDiscoveryAnnouncer()
|
||||||
|
|
||||||
return svc
|
return svc
|
||||||
@@ -149,44 +150,132 @@ func (s *Service) startDiscoveryAnnouncer() {
|
|||||||
if id := strings.TrimSpace(s.gatewayDescriptor.GetId()); id != "" {
|
if id := strings.TrimSpace(s.gatewayDescriptor.GetId()); id != "" {
|
||||||
announce.ID = id
|
announce.ID = id
|
||||||
}
|
}
|
||||||
announce.Network = strings.TrimSpace(s.gatewayDescriptor.GetNetwork())
|
announce.Currencies = currenciesFromDescriptor(s.gatewayDescriptor)
|
||||||
announce.Currencies = append([]string(nil), s.gatewayDescriptor.GetCurrencies()...)
|
|
||||||
announce.Limits = limitsFromDescriptor(s.gatewayDescriptor.GetLimits())
|
|
||||||
}
|
}
|
||||||
s.announcer = discovery.NewAnnouncer(s.logger, s.producer, string(mservice.MntxGateway), announce)
|
s.announcer = discovery.NewAnnouncer(s.logger, s.producer, string(mservice.MntxGateway), announce)
|
||||||
s.announcer.Start()
|
s.announcer.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func limitsFromDescriptor(src *gatewayv1.Limits) *discovery.Limits {
|
func currenciesFromDescriptor(src *gatewayv1.GatewayInstanceDescriptor) []discovery.CurrencyAnnouncement {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
limits := &discovery.Limits{
|
network := strings.TrimSpace(src.GetNetwork())
|
||||||
MinAmount: strings.TrimSpace(src.GetMinAmount()),
|
limitsCfg := src.GetLimits()
|
||||||
MaxAmount: strings.TrimSpace(src.GetMaxAmount()),
|
values := src.GetCurrencies()
|
||||||
VolumeLimit: map[string]string{},
|
if len(values) == 0 {
|
||||||
VelocityLimit: map[string]int{},
|
return nil
|
||||||
}
|
}
|
||||||
for key, value := range src.GetVolumeLimit() {
|
seen := map[string]bool{}
|
||||||
k := strings.TrimSpace(key)
|
result := make([]discovery.CurrencyAnnouncement, 0, len(values))
|
||||||
v := strings.TrimSpace(value)
|
for _, value := range values {
|
||||||
if k == "" || v == "" {
|
currency := strings.ToUpper(strings.TrimSpace(value))
|
||||||
|
if currency == "" || seen[currency] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
limits.VolumeLimit[k] = v
|
seen[currency] = true
|
||||||
|
result = append(result, discovery.CurrencyAnnouncement{
|
||||||
|
Currency: currency,
|
||||||
|
Network: network,
|
||||||
|
Limits: currencyLimitsFromDescriptor(limitsCfg, currency),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
for key, value := range src.GetVelocityLimit() {
|
if len(result) == 0 {
|
||||||
k := strings.TrimSpace(key)
|
return nil
|
||||||
if k == "" {
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func currencyLimitsFromDescriptor(src *gatewayv1.Limits, currency string) *discovery.CurrencyLimits {
|
||||||
|
if src == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
amountMin := firstNonEmpty(src.GetPerTxMinAmount(), src.GetMinAmount())
|
||||||
|
amountMax := firstNonEmpty(src.GetPerTxMaxAmount(), src.GetMaxAmount())
|
||||||
|
|
||||||
|
limits := &discovery.CurrencyLimits{}
|
||||||
|
if amountMin != "" || amountMax != "" {
|
||||||
|
limits.Amount = &discovery.CurrencyAmount{
|
||||||
|
Min: amountMin,
|
||||||
|
Max: amountMax,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
running := &discovery.CurrencyRunningLimits{}
|
||||||
|
for bucket, max := range src.GetVolumeLimit() {
|
||||||
|
bucket = strings.TrimSpace(bucket)
|
||||||
|
max = strings.TrimSpace(max)
|
||||||
|
if bucket == "" || max == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
limits.VelocityLimit[k] = int(value)
|
running.Volume = append(running.Volume, discovery.VolumeLimit{
|
||||||
|
Window: discovery.Window{
|
||||||
|
Raw: bucket,
|
||||||
|
Named: bucket,
|
||||||
|
},
|
||||||
|
Max: max,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if len(limits.VolumeLimit) == 0 {
|
for bucket, max := range src.GetVelocityLimit() {
|
||||||
limits.VolumeLimit = nil
|
bucket = strings.TrimSpace(bucket)
|
||||||
|
if bucket == "" || max <= 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
running.Velocity = append(running.Velocity, discovery.VelocityLimit{
|
||||||
|
Window: discovery.Window{
|
||||||
|
Raw: bucket,
|
||||||
|
Named: bucket,
|
||||||
|
},
|
||||||
|
Max: int(max),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
if len(limits.VelocityLimit) == 0 {
|
if override := src.GetCurrencyLimits()[strings.ToUpper(strings.TrimSpace(currency))]; override != nil {
|
||||||
limits.VelocityLimit = nil
|
if min := strings.TrimSpace(override.GetMinAmount()); min != "" {
|
||||||
|
if limits.Amount == nil {
|
||||||
|
limits.Amount = &discovery.CurrencyAmount{}
|
||||||
|
}
|
||||||
|
limits.Amount.Min = min
|
||||||
|
}
|
||||||
|
if max := strings.TrimSpace(override.GetMaxAmount()); max != "" {
|
||||||
|
if limits.Amount == nil {
|
||||||
|
limits.Amount = &discovery.CurrencyAmount{}
|
||||||
|
}
|
||||||
|
limits.Amount.Max = max
|
||||||
|
}
|
||||||
|
if maxVolume := strings.TrimSpace(override.GetMaxVolume()); maxVolume != "" {
|
||||||
|
running.Volume = append(running.Volume, discovery.VolumeLimit{
|
||||||
|
Window: discovery.Window{
|
||||||
|
Raw: "default",
|
||||||
|
Named: "default",
|
||||||
|
},
|
||||||
|
Max: maxVolume,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if maxOps := int(override.GetMaxOps()); maxOps > 0 {
|
||||||
|
running.Velocity = append(running.Velocity, discovery.VelocityLimit{
|
||||||
|
Window: discovery.Window{
|
||||||
|
Raw: "default",
|
||||||
|
Named: "default",
|
||||||
|
},
|
||||||
|
Max: maxOps,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(running.Volume) > 0 || len(running.Velocity) > 0 {
|
||||||
|
limits.Running = running
|
||||||
|
}
|
||||||
|
if limits.Amount == nil && limits.Running == nil {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return limits
|
return limits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func firstNonEmpty(values ...string) string {
|
||||||
|
for _, value := range values {
|
||||||
|
clean := strings.TrimSpace(value)
|
||||||
|
if clean != "" {
|
||||||
|
return clean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/tech/sendico/gateway/mntx/storage/model"
|
"github.com/tech/sendico/gateway/mntx/storage/model"
|
||||||
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
paymentgateway "github.com/tech/sendico/pkg/messaging/notifications/paymentgateway"
|
paymentgateway "github.com/tech/sendico/pkg/messaging/notifications/paymentgateway"
|
||||||
pmodel "github.com/tech/sendico/pkg/model"
|
pmodel "github.com/tech/sendico/pkg/model"
|
||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
"github.com/tech/sendico/pkg/mutil/mzap"
|
"github.com/tech/sendico/pkg/mutil/mzap"
|
||||||
"github.com/tech/sendico/pkg/payments/rail"
|
"github.com/tech/sendico/pkg/payments/rail"
|
||||||
paytypes "github.com/tech/sendico/pkg/payments/types"
|
paytypes "github.com/tech/sendico/pkg/payments/types"
|
||||||
gatewayv1 "github.com/tech/sendico/pkg/proto/common/gateway/v1"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,31 +24,24 @@ func isFinalStatus(t *model.CardPayout) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toOpStatus(t *model.CardPayout) rail.OperationResult {
|
func toOpStatus(t *model.CardPayout) (rail.OperationResult, error) {
|
||||||
switch t.Status {
|
switch t.Status {
|
||||||
case model.PayoutStatusFailed:
|
case model.PayoutStatusFailed:
|
||||||
return rail.OperationResultFailed
|
return rail.OperationResultFailed, nil
|
||||||
case model.PayoutStatusSuccess:
|
case model.PayoutStatusSuccess:
|
||||||
return rail.OperationResultSuccess
|
return rail.OperationResultSuccess, nil
|
||||||
case model.PayoutStatusCancelled:
|
case model.PayoutStatusCancelled:
|
||||||
return rail.OperationResultCancelled
|
return rail.OperationResultCancelled, nil
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unexpected transfer status, %s", t.Status))
|
return rail.OperationResultFailed, merrors.InvalidArgument(fmt.Sprintf("unexpected transfer status, %s", t.Status), "t.Status")
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func toError(t *model.CardPayout) *gatewayv1.OperationError {
|
|
||||||
if t.Status == model.PayoutStatusSuccess {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &gatewayv1.OperationError{
|
|
||||||
Message: t.FailureReason,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *cardPayoutProcessor) updatePayoutStatus(ctx context.Context, state *model.CardPayout) error {
|
func (p *cardPayoutProcessor) updatePayoutStatus(ctx context.Context, state *model.CardPayout) error {
|
||||||
if err := p.store.Payouts().Upsert(ctx, state); err != nil {
|
if err := p.store.Payouts().Upsert(ctx, state); err != nil {
|
||||||
p.logger.Warn("Failed to update transfer status", zap.String("transfer_ref", state.PayoutID), zap.String("status", string(state.Status)), zap.Error(err))
|
p.logger.Warn("Failed to update transfer status", zap.Error(err), mzap.ObjRef("payout_ref", state.ID),
|
||||||
|
zap.String("payment_ref", state.PaymentRef), zap.String("status", string(state.Status)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if isFinalStatus(state) {
|
if isFinalStatus(state) {
|
||||||
p.emitTransferStatusEvent(state)
|
p.emitTransferStatusEvent(state)
|
||||||
@@ -61,6 +54,13 @@ func (p *cardPayoutProcessor) emitTransferStatusEvent(payout *model.CardPayout)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status, err := toOpStatus(payout)
|
||||||
|
if err != nil {
|
||||||
|
p.logger.Warn("Failed to convert payout status to operation status for transfer status event", zap.Error(err),
|
||||||
|
mzap.ObjRef("payout_ref", payout.ID), zap.String("payment_ref", payout.PaymentRef), zap.String("status", string(payout.Status)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
exec := pmodel.PaymentGatewayExecution{
|
exec := pmodel.PaymentGatewayExecution{
|
||||||
PaymentIntentID: payout.IntentRef,
|
PaymentIntentID: payout.IntentRef,
|
||||||
IdempotencyKey: payout.IdempotencyKey,
|
IdempotencyKey: payout.IdempotencyKey,
|
||||||
@@ -69,7 +69,7 @@ func (p *cardPayoutProcessor) emitTransferStatusEvent(payout *model.CardPayout)
|
|||||||
Currency: payout.Currency,
|
Currency: payout.Currency,
|
||||||
},
|
},
|
||||||
PaymentRef: payout.PaymentRef,
|
PaymentRef: payout.PaymentRef,
|
||||||
Status: toOpStatus(payout),
|
Status: status,
|
||||||
OperationRef: payout.OperationRef,
|
OperationRef: payout.OperationRef,
|
||||||
Error: payout.FailureReason,
|
Error: payout.FailureReason,
|
||||||
TransferRef: payout.GetID().Hex(),
|
TransferRef: payout.GetID().Hex(),
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
// CardPayout is a Mongo/JSON representation of proto CardPayout
|
// CardPayout is a Mongo/JSON representation of proto CardPayout
|
||||||
type CardPayout struct {
|
type CardPayout struct {
|
||||||
storable.Base `bson:",inline" json:",inline"`
|
storable.Base `bson:",inline" json:",inline"`
|
||||||
PayoutID string `bson:"payoutId" json:"payout_id"`
|
|
||||||
PaymentRef string `bson:"paymentRef" json:"payment_ref"`
|
PaymentRef string `bson:"paymentRef" json:"payment_ref"`
|
||||||
OperationRef string `bson:"operationRef" json:"operation_ref"`
|
OperationRef string `bson:"operationRef" json:"operation_ref"`
|
||||||
IdempotencyKey string `bson:"idempotencyKey" json:"idempotency_key"`
|
IdempotencyKey string `bson:"idempotencyKey" json:"idempotency_key"`
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ package store
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
storage "github.com/tech/sendico/gateway/mntx/storage"
|
storage "github.com/tech/sendico/gateway/mntx/storage"
|
||||||
"github.com/tech/sendico/gateway/mntx/storage/model"
|
"github.com/tech/sendico/gateway/mntx/storage/model"
|
||||||
@@ -12,21 +10,20 @@ import (
|
|||||||
ri "github.com/tech/sendico/pkg/db/repository/index"
|
ri "github.com/tech/sendico/pkg/db/repository/index"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
"github.com/tech/sendico/pkg/mlogger"
|
"github.com/tech/sendico/pkg/mlogger"
|
||||||
"go.mongodb.org/mongo-driver/v2/bson"
|
"github.com/tech/sendico/pkg/mutil/mzap"
|
||||||
"go.mongodb.org/mongo-driver/v2/mongo"
|
"go.mongodb.org/mongo-driver/v2/mongo"
|
||||||
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
payoutsCollection = "card_payouts"
|
payoutsCollection = "card_payouts"
|
||||||
payoutIdemField = "idempotencyKey"
|
payoutIdemField = "idempotencyKey"
|
||||||
payoutIdField = "payoutId"
|
payoutIdField = "paymentRef"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Payouts struct {
|
type Payouts struct {
|
||||||
logger mlogger.Logger
|
logger mlogger.Logger
|
||||||
coll *mongo.Collection
|
repository repository.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPayouts(logger mlogger.Logger, db *mongo.Database) (*Payouts, error) {
|
func NewPayouts(logger mlogger.Logger, db *mongo.Database) (*Payouts, error) {
|
||||||
@@ -50,38 +47,20 @@ func NewPayouts(logger mlogger.Logger, db *mongo.Database) (*Payouts, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p := &Payouts{
|
p := &Payouts{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
coll: db.Collection(payoutsCollection),
|
repository: repo,
|
||||||
}
|
}
|
||||||
p.logger.Debug("Payouts store initialised")
|
p.logger.Debug("Payouts store initialised")
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Payouts) findOneByField(ctx context.Context, field, value string) (*model.CardPayout, error) {
|
func (p *Payouts) findOneByField(ctx context.Context, field, value string) (*model.CardPayout, error) {
|
||||||
value = strings.TrimSpace(value)
|
var res model.CardPayout
|
||||||
if value == "" {
|
return &res, p.repository.FindOneByFilter(ctx, repository.Filter(field, value), &res)
|
||||||
return nil, merrors.InvalidArgument("lookup key is required", field)
|
|
||||||
}
|
|
||||||
|
|
||||||
var result model.CardPayout
|
|
||||||
err := p.coll.FindOne(ctx, bson.M{field: value}).Decode(&result)
|
|
||||||
if err == mongo.ErrNoDocuments {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
if !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) {
|
|
||||||
p.logger.Warn("Payout record lookup failed",
|
|
||||||
zap.String("field", field),
|
|
||||||
zap.String("value", value),
|
|
||||||
zap.Error(err))
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &result, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Payouts) FindByIdempotencyKey(ctx context.Context, key string) (*model.CardPayout, error) {
|
func (p *Payouts) FindByIdempotencyKey(ctx context.Context, key string) (*model.CardPayout, error) {
|
||||||
return p.findOneByField(ctx, payoutIdemField, key) // operationRef
|
return p.findOneByField(ctx, payoutIdemField, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Payouts) FindByPaymentID(ctx context.Context, paymentID string) (*model.CardPayout, error) {
|
func (p *Payouts) FindByPaymentID(ctx context.Context, paymentID string) (*model.CardPayout, error) {
|
||||||
@@ -90,45 +69,24 @@ func (p *Payouts) FindByPaymentID(ctx context.Context, paymentID string) (*model
|
|||||||
|
|
||||||
func (p *Payouts) Upsert(ctx context.Context, record *model.CardPayout) error {
|
func (p *Payouts) Upsert(ctx context.Context, record *model.CardPayout) error {
|
||||||
if record == nil {
|
if record == nil {
|
||||||
|
p.logger.Warn("Invalid argument provided: nil record")
|
||||||
return merrors.InvalidArgument("payout record is nil", "record")
|
return merrors.InvalidArgument("payout record is nil", "record")
|
||||||
}
|
}
|
||||||
|
|
||||||
record.OperationRef = strings.TrimSpace(record.OperationRef)
|
record.OperationRef = strings.TrimSpace(record.OperationRef)
|
||||||
record.PayoutID = strings.TrimSpace(record.PayoutID)
|
record.PaymentRef = strings.TrimSpace(record.PaymentRef)
|
||||||
record.CustomerID = strings.TrimSpace(record.CustomerID)
|
record.CustomerID = strings.TrimSpace(record.CustomerID)
|
||||||
record.ProviderCode = strings.TrimSpace(record.ProviderCode)
|
record.ProviderCode = strings.TrimSpace(record.ProviderCode)
|
||||||
record.ProviderPaymentID = strings.TrimSpace(record.ProviderPaymentID)
|
record.ProviderPaymentID = strings.TrimSpace(record.ProviderPaymentID)
|
||||||
|
|
||||||
if record.OperationRef == "" {
|
if record.OperationRef == "" {
|
||||||
|
p.logger.Warn("Invalid argument provided: operation reference missing")
|
||||||
return merrors.InvalidArgument("operation ref is required", "operation_ref")
|
return merrors.InvalidArgument("operation ref is required", "operation_ref")
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
if err := p.repository.Upsert(ctx, record); err != nil {
|
||||||
if record.CreatedAt.IsZero() {
|
p.logger.Warn("Failed to upsert payout record", zap.Error(err), mzap.ObjRef("payout_ref", record.ID),
|
||||||
record.CreatedAt = now
|
zap.String("operation_ref", record.OperationRef), zap.String("payment_ref", record.PaymentRef))
|
||||||
}
|
|
||||||
record.UpdatedAt = now
|
|
||||||
|
|
||||||
// critical: never let caller override _id
|
|
||||||
record.ID = bson.NilObjectID
|
|
||||||
|
|
||||||
update := bson.M{
|
|
||||||
"$set": record,
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := p.coll.UpdateOne(
|
|
||||||
ctx,
|
|
||||||
bson.M{payoutIdemField: record.OperationRef},
|
|
||||||
update,
|
|
||||||
options.UpdateOne().SetUpsert(true),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
if !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) {
|
|
||||||
p.logger.Warn("Failed to upsert payout record",
|
|
||||||
zap.String("operation_ref", record.OperationRef),
|
|
||||||
zap.String("payout_id", record.PayoutID),
|
|
||||||
zap.Error(err))
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/tech/sendico/gateway/tgsettle
|
module github.com/tech/sendico/gateway/tgsettle
|
||||||
|
|
||||||
go 1.25.6
|
go 1.25.7
|
||||||
|
|
||||||
replace github.com/tech/sendico/pkg => ../../pkg
|
replace github.com/tech/sendico/pkg => ../../pkg
|
||||||
|
|
||||||
@@ -20,9 +20,9 @@ require (
|
|||||||
github.com/casbin/govaluate v1.10.0 // indirect
|
github.com/casbin/govaluate v1.10.0 // indirect
|
||||||
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/go-chi/chi/v5 v5.2.4 // indirect
|
github.com/go-chi/chi/v5 v5.2.5 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/klauspost/compress v1.18.3 // indirect
|
github.com/klauspost/compress v1.18.4 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
@@ -40,10 +40,10 @@ require (
|
|||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/crypto v0.47.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/net v0.49.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
|
|||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
|
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||||
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
@@ -57,8 +57,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@@ -172,15 +172,15 @@ go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
|||||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
@@ -191,16 +191,16 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
@@ -208,8 +208,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b h1:GZxXGdFaHX27ZSMHudWc4FokdD+xl8BC2UJm1OVIEzs=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
|||||||
@@ -253,6 +253,10 @@ func (s *Service) onIntent(ctx context.Context, intent *model.PaymentGatewayInte
|
|||||||
s.logger.Warn("Payment gateway intent rejected", zap.String("reason", "requested_money is required"), zap.String("idempotency_key", intent.IdempotencyKey))
|
s.logger.Warn("Payment gateway intent rejected", zap.String("reason", "requested_money is required"), zap.String("idempotency_key", intent.IdempotencyKey))
|
||||||
return merrors.InvalidArgument("requested_money is required", "requested_money")
|
return merrors.InvalidArgument("requested_money is required", "requested_money")
|
||||||
}
|
}
|
||||||
|
if intent.OperationRef == "" {
|
||||||
|
s.logger.Warn("Payment gateway intent rejected", zap.String("reason", "operation_ref is required"))
|
||||||
|
return merrors.InvalidArgument("operation_ref is required", "operation_ref")
|
||||||
|
}
|
||||||
if s.repo == nil || s.repo.Payments() == nil {
|
if s.repo == nil || s.repo.Payments() == nil {
|
||||||
s.logger.Warn("Payment gateway storage unavailable", zap.String("idempotency_key", intent.IdempotencyKey))
|
s.logger.Warn("Payment gateway storage unavailable", zap.String("idempotency_key", intent.IdempotencyKey))
|
||||||
return merrors.Internal("payment gateway storage unavailable")
|
return merrors.Internal("payment gateway storage unavailable")
|
||||||
@@ -274,7 +278,9 @@ func (s *Service) onIntent(ctx context.Context, intent *model.PaymentGatewayInte
|
|||||||
zap.String("payment_intent_id", confirmReq.PaymentIntentID),
|
zap.String("payment_intent_id", confirmReq.PaymentIntentID),
|
||||||
zap.String("quote_ref", confirmReq.QuoteRef),
|
zap.String("quote_ref", confirmReq.QuoteRef),
|
||||||
zap.String("rail", confirmReq.Rail),
|
zap.String("rail", confirmReq.Rail),
|
||||||
zap.String("status", string(existing.Status)))
|
zap.String("status", string(existing.Status)),
|
||||||
|
zap.String("operation_ref", confirmReq.OperationRef),
|
||||||
|
)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,22 +556,6 @@ func paymentRecordFromIntent(intent *model.PaymentGatewayIntent, confirmReq *mod
|
|||||||
return record
|
return record
|
||||||
}
|
}
|
||||||
|
|
||||||
func intentFromPayment(record *storagemodel.PaymentRecord) *model.PaymentGatewayIntent {
|
|
||||||
if record == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &model.PaymentGatewayIntent{
|
|
||||||
PaymentRef: strings.TrimSpace(record.PaymentRef),
|
|
||||||
PaymentIntentID: strings.TrimSpace(record.PaymentIntentID),
|
|
||||||
IdempotencyKey: strings.TrimSpace(record.IdempotencyKey),
|
|
||||||
OutgoingLeg: strings.TrimSpace(record.OutgoingLeg),
|
|
||||||
QuoteRef: strings.TrimSpace(record.QuoteRef),
|
|
||||||
IntentRef: strings.TrimSpace(record.IntentRef),
|
|
||||||
OperationRef: strings.TrimSpace(record.OperationRef),
|
|
||||||
RequestedMoney: record.RequestedMoney,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func intentFromSubmitTransfer(req *chainv1.SubmitTransferRequest, defaultRail, defaultChatID string) (*model.PaymentGatewayIntent, error) {
|
func intentFromSubmitTransfer(req *chainv1.SubmitTransferRequest, defaultRail, defaultChatID string) (*model.PaymentGatewayIntent, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return nil, merrors.InvalidArgument("submit_transfer: request is required")
|
return nil, merrors.InvalidArgument("submit_transfer: request is required")
|
||||||
@@ -609,6 +599,10 @@ func intentFromSubmitTransfer(req *chainv1.SubmitTransferRequest, defaultRail, d
|
|||||||
if paymentRef == "" {
|
if paymentRef == "" {
|
||||||
return nil, merrors.InvalidArgument("submit_transfer: payment_ref is required")
|
return nil, merrors.InvalidArgument("submit_transfer: payment_ref is required")
|
||||||
}
|
}
|
||||||
|
operationRef := strings.TrimSpace(req.OperationRef)
|
||||||
|
if operationRef == "" {
|
||||||
|
return nil, merrors.InvalidArgument("submit_transfer: operation_ref is required")
|
||||||
|
}
|
||||||
quoteRef := strings.TrimSpace(metadata[metadataQuoteRef])
|
quoteRef := strings.TrimSpace(metadata[metadataQuoteRef])
|
||||||
targetChatID := strings.TrimSpace(metadata[metadataTargetChatID])
|
targetChatID := strings.TrimSpace(metadata[metadataTargetChatID])
|
||||||
outgoingLeg := strings.TrimSpace(metadata[metadataOutgoingLeg])
|
outgoingLeg := strings.TrimSpace(metadata[metadataOutgoingLeg])
|
||||||
@@ -626,6 +620,7 @@ func intentFromSubmitTransfer(req *chainv1.SubmitTransferRequest, defaultRail, d
|
|||||||
QuoteRef: quoteRef,
|
QuoteRef: quoteRef,
|
||||||
RequestedMoney: requestedMoney,
|
RequestedMoney: requestedMoney,
|
||||||
IntentRef: intentRef,
|
IntentRef: intentRef,
|
||||||
|
OperationRef: operationRef,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,9 +49,7 @@ chains:
|
|||||||
max_topup_trx: 100
|
max_topup_trx: 100
|
||||||
tokens:
|
tokens:
|
||||||
- symbol: USDT
|
- symbol: USDT
|
||||||
contract: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
|
contract: "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf"
|
||||||
- symbol: USDC
|
|
||||||
contract: "TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8"
|
|
||||||
|
|
||||||
service_wallet:
|
service_wallet:
|
||||||
chain: tron_nile
|
chain: tron_nile
|
||||||
|
|||||||
@@ -50,8 +50,6 @@ chains:
|
|||||||
tokens:
|
tokens:
|
||||||
- symbol: USDT
|
- symbol: USDT
|
||||||
contract: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
|
contract: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
|
||||||
- symbol: USDC
|
|
||||||
contract: "TEkxiTehnzSmSe2XqrBj4w32RUN966rdz8"
|
|
||||||
|
|
||||||
service_wallet:
|
service_wallet:
|
||||||
chain: tron_mainnet
|
chain: tron_mainnet
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/tech/sendico/gateway/tron
|
module github.com/tech/sendico/gateway/tron
|
||||||
|
|
||||||
go 1.25.6
|
go 1.25.7
|
||||||
|
|
||||||
replace github.com/tech/sendico/pkg => ../../pkg
|
replace github.com/tech/sendico/pkg => ../../pkg
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ require (
|
|||||||
github.com/hashicorp/vault/api v1.22.0
|
github.com/hashicorp/vault/api v1.22.0
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/prometheus/client_golang v1.23.2
|
github.com/prometheus/client_golang v1.23.2
|
||||||
|
github.com/shengdoushi/base58 v1.0.0
|
||||||
github.com/shopspring/decimal v1.4.0
|
github.com/shopspring/decimal v1.4.0
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/tech/sendico/pkg v0.1.0
|
github.com/tech/sendico/pkg v0.1.0
|
||||||
@@ -23,7 +24,7 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260201044653-ee82dce4af02 // indirect
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260212005555-3a7e5700f354 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
||||||
@@ -34,14 +35,14 @@ require (
|
|||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/consensys/gnark-crypto v0.19.2 // indirect
|
github.com/consensys/gnark-crypto v0.19.2 // indirect
|
||||||
github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect
|
github.com/crate-crypto/go-eth-kzg v1.5.0 // indirect
|
||||||
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
|
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/deckarep/golang-set v1.8.0 // indirect
|
github.com/deckarep/golang-set v1.8.0 // indirect
|
||||||
github.com/deckarep/golang-set/v2 v2.8.0 // indirect
|
github.com/deckarep/golang-set/v2 v2.8.0 // indirect
|
||||||
github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect
|
github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect
|
||||||
github.com/ethereum/go-verkle v0.2.2 // indirect
|
github.com/ethereum/go-verkle v0.2.2 // indirect
|
||||||
github.com/go-chi/chi/v5 v5.2.4 // indirect
|
github.com/go-chi/chi/v5 v5.2.5 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
@@ -56,7 +57,7 @@ require (
|
|||||||
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
|
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.1-vault-7 // indirect
|
github.com/hashicorp/hcl v1.0.1-vault-7 // indirect
|
||||||
github.com/holiman/uint256 v1.3.2 // indirect
|
github.com/holiman/uint256 v1.3.2 // indirect
|
||||||
github.com/klauspost/compress v1.18.3 // indirect
|
github.com/klauspost/compress v1.18.4 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
@@ -72,7 +73,6 @@ require (
|
|||||||
github.com/prometheus/procfs v0.19.2 // indirect
|
github.com/prometheus/procfs v0.19.2 // indirect
|
||||||
github.com/rjeczalik/notify v0.9.3 // indirect
|
github.com/rjeczalik/notify v0.9.3 // indirect
|
||||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||||
github.com/shengdoushi/base58 v1.0.0 // indirect
|
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
|
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
|
||||||
github.com/supranational/blst v0.3.16 // indirect
|
github.com/supranational/blst v0.3.16 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.16 // indirect
|
github.com/tklauser/go-sysconf v0.3.16 // indirect
|
||||||
@@ -85,13 +85,13 @@ require (
|
|||||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/crypto v0.47.0 // indirect
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
||||||
golang.org/x/net v0.49.0 // indirect
|
golang.org/x/net v0.50.0 // indirect
|
||||||
golang.org/x/sync v0.19.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.40.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
golang.org/x/text v0.33.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
golang.org/x/time v0.14.0 // indirect
|
golang.org/x/time v0.14.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20260202165425-ce8ad4cf556b // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
|
|||||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260201044653-ee82dce4af02 h1:0uY5Ooun4eqGmP0IrQhiKVqeeEXoeEcL8KVRtug8+r8=
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260212005555-3a7e5700f354 h1:BgaMXBpcqcW74afzqI3iKo07K3tC+VuyWU3/FIvLlNI=
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260201044653-ee82dce4af02/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260212005555-3a7e5700f354/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
|
||||||
github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0=
|
github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0=
|
||||||
github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU=
|
github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
@@ -52,8 +52,8 @@ github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GK
|
|||||||
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
|
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
github.com/crate-crypto/go-eth-kzg v1.4.0 h1:WzDGjHk4gFg6YzV0rJOAsTK4z3Qkz5jd4RE3DAvPFkg=
|
github.com/crate-crypto/go-eth-kzg v1.5.0 h1:FYRiJMJG2iv+2Dy3fi14SVGjcPteZ5HAAUe4YWlJygc=
|
||||||
github.com/crate-crypto/go-eth-kzg v1.4.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI=
|
github.com/crate-crypto/go-eth-kzg v1.5.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI=
|
||||||
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg=
|
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a h1:W8mUrRp6NOVl3J+MYp5kPMoUZPp7aOYHtaua31lwRHg=
|
||||||
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM=
|
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a/go.mod h1:sTwzHBvIzm2RfVCGNEBZgRyjwK40bVoun3ZnGOCafNM=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
@@ -96,8 +96,8 @@ github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeD
|
|||||||
github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg=
|
github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg=
|
||||||
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
|
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
|
||||||
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||||
github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4=
|
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||||
github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
|
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
@@ -166,8 +166,8 @@ github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
|
|||||||
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
||||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
@@ -334,8 +334,8 @@ go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
@@ -344,8 +344,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
@@ -360,16 +360,16 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||||
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@@ -379,10 +379,10 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20260202165425-ce8ad4cf556b h1:SGYyueaEovpqmWmtTvwtVgo638V/QFE2zlTCnRrR3jg=
|
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20260202165425-ce8ad4cf556b/go.mod h1:ZdbssH/1SOVnjnDlXzxDHK2MCidiqXtbYccJNzNYPEE=
|
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b h1:GZxXGdFaHX27ZSMHudWc4FokdD+xl8BC2UJm1OVIEzs=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260202165425-ce8ad4cf556b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import (
|
|||||||
gatewayservice "github.com/tech/sendico/gateway/tron/internal/service/gateway"
|
gatewayservice "github.com/tech/sendico/gateway/tron/internal/service/gateway"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/drivers"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/drivers"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/rpcclient"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/rpcclient"
|
||||||
gatewayshared "github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/tronclient"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/tronclient"
|
||||||
|
gatewayshared "github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage"
|
"github.com/tech/sendico/gateway/tron/storage"
|
||||||
gatewaymongo "github.com/tech/sendico/gateway/tron/storage/mongo"
|
gatewaymongo "github.com/tech/sendico/gateway/tron/storage/mongo"
|
||||||
"github.com/tech/sendico/pkg/api/routers"
|
"github.com/tech/sendico/pkg/api/routers"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"github.com/tech/sendico/gateway/tron/internal/keymanager"
|
"github.com/tech/sendico/gateway/tron/internal/keymanager"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/drivers"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/drivers"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/rpcclient"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/rpcclient"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/tronclient"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/tronclient"
|
||||||
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage"
|
"github.com/tech/sendico/gateway/tron/storage"
|
||||||
clockpkg "github.com/tech/sendico/pkg/clock"
|
clockpkg "github.com/tech/sendico/pkg/clock"
|
||||||
"github.com/tech/sendico/pkg/mlogger"
|
"github.com/tech/sendico/pkg/mlogger"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/commands/wallet"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/commands/wallet"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver/evm"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver/evm"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver/tron"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver/tron"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package transfer
|
package transfer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
||||||
"google.golang.org/protobuf/types/known/timestamppb"
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
@@ -76,7 +76,7 @@ func (c *createManagedWalletCommand) Execute(ctx context.Context, req *chainv1.C
|
|||||||
c.deps.Logger.Warn("Missing token symbol")
|
c.deps.Logger.Warn("Missing token symbol")
|
||||||
return gsresponse.InvalidArgument[chainv1.CreateManagedWalletResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("asset.token_symbol is required"))
|
return gsresponse.InvalidArgument[chainv1.CreateManagedWalletResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("asset.token_symbol is required"))
|
||||||
}
|
}
|
||||||
contractAddress := strings.ToLower(strings.TrimSpace(asset.GetContractAddress()))
|
contractAddress := strings.TrimSpace(asset.GetContractAddress())
|
||||||
if contractAddress == "" {
|
if contractAddress == "" {
|
||||||
if !strings.EqualFold(tokenSymbol, networkCfg.NativeToken) {
|
if !strings.EqualFold(tokenSymbol, networkCfg.NativeToken) {
|
||||||
contractAddress = shared.ResolveContractAddress(networkCfg.TokenConfigs, tokenSymbol)
|
contractAddress = shared.ResolveContractAddress(networkCfg.TokenConfigs, tokenSymbol)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
"github.com/tech/sendico/pkg/api/routers/gsresponse"
|
||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package wallet
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
describablev1 "github.com/tech/sendico/pkg/proto/common/describable/v1"
|
describablev1 "github.com/tech/sendico/pkg/proto/common/describable/v1"
|
||||||
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/tech/sendico/gateway/tron/internal/appversion"
|
"github.com/tech/sendico/gateway/tron/internal/appversion"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
chainasset "github.com/tech/sendico/pkg/chain"
|
chainasset "github.com/tech/sendico/pkg/chain"
|
||||||
"github.com/tech/sendico/pkg/connector/params"
|
"github.com/tech/sendico/pkg/connector/params"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/keymanager"
|
"github.com/tech/sendico/gateway/tron/internal/keymanager"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/rpcclient"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/rpcclient"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/tronclient"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/tronclient"
|
||||||
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/mlogger"
|
"github.com/tech/sendico/pkg/mlogger"
|
||||||
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||||
@@ -116,7 +116,7 @@ func Balance(ctx context.Context, deps driver.Deps, network shared.Network, wall
|
|||||||
zap.String("wallet_ref", wallet.WalletRef),
|
zap.String("wallet_ref", wallet.WalletRef),
|
||||||
zap.String("network", network.Name.String()),
|
zap.String("network", network.Name.String()),
|
||||||
zap.String("token_symbol", strings.ToUpper(strings.TrimSpace(wallet.TokenSymbol))),
|
zap.String("token_symbol", strings.ToUpper(strings.TrimSpace(wallet.TokenSymbol))),
|
||||||
zap.String("contract", strings.ToLower(strings.TrimSpace(wallet.ContractAddress))),
|
zap.String("contract", strings.TrimSpace(wallet.ContractAddress)),
|
||||||
zap.String("wallet_address", normalizedAddress),
|
zap.String("wallet_address", normalizedAddress),
|
||||||
}
|
}
|
||||||
if rpcURL == "" {
|
if rpcURL == "" {
|
||||||
@@ -124,7 +124,11 @@ func Balance(ctx context.Context, deps driver.Deps, network shared.Network, wall
|
|||||||
return nil, merrors.Internal("network rpc url is not configured")
|
return nil, merrors.Internal("network rpc url is not configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
contract := strings.TrimSpace(wallet.ContractAddress)
|
contract, err := shared.TronBase58ToHex(strings.TrimSpace(wallet.ContractAddress))
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn("Failed to convert contract address", zap.String("contract_address", wallet.ContractAddress))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if contract == "" {
|
if contract == "" {
|
||||||
logger.Debug("Native balance requested", logFields...)
|
logger.Debug("Native balance requested", logFields...)
|
||||||
return NativeBalance(ctx, deps, network, wallet, normalizedAddress)
|
return NativeBalance(ctx, deps, network, wallet, normalizedAddress)
|
||||||
@@ -436,7 +440,11 @@ func SubmitTransfer(ctx context.Context, deps driver.Deps, network shared.Networ
|
|||||||
|
|
||||||
chainID := new(big.Int).SetUint64(network.ChainID)
|
chainID := new(big.Int).SetUint64(network.ChainID)
|
||||||
|
|
||||||
contract := strings.TrimSpace(transfer.ContractAddress)
|
contract, err := shared.TronBase58ToHex(strings.TrimSpace(transfer.ContractAddress))
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn("Failed to convert contract address", zap.String("contract_address", transfer.ContractAddress))
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
amount := transfer.NetAmount
|
amount := transfer.NetAmount
|
||||||
if amount == nil || strings.TrimSpace(amount.Amount) == "" {
|
if amount == nil || strings.TrimSpace(amount.Amount) == "" {
|
||||||
logger.Warn("Transfer missing net amount", zap.String("transfer_ref", transfer.TransferRef))
|
logger.Warn("Transfer missing net amount", zap.String("transfer_ref", transfer.TransferRef))
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ func rpcAddress(address string) (string, error) {
|
|||||||
if strings.HasPrefix(trimmed, tronHexPrefix) || isHexString(trimmed) {
|
if strings.HasPrefix(trimmed, tronHexPrefix) || isHexString(trimmed) {
|
||||||
return normalizeHexRPC(trimmed)
|
return normalizeHexRPC(trimmed)
|
||||||
}
|
}
|
||||||
return base58ToHex(trimmed)
|
return shared.TronBase58ToHex(trimmed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func hexToBase58(address string) (string, error) {
|
func hexToBase58(address string) (string, error) {
|
||||||
@@ -53,17 +54,6 @@ func hexToBase58(address string) (string, error) {
|
|||||||
return base58Encode(payload), nil
|
return base58Encode(payload), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func base58ToHex(address string) (string, error) {
|
|
||||||
decoded, err := base58Decode(address)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if err := validateChecksum(decoded); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return tronHexPrefix + hex.EncodeToString(decoded[1:21]), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseHexAddress(address string) ([]byte, error) {
|
func parseHexAddress(address string) ([]byte, error) {
|
||||||
trimmed := strings.TrimPrefix(strings.TrimSpace(address), tronHexPrefix)
|
trimmed := strings.TrimPrefix(strings.TrimSpace(address), tronHexPrefix)
|
||||||
if trimmed == "" {
|
if trimmed == "" {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver/evm"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver/evm"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
"github.com/tech/sendico/pkg/mlogger"
|
"github.com/tech/sendico/pkg/mlogger"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver"
|
"github.com/tech/sendico/gateway/tron/internal/service/gateway/driver"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/tech/sendico/gateway/tron/internal/service/gateway/shared"
|
"github.com/tech/sendico/gateway/tron/shared"
|
||||||
"github.com/tech/sendico/gateway/tron/storage/model"
|
"github.com/tech/sendico/gateway/tron/storage/model"
|
||||||
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
||||||
)
|
)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user