aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-03-16 16:35:11 -0700
committerAdam Soltys <[email protected]>2026-03-16 16:37:03 -0700
commit8c1385eaf8e68ef0ad436ad9b74e5813e92bb378 (patch)
tree16edd2c353a5d435768f901063fa146e97536d83 /lib
parent4a3d3b676ec7c21077786c7cdd33772385b87a6d (diff)
downloadcoinos-server-8c1385eaf8e68ef0ad436ad9b74e5813e92bb378.tar.gz
coinos-server-8c1385eaf8e68ef0ad436ad9b74e5813e92bb378.zip
update migrate script
Diffstat (limited to 'lib')
-rw-r--r--lib/migrate.ts237
-rw-r--r--lib/tb.ts49
2 files changed, 0 insertions, 286 deletions
diff --git a/lib/migrate.ts b/lib/migrate.ts
deleted file mode 100644
index f2320390..00000000
--- a/lib/migrate.ts
+++ /dev/null
@@ -1,237 +0,0 @@
-import { db, g, s, scan } from "$lib/db";
-import { findLastUsedIndex, parseDescriptor } from "$lib/esplora";
-import { l, warn } from "$lib/logging";
-import {
- createBalanceAccount,
- createCreditAccounts,
- createFundAccount,
- tbFundCredit,
- tbSetBalance,
- tbSetPending,
- tbSetCredit,
- tbMultiplyForMicrosats,
-} from "$lib/tb";
-
-async function migrate(id) {
- const k = id?.replace(/\s/g, "").toLowerCase();
- let user = await g(`user:${k}`);
- if (typeof user === "string") user = await g(`user:${user}`);
- return user;
-}
-
-export const migrateAccounts = async () => {
- const keys = await db.keys("account:*");
- let migrated = 0;
-
- for (const key of keys) {
- try {
- if ((key as string).endsWith(":invoices")) continue;
- const keyType = await db.type(key);
- if (keyType !== "string") continue;
-
- const account = await g(key);
- if (!account || !account.id) continue;
- if (account.pubkey || account.type === "ark" || !account.seed) continue;
- if (!account.descriptors?.length) continue;
-
- const parsed = parseDescriptor(account.descriptors[0].desc);
- if (!parsed) continue;
-
- account.pubkey = parsed.pubkey;
- account.fingerprint = parsed.fingerprint;
- try {
- account.nextIndex = await findLastUsedIndex(parsed.pubkey, parsed.fingerprint);
- } catch (e) {
- warn("account migration index scan skipped", key, e.message);
- account.nextIndex = account.nextIndex || 0;
- }
-
- await s(`account:${account.id}`, account);
- migrated++;
- } catch (e) {
- warn("failed to migrate account", key, e.message);
- }
- }
-
- return migrated;
-};
-
-export const migrateBalancesToTB = async () => {
- const migrated = await db.get("tb:migrated");
- if (migrated) return 0;
-
- let count = 0;
-
- // Migrate balance:* keys
- for await (const k of scan("balance:*")) {
- try {
- const id = (k as string).split(":")[1];
- const balance = Number.parseInt(((await db.get(k)) as string) || "0");
- await createBalanceAccount(id);
- if (balance > 0) await tbSetBalance(id, balance);
- count++;
- } catch (e) {
- warn("failed to migrate balance", k, e.message);
- }
- }
-
- // Migrate pending:* keys
- for await (const k of scan("pending:*")) {
- try {
- const id = (k as string).split(":")[1];
- const pending = Number.parseInt(((await db.get(k)) as string) || "0");
- if (pending > 0) await tbSetPending(id, pending);
- } catch (e) {
- warn("failed to migrate pending", k, e.message);
- }
- }
-
- // Migrate credit:*:* keys
- for await (const k of scan("credit:*:*")) {
- try {
- const parts = (k as string).split(":");
- const type = parts[1];
- const uid = parts[2];
- const amount = Number.parseInt(((await db.get(k)) as string) || "0");
- await createCreditAccounts(uid);
- if (amount > 0) await tbSetCredit(uid, type, amount);
- } catch (e) {
- warn("failed to migrate credit", k, e.message);
- }
- }
-
- await db.set("tb:migrated", Date.now().toString());
- l(`Migrated ${count} balances to TigerBeetle`);
- return count;
-};
-
-export const migrateToMicrosats = async () => {
- const migrated = await db.get("tb:microsats");
- if (migrated) return 0;
-
- let count = 0;
-
- // Iterate through all users and multiply their TB balances
- for await (const k of scan("user:*")) {
- try {
- const raw = await db.get(k);
- if (!raw) continue;
-
- // Skip user alias keys (they just contain another key reference)
- if (!(raw as string).startsWith("{")) continue;
-
- const user = JSON.parse(raw as string);
- if (!user.id) continue;
-
- const multiplied = await tbMultiplyForMicrosats(user.id);
- if (multiplied > 0) count++;
- } catch (e) {
- warn("microsats migration error", k, e.message);
- }
- }
-
- await db.set("tb:microsats", Date.now().toString());
- l(`Migrated ${count} users to microsats`);
- return count;
-};
-
-export const migrateAutowithdraw = async () => {
- const migrated = await db.get("autowithdraw:migrated");
- if (migrated) return 0;
-
- let count = 0;
-
- for await (const k of scan("user:*")) {
- try {
- const raw = await db.get(k);
- if (!raw || !(raw as string).startsWith("{")) continue;
-
- const user = JSON.parse(raw as string);
- if (!user.id || !user.autowithdraw) continue;
-
- const accountIds = await db.lRange(`${user.id}:accounts`, 0, -1);
-
- for (const aid of accountIds) {
- const account = await g(`account:${aid}`);
- if (!account) continue;
- if (account.seed || account.type === "ark") continue;
- if (account.autowithdraw) continue;
-
- account.autowithdraw = true;
- account.threshold = account.threshold ?? user.threshold;
- account.reserve = account.reserve ?? user.reserve;
- account.destination = account.destination ?? user.destination;
-
- await s(`account:${aid}`, account);
- count++;
- }
- } catch (e) {
- warn("autowithdraw migration error", k, e.message);
- }
- }
-
- await db.set("autowithdraw:migrated", Date.now().toString());
- l(`Migrated autowithdraw to ${count} accounts`);
- return count;
-};
-
-export const migrateFundsToTB = async () => {
- const migrated = await db.get("tb:funds-migrated");
- if (migrated) return 0;
-
- let count = 0;
-
- for await (const k of scan("fund:*")) {
- try {
- // Skip sub-keys like fund:name:payments, fund:name:managers, fund:limit
- const parts = (k as string).split(":");
- if (parts.length !== 2) continue;
- const name = parts[1];
- if (name === "limit") continue;
-
- const keyType = await db.type(k);
- if (keyType !== "string") continue;
-
- const balance = Number.parseInt(((await db.get(k)) as string) || "0");
- await createFundAccount(name);
- if (balance > 0) await tbFundCredit(name, balance);
- count++;
- } catch (e) {
- warn("failed to migrate fund", k, e.message);
- }
- }
-
- await db.set("tb:funds-migrated", Date.now().toString());
- l(`Migrated ${count} funds to TigerBeetle`);
- return count;
-};
-
-export const hashPins = async () => {
- const migrated = await db.get("pins:hashed");
- if (migrated) return 0;
-
- let count = 0;
-
- for await (const k of scan("user:*")) {
- try {
- const raw = await db.get(k);
- if (!raw || !(raw as string).startsWith("{")) continue;
-
- const user = JSON.parse(raw as string);
- if (!user.pin || user.pin.length !== 6) continue;
-
- const hash = new Bun.CryptoHasher("sha256").update(user.pin).digest("hex");
- user.pin = hash;
- await s(k as string, user);
- count++;
- } catch (e) {
- warn("pin hash migration error", k, e.message);
- }
- }
-
- await db.set("pins:hashed", Date.now().toString());
- l(`Hashed ${count} user PINs`);
- return count;
-};
-
-export default migrate;
diff --git a/lib/tb.ts b/lib/tb.ts
index 9fbff6c8..aa758bef 100644
--- a/lib/tb.ts
+++ b/lib/tb.ts
@@ -671,52 +671,3 @@ export async function getFundBalance(name: string): Promise<number | null> {
return accountBalance(account);
}
-// Migration helper: multiply existing balance by MULTIPLIER to convert sats→microsats
-// Called by migrateToMicrosats() - adds (balance * 999999) to turn X into X*1000000
-// NOTE: This migration should only run ONCE - guarded by tb:microsats flag in migrate.ts
-export async function tbMultiplyForMicrosats(uid: string): Promise<number> {
- // Ensure client is initialized (needed when called during startup)
- if (!client) {
- await initTigerBeetle();
- }
-
- const MULTIPLIER = 999999n; // Adding this turns X into X*1000000
- let count = 0;
-
- const multiplyAccount = async (accountId: bigint, ledger: number, houseId: bigint) => {
- const acct = await client.lookupAccounts([u128(accountId)]);
- if (!acct.length) return;
- const current = BigInt(acct[0].credits_posted) - BigInt(acct[0].debits_posted);
- if (current <= 0n) return;
-
- const results = await client.createTransfers([
- {
- id: nextTransferId(),
- debit_account_id: u128(houseId),
- credit_account_id: u128(accountId),
- amount: current * MULTIPLIER,
- pending_id: 0n,
- user_data_128: 0n,
- user_data_64: 0n,
- user_data_32: 0,
- timeout: 0,
- ledger,
- code: 1,
- flags: 0,
- timestamp: 0n,
- },
- ]);
- if (results.length === 0) count++;
- };
-
- const balId = balanceId(uid);
- const pendId = pendingId(uid);
-
- await multiplyAccount(balId, LEDGER_SATS, HOUSE_SATS);
- await multiplyAccount(pendId, LEDGER_SATS, HOUSE_SATS);
- await multiplyAccount(creditId(uid, "bitcoin"), LEDGER_CREDIT_BTC, HOUSE_BTC);
- await multiplyAccount(creditId(uid, "lightning"), LEDGER_CREDIT_LN, HOUSE_LN);
- await multiplyAccount(creditId(uid, "liquid"), LEDGER_CREDIT_LQ, HOUSE_LQ);
-
- return count;
-}