go-crypto-wallet / internal
Cursor rule128 starsChanged 6 months agoMITView on GitHub
Interface Definition Rules for `internal/`
We split this internal-interface.mdc into the rules it gives an agent
6 rules. About 0 are common, 2 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 22
Use cases and adapters must declare only the interface surface they need — never a broader one.
- Very specific: line 28
All interfaces for external dependencies (blockchain APIs, repositories, file storage) MUST be defined in internal/application/ports/.
- Very specific: line 89
If the same interface combination is needed in two or more files, promote it to a named interface in …
- Very specific: line 129
When a composed interface already exists in apibtc, use it — do not redefine locally.
- Very specific: line 143
Use cases never receive Bitcoiner — the DI layer narrows it to the required small interface.
- Distinctive: line 161
Place them in the "Composed Interfaces for Common Use Cases" section with a descriptive comment explaining which use cases they serve.
≈ “Common” is an estimate: at least 1 in 5 of the 6,350 Cursor rule files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
---
description: Interface Definition Rules for `internal/`
globs: ["internal/**"]
alwaysApply: false
---
# Interface Definition Rules for `internal/`
## Overview
Rules for defining and using interfaces inside the `internal/` directory.
These rules enforce the Interface Segregation Principle (ISP) throughout the codebase.
## Core Principles
**Interfaces are defined where they are used, not where they are implemented.**
The `application/ports` layer owns all interface definitions.
The `infrastructure` layer contains only concrete implementations — never interface definitions.
**Depend only on the methods you actually call.**
Use cases and adapters must declare only the interface surface they need — never a broader one.
## Rules
### 0. Interface Ownership: `application/ports` Defines, `infrastructure` Implements
All interfaces for external dependencies (blockchain APIs, repositories, file storage) MUST be defined in `internal/application/ports/`.
The `infrastructure/` layer MUST NOT define any interfaces — only concrete structs that implement them.
```
internal/application/ports/api/btc/interface.go ← interface definitions live here
internal/infrastructure/api/btc/bitcoin.go ← concrete implementation only
```
```go
// ❌ BAD: interface defined in infrastructure layer
// internal/infrastructure/api/btc/bitcoin.go
type BitcoinAPI interface {
GetBalance() (float64, error)
}
// ✅ GOOD: interface defined in application/ports, infrastructure only implements
// internal/application/ports/api/btc/interface.go
type BalanceChecker interface {
GetBalance() (btcutil.Amount, error)
}
// internal/infrastructure/api/btc/bitcoin.go
type Bitcoin struct { ... }
func (b *Bitcoin) GetBalance() (btcutil.Amount, error) { ... } // implements BalanceChecker
```
### 1. Never Use `Bitcoiner` or `BCHer` Directly
`apibtc.Bitcoiner` and `apibtc.BCHer` are legacy monolithic interfaces.
They must NEVER appear as parameters or field types in use cases or adapters.
```go
// ❌ BAD: depends on the full monolithic interface
type myUseCase struct {
btc apibtc.Bitcoiner
}
// ✅ GOOD: depends on only what is needed
type myUseCase struct {
btc apibtc.MultisigManager
}
```
### 2. No Single-Interface Wrappers
A local type that simply re-wraps one existing interface adds no value. Use the named interface directly.
```go
// ❌ BAD: redundant wrapper
type sendTxBCHClient interface {
apibtc.TransactionSender
}
// ✅ GOOD: use the named interface directly
type sendTransactionUseCase struct {
bchClient apibtc.TransactionSender
}
```
### 3. No Duplicate Local Interfaces Across Packages
If the same interface combination is needed in two or more files, promote it to a named interface in `internal/application/ports/api/btc/interface.go`.
```go
// ❌ BAD: identical definition in keygen/btc/ AND sign/btc/
type importPrivKeyBTCClient interface {
apibtc.ChainConfigProvider
apibtc.PrivateKeyImporter
apibtc.AddressOperator
}
// ✅ GOOD: promote to interface.go, use everywhere
// In interface.go:
type PrivateKeyImportClient interface {
ChainConfigProvider
PrivateKeyImporter
AddressOperator
}
// In use case files:
func NewImportPrivateKeyUseCase(btc apibtc.PrivateKeyImportClient, ...) { ... }
```
### 4. When to Define a Local Interface
Define a local interface **only** when:
- It combines 2+ small interfaces that do **not** yet form a named composite in `apibtc`
- **AND** it is used in exactly one file (not duplicated)
Once two files share the same combination, promote it to `interface.go`.
```go
// ✅ ACCEPTABLE: unique combination used only in this file
type createTxBCHClient interface {
apibtc.TransactionCreationDeps
apibtc.SomeOtherInterface
}
```
### 5. Use Named Composed Interfaces from `interface.go`
When a composed interface already exists in `apibtc`, use it — do not redefine locally.
| Named interface | Composed from |
|---|---|
| `BTCTransactionSigner` | `ChainConfigProvider` + `PSBTSigner` + `PSBTHandler` |
| `BCHTransactionSigner` | `RawTransactionConverter` + `RawTransactionSigner` |
| `TransactionCreationDeps` | `ChainConfigProvider` + `AmountConverter` + `UTXOProvider` + `RawTransactionCreator` + `AddressOperator` + `BalanceChecker` |
| `PrivateKeyImportClient` | `ChainConfigProvider` + `PrivateKeyImporter` + `AddressOperator` |
| `AddressImportClient` | `ChainConfigProvider` + `LegacyAddressImporter` + `AddressOperator` |
### 6. DI Layer and Infrastructure Use `Bitcoiner`
The DI container and infrastructure factories use `apibtc.Bitcoiner` (the full monolithic interface).
`Bitcoiner` is the ONLY place where the full interface is permitted — all other layers use small focused interfaces.
Use cases never receive `Bitcoiner` — the DI layer narrows it to the required small interface.
```go
// DI container (internal/di/container.go) — Bitcoiner is fine here
btc apibtc.Bitcoiner
// Use case constructor — only what is needed
func NewSignTransactionUseCase(btc apibtc.BTCTransactionSigner, ...) { ... }
```
### 7. Where to Add New Composed Interfaces
New composed interfaces belong in:
```
internal/application/ports/api/btc/interface.go
```
Place them in the **"Composed Interfaces for Common Use Cases"** section with a descriptive comment explaining which use cases they serve.
## Decision Flowchart
```
Need an interface for a use case or adapter?
│
├─ Is there already a named interface in apibtc that covers exactly the needed methods?
│ └─ YES → Use it directly. Done.
│
├─ Is this combination used in 2+ files?
│ └─ YES → Add a named composed interface to interface.go. Use it everywhere.
│
├─ Is it a wrapper around exactly 1 existing interface?
│ └─ YES → Use that interface directly. No wrapper needed.
│
└─ Only 1 file, combines 2+ interfaces not yet composited → Define local interface in that file.
When a second file needs the same combo → promote to interface.go.
```
## Related Files
- `internal/application/ports/api/btc/interface.go` — all small + composed BTC/BCH interfaces
- `.claude/rules/internal/application-layer.md` — application layer rules
- `.claude/rules/internal/clean-architecture.md` — layer dependency rules
Where files are headingNew Cursor rule files have more rules about planning and tracking tasks, and fewer about code style.
Of the Cursor rule files we read, the 3,978 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository62 other files it gives its agents.
- AGENTS.mdAGENTS.md
- internal/AGENTS.mdAGENTS.md
- pkg/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- internal/CLAUDE.mdCLAUDE.md
- pkg/CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- .cursor/rules/agent-files.mdcCursor rule
- .cursor/rules/apps/bun.mdcCursor rule
- .cursor/rules/apps/eth-contracts.mdcCursor rule
- .cursor/rules/apps/xrp-server.mdcCursor rule
- .cursor/rules/database/atlas-hcl.mdcCursor rule
- .cursor/rules/database/sqlc.mdcCursor rule
- .cursor/rules/documentation-language.mdcCursor rule
- .cursor/rules/general.mdcCursor rule
- .cursor/rules/github-actions.mdcCursor rule
- .cursor/rules/go/conventions.mdcCursor rule
- .cursor/rules/go/di.mdcCursor rule
- .cursor/rules/go/go-path.mdcCursor rule
- .cursor/rules/go/go-test.mdcCursor rule
- .cursor/rules/internal/application-layer.mdcCursor rule
- .cursor/rules/internal/btc-shared.mdcCursor rule
- .cursor/rules/internal/clean-architecture.mdcCursor rule
- .cursor/rules/internal/cli-structure.mdcCursor rule
- .cursor/rules/internal/domain-layer.mdcCursor rule
- .cursor/rules/internal/dto.mdcCursor rule
- .cursor/rules/internal/infrastructure-layer.mdcCursor rule
- .cursor/rules/internal/interface-adapters-layer.mdcCursor rule
- .cursor/rules/internal/mockery.mdcCursor rule
- .cursor/rules/internal/repository.mdcCursor rule
- .cursor/rules/internal/usecase.mdcCursor rule
- .cursor/rules/proto.mdcCursor rule
- .cursor/rules/README.mdCursor rule
- .cursor/rules/security.mdcCursor rule
- .cursor/rules/shell-script.mdcCursor rule
- .cursor/rules/ssot.mdcCursor rule
- .cursor/rules/task-context-loading.mdcCursor rule
- .cursor/rules/typescript.mdcCursor rule
- .cursor/rules/yaml.mdcCursor rule
- llms.txtllms.txt
- bch-developmentSkill
- btc-terminologySkill
- db-migrationSkill
- devopsSkill
- docs-ssotSkill
- docs-updateSkill
- fix-pr-reviewSkill
- github-issue-creationSkill
- git-workflowSkill
- go-developmentSkill
- knowledge-gapSkill
- label-context-mappingSkill
- makefile-updateSkill
- mockerySkill
- openspec-apply-changeSkill
- openspec-archive-changeSkill
- openspec-exploreSkill
- openspec-proposeSkill
- shell-scriptsSkill
- solidity-developmentSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

