solforge 0.1.6 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agi/agi.sqlite +0 -0
- package/.claude/settings.local.json +9 -0
- package/.github/workflows/release-binaries.yml +133 -0
- package/.tmp/.787ebcdbf7b8fde8-00000000.hm +0 -0
- package/.tmp/.bffe6efebdf8aedc-00000000.hm +0 -0
- package/AGENTS.md +271 -0
- package/CLAUDE.md +106 -0
- package/PROJECT_STRUCTURE.md +124 -0
- package/README.md +367 -393
- package/SOLANA_KIT_GUIDE.md +251 -0
- package/SOLFORGE.md +119 -0
- package/biome.json +34 -0
- package/bun.lock +743 -0
- package/docs/bun-single-file-executable.md +585 -0
- package/docs/cli-plan.md +154 -0
- package/docs/data-indexing-plan.md +214 -0
- package/docs/gui-roadmap.md +202 -0
- package/drizzle/0000_friendly_millenium_guard.sql +53 -0
- package/drizzle/0001_stale_sentinels.sql +2 -0
- package/drizzle/meta/0000_snapshot.json +329 -0
- package/drizzle/meta/0001_snapshot.json +345 -0
- package/drizzle/meta/_journal.json +20 -0
- package/drizzle.config.ts +12 -0
- package/index.ts +21 -0
- package/mint.sh +47 -0
- package/package.json +45 -69
- package/postcss.config.js +6 -0
- package/rpc-server.ts.backup +519 -0
- package/server/index.ts +5 -0
- package/server/lib/base58.ts +33 -0
- package/server/lib/faucet.ts +110 -0
- package/server/lib/spl-token.ts +57 -0
- package/server/methods/TEMPLATE.md +117 -0
- package/server/methods/account/get-account-info.ts +90 -0
- package/server/methods/account/get-balance.ts +27 -0
- package/server/methods/account/get-multiple-accounts.ts +83 -0
- package/server/methods/account/get-parsed-account-info.ts +21 -0
- package/server/methods/account/index.ts +12 -0
- package/server/methods/account/parsers/index.ts +52 -0
- package/server/methods/account/parsers/loader-upgradeable.ts +66 -0
- package/server/methods/account/parsers/spl-token.ts +237 -0
- package/server/methods/account/parsers/system.ts +4 -0
- package/server/methods/account/request-airdrop.ts +219 -0
- package/server/methods/admin/adopt-mint-authority.ts +94 -0
- package/server/methods/admin/clone-program-accounts.ts +55 -0
- package/server/methods/admin/clone-program.ts +152 -0
- package/server/methods/admin/clone-token-accounts.ts +117 -0
- package/server/methods/admin/clone-token-mint.ts +82 -0
- package/server/methods/admin/create-mint.ts +114 -0
- package/server/methods/admin/create-token-account.ts +137 -0
- package/server/methods/admin/helpers.ts +70 -0
- package/server/methods/admin/index.ts +10 -0
- package/server/methods/admin/list-mints.ts +21 -0
- package/server/methods/admin/load-program.ts +52 -0
- package/server/methods/admin/mint-to.ts +278 -0
- package/server/methods/block/get-block-height.ts +5 -0
- package/server/methods/block/get-block.ts +35 -0
- package/server/methods/block/get-blocks-with-limit.ts +23 -0
- package/server/methods/block/get-latest-blockhash.ts +12 -0
- package/server/methods/block/get-slot.ts +5 -0
- package/server/methods/block/index.ts +6 -0
- package/server/methods/block/is-blockhash-valid.ts +23 -0
- package/server/methods/epoch/get-cluster-nodes.ts +17 -0
- package/server/methods/epoch/get-epoch-info.ts +16 -0
- package/server/methods/epoch/get-epoch-schedule.ts +15 -0
- package/server/methods/epoch/get-highest-snapshot-slot.ts +9 -0
- package/server/methods/epoch/get-leader-schedule.ts +8 -0
- package/server/methods/epoch/get-max-retransmit-slot.ts +9 -0
- package/server/methods/epoch/get-max-shred-insert-slot.ts +9 -0
- package/server/methods/epoch/get-slot-leader.ts +6 -0
- package/server/methods/epoch/get-slot-leaders.ts +9 -0
- package/server/methods/epoch/get-stake-activation.ts +9 -0
- package/server/methods/epoch/get-stake-minimum-delegation.ts +9 -0
- package/server/methods/epoch/get-vote-accounts.ts +19 -0
- package/server/methods/epoch/index.ts +13 -0
- package/server/methods/epoch/minimum-ledger-slot.ts +5 -0
- package/server/methods/fee/get-fee-calculator-for-blockhash.ts +12 -0
- package/server/methods/fee/get-fee-for-message.ts +8 -0
- package/server/methods/fee/get-fee-rate-governor.ts +16 -0
- package/server/methods/fee/get-fees.ts +14 -0
- package/server/methods/fee/get-recent-prioritization-fees.ts +22 -0
- package/server/methods/fee/index.ts +5 -0
- package/server/methods/get-address-lookup-table.ts +31 -0
- package/server/methods/index.ts +265 -0
- package/server/methods/performance/get-recent-performance-samples.ts +25 -0
- package/server/methods/performance/get-transaction-count.ts +5 -0
- package/server/methods/performance/index.ts +2 -0
- package/server/methods/program/get-block-commitment.ts +9 -0
- package/server/methods/program/get-block-production.ts +14 -0
- package/server/methods/program/get-block-time.ts +21 -0
- package/server/methods/program/get-blocks.ts +11 -0
- package/server/methods/program/get-first-available-block.ts +9 -0
- package/server/methods/program/get-genesis-hash.ts +6 -0
- package/server/methods/program/get-identity.ts +6 -0
- package/server/methods/program/get-inflation-governor.ts +15 -0
- package/server/methods/program/get-inflation-rate.ts +10 -0
- package/server/methods/program/get-inflation-reward.ts +12 -0
- package/server/methods/program/get-largest-accounts.ts +8 -0
- package/server/methods/program/get-parsed-program-accounts.ts +12 -0
- package/server/methods/program/get-parsed-token-accounts-by-delegate.ts +12 -0
- package/server/methods/program/get-parsed-token-accounts-by-owner.ts +12 -0
- package/server/methods/program/get-program-accounts.ts +221 -0
- package/server/methods/program/get-supply.ts +13 -0
- package/server/methods/program/get-token-account-balance.ts +64 -0
- package/server/methods/program/get-token-accounts-by-delegate.ts +81 -0
- package/server/methods/program/get-token-accounts-by-owner.ts +390 -0
- package/server/methods/program/get-token-largest-accounts.ts +80 -0
- package/server/methods/program/get-token-supply.ts +38 -0
- package/server/methods/program/index.ts +21 -0
- package/server/methods/solforge/index.ts +155 -0
- package/server/methods/system/get-health.ts +5 -0
- package/server/methods/system/get-minimum-balance-for-rent-exemption.ts +13 -0
- package/server/methods/system/get-version.ts +9 -0
- package/server/methods/system/index.ts +3 -0
- package/server/methods/transaction/get-confirmed-transaction.ts +11 -0
- package/server/methods/transaction/get-parsed-transaction.ts +21 -0
- package/server/methods/transaction/get-signature-statuses.ts +72 -0
- package/server/methods/transaction/get-signatures-for-address.ts +45 -0
- package/server/methods/transaction/get-transaction.ts +428 -0
- package/server/methods/transaction/index.ts +7 -0
- package/server/methods/transaction/send-transaction.ts +232 -0
- package/server/methods/transaction/simulate-transaction.ts +56 -0
- package/server/rpc-server.ts +474 -0
- package/server/types.ts +74 -0
- package/server/ws-server.ts +171 -0
- package/sf.config.json +38 -0
- package/src/cli/bootstrap.ts +67 -0
- package/src/cli/commands/airdrop.ts +37 -0
- package/src/cli/commands/config.ts +39 -0
- package/src/cli/commands/mint.ts +187 -0
- package/src/cli/commands/program-clone.ts +124 -0
- package/src/cli/commands/program-load.ts +64 -0
- package/src/cli/commands/rpc-start.ts +46 -0
- package/src/cli/commands/token-adopt-authority.ts +37 -0
- package/src/cli/commands/token-clone.ts +113 -0
- package/src/cli/commands/token-create.ts +81 -0
- package/src/cli/main.ts +130 -0
- package/src/cli/run-solforge.ts +98 -0
- package/src/cli/setup-utils.ts +54 -0
- package/src/cli/setup-wizard.ts +256 -0
- package/src/cli/utils/args.ts +15 -0
- package/src/config/index.ts +130 -0
- package/src/db/index.ts +83 -0
- package/src/db/schema/accounts.ts +23 -0
- package/src/db/schema/address-signatures.ts +31 -0
- package/src/db/schema/index.ts +5 -0
- package/src/db/schema/meta-kv.ts +9 -0
- package/src/db/schema/transactions.ts +29 -0
- package/src/db/schema/tx-accounts.ts +33 -0
- package/src/db/tx-store.ts +229 -0
- package/src/gui/public/app.css +1 -0
- package/src/gui/public/index.html +19 -0
- package/src/gui/server.ts +297 -0
- package/src/gui/src/api.ts +127 -0
- package/src/gui/src/app.tsx +390 -0
- package/src/gui/src/components/airdrop-mint-form.tsx +216 -0
- package/src/gui/src/components/clone-program-modal.tsx +183 -0
- package/src/gui/src/components/clone-token-modal.tsx +211 -0
- package/src/gui/src/components/modal.tsx +127 -0
- package/src/gui/src/components/programs-panel.tsx +112 -0
- package/src/gui/src/components/status-panel.tsx +122 -0
- package/src/gui/src/components/tokens-panel.tsx +116 -0
- package/src/gui/src/hooks/use-interval.ts +17 -0
- package/src/gui/src/index.css +529 -0
- package/src/gui/src/main.tsx +17 -0
- package/src/migrations-bundled.ts +17 -0
- package/src/rpc/start.ts +44 -0
- package/tailwind.config.js +27 -0
- package/test-client.ts +120 -0
- package/tmp/inspect-html.ts +4 -0
- package/tmp/response-test.ts +5 -0
- package/tmp/test-html.ts +5 -0
- package/tmp/test-server.ts +13 -0
- package/tsconfig.json +24 -23
- package/LICENSE +0 -21
- package/scripts/postinstall.cjs +0 -103
- package/src/api-server-entry.ts +0 -109
- package/src/commands/add-program.ts +0 -337
- package/src/commands/init.ts +0 -122
- package/src/commands/list.ts +0 -136
- package/src/commands/mint.ts +0 -336
- package/src/commands/start.ts +0 -878
- package/src/commands/status.ts +0 -99
- package/src/commands/stop.ts +0 -406
- package/src/config/manager.ts +0 -157
- package/src/index.ts +0 -188
- package/src/services/api-server.ts +0 -532
- package/src/services/port-manager.ts +0 -177
- package/src/services/process-registry.ts +0 -154
- package/src/services/program-cloner.ts +0 -317
- package/src/services/token-cloner.ts +0 -809
- package/src/services/validator.ts +0 -295
- package/src/types/config.ts +0 -110
- package/src/utils/shell.ts +0 -110
package/.agi/agi.sqlite
ADDED
|
Binary file
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
name: Build and Release Binaries
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: write
|
|
11
|
+
actions: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
check-version:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
outputs:
|
|
17
|
+
version: ${{ steps.get_version.outputs.version }}
|
|
18
|
+
tag_exists: ${{ steps.check_tag.outputs.exists }}
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
with:
|
|
22
|
+
fetch-depth: 0
|
|
23
|
+
|
|
24
|
+
- name: Get version from package.json
|
|
25
|
+
id: get_version
|
|
26
|
+
run: echo "version=$(node -p \"require('./package.json').version\")" >> $GITHUB_OUTPUT
|
|
27
|
+
|
|
28
|
+
- name: Check if version tag exists
|
|
29
|
+
id: check_tag
|
|
30
|
+
run: |
|
|
31
|
+
if git rev-parse "v${{ steps.get_version.outputs.version }}" >/dev/null 2>&1; then
|
|
32
|
+
echo "exists=true" >> $GITHUB_OUTPUT
|
|
33
|
+
echo "Tag v${{ steps.get_version.outputs.version }} already exists, skipping"
|
|
34
|
+
else
|
|
35
|
+
echo "exists=false" >> $GITHUB_OUTPUT
|
|
36
|
+
echo "Tag v${{ steps.get_version.outputs.version }} does not exist, proceeding"
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
build-binaries:
|
|
40
|
+
needs: check-version
|
|
41
|
+
if: needs.check-version.outputs.tag_exists == 'false'
|
|
42
|
+
runs-on: ${{ matrix.runner }}
|
|
43
|
+
strategy:
|
|
44
|
+
matrix:
|
|
45
|
+
include:
|
|
46
|
+
- os: darwin
|
|
47
|
+
arch: x64
|
|
48
|
+
runner: macos-latest
|
|
49
|
+
- os: darwin
|
|
50
|
+
arch: arm64
|
|
51
|
+
runner: macos-latest
|
|
52
|
+
- os: linux
|
|
53
|
+
arch: x64
|
|
54
|
+
runner: ubuntu-latest
|
|
55
|
+
- os: linux
|
|
56
|
+
arch: arm64
|
|
57
|
+
runner: ubuntu-latest
|
|
58
|
+
- os: windows
|
|
59
|
+
arch: x64
|
|
60
|
+
runner: windows-latest
|
|
61
|
+
steps:
|
|
62
|
+
- uses: actions/checkout@v4
|
|
63
|
+
|
|
64
|
+
- uses: oven-sh/setup-bun@v1
|
|
65
|
+
with:
|
|
66
|
+
bun-version: latest
|
|
67
|
+
|
|
68
|
+
- name: Install dependencies
|
|
69
|
+
run: bun install
|
|
70
|
+
|
|
71
|
+
- name: Build binary
|
|
72
|
+
shell: bash
|
|
73
|
+
run: |
|
|
74
|
+
mkdir -p dist
|
|
75
|
+
TARGET="bun-${{ matrix.os }}-${{ matrix.arch }}"
|
|
76
|
+
OUTFILE="dist/solforge-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.os == 'windows' && '.exe' || '' }}"
|
|
77
|
+
bun build --compile --target="$TARGET" src/cli/main.ts --outfile "$OUTFILE"
|
|
78
|
+
|
|
79
|
+
- name: Upload artifact
|
|
80
|
+
uses: actions/upload-artifact@v4
|
|
81
|
+
with:
|
|
82
|
+
name: solforge-${{ matrix.os }}-${{ matrix.arch }}
|
|
83
|
+
path: dist/solforge-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.os == 'windows' && '.exe' || '' }}
|
|
84
|
+
|
|
85
|
+
publish:
|
|
86
|
+
needs: [check-version, build-binaries]
|
|
87
|
+
if: needs.check-version.outputs.tag_exists == 'false'
|
|
88
|
+
runs-on: ubuntu-latest
|
|
89
|
+
steps:
|
|
90
|
+
- uses: actions/checkout@v4
|
|
91
|
+
with:
|
|
92
|
+
fetch-depth: 0
|
|
93
|
+
|
|
94
|
+
- name: Download all artifacts
|
|
95
|
+
uses: actions/download-artifact@v4
|
|
96
|
+
with:
|
|
97
|
+
path: ./artifacts
|
|
98
|
+
|
|
99
|
+
- name: Flatten artifacts
|
|
100
|
+
run: |
|
|
101
|
+
mkdir -p ./release
|
|
102
|
+
find ./artifacts -type f -exec cp {} ./release/ \;
|
|
103
|
+
ls -la ./release/
|
|
104
|
+
|
|
105
|
+
- name: Create and push git tag
|
|
106
|
+
run: |
|
|
107
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
108
|
+
git config --local user.email "action@github.com"
|
|
109
|
+
git config --local user.name "GitHub Action"
|
|
110
|
+
git tag "v${VERSION}"
|
|
111
|
+
git push origin "v${VERSION}"
|
|
112
|
+
|
|
113
|
+
- name: Create GitHub Release
|
|
114
|
+
uses: softprops/action-gh-release@v2
|
|
115
|
+
with:
|
|
116
|
+
tag_name: v${{ needs.check-version.outputs.version }}
|
|
117
|
+
name: "SolForge v${{ needs.check-version.outputs.version }}"
|
|
118
|
+
body: |
|
|
119
|
+
## SolForge v${{ needs.check-version.outputs.version }}
|
|
120
|
+
|
|
121
|
+
Platform binaries are attached below.
|
|
122
|
+
|
|
123
|
+
- macOS (Intel): solforge-darwin-x64
|
|
124
|
+
- macOS (Apple Silicon): solforge-darwin-arm64
|
|
125
|
+
- Linux (x64): solforge-linux-x64
|
|
126
|
+
- Linux (ARM64): solforge-linux-arm64
|
|
127
|
+
- Windows (x64): solforge-windows-x64.exe
|
|
128
|
+
files: ./release/*
|
|
129
|
+
draft: false
|
|
130
|
+
prerelease: false
|
|
131
|
+
env:
|
|
132
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
133
|
+
|
|
File without changes
|
|
File without changes
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# Development Guidelines for SolForge
|
|
2
|
+
|
|
3
|
+
## Core Principles
|
|
4
|
+
|
|
5
|
+
### 1. Keep It Modular
|
|
6
|
+
- **No huge files**: If a file exceeds 200 lines, consider splitting it
|
|
7
|
+
- **Single responsibility**: Each module should do one thing well
|
|
8
|
+
- **Clear boundaries**: Well-defined interfaces between modules
|
|
9
|
+
|
|
10
|
+
### 2. Keep It Simple
|
|
11
|
+
- **Straightforward code**: Prefer clarity over cleverness
|
|
12
|
+
- **Minimal abstractions**: Only abstract when there's clear benefit
|
|
13
|
+
- **Explicit over implicit**: Make intentions clear in code
|
|
14
|
+
|
|
15
|
+
### 3. Keep It Fast
|
|
16
|
+
- **Performance matters**: This is a performance-critical tool
|
|
17
|
+
- **Measure first**: Profile before optimizing
|
|
18
|
+
- **Memory conscious**: Avoid unnecessary allocations
|
|
19
|
+
|
|
20
|
+
## Technology Rules
|
|
21
|
+
|
|
22
|
+
### Package Manager
|
|
23
|
+
- **ALWAYS use Bun**: No npm, yarn, pnpm, or anything else
|
|
24
|
+
- Commands:
|
|
25
|
+
- `bun install` (not npm install)
|
|
26
|
+
- `bun run` (not npm run)
|
|
27
|
+
- `bun test` (not jest/vitest)
|
|
28
|
+
- `bun build` (not webpack/esbuild)
|
|
29
|
+
|
|
30
|
+
### Runtime
|
|
31
|
+
- **Bun exclusively**: Use Bun-native APIs when available
|
|
32
|
+
- Prefer `Bun.serve()` over Express
|
|
33
|
+
- Use `Bun.file()` over `fs.readFile()`
|
|
34
|
+
- Use `bun:test` for testing
|
|
35
|
+
|
|
36
|
+
## Code Style
|
|
37
|
+
|
|
38
|
+
### File Naming
|
|
39
|
+
- **kebab-case**: All files use kebab-case
|
|
40
|
+
- ✅ `rpc-server.ts`
|
|
41
|
+
- ✅ `get-account-info.ts`
|
|
42
|
+
- ❌ `rpcServer.ts`
|
|
43
|
+
- ❌ `GetAccountInfo.ts`
|
|
44
|
+
|
|
45
|
+
### Directory Structure
|
|
46
|
+
```
|
|
47
|
+
server/
|
|
48
|
+
├── methods/
|
|
49
|
+
│ ├── account/ # When account.ts gets too big
|
|
50
|
+
│ │ ├── get-account-info.ts
|
|
51
|
+
│ │ ├── get-balance.ts
|
|
52
|
+
│ │ ├── get-multiple-accounts.ts
|
|
53
|
+
│ │ └── index.ts
|
|
54
|
+
│ ├── transaction/ # When transaction.ts gets too big
|
|
55
|
+
│ │ ├── send-transaction.ts
|
|
56
|
+
│ │ ├── simulate-transaction.ts
|
|
57
|
+
│ │ └── index.ts
|
|
58
|
+
│ └── index.ts
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### File Size Guidelines
|
|
62
|
+
- **< 100 lines**: Ideal file size
|
|
63
|
+
- **100-200 lines**: Acceptable
|
|
64
|
+
- **> 200 lines**: Consider splitting
|
|
65
|
+
- **> 300 lines**: Must split
|
|
66
|
+
|
|
67
|
+
### When to Split Files
|
|
68
|
+
If `account.ts` or `transaction.ts` grows large:
|
|
69
|
+
1. Create a directory with the same name
|
|
70
|
+
2. Split into individual method files
|
|
71
|
+
3. Create an index.ts that exports everything
|
|
72
|
+
4. Update imports to maintain compatibility
|
|
73
|
+
|
|
74
|
+
Example migration:
|
|
75
|
+
```typescript
|
|
76
|
+
// Before: server/methods/account.ts (300+ lines)
|
|
77
|
+
export const getAccountInfo = ...
|
|
78
|
+
export const getBalance = ...
|
|
79
|
+
export const requestAirdrop = ...
|
|
80
|
+
|
|
81
|
+
// After: server/methods/account/index.ts
|
|
82
|
+
export { getAccountInfo } from './get-account-info';
|
|
83
|
+
export { getBalance } from './get-balance';
|
|
84
|
+
export { requestAirdrop } from './request-airdrop';
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## TypeScript Guidelines
|
|
88
|
+
|
|
89
|
+
### Types
|
|
90
|
+
- **Define interfaces**: Use interfaces for object shapes
|
|
91
|
+
- **Avoid `any`**: Use `unknown` if type is truly unknown
|
|
92
|
+
- **Export types**: Keep types in separate files when shared
|
|
93
|
+
|
|
94
|
+
### Imports
|
|
95
|
+
- **Explicit imports**: Import only what you need
|
|
96
|
+
- **Type imports**: Use `import type` when importing only types
|
|
97
|
+
- **Organized imports**: Group by external, internal, types
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// External
|
|
101
|
+
import { PublicKey } from "@solana/web3.js";
|
|
102
|
+
|
|
103
|
+
// Internal
|
|
104
|
+
import { someHelper } from "../helpers";
|
|
105
|
+
|
|
106
|
+
// Types
|
|
107
|
+
import type { RpcMethodHandler } from "../types";
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Method Implementation
|
|
111
|
+
|
|
112
|
+
### Structure
|
|
113
|
+
Each RPC method should follow this pattern:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import type { RpcMethodHandler } from "../types";
|
|
117
|
+
|
|
118
|
+
export const methodName: RpcMethodHandler = (id, params, context) => {
|
|
119
|
+
// 1. Parse and validate params
|
|
120
|
+
const [param1, param2] = params;
|
|
121
|
+
|
|
122
|
+
// 2. Execute logic
|
|
123
|
+
try {
|
|
124
|
+
const result = context.svm.someOperation();
|
|
125
|
+
|
|
126
|
+
// 3. Return formatted response
|
|
127
|
+
return context.createSuccessResponse(id, result);
|
|
128
|
+
} catch (error: any) {
|
|
129
|
+
// 4. Handle errors appropriately
|
|
130
|
+
return context.createErrorResponse(id, -32602, "Error message", error.message);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Error Codes
|
|
136
|
+
Use standard JSON-RPC error codes:
|
|
137
|
+
- `-32700`: Parse error
|
|
138
|
+
- `-32600`: Invalid request
|
|
139
|
+
- `-32601`: Method not found
|
|
140
|
+
- `-32602`: Invalid params
|
|
141
|
+
- `-32603`: Internal error
|
|
142
|
+
- `-32000` to `-32099`: Server errors
|
|
143
|
+
|
|
144
|
+
## Testing
|
|
145
|
+
|
|
146
|
+
### Test Organization
|
|
147
|
+
- Test files next to source: `method-name.test.ts`
|
|
148
|
+
- Use descriptive test names
|
|
149
|
+
- Test both success and error cases
|
|
150
|
+
|
|
151
|
+
### Test Structure
|
|
152
|
+
```typescript
|
|
153
|
+
import { test, expect } from "bun:test";
|
|
154
|
+
|
|
155
|
+
test("getAccountInfo returns account data", async () => {
|
|
156
|
+
// Arrange
|
|
157
|
+
const server = createTestServer();
|
|
158
|
+
|
|
159
|
+
// Act
|
|
160
|
+
const result = await server.handleRequest({...});
|
|
161
|
+
|
|
162
|
+
// Assert
|
|
163
|
+
expect(result.result).toBeDefined();
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Documentation
|
|
168
|
+
|
|
169
|
+
### Code Comments
|
|
170
|
+
- **Minimal comments**: Code should be self-documenting
|
|
171
|
+
- **Why, not what**: Explain complex logic, not obvious code
|
|
172
|
+
- **TODO format**: `// TODO: [description]`
|
|
173
|
+
|
|
174
|
+
### Method Documentation
|
|
175
|
+
Each new RPC method needs:
|
|
176
|
+
1. Entry in README.md
|
|
177
|
+
2. TypeScript types defined
|
|
178
|
+
3. Test coverage
|
|
179
|
+
4. Error cases documented
|
|
180
|
+
|
|
181
|
+
## Git Workflow
|
|
182
|
+
|
|
183
|
+
### Commit Messages
|
|
184
|
+
- **Conventional commits**: `type: description`
|
|
185
|
+
- Types: `feat`, `fix`, `docs`, `refactor`, `test`, `chore`
|
|
186
|
+
- Examples:
|
|
187
|
+
- `feat: add getTokenAccounts RPC method`
|
|
188
|
+
- `fix: handle empty transaction array`
|
|
189
|
+
- `refactor: split account methods into separate files`
|
|
190
|
+
|
|
191
|
+
### Branch Naming
|
|
192
|
+
- `feature/method-name` for new methods
|
|
193
|
+
- `fix/issue-description` for bug fixes
|
|
194
|
+
- `refactor/module-name` for refactoring
|
|
195
|
+
|
|
196
|
+
## Performance Considerations
|
|
197
|
+
|
|
198
|
+
### Do's
|
|
199
|
+
- ✅ Use `BigInt` for lamports
|
|
200
|
+
- ✅ Cache frequently accessed data
|
|
201
|
+
- ✅ Use batch operations when possible
|
|
202
|
+
- ✅ Profile before optimizing
|
|
203
|
+
|
|
204
|
+
### Don'ts
|
|
205
|
+
- ❌ Premature optimization
|
|
206
|
+
- ❌ Synchronous file I/O
|
|
207
|
+
- ❌ Unnecessary object cloning
|
|
208
|
+
- ❌ Large in-memory buffers
|
|
209
|
+
|
|
210
|
+
## Adding New RPC Methods
|
|
211
|
+
|
|
212
|
+
### Checklist
|
|
213
|
+
- [ ] Create method file in appropriate directory
|
|
214
|
+
- [ ] Implement method following standard pattern
|
|
215
|
+
- [ ] Add to method exports in index.ts
|
|
216
|
+
- [ ] Register in rpcMethods object
|
|
217
|
+
- [ ] Add tests
|
|
218
|
+
- [ ] Update README.md
|
|
219
|
+
- [ ] Test with real client
|
|
220
|
+
|
|
221
|
+
### Template
|
|
222
|
+
```typescript
|
|
223
|
+
// server/methods/category/method-name.ts
|
|
224
|
+
import type { RpcMethodHandler } from "../../types";
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Implements the getMethodName RPC method
|
|
228
|
+
* @see https://docs.solana.com/api/http#getmethodname
|
|
229
|
+
*/
|
|
230
|
+
export const getMethodName: RpcMethodHandler = (id, params, context) => {
|
|
231
|
+
const [param1, config] = params;
|
|
232
|
+
|
|
233
|
+
try {
|
|
234
|
+
// Implementation
|
|
235
|
+
const result = {};
|
|
236
|
+
|
|
237
|
+
return context.createSuccessResponse(id, {
|
|
238
|
+
context: { slot: Number(context.slot) },
|
|
239
|
+
value: result
|
|
240
|
+
});
|
|
241
|
+
} catch (error: any) {
|
|
242
|
+
return context.createErrorResponse(
|
|
243
|
+
id,
|
|
244
|
+
-32602,
|
|
245
|
+
"Invalid params",
|
|
246
|
+
error.message
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Review Checklist
|
|
253
|
+
|
|
254
|
+
Before submitting code:
|
|
255
|
+
- [ ] Files under 200 lines
|
|
256
|
+
- [ ] Using kebab-case filenames
|
|
257
|
+
- [ ] No npm/yarn commands
|
|
258
|
+
- [ ] Types properly defined
|
|
259
|
+
- [ ] Errors handled appropriately
|
|
260
|
+
- [ ] Tests written
|
|
261
|
+
- [ ] Documentation updated
|
|
262
|
+
|
|
263
|
+
## Questions?
|
|
264
|
+
|
|
265
|
+
When in doubt:
|
|
266
|
+
1. Keep it simple
|
|
267
|
+
2. Keep it modular
|
|
268
|
+
3. Keep it fast
|
|
269
|
+
4. Use Bun
|
|
270
|
+
|
|
271
|
+
Remember: We're building a tool that developers will use hundreds of times per day. Every millisecond counts, and every good developer experience decision matters.
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
|
|
2
|
+
Default to using Bun instead of Node.js.
|
|
3
|
+
|
|
4
|
+
- Use `bun <file>` instead of `node <file>` or `ts-node <file>`
|
|
5
|
+
- Use `bun test` instead of `jest` or `vitest`
|
|
6
|
+
- Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
|
|
7
|
+
- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
|
|
8
|
+
- Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
|
|
9
|
+
- Bun automatically loads .env, so don't use dotenv.
|
|
10
|
+
|
|
11
|
+
## APIs
|
|
12
|
+
|
|
13
|
+
- `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
|
|
14
|
+
- `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
|
|
15
|
+
- `Bun.redis` for Redis. Don't use `ioredis`.
|
|
16
|
+
- `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
|
|
17
|
+
- `WebSocket` is built-in. Don't use `ws`.
|
|
18
|
+
- Prefer `Bun.file` over `node:fs`'s readFile/writeFile
|
|
19
|
+
- Bun.$`ls` instead of execa.
|
|
20
|
+
|
|
21
|
+
## Testing
|
|
22
|
+
|
|
23
|
+
Use `bun test` to run tests.
|
|
24
|
+
|
|
25
|
+
```ts#index.test.ts
|
|
26
|
+
import { test, expect } from "bun:test";
|
|
27
|
+
|
|
28
|
+
test("hello world", () => {
|
|
29
|
+
expect(1).toBe(1);
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Frontend
|
|
34
|
+
|
|
35
|
+
Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
|
|
36
|
+
|
|
37
|
+
Server:
|
|
38
|
+
|
|
39
|
+
```ts#index.ts
|
|
40
|
+
import index from "./index.html"
|
|
41
|
+
|
|
42
|
+
Bun.serve({
|
|
43
|
+
routes: {
|
|
44
|
+
"/": index,
|
|
45
|
+
"/api/users/:id": {
|
|
46
|
+
GET: (req) => {
|
|
47
|
+
return new Response(JSON.stringify({ id: req.params.id }));
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
// optional websocket support
|
|
52
|
+
websocket: {
|
|
53
|
+
open: (ws) => {
|
|
54
|
+
ws.send("Hello, world!");
|
|
55
|
+
},
|
|
56
|
+
message: (ws, message) => {
|
|
57
|
+
ws.send(message);
|
|
58
|
+
},
|
|
59
|
+
close: (ws) => {
|
|
60
|
+
// handle close
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
development: {
|
|
64
|
+
hmr: true,
|
|
65
|
+
console: true,
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
|
|
71
|
+
|
|
72
|
+
```html#index.html
|
|
73
|
+
<html>
|
|
74
|
+
<body>
|
|
75
|
+
<h1>Hello, world!</h1>
|
|
76
|
+
<script type="module" src="./frontend.tsx"></script>
|
|
77
|
+
</body>
|
|
78
|
+
</html>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
With the following `frontend.tsx`:
|
|
82
|
+
|
|
83
|
+
```tsx#frontend.tsx
|
|
84
|
+
import React from "react";
|
|
85
|
+
|
|
86
|
+
// import .css files directly and it works
|
|
87
|
+
import './index.css';
|
|
88
|
+
|
|
89
|
+
import { createRoot } from "react-dom/client";
|
|
90
|
+
|
|
91
|
+
const root = createRoot(document.body);
|
|
92
|
+
|
|
93
|
+
export default function Frontend() {
|
|
94
|
+
return <h1>Hello, world!</h1>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
root.render(<Frontend />);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Then, run index.ts
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
bun --hot ./index.ts
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
For more information, read the Bun API docs in `node_modules/bun-types/docs/**.md`.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# SolForge Project Structure
|
|
2
|
+
|
|
3
|
+
## Current Architecture
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
solforge/
|
|
7
|
+
├── index.ts # Main entry point
|
|
8
|
+
├── server/ # Core server module
|
|
9
|
+
│ ├── index.ts # Module exports
|
|
10
|
+
│ ├── rpc-server.ts # Main RPC server class
|
|
11
|
+
│ ├── types.ts # Shared TypeScript types
|
|
12
|
+
│ └── methods/ # RPC method implementations
|
|
13
|
+
│ ├── index.ts # Method registry
|
|
14
|
+
│ ├── account/ # Account methods (modular)
|
|
15
|
+
│ │ ├── index.ts
|
|
16
|
+
│ │ ├── get-account-info.ts
|
|
17
|
+
│ │ ├── get-balance.ts
|
|
18
|
+
│ │ ├── get-multiple-accounts.ts
|
|
19
|
+
│ │ └── request-airdrop.ts
|
|
20
|
+
│ ├── transaction.ts # Transaction methods (monolithic for now)
|
|
21
|
+
│ ├── block.ts # Block/slot methods
|
|
22
|
+
│ ├── system.ts # System methods
|
|
23
|
+
│ └── TEMPLATE.md # Template for new methods
|
|
24
|
+
├── test-client.ts # Test client implementation
|
|
25
|
+
├── package.json # Dependencies (Bun-based)
|
|
26
|
+
├── tsconfig.json # TypeScript configuration
|
|
27
|
+
├── SOLFORGE.md # Project vision and roadmap
|
|
28
|
+
├── AGENTS.md # Development guidelines
|
|
29
|
+
├── README.md # User documentation
|
|
30
|
+
└── SOLANA_KIT_GUIDE.md # Solana Kit usage guide
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Module Organization
|
|
34
|
+
|
|
35
|
+
### When to Split Files
|
|
36
|
+
|
|
37
|
+
Files start as single modules and split when they exceed 200 lines:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Initial: methods/category.ts (< 200 lines)
|
|
41
|
+
↓
|
|
42
|
+
Growth: methods/category.ts (> 200 lines)
|
|
43
|
+
↓
|
|
44
|
+
Split: methods/category/
|
|
45
|
+
├── index.ts
|
|
46
|
+
├── method-one.ts
|
|
47
|
+
├── method-two.ts
|
|
48
|
+
└── method-three.ts
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Current Status
|
|
52
|
+
|
|
53
|
+
- ✅ **Account methods**: Already modularized (4 methods)
|
|
54
|
+
- 📦 **Transaction methods**: Single file (4 methods, ~145 lines)
|
|
55
|
+
- 📦 **Block methods**: Single file (3 methods, ~20 lines)
|
|
56
|
+
- 📦 **System methods**: Single file (3 methods, ~27 lines)
|
|
57
|
+
|
|
58
|
+
### Adding New Methods
|
|
59
|
+
|
|
60
|
+
1. **Determine category** (account/transaction/block/system/custom)
|
|
61
|
+
2. **Check file size** of target category
|
|
62
|
+
3. **If < 200 lines**: Add to existing file
|
|
63
|
+
4. **If > 200 lines**: Create subdirectory structure
|
|
64
|
+
5. **Follow template** in `methods/TEMPLATE.md`
|
|
65
|
+
6. **Register method** in `methods/index.ts`
|
|
66
|
+
7. **Update documentation**
|
|
67
|
+
|
|
68
|
+
## Key Files
|
|
69
|
+
|
|
70
|
+
### Core Components
|
|
71
|
+
|
|
72
|
+
- `server/rpc-server.ts`: Main server class, handles routing
|
|
73
|
+
- `server/types.ts`: TypeScript interfaces for RPC
|
|
74
|
+
- `server/methods/index.ts`: Method registry and exports
|
|
75
|
+
|
|
76
|
+
### Configuration
|
|
77
|
+
|
|
78
|
+
- `package.json`: Dependencies (minimal, Bun-focused)
|
|
79
|
+
- `tsconfig.json`: TypeScript settings
|
|
80
|
+
|
|
81
|
+
### Documentation
|
|
82
|
+
|
|
83
|
+
- `SOLFORGE.md`: What we're building and why
|
|
84
|
+
- `AGENTS.md`: How to develop for SolForge
|
|
85
|
+
- `README.md`: User-facing documentation
|
|
86
|
+
- `PROJECT_STRUCTURE.md`: This file
|
|
87
|
+
|
|
88
|
+
## Naming Conventions
|
|
89
|
+
|
|
90
|
+
- **Files**: `kebab-case.ts`
|
|
91
|
+
- **Directories**: `kebab-case/`
|
|
92
|
+
- **Exports**: `camelCase`
|
|
93
|
+
- **Types/Interfaces**: `PascalCase`
|
|
94
|
+
|
|
95
|
+
## Import Hierarchy
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// 1. External packages
|
|
99
|
+
import { PublicKey } from "@solana/web3.js";
|
|
100
|
+
|
|
101
|
+
// 2. Internal modules
|
|
102
|
+
import { helper } from "../utils";
|
|
103
|
+
|
|
104
|
+
// 3. Types
|
|
105
|
+
import type { RpcMethodHandler } from "../types";
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Future Growth
|
|
109
|
+
|
|
110
|
+
As we add more RPC methods, the structure will evolve:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
methods/
|
|
114
|
+
├── account/ # 10+ methods
|
|
115
|
+
├── transaction/ # 8+ methods
|
|
116
|
+
├── block/ # 5+ methods
|
|
117
|
+
├── system/ # 6+ methods
|
|
118
|
+
├── token/ # Future: SPL token methods
|
|
119
|
+
├── stake/ # Future: Staking methods
|
|
120
|
+
├── vote/ # Future: Vote methods
|
|
121
|
+
└── deprecated/ # Future: Legacy compatibility
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Each category becomes modular when it reaches complexity threshold.
|