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
58 changes: 58 additions & 0 deletions .contract-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Contract Configuration File

This file (`contract-config.json`) is the single source of truth for all contract configuration in the SprintFund project.

## Fields

### version
The contract version number (as a string). Currently "3" for sprintfund-core-v3.

### contract.address
The Stacks address that deployed the contract. This is the contract owner address.

### contract.name
The name of the active contract. Must match the deployed contract name exactly.

### contract.principal
The full contract principal in the format `address.name`. This is automatically constructed but included for convenience.

### network.default
The default network to use when no network is specified. Should be "mainnet" for production.

### network.mainnet
Configuration for Stacks mainnet including API and explorer URLs.

### network.testnet
Configuration for Stacks testnet including API and explorer URLs.

### legacy
Information about deprecated contract versions. Used for migration scripts and documentation.

## Usage

### JavaScript/Node.js
```javascript
import { getContractAddress, getContractName } from './scripts/lib/contract-config.js';
```

### TypeScript/Frontend
```typescript
import { config } from './frontend/src/lib/contract-config';
```

### Shell Scripts
```bash
CONTRACT_ADDRESS=$(jq -r '.contract.address' contract-config.json)
CONTRACT_NAME=$(jq -r '.contract.name' contract-config.json)
```

## Updating

When updating contract configuration:

1. Edit this file with new values
2. Run `npm run validate-config` to verify consistency
3. Update any documentation that references the old values
4. Commit the changes

See `CONFIGURATION.md` for more details.
17 changes: 17 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.{js,ts,tsx,json}]
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false

[*.json]
insert_final_newline = false
12 changes: 1 addition & 11 deletions .github/workflows/validate-config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Validate Configuration
name: Validate Contract Configuration

on:
pull_request:
Expand All @@ -13,9 +13,6 @@ on:
- main
paths:
- 'contract-config.json'
- 'frontend/src/config.ts'
- 'frontend/config.ts'
- '.env.example'

jobs:
validate:
Expand All @@ -39,10 +36,3 @@ jobs:
run: |
cd scripts
npm run validate-config

- name: Check for config drift
if: failure()
run: |
echo "Configuration validation failed!"
echo "Please ensure all config files reference the centralized contract-config.json"
exit 1
41 changes: 41 additions & 0 deletions CHANGELOG_CONFIG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Configuration System Changelog

## [1.0.0] - 2026-04-28

### Added
- Centralized contract configuration file (`contract-config.json`)
- Configuration loader utilities for JavaScript and TypeScript
- Validation script to check config consistency across files
- Update script to propagate config changes
- Comprehensive documentation (CONFIGURATION.md, MIGRATION_CONFIG.md)
- TypeScript definitions for config loader
- Unit tests for config loader functions
- GitHub Actions workflow for automated validation
- Helper functions for network and legacy contract management

### Changed
- Updated `frontend/src/config.ts` to use centralized config as fallback
- Fixed `frontend/config.ts` to use correct contract name (v3)
- Updated all scripts to load from centralized config:
- `scripts/create-proposal.js`
- `scripts/stake.js`
- `scripts/call-logger.js`
- `scripts/withdraw-legacy.js`
- Updated `create-test-proposal.sh` to load from centralized config
- Updated `.env.example` to include contract name
- Updated `CONTRACT_VERSIONS.md` to reference centralized config
- Updated `scripts/README.md` with configuration section

### Fixed
- Contract name drift between root and src config files
- Hardcoded contract values in multiple scripts
- Missing contract name in environment example
- Inconsistent configuration across the codebase

### Benefits
- Single source of truth prevents configuration drift
- Easy updates by changing one file
- Automated validation catches mismatches
- Clear documentation for configuration management
- Type-safe configuration access
- Reduced maintenance burden for version updates
1 change: 1 addition & 0 deletions scripts/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
5 changes: 5 additions & 0 deletions scripts/lib/contract-config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,10 @@ export function getContractName(): string;
export function getContractPrincipal(): string;
export function getNetworkConfig(networkName?: string): { apiUrl: string; explorerUrl: string };
export function getContractVersion(): string;
export function getLegacyContractName(version: string): string | null;
export function isLegacyContract(contractName: string): boolean;
export function getAllNetworks(): string[];
export function getDefaultNetwork(): string;

export function getLegacyContractName(version: string | number): string | null;
export function isLegacyContract(contractName: string): boolean;
10 changes: 10 additions & 0 deletions scripts/lib/contract-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,13 @@ export function isLegacyContract(contractName) {
const legacyNames = Object.values(config.legacy || {}).map(v => v.name);
return legacyNames.includes(contractName);
}

export function getAllNetworks() {
const config = loadContractConfig();
return Object.keys(config.network).filter(key => key !== 'default');
}

export function getDefaultNetwork() {
const config = loadContractConfig();
return config.network.default;
}
40 changes: 40 additions & 0 deletions scripts/lib/contract-config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,43 @@ describe('contract-config', () => {
});
});
});

describe('getLegacyContractName', () => {
it('returns legacy contract name for v1', () => {
const name = getLegacyContractName('1');
expect(name).toBe('sprintfund-core');
});

it('returns null for non-existent version', () => {
const name = getLegacyContractName('99');
expect(name).toBeNull();
});
});

describe('isLegacyContract', () => {
it('returns true for legacy contract', () => {
const result = isLegacyContract('sprintfund-core');
expect(result).toBe(true);
});

it('returns false for current contract', () => {
const result = isLegacyContract('sprintfund-core-v3');
expect(result).toBe(false);
});
});

describe('getAllNetworks', () => {
it('returns all network names', () => {
const networks = getAllNetworks();
expect(networks).toContain('mainnet');
expect(networks).toContain('testnet');
expect(networks).not.toContain('default');
});
});

describe('getDefaultNetwork', () => {
it('returns the default network', () => {
const network = getDefaultNetwork();
expect(network).toBe('mainnet');
});
});
2 changes: 1 addition & 1 deletion scripts/lib/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"deploy-logger": "node deploy-logger.js",
"call-logger": "node call-logger.js",
"validate-config": "node scripts/validate-config.js",
"update-config": "node scripts/update-config.js",
"test": "jest"
},
"dependencies": {
Expand Down
Loading