Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: golangci-lint
on:
pull_request:
branches:
- master
permissions:
contents: read

jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
with:
go-version: '1.25.4'
cache: true
- uses: extractions/setup-just@v3
- name: Set up Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install dependencies
run: just install-deps
- name: Generate code (proto, templ)
run: |
just gen-proto
just gen-templ
just web-install
just web-build-prod
- name: golangci-lint
uses: golangci/golangci-lint-action@v9
37 changes: 7 additions & 30 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,7 @@ jobs:
with:
go-version: '1.25.4'
cache: true

- name: Go Toolchain info
run: |
go version

- name: Install Just
run: |
sudo apt-get update
sudo apt-get install -y just

- uses: extractions/setup-just@v3
- name: Set up Bun
uses: oven-sh/setup-bun@v1
with:
Expand All @@ -47,16 +38,7 @@ jobs:
with:
go-version: '1.25.4'
cache: true

- name: Go Toolchain info
run: |
go version

- name: Install Just
run: |
sudo apt-get update
sudo apt-get install -y just

- uses: extractions/setup-just@v3
- name: Set up Bun
uses: oven-sh/setup-bun@v1
with:
Expand Down Expand Up @@ -99,21 +81,16 @@ jobs:
with:
go-version: '1.25.4'
cache: true

- name: Go Toolchain info
run: |
go version

- name: Install Just
run: |
sudo apt-get update
sudo apt-get install -y just

- uses: extractions/setup-just@v3
- name: Set up Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest

- name: Go Toolchain info
run: |
go version

- name: Install dependencies
run: just install-deps

Expand Down
117 changes: 117 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
version: "2"

run:
timeout: 5m
tests: true
modules-download-mode: readonly

linters:
enable:
# Security-focused linters
- gosec # Security vulnerability scanner
- bidichk # Checks for dangerous unicode character sequences
- bodyclose # Checks HTTP response body is closed
# - contextcheck # Check for non-inherited context

# Bug detection
- staticcheck # Comprehensive static analysis
- govet # Reports suspicious constructs
- errcheck # Unchecked errors
- ineffassign # Detects unused assignments

# Code quality
# - revive # Fast, extensible linter
# - gocyclo # Cyclomatic complexity
- unconvert # Unnecessary type conversions
- unparam # Unused function parameters
- misspell # Commonly misspelled words

settings:
gosec:
# Enable all security rules - these check for common vulnerabilities
includes:
- G101 # Look for hardcoded credentials
- G102 # Bind to all interfaces
- G103 # Audit the use of unsafe block
- G104 # Audit errors not checked
- G106 # Audit the use of ssh.InsecureIgnoreHostKey function
- G107 # URL provided to HTTP request as taint input
- G108 # Profiling endpoint is automatically exposed
- G109 # Converting strconv.Atoi result to int32/int16
- G110 # Detect io.Copy instead of io.CopyN when decompression
- G111 # Detect http.Dir('/') as a potential risk
- G112 # Detect ReadHeaderTimeout not configured
- G114 # Use of net/http serve function without timeouts
- G116 # Detect Trojan Source attacks using bidirectional Unicode
- G201 # SQL query construction using format string
- G202 # SQL query construction using string concatenation
- G203 # Use of unescaped data in HTML templates
- G204 # Audit use of command execution
- G301 # Poor file permissions used when creating a directory
- G302 # Poor file permissions used with chmod
- G303 # Creating tempfile using a predictable path
- G304 # File path provided as taint input
- G305 # File traversal when extracting zip/tar archive
- G306 # Poor file permissions used when writing to a new file
- G307 # Poor file permissions used with os.Create
- G401 # Detect the usage of MD5 or SHA1
- G402 # Look for bad TLS connection settings
- G403 # Ensure minimum RSA key length of 2048 bits
- G404 # Insecure random number source (rand instead of crypto/rand)
- G501 # Import blocklist: crypto/md5
- G502 # Import blocklist: crypto/des
- G503 # Import blocklist: crypto/rc4
- G504 # Import blocklist: net/http/cgi
- G505 # Import blocklist: crypto/sha1
- G601 # Implicit memory aliasing in for loop (Go < 1.22)
- G602 # Slice access out of bounds

# Configure specific rules
config:
G101:
pattern: "(?i)passwd|pass|password|pwd|secret|private_key|token|api_key|apikey|access_key|auth"
ignore_entropy: false
entropy_threshold: "80.0"
per_char_threshold: "3.0"
truncate: "32"
G306:
"0600"

errcheck:
check-type-assertions: true
# check-blank: true

govet:
enable-all: true
disable:
- shadow

gocyclo:
min-complexity: 15

bidichk:
# Check for all dangerous bidirectional unicode characters
left-to-right-embedding: true
right-to-left-embedding: true
pop-directional-formatting: true
left-to-right-override: true
right-to-left-override: true
left-to-right-isolate: true
right-to-left-isolate: true
first-strong-isolate: true
pop-directional-isolate: true

exclusions:
presets:
- common-false-positives
rules:
# Relax some checks in test files, but keep security checks active
- path: '(.+)_test\.go'
linters:
- gocyclo
- dupl
- funlen

issues:
max-issues-per-linter: 0
max-same-issues: 0
1 change: 0 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@
- if you don't know how to do something don't guess. It's okey if you don't know.
- Before you change anything review this proposal critically.

When scanning source files, use repomix to save space and tokens.
Use the Context7 MCP server to know the latest way to use libraries like `gin` and `templ`.
6 changes: 3 additions & 3 deletions api/cashu/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ type PostAuthBlindMintRequest struct {
}

type AuthProof struct {
C WrappedPublicKey `json:"C" db:"c"`
Id string `json:"id"`
Secret string `json:"secret"`
C WrappedPublicKey `json:"C" db:"c"`
Amount uint64 `json:"amount" db:"amount"`
}

Expand Down Expand Up @@ -66,17 +66,17 @@ func (a AuthProof) Proof(y WrappedPublicKey, state ProofState) Proof {
}

type AuthClams struct {
Aud *[]string `json:"aud"`
Sub string `json:"sub"`
ClientId string `json:"client_id"`
Aud *[]string `json:"aud"`
}

type PostAuthBlindMintResponse struct {
Signatures []BlindSignature `json:"signatures"`
}
type Nut22Info struct {
BatMaxMint uint64 `json:"bat_max_mint"`
ProtectedRoutes []ProtectedRoute `json:"protected_endpoints"`
BatMaxMint uint64 `json:"bat_max_mint"`
}

func ConvertRouteListToProtectedRouteList(list []string) []ProtectedRoute {
Expand Down
9 changes: 3 additions & 6 deletions api/cashu/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,9 @@ func (e ErrorCode) String() string {
}

type ErrorResponse struct {
// integer code
Code ErrorCode `json:"code"`
// Human readable error
Error string `json:"error,omitempty"`
// Extended explanation of error
Detail *string `json:"detail,omitempty"`
Detail *string `json:"detail,omitempty"`
Error string `json:"error,omitempty"`
Code ErrorCode `json:"code"`
}

func ErrorCodeToResponse(code ErrorCode, detail *string) ErrorResponse {
Expand Down
4 changes: 2 additions & 2 deletions api/cashu/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ func TestChangeProofsStateToPendingAndQuoteSet(t *testing.T) {

func convertJsonMapIntoOrderedArray(raw map[string]string) []*secp256k1.PublicKey {
arrays := []struct {
Amount uint64
Pubkey *secp256k1.PublicKey
Amount uint64
}{}
// Build the final map[uint64]*btcec.PublicKey
// pubkeys := make(map[uint64]*btcec.PublicKey)
Expand Down Expand Up @@ -149,8 +149,8 @@ func convertJsonMapIntoOrderedArray(raw map[string]string) []*secp256k1.PublicKe
}

arrays = append(arrays, struct {
Amount uint64
Pubkey *secp256k1.PublicKey
Amount uint64
}{
Amount: uKey,
Pubkey: pk,
Expand Down
37 changes: 16 additions & 21 deletions api/cashu/melt.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,26 @@ const (
)

type MeltRequestDB struct {
Quote string `json:"quote"`
Unit string `json:"unit"`
Expiry int64 `json:"expiry"`
Amount uint64 `json:"amount"`
FeeReserve uint64 `json:"fee_reserve" db:"fee_reserve"`
FeePaid uint64 `json:"paid_fee" db:"fee_paid"`
// Deprecated: Should be removed after all main wallets change to the new State format
RequestPaid bool `json:"paid" db:"request_paid"`
PaymentPreimage string `json:"payment_preimage"`
Unit string `json:"unit"`
Request string `json:"request"`
Melted bool `json:"melted"`
State ACTION_STATE `json:"state"`
PaymentPreimage string `json:"payment_preimage"`
Quote string `json:"quote"`
CheckingId string `json:"checking_id"`
Expiry int64 `json:"expiry"`
Amount uint64 `json:"amount"`
FeeReserve uint64 `json:"fee_reserve" db:"fee_reserve"`
FeePaid uint64 `json:"paid_fee" db:"fee_paid"`
SeenAt int64 `json:"seen_at"`
Melted bool `json:"melted"`
Mpp bool `json:"mpp"`
CheckingId string `json:"checking_id"`
}

func (meltRequest *MeltRequestDB) GetPostMeltQuoteResponse() PostMeltQuoteBolt11Response {
return PostMeltQuoteBolt11Response{
Quote: meltRequest.Quote,
Amount: meltRequest.Amount,
FeeReserve: meltRequest.FeeReserve,
Paid: meltRequest.RequestPaid,
Expiry: meltRequest.Expiry,
State: meltRequest.State,
PaymentPreimage: meltRequest.PaymentPreimage,
Expand All @@ -52,9 +49,9 @@ type PostMeltQuoteBolt11Options struct {
}

type PostMeltQuoteBolt11Request struct {
Options PostMeltQuoteBolt11Options `json:"options"`
Request string `json:"request"`
Unit string `json:"unit"`
Options PostMeltQuoteBolt11Options `json:"options"`
}

func (p PostMeltQuoteBolt11Request) IsMpp() uint64 {
Expand All @@ -65,17 +62,15 @@ func (p PostMeltQuoteBolt11Request) IsMpp() uint64 {
}

type PostMeltQuoteBolt11Response struct {
Quote string `json:"quote"`
Amount uint64 `json:"amount"`
FeeReserve uint64 `json:"fee_reserve"`
// Deprecated: Should be removed after all main wallets change to the new State format
Paid bool `json:"paid"`
Expiry int64 `json:"expiry"`
Quote string `json:"quote"`
State ACTION_STATE `json:"state"`
Change []BlindSignature `json:"change"`
Unit string `json:"unit"`
Request string `json:"request"`
PaymentPreimage string `json:"payment_preimage"`
Change []BlindSignature `json:"change"`
Amount uint64 `json:"amount"`
FeeReserve uint64 `json:"fee_reserve"`
Expiry int64 `json:"expiry"`
}

type PostMeltBolt11Request struct {
Expand Down Expand Up @@ -157,7 +152,7 @@ func (p *PostMeltBolt11Request) verifyConditions() error {
return fmt.Errorf("not same data field %w", ErrInvalidSpendCondition)
}

if string(spendCondition.Data.Tags.originalTag) != string(firstSpendCondition.Data.Tags.originalTag) {
if spendCondition.Data.Tags.originalTag != firstSpendCondition.Data.Tags.originalTag {
return fmt.Errorf("not same tags %w", ErrInvalidSpendCondition)
}

Expand Down
Loading