Skip to content

Commit 6cd4764

Browse files
committed
System Touch
1 parent 50cf0b0 commit 6cd4764

3 files changed

Lines changed: 257 additions & 0 deletions

File tree

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
package bitcoin.module;
2+
3+
import connections.Connection;
4+
import national.NationalFinanceID;
5+
6+
import java.sql.*;
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
10+
/**
11+
* BitcoinWalletSession — handles telnet commands for browsing/selecting/trading BTC wallets.
12+
*
13+
* Commands:
14+
* bitcoin — show available versions (24-30)
15+
* bitcoin <version> — list wallets for that version
16+
* set wallet.name <name> — select wallet for session (persists to DB)
17+
* unset wallet.name — deselect wallet
18+
* trade btc <amount> — trade BTC from selected wallet (recorded in trades table)
19+
*
20+
* Original wallet data in bitcoin_wallets_v{N} is NEVER modified.
21+
* Trades are recorded in bitcoin_trades_v{N} tables.
22+
*/
23+
public class BitcoinWalletSession
24+
{
25+
private static final String AUTHOR = "Max Ruppln - Clear 21 Branch US Military";
26+
27+
/** Handle a bitcoin-related command. Returns response string. */
28+
public static String handle(String cmd, Connection conn, NationalFinanceID nfid)
29+
{
30+
String lower = cmd.trim().toLowerCase();
31+
32+
if (lower.equals("bitcoin"))
33+
return listVersions(conn);
34+
else if (lower.startsWith("bitcoin "))
35+
return listWallets(cmd.trim().substring(8).trim(), conn);
36+
else if (lower.startsWith("set wallet.name "))
37+
return setWallet(cmd.trim().substring(16).trim(), conn, nfid);
38+
else if (lower.equals("unset wallet.name"))
39+
return unsetWallet(conn, nfid);
40+
else if (lower.startsWith("trade btc "))
41+
return tradeBtc(cmd.trim().substring(10).trim(), conn, nfid);
42+
else if (lower.equals("show wallet"))
43+
return showWallet(conn);
44+
45+
return null; // not a bitcoin command
46+
}
47+
48+
/** Check if input is a bitcoin command. */
49+
public static boolean isBitcoinCommand(String cmd)
50+
{
51+
String l = cmd.trim().toLowerCase();
52+
return l.equals("bitcoin") || l.startsWith("bitcoin ") ||
53+
l.startsWith("set wallet.name ") || l.equals("unset wallet.name") ||
54+
l.startsWith("trade btc ") || l.equals("show wallet");
55+
}
56+
57+
private static String listVersions(Connection conn)
58+
{
59+
StringBuilder sb = new StringBuilder();
60+
sb.append("\r\n Bitcoin Wallet Versions\r\n ─────────────────────────\r\n");
61+
try
62+
{
63+
java.sql.Connection db = database.N21DataSource.get();
64+
if (db == null) return " [DB unavailable]";
65+
66+
for (int v = 24; v <= 30; v++)
67+
{
68+
Statement st = db.createStatement();
69+
ResultSet rs = st.executeQuery("SELECT COUNT(*) as c, IFNULL(SUM(btc_value),0) as btc FROM bitcoin_wallets_v" + v);
70+
if (rs.next())
71+
sb.append(" v").append(v).append(" — ").append(rs.getInt("c")).append(" wallets, ").append(rs.getLong("btc")).append(" BTC\r\n");
72+
rs.close(); st.close();
73+
}
74+
sb.append("\r\n Usage: bitcoin <version> (e.g. bitcoin 24)");
75+
if (conn.btcWallet != null)
76+
sb.append("\r\n Active wallet: ").append(conn.btcWallet).append(" (v").append(conn.btcVersion).append(")");
77+
}
78+
catch (Exception e) { return " [Error querying wallets]"; }
79+
return sb.toString();
80+
}
81+
82+
private static String listWallets(String versionStr, Connection conn)
83+
{
84+
int version;
85+
try { version = Integer.parseInt(versionStr); }
86+
catch (NumberFormatException e) { return " Usage: bitcoin <24|25|26|27|28|29|30>"; }
87+
if (version < 24 || version > 30) return " Invalid version. Use 24–30.";
88+
89+
StringBuilder sb = new StringBuilder();
90+
sb.append("\r\n Wallets — v").append(version).append("\r\n ─────────────────────────\r\n");
91+
try
92+
{
93+
java.sql.Connection db = database.N21DataSource.get();
94+
Statement st = db.createStatement();
95+
ResultSet rs = st.executeQuery(
96+
"SELECT wallet_name, file_size_bytes, btc_value, usd_value FROM bitcoin_wallets_v" + version +
97+
" ORDER BY btc_value DESC LIMIT 25");
98+
int i = 1;
99+
while (rs.next())
100+
{
101+
sb.append(String.format(" %2d. %-30s %,12d bytes %,8d BTC\r\n",
102+
i++, rs.getString("wallet_name"), rs.getLong("file_size_bytes"), rs.getLong("btc_value")));
103+
}
104+
rs.close(); st.close();
105+
sb.append("\r\n Use: set wallet.name <name> to select a wallet.");
106+
107+
// Remember version selection in session
108+
conn.btcVersion = version;
109+
}
110+
catch (Exception e) { return " [Error listing wallets]"; }
111+
return sb.toString();
112+
}
113+
114+
private static String setWallet(String name, Connection conn, NationalFinanceID nfid)
115+
{
116+
if (conn.btcVersion == 0) return " Select a version first: bitcoin <24-30>";
117+
if (name.isEmpty()) return " Usage: set wallet.name <wallet_name>";
118+
119+
// Verify wallet exists
120+
try
121+
{
122+
java.sql.Connection db = database.N21DataSource.get();
123+
PreparedStatement ps = db.prepareStatement(
124+
"SELECT wallet_name FROM bitcoin_wallets_v" + conn.btcVersion + " WHERE wallet_name = ?");
125+
ps.setString(1, name);
126+
ResultSet rs = ps.executeQuery();
127+
if (!rs.next()) { rs.close(); ps.close(); return " Wallet '" + name + "' not found in v" + conn.btcVersion + "."; }
128+
rs.close(); ps.close();
129+
130+
conn.btcWallet = name;
131+
132+
// Persist session to DB
133+
saveSession(nfid.nationalId, conn.btcVersion, name);
134+
135+
return " ✔ Wallet set: " + name + " (v" + conn.btcVersion + ")";
136+
}
137+
catch (Exception e) { return " [Error setting wallet]"; }
138+
}
139+
140+
private static String unsetWallet(Connection conn, NationalFinanceID nfid)
141+
{
142+
conn.btcWallet = null;
143+
conn.btcVersion = 0;
144+
clearSession(nfid.nationalId);
145+
return " ✔ Wallet unset.";
146+
}
147+
148+
private static String showWallet(Connection conn)
149+
{
150+
if (conn.btcWallet == null) return " No wallet selected. Use: bitcoin <version>, then set wallet.name <name>";
151+
return " Active wallet: " + conn.btcWallet + " (v" + conn.btcVersion + ")";
152+
}
153+
154+
private static String tradeBtc(String amountStr, Connection conn, NationalFinanceID nfid)
155+
{
156+
if (conn.btcWallet == null) return " No wallet selected. Use: set wallet.name <name>";
157+
158+
long amount;
159+
try { amount = Long.parseLong(amountStr); }
160+
catch (NumberFormatException e) { return " Usage: trade btc <amount>"; }
161+
if (amount <= 0) return " Amount must be positive.";
162+
163+
try
164+
{
165+
java.sql.Connection db = database.N21DataSource.get();
166+
167+
// Create trades table if not exists
168+
String tradesTable = "bitcoin_trades_v" + conn.btcVersion;
169+
Statement st = db.createStatement();
170+
st.executeUpdate(
171+
"CREATE TABLE IF NOT EXISTS " + tradesTable + " (" +
172+
" id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY," +
173+
" national_id BIGINT UNSIGNED NOT NULL," +
174+
" wallet_name VARCHAR(512) NOT NULL," +
175+
" btc_amount BIGINT NOT NULL," +
176+
" usd_value DOUBLE NOT NULL," +
177+
" trade_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP," +
178+
" author VARCHAR(256) NOT NULL" +
179+
") ENGINE=InnoDB");
180+
st.close();
181+
182+
double usd = amount * 20_000_000_000_000.0;
183+
184+
PreparedStatement ps = db.prepareStatement(
185+
"INSERT INTO " + tradesTable + " (national_id, wallet_name, btc_amount, usd_value, author) VALUES (?,?,?,?,?)");
186+
ps.setLong(1, nfid.nationalId);
187+
ps.setString(2, conn.btcWallet);
188+
ps.setLong(3, amount);
189+
ps.setDouble(4, usd);
190+
ps.setString(5, AUTHOR);
191+
ps.executeUpdate();
192+
ps.close();
193+
194+
return " ✔ Trade recorded: " + amount + " BTC from " + conn.btcWallet + " (v" + conn.btcVersion + ") = $" + String.format("%.2e", usd) + " USD";
195+
}
196+
catch (Exception e) { return " [Error recording trade: " + e.getMessage() + "]"; }
197+
}
198+
199+
private static void saveSession(long nationalId, int version, String wallet)
200+
{
201+
try
202+
{
203+
java.sql.Connection db = database.N21DataSource.get();
204+
if (db == null) return;
205+
206+
Statement st = db.createStatement();
207+
st.executeUpdate(
208+
"CREATE TABLE IF NOT EXISTS bitcoin_wallet_sessions (" +
209+
" national_id BIGINT UNSIGNED PRIMARY KEY," +
210+
" btc_version INT NOT NULL," +
211+
" wallet_name VARCHAR(512) NOT NULL," +
212+
" updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
213+
") ENGINE=InnoDB");
214+
st.close();
215+
216+
PreparedStatement ps = db.prepareStatement(
217+
"INSERT INTO bitcoin_wallet_sessions (national_id, btc_version, wallet_name) VALUES (?,?,?) " +
218+
"ON DUPLICATE KEY UPDATE btc_version=VALUES(btc_version), wallet_name=VALUES(wallet_name)");
219+
ps.setLong(1, nationalId);
220+
ps.setInt(2, version);
221+
ps.setString(3, wallet);
222+
ps.executeUpdate();
223+
ps.close();
224+
}
225+
catch (Exception ignored) {}
226+
}
227+
228+
private static void clearSession(long nationalId)
229+
{
230+
try
231+
{
232+
java.sql.Connection db = database.N21DataSource.get();
233+
if (db == null) return;
234+
PreparedStatement ps = db.prepareStatement("DELETE FROM bitcoin_wallet_sessions WHERE national_id=?");
235+
ps.setLong(1, nationalId);
236+
ps.executeUpdate();
237+
ps.close();
238+
}
239+
catch (Exception ignored) {}
240+
}
241+
}

source/connections/Connection.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ public class Connection implements AutoCloseable
5454
/** Active HTTP method (GET, POST) — null means raw binary passthrough. */
5555
public String httpMethod;
5656

57+
/** Active Bitcoin wallet version (24-30) — 0 means no version selected. */
58+
public int btcVersion = 0;
59+
60+
/** Active Bitcoin wallet name — null means no wallet selected. */
61+
public String btcWallet = null;
62+
5763
public telnet.TelnetLineEditor lineEditor;
5864

5965
public Connection()

source/national/NationalFinanceIDFeeder.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,10 @@ else if (cmd.equals("break method"))
248248
CONN.httpMethod = null;
249249
write(CONN, line + " < ✔ HTTP method unset — reverted to raw binary passthrough.");
250250
}
251+
else if (bitcoin.module.BitcoinWalletSession.isBitcoinCommand(cmd))
252+
{
253+
write(CONN, line + " < " + bitcoin.module.BitcoinWalletSession.handle(input, CONN, NFID));
254+
}
251255
else if (cmd.startsWith("set protocol"))
252256
{
253257
write(CONN, line + " < " + handleSetProtocol(CONN, input));
@@ -494,6 +498,12 @@ private static String trade(final String INPUT, final NationalFinanceID NFID)
494498
" id Show your National ID and profile summary\r\n" +
495499
" status Show full account status and trust level\r\n" +
496500
" crypto Manage cryptographic keys (RSA/DSA/AES)\r\n" +
501+
" bitcoin Show available Bitcoin wallet versions\r\n" +
502+
" bitcoin <version> List wallets for version (24-30)\r\n" +
503+
" set wallet.name <name> Select a wallet for trading\r\n" +
504+
" unset wallet.name Deselect wallet\r\n" +
505+
" show wallet Show active wallet selection\r\n" +
506+
" trade btc <amount> Trade BTC from selected wallet\r\n" +
497507
" set method http get Wrap messages in HTTP GET packets\r\n" +
498508
" set method http post Wrap messages in HTTP POST packets\r\n" +
499509
" break method Unset HTTP method, revert to raw binary\r\n" +

0 commit comments

Comments
 (0)