sovereignclaw 0.1.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/README.md +187 -0
- package/SKILL.md +186 -0
- package/bin/sovereignclaw.js +146 -0
- package/package.json +48 -0
- package/scripts/bridge.ts +431 -0
- package/scripts/bungee.ts +557 -0
- package/scripts/wallet.ts +195 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet Management for SovereignClaw
|
|
3
|
+
* Secure key generation, encryption, and storage
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { privateKeyToAccount, generateMnemonic, mnemonicToAccount, english } from 'viem/accounts';
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as crypto from 'crypto';
|
|
9
|
+
|
|
10
|
+
const WALLET_PATH = process.env.WALLET_PATH || './.wallet.enc';
|
|
11
|
+
const ENCRYPTION_KEY = process.env.WALLET_KEY || 'sovereignclaw-default-key-change-me';
|
|
12
|
+
|
|
13
|
+
interface WalletData {
|
|
14
|
+
address: string;
|
|
15
|
+
encryptedKey: string;
|
|
16
|
+
iv: string;
|
|
17
|
+
createdAt: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// ============ Encryption ============
|
|
21
|
+
|
|
22
|
+
function encrypt(text: string, password: string): { encrypted: string; iv: string } {
|
|
23
|
+
const key = crypto.scryptSync(password, 'salt', 32);
|
|
24
|
+
const iv = crypto.randomBytes(16);
|
|
25
|
+
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
|
26
|
+
let encrypted = cipher.update(text, 'utf8', 'hex');
|
|
27
|
+
encrypted += cipher.final('hex');
|
|
28
|
+
return { encrypted, iv: iv.toString('hex') };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function decrypt(encrypted: string, iv: string, password: string): string {
|
|
32
|
+
const key = crypto.scryptSync(password, 'salt', 32);
|
|
33
|
+
const decipher = crypto.createDecipheriv('aes-256-cbc', key, Buffer.from(iv, 'hex'));
|
|
34
|
+
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
|
35
|
+
decrypted += decipher.final('utf8');
|
|
36
|
+
return decrypted;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// ============ Wallet Operations ============
|
|
40
|
+
|
|
41
|
+
export function createWallet(): { mnemonic: string; address: string } {
|
|
42
|
+
const mnemonic = generateMnemonic(english);
|
|
43
|
+
const account = mnemonicToAccount(mnemonic);
|
|
44
|
+
|
|
45
|
+
const { encrypted, iv } = encrypt(mnemonic, ENCRYPTION_KEY);
|
|
46
|
+
const walletData: WalletData = {
|
|
47
|
+
address: account.address,
|
|
48
|
+
encryptedKey: encrypted,
|
|
49
|
+
iv,
|
|
50
|
+
createdAt: new Date().toISOString(),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
fs.writeFileSync(WALLET_PATH, JSON.stringify(walletData, null, 2));
|
|
54
|
+
|
|
55
|
+
return { mnemonic, address: account.address };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function importWallet(privateKeyOrMnemonic: string): string {
|
|
59
|
+
let address: string;
|
|
60
|
+
let toEncrypt: string;
|
|
61
|
+
|
|
62
|
+
if (privateKeyOrMnemonic.includes(' ')) {
|
|
63
|
+
const account = mnemonicToAccount(privateKeyOrMnemonic);
|
|
64
|
+
address = account.address;
|
|
65
|
+
toEncrypt = privateKeyOrMnemonic;
|
|
66
|
+
} else {
|
|
67
|
+
const normalized = privateKeyOrMnemonic.startsWith('0x')
|
|
68
|
+
? privateKeyOrMnemonic
|
|
69
|
+
: `0x${privateKeyOrMnemonic}`;
|
|
70
|
+
const account = privateKeyToAccount(normalized as `0x${string}`);
|
|
71
|
+
address = account.address;
|
|
72
|
+
toEncrypt = normalized;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { encrypted, iv } = encrypt(toEncrypt, ENCRYPTION_KEY);
|
|
76
|
+
const walletData: WalletData = {
|
|
77
|
+
address,
|
|
78
|
+
encryptedKey: encrypted,
|
|
79
|
+
iv,
|
|
80
|
+
createdAt: new Date().toISOString(),
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
fs.writeFileSync(WALLET_PATH, JSON.stringify(walletData, null, 2));
|
|
84
|
+
return address;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function loadWallet(): { address: string; privateKey: string } | null {
|
|
88
|
+
if (!fs.existsSync(WALLET_PATH)) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const data: WalletData = JSON.parse(fs.readFileSync(WALLET_PATH, 'utf8'));
|
|
93
|
+
const decrypted = decrypt(data.encryptedKey, data.iv, ENCRYPTION_KEY);
|
|
94
|
+
|
|
95
|
+
if (decrypted.includes(' ')) {
|
|
96
|
+
const account = mnemonicToAccount(decrypted);
|
|
97
|
+
return { address: account.address, privateKey: decrypted };
|
|
98
|
+
} else {
|
|
99
|
+
return { address: data.address, privateKey: decrypted };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function getWalletAddress(): string | null {
|
|
104
|
+
if (!fs.existsSync(WALLET_PATH)) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
const data: WalletData = JSON.parse(fs.readFileSync(WALLET_PATH, 'utf8'));
|
|
108
|
+
return data.address;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function walletExists(): boolean {
|
|
112
|
+
return fs.existsSync(WALLET_PATH);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ============ CLI ============
|
|
116
|
+
|
|
117
|
+
// Only run CLI when called directly (not when imported)
|
|
118
|
+
const isMainModule = import.meta.url === `file://${process.argv[1]}` ||
|
|
119
|
+
process.argv[1]?.endsWith('wallet.ts');
|
|
120
|
+
|
|
121
|
+
async function main() {
|
|
122
|
+
if (!isMainModule) return;
|
|
123
|
+
const args = process.argv.slice(2);
|
|
124
|
+
const [action] = args;
|
|
125
|
+
|
|
126
|
+
if (action === 'create') {
|
|
127
|
+
if (walletExists()) {
|
|
128
|
+
console.error('❌ Wallet already exists. Delete .wallet.enc to create a new one.');
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const { mnemonic, address } = createWallet();
|
|
133
|
+
console.log(`
|
|
134
|
+
🔐 SovereignClaw Treasury Created
|
|
135
|
+
|
|
136
|
+
⚠️ CRITICAL: Save this seed phrase NOW.
|
|
137
|
+
It will NEVER be shown again.
|
|
138
|
+
|
|
139
|
+
┌────────────────────────────────────────────────────────────┐
|
|
140
|
+
${mnemonic}
|
|
141
|
+
└────────────────────────────────────────────────────────────┘
|
|
142
|
+
|
|
143
|
+
📍 Address: ${address}
|
|
144
|
+
|
|
145
|
+
After saving securely, delete this terminal output.
|
|
146
|
+
`);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (action === 'import') {
|
|
151
|
+
const keyOrMnemonic = args.slice(1).join(' ');
|
|
152
|
+
if (!keyOrMnemonic) {
|
|
153
|
+
console.error('Usage: npx tsx wallet.ts import <private-key-or-mnemonic>');
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const address = importWallet(keyOrMnemonic);
|
|
158
|
+
console.log(`✅ Wallet imported: ${address}`);
|
|
159
|
+
console.log('⚠️ Delete the command containing your key from terminal history!');
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (action === 'address') {
|
|
164
|
+
const address = getWalletAddress();
|
|
165
|
+
if (!address) {
|
|
166
|
+
console.error('No wallet found. Run: npx tsx wallet.ts create');
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
console.log(address);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (action === 'exists') {
|
|
174
|
+
console.log(walletExists() ? 'true' : 'false');
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
console.log(`
|
|
179
|
+
SovereignClaw Wallet Manager
|
|
180
|
+
|
|
181
|
+
Usage:
|
|
182
|
+
npx tsx wallet.ts create Create new wallet (shows seed ONCE)
|
|
183
|
+
npx tsx wallet.ts import <key|phrase> Import existing wallet
|
|
184
|
+
npx tsx wallet.ts address Show wallet address
|
|
185
|
+
npx tsx wallet.ts exists Check if wallet exists
|
|
186
|
+
|
|
187
|
+
Environment:
|
|
188
|
+
WALLET_PATH Path to encrypted wallet file (default: .wallet.enc)
|
|
189
|
+
WALLET_KEY Encryption password (default: built-in, change for production!)
|
|
190
|
+
`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (isMainModule) {
|
|
194
|
+
main().catch(console.error);
|
|
195
|
+
}
|