Skip to content

Commit 91dc72f

Browse files
Merge branch 'main' into ws-fix
2 parents fc4abef + edcedcc commit 91dc72f

123 files changed

Lines changed: 648 additions & 442 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/lint.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
on:
2+
push:
3+
paths:
4+
- "**.go"
5+
- "go.mod"
6+
- "go.sum"
7+
- ".golangci.yml"
8+
- ".github/workflows/lint.yml"
9+
pull_request:
10+
paths:
11+
- "**.go"
12+
- "go.mod"
13+
- "go.sum"
14+
- ".golangci.yml"
15+
- ".github/workflows/lint.yml"
16+
name: lint
17+
jobs:
18+
golangci-lint:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Checkout code
22+
uses: actions/checkout@v4
23+
- name: Install Go
24+
uses: actions/setup-go@v5
25+
with:
26+
go-version: "1.24.x"
27+
cache: false
28+
- name: golangci-lint
29+
uses: golangci/golangci-lint-action@v7
30+
with:
31+
version: v2.11.4
32+
args: --timeout=10m

.golangci.yml

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
version: "2"
2+
3+
run:
4+
timeout: 10m
5+
6+
issues:
7+
max-issues-per-linter: 0
8+
max-same-issues: 0
9+
10+
linters:
11+
default: none
12+
enable:
13+
- errcheck
14+
- govet
15+
- ineffassign
16+
- staticcheck
17+
- unused
18+
- errorlint
19+
- misspell
20+
settings:
21+
errcheck:
22+
check-type-assertions: false
23+
check-blank: false
24+
exclude-functions:
25+
- (io.Closer).Close
26+
- (*os.File).Close
27+
- (net.Listener).Close
28+
- (*net.TCPConn).Close
29+
- (*net.UDPConn).Close
30+
- (*bytes.Buffer).WriteString
31+
- (*bytes.Buffer).WriteByte
32+
- (*bytes.Buffer).Write
33+
- (*strings.Builder).WriteString
34+
- (*strings.Builder).WriteByte
35+
- (*strings.Builder).WriteRune
36+
- (*strings.Builder).Write
37+
- (*go.uber.org/zap/buffer.Buffer).Write
38+
- (*github.com/gorilla/websocket.Conn).SetReadDeadline
39+
- (*github.com/gorilla/websocket.Conn).SetWriteDeadline
40+
- fmt.Fprint
41+
- fmt.Fprintln
42+
- fmt.Fprintf
43+
- github.com/gagliardetto/binary.EncodeCompactU16Length
44+
errorlint:
45+
errorf: true
46+
asserts: true
47+
comparison: true
48+
staticcheck:
49+
checks:
50+
- all
51+
# Known follow-ups — tracked separately, not in scope for the lint rollout:
52+
- -SA1019 # deprecated API usage (logging package, ssh/terminal -> x/term, cloudkms.New)
53+
- -ST1001 # dot imports (text/format, zap-box) — refactor-scale change
54+
- -ST1003 # underscore naming in exported consts/params — breaking API change
55+
- -ST1016 # receiver name consistency — ws pkg mixes "c"/"cl", refactor-scale
56+
- -ST1019 # duplicate imports (same files)
57+
- -QF1008 # could remove embedded field selector — stylistic, keep for legibility
58+
- -SA9003 # empty branches — scaffolding in rpc/ws/examples/
59+
misspell:
60+
locale: US
61+
exclusions:
62+
generated: lax
63+
presets:
64+
- comments
65+
- common-false-positives
66+
- legacy
67+
- std-error-handling
68+
rules:
69+
# Test files: allow unchecked errors and legacy error comparisons.
70+
- path: _test\.go
71+
linters:
72+
- errcheck
73+
- errorlint
74+
# CLI / cmd binaries: unchecked errors on stdout prints are fine.
75+
- path: cmd/
76+
linters:
77+
- errcheck
78+
- path: cli/
79+
linters:
80+
- errcheck
81+
# WS subscription examples are demo code using `if false {}` to show
82+
# multiple patterns side by side. Exclude from lint.
83+
- path: rpc/ws/examples/
84+
linters:
85+
- govet
86+
- staticcheck
87+
# Unused identifiers that are either intentionally kept (lookup tables
88+
# reserved for future work, logging-side-effect registrations) or live
89+
# in code paths pending refactor. Tracked as follow-up.
90+
- path: base58/tables\.go
91+
linters:
92+
- unused
93+
- path: logging\.go
94+
linters:
95+
- unused
96+
- path: diff/
97+
linters:
98+
- unused
99+
- staticcheck
100+
- path: text/encoder\.go
101+
linters:
102+
- staticcheck
103+
- path: zap-box/
104+
linters:
105+
- unused
106+
- path: programs/token(-2022)?/json\.go
107+
linters:
108+
- unused
109+
- path: rpc/client\.go
110+
linters:
111+
- unused
112+
- path: rpc/ws/client\.go
113+
linters:
114+
- unused
115+
116+
formatters:
117+
enable:
118+
- gofmt
119+
- goimports
120+
exclusions:
121+
generated: lax

CONTRIBUTING.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ We encourage everyone to contribute — submit issues, PRs, and discuss. Every k
88
2. Make sure you have Go 1.24+ installed
99
3. Run `go mod download` to fetch dependencies
1010
4. Run the tests to verify everything works: `go test ./... -count=1`
11+
5. Install [`golangci-lint`](https://golangci-lint.run/welcome/install/) (v2.11+) and run `golangci-lint run` to verify the linters pass
1112

1213
## Development Workflow
1314

@@ -17,6 +18,36 @@ We encourage everyone to contribute — submit issues, PRs, and discuss. Every k
1718
4. Commit using [Conventional Commits](#commit-messages) format
1819
5. Open a pull request against `main`
1920

21+
## Linting
22+
23+
This project uses [golangci-lint](https://golangci-lint.run/) with the config at [`.golangci.yml`](.golangci.yml). The enabled linters are:
24+
25+
| Linter | Purpose |
26+
| -------------- | ------------------------------------------------------------- |
27+
| `errcheck` | Flags unchecked errors |
28+
| `govet` | Go's standard static analyzer (composites, unusedresult, etc.) |
29+
| `ineffassign` | Catches ineffectual assignments |
30+
| `staticcheck` | Detects bugs, performance issues, and style violations |
31+
| `unused` | Finds unused constants, variables, functions, and types |
32+
| `errorlint` | Enforces `%w` wrapping and `errors.Is` / `errors.As` |
33+
| `misspell` | Catches common misspellings (US English) |
34+
| `gofmt` | Standard Go formatting |
35+
| `goimports` | Import ordering and grouping |
36+
37+
Run locally:
38+
39+
```bash
40+
# Run all linters
41+
golangci-lint run
42+
43+
# Auto-fix where possible (errorlint, gofmt, goimports, misspell)
44+
golangci-lint run --fix
45+
```
46+
47+
The `lint` CI check must pass before a PR can merge. If you need to disable a rule for a specific line, use `//nolint:<linter> // reason` and include a reason — unjustified nolint directives will be flagged in review.
48+
49+
A small number of deprecation warnings (`SA1019`), stylistic checks (`ST1003` naming, `ST1001` dot imports), and known-refactor items are disabled in config and tracked as follow-up work — not as accepted debt. See [`.golangci.yml`](.golangci.yml) for the current exclusion list.
50+
2051
## Commit Messages
2152

2253
This project uses [Conventional Commits](https://www.conventionalcommits.org/). All commit messages must follow this format:
@@ -95,6 +126,7 @@ Every pull request runs the following checks:
95126
| Check | What it does |
96127
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
97128
| **tests** | Runs `go test ./...` across Go 1.24.x on ubuntu, macos, and windows. Only triggered when `.go`, `go.mod`, `go.sum`, or the workflow file itself changes. |
129+
| **lint** | Runs `golangci-lint` on ubuntu-latest with the config at `.golangci.yml`. See [Linting](#linting) above. |
98130
| **semver-check** | Runs `gorelease` to compare the public API against the latest release tag. Fails if breaking changes are detected without a major version bump. |
99131
| **commit-lint** | Validates that all commits in the PR follow Conventional Commits format. |
100132

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
[![GoDoc](https://pkg.go.dev/badge/github.com/gagliardetto/solana-go?status.svg)](https://pkg.go.dev/github.com/gagliardetto/solana-go@v1.16.0?tab=doc)
44
[![GitHub tag (latest SemVer pre-release)](https://img.shields.io/github/v/tag/gagliardetto/solana-go?include_prereleases&label=release-tag)](https://github.com/gagliardetto/solana-go/releases)
55
[![Build Status](https://github.com/gagliardetto/solana-go/workflows/tests/badge.svg?branch=main)](https://github.com/gagliardetto/solana-go/actions?query=branch%3Amain)
6+
[![Lint Status](https://github.com/gagliardetto/solana-go/workflows/lint/badge.svg?branch=main)](https://github.com/gagliardetto/solana-go/actions?query=branch%3Amain+workflow%3Alint)
67
[![TODOs](https://badgen.net/https/api.tickgit.com/badgen/github.com/gagliardetto/solana-go/main)](https://www.tickgit.com/browse?repo=github.com/gagliardetto/solana-go&branch=main)
78
[![Go Report Card](https://goreportcard.com/badge/github.com/gagliardetto/solana-go)](https://goreportcard.com/report/github.com/gagliardetto/solana-go)
89

@@ -831,7 +832,16 @@ Each subscription has a testable example in [`rpc/ws/example_test.go`](rpc/ws/ex
831832

832833
We encourage everyone to contribute, submit issues, PRs, discuss. Every kind of help is welcome.
833834

834-
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on commit messages, semver policy, and CI checks.
835+
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on commit messages, semver policy, linting, and CI checks.
836+
837+
Before opening a PR, run:
838+
839+
```bash
840+
go test ./... -count=1
841+
golangci-lint run
842+
```
843+
844+
Both must pass in CI.
835845

836846
## License
837847

base58/fuzz_test.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import (
1010
// --- Encode fuzz: our output must match mr-tron for every input ---
1111

1212
func FuzzEncode32_MatchesMrTron(f *testing.F) {
13-
f.Add(make([]byte, 32)) // all zeros
14-
f.Add(bytes.Repeat([]byte{0xff}, 32)) // all 0xFF
15-
f.Add(append([]byte{1}, make([]byte, 31)...)) // single leading byte
16-
f.Add(append(make([]byte, 31), 1)) // trailing 1
13+
f.Add(make([]byte, 32)) // all zeros
14+
f.Add(bytes.Repeat([]byte{0xff}, 32)) // all 0xFF
15+
f.Add(append([]byte{1}, make([]byte, 31)...)) // single leading byte
16+
f.Add(append(make([]byte, 31), 1)) // trailing 1
1717

1818
f.Fuzz(func(t *testing.T, data []byte) {
1919
if len(data) != 32 {
@@ -119,14 +119,14 @@ func FuzzDecode64_MatchesMrTron(f *testing.F) {
119119

120120
func FuzzDecode32_NoPanic(f *testing.F) {
121121
f.Add([]byte(""))
122-
f.Add([]byte("0")) // invalid char
123-
f.Add([]byte("O")) // invalid char
124-
f.Add([]byte("I")) // invalid char
125-
f.Add([]byte("l")) // invalid char
126-
f.Add([]byte("\x00")) // null byte
127-
f.Add([]byte("\xff")) // high byte
128-
f.Add(bytes.Repeat([]byte("z"), 45)) // too long
129-
f.Add(bytes.Repeat([]byte("1"), 50)) // way too long
122+
f.Add([]byte("0")) // invalid char
123+
f.Add([]byte("O")) // invalid char
124+
f.Add([]byte("I")) // invalid char
125+
f.Add([]byte("l")) // invalid char
126+
f.Add([]byte("\x00")) // null byte
127+
f.Add([]byte("\xff")) // high byte
128+
f.Add(bytes.Repeat([]byte("z"), 45)) // too long
129+
f.Add(bytes.Repeat([]byte("1"), 50)) // way too long
130130

131131
f.Fuzz(func(t *testing.T, data []byte) {
132132
var dst [32]byte

base58/matmul_amd64.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ TEXT ·decodeMatMul32(SB), NOSPLIT|NOFRAME, $0-16
339339
IMULQ BX, AX
340340
ADDQ AX, R15
341341

342-
// Row 8: table[8] = {0,0,0,0,0,0,0,1} bin[7] += intermediate[8]
342+
// Row 8: table[8] = {0,0,0,0,0,0,0,1} -> bin[7] += intermediate[8]
343343
MOVQ 64(SI), BX
344344
ADDQ BX, R15
345345

base58/matmul_arm64.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// All intermediate values kept in registers to avoid memory traffic.
99
// Fully unrolled, zero entries skipped.
1010
//
11-
// ARM64 MADD semantics in Go asm: MADD Rm, Ra, Rn, Rd Rd = Ra + Rn * Rm
11+
// ARM64 MADD semantics in Go asm: MADD Rm, Ra, Rn, Rd -> Rd = Ra + Rn * Rm
1212
TEXT ·encodeMatMul32(SB), NOSPLIT|NOFRAME, $0-16
1313
MOVD src+0(FP), R0
1414
MOVD intermediate+8(FP), R2
@@ -258,7 +258,7 @@ TEXT ·decodeMatMul32(SB), NOSPLIT|NOFRAME, $0-16
258258
MOVWU 252(R1), R20
259259
MADD R10, R19, R20, R19
260260

261-
// Row 8: table[8] = {0,0,0,0,0,0,0,1} bin[7] += intermediate[8]
261+
// Row 8: table[8] = {0,0,0,0,0,0,0,1} -> bin[7] += intermediate[8]
262262
ADD R21, R19, R19
263263

264264
// Store bin[0..7].

cli/cli.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,20 @@ import (
2323
func GetDecryptPassphrase() (string, error) {
2424
passphrase, err := GetPassword("Enter passphrase to decrypt your vault: ")
2525
if err != nil {
26-
return "", fmt.Errorf("reading password: %s", err)
26+
return "", fmt.Errorf("reading password: %w", err)
2727
}
2828

2929
return passphrase, nil
3030
}
3131
func GetEncryptPassphrase() (string, error) {
3232
passphrase, err := GetPassword("Enter passphrase to encrypt your vault: ")
3333
if err != nil {
34-
return "", fmt.Errorf("reading password: %s", err)
34+
return "", fmt.Errorf("reading password: %w", err)
3535
}
3636

3737
passphraseConfirm, err := GetPassword("Confirm passphrase: ")
3838
if err != nil {
39-
return "", fmt.Errorf("reading confirmation password: %s", err)
39+
return "", fmt.Errorf("reading confirmation password: %w", err)
4040
}
4141

4242
if passphrase != passphraseConfirm {

cmd/slnc/cmd/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import (
3030
// Version represents the cmd command version
3131
var Version string
3232

33-
//const defaultRPCURL = "http://localhost:8899"
33+
// const defaultRPCURL = "http://localhost:8899"
3434
const defaultRPCURL = "http://api.mainnet-beta.solana.com"
3535

3636
// RootCmd represents the eosc command

cmd/slnc/cmd/token_list_mints.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ var tokenListMintsCmd = &cobra.Command{
4343
fmt.Sprintf("%d", m.Decimals),
4444
}
4545
if m.MintAuthority != nil {
46-
line = append(line, fmt.Sprintf("%s", m.MintAuthority))
46+
line = append(line, m.MintAuthority.String())
4747
} else {
4848
line = append(line, "No mint authority")
4949
}
5050
if m.FreezeAuthority != nil {
51-
line = append(line, fmt.Sprintf("%s", m.FreezeAuthority))
51+
line = append(line, m.FreezeAuthority.String())
5252
} else {
5353
line = append(line, "No freeze authority")
5454
}

0 commit comments

Comments
 (0)