aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-03-14 04:49:54 +0000
committerAdam Soltys <[email protected]>2026-03-14 04:49:54 +0000
commitfddfe10f84908c058e239b93985dfe02ba37df04 (patch)
tree563740d528cf7cc2f4ebe5a06a598a40a8cfed1c
parent76f886edde74e8a77d62ecf7caa0b7bd8232a2fe (diff)
downloadcoinos-server-fddfe10f84908c058e239b93985dfe02ba37df04.tar.gz
coinos-server-fddfe10f84908c058e239b93985dfe02ba37df04.zip
slow down ark checksark2
-rw-r--r--lib/ark.ts14
-rw-r--r--lib/payments.ts7
-rw-r--r--scripts/ark-boarding-address.ts48
3 files changed, 53 insertions, 16 deletions
diff --git a/lib/ark.ts b/lib/ark.ts
index 5f695f6e..d24b0bc1 100644
--- a/lib/ark.ts
+++ b/lib/ark.ts
@@ -36,7 +36,7 @@ const getWallet = async () => {
let refreshing = false;
let lastRefresh = 0;
-const REFRESH_COOLDOWN = 30_000;
+const REFRESH_COOLDOWN = 300_000;
let failedBoardingOutpoints = new Set<string>();
const FAILED_BOARDING_KEY = "ark:failedBoardingOutpoints";
const loadFailedOutpoints = async () => {
@@ -66,6 +66,7 @@ export const refreshArkWallet = async (force = false) => {
lastRefresh = now;
const w = await getWallet();
const balance = await w.getBalance();
+ cachedArkBalance = balance;
const manager = new VtxoManager(w);
const provider = new RestArkProvider(config.ark.arkServerUrl);
const info = await provider.getInfo();
@@ -184,8 +185,8 @@ export const refreshArkWallet = async (force = false) => {
};
// Initial check after 60s startup delay; retry every 60s to catch ark rounds
-setTimeout(refreshArkWallet, 60_000);
-setInterval(() => refreshArkWallet(), 60_000);
+setTimeout(refreshArkWallet, 300_000);
+setInterval(() => refreshArkWallet(), 300_000);
export const sendArk = async (address: string, amount: number) => {
@@ -219,10 +220,9 @@ export const getArkAddress = async () => {
return w.getAddress();
};
-export const getArkBalance = async () => {
- const w = await getWallet();
- return w.getBalance();
-};
+let cachedArkBalance: any = null;
+
+export const getArkBalance = () => cachedArkBalance;
export const verifyArkVtxo = async (hash: string) => {
const { bech32m } = await import("@scure/base");
diff --git a/lib/payments.ts b/lib/payments.ts
index dfbdd3c4..5650dda4 100644
--- a/lib/payments.ts
+++ b/lib/payments.ts
@@ -1750,12 +1750,11 @@ const freezeCheck = async () => {
await s("ecash:limit", Math.max(lnbalance - lnthreshold, 0));
await s("bolt12:limit", Math.max(lnbalance - lnthreshold, 0));
- try {
- const arkBalance = await getArkBalance();
+ const arkBalance = getArkBalance();
+ if (arkBalance) {
const arkthreshold = (await g("ark:threshold")) || 0;
+ await s("ark:available", arkBalance.available);
await s("ark:limit", Math.max(arkBalance.available - arkthreshold, 0));
- } catch (e) {
- warn("freezeCheck ark balance failed:", e.message);
}
setTimeout(freezeCheck, 10000);
diff --git a/scripts/ark-boarding-address.ts b/scripts/ark-boarding-address.ts
index f3e7f84e..fbca4575 100644
--- a/scripts/ark-boarding-address.ts
+++ b/scripts/ark-boarding-address.ts
@@ -1,11 +1,46 @@
-import config from "../config.ts";
import { SingleKey, Wallet } from "@arkade-os/sdk";
+import { createClient } from "redis";
+
+const { ark: { arkPrivateKey, arkServerUrl, esploraUrl } } = (await import("../config.ts")).default;
+
+const redis = createClient({ url: "redis://localhost" });
+await redis.connect();
+
+// Inline minimal Valkey repos to avoid pulling in the full app
+const PREFIX = "ark:repo";
+const walletRepository = {
+ version: 1 as const,
+ async getVtxos(address: string) { const r = await redis.get(`${PREFIX}:vtxos:${address}`); return r ? JSON.parse(r) : []; },
+ async saveVtxos(address: string, vtxos: any[]) { const existing = await this.getVtxos(address); const map = new Map(); for (const v of existing) map.set(`${v.txid}:${v.vout}`, v); for (const v of vtxos) map.set(`${v.txid}:${v.vout}`, v); await redis.set(`${PREFIX}:vtxos:${address}`, JSON.stringify([...map.values()])); },
+ async deleteVtxos(address: string) { await redis.del(`${PREFIX}:vtxos:${address}`); },
+ async getUtxos(address: string) { const r = await redis.get(`${PREFIX}:utxos:${address}`); return r ? JSON.parse(r) : []; },
+ async saveUtxos(address: string, utxos: any[]) { const existing = await this.getUtxos(address); const map = new Map(); for (const u of existing) map.set(`${u.txid}:${u.vout}`, u); for (const u of utxos) map.set(`${u.txid}:${u.vout}`, u); await redis.set(`${PREFIX}:utxos:${address}`, JSON.stringify([...map.values()])); },
+ async deleteUtxos(address: string) { await redis.del(`${PREFIX}:utxos:${address}`); },
+ async getTransactionHistory(address: string) { const r = await redis.get(`${PREFIX}:txs:${address}`); return r ? JSON.parse(r) : []; },
+ async saveTransactions(address: string, txs: any[]) { await redis.set(`${PREFIX}:txs:${address}`, JSON.stringify(txs)); },
+ async deleteTransactions(address: string) { await redis.del(`${PREFIX}:txs:${address}`); },
+ async getWalletState() { const r = await redis.get(`${PREFIX}:state`); return r ? JSON.parse(r) : null; },
+ async saveWalletState(state: any) { await redis.set(`${PREFIX}:state`, JSON.stringify(state)); },
+ async clear() { const keys = await redis.keys(`${PREFIX}:*`); if (keys.length) await redis.del(keys); },
+ async [Symbol.asyncDispose]() {},
+};
+
+const contractRepository = {
+ version: 1 as const,
+ async getContracts(filter?: any) { const r = await redis.get(`${PREFIX}:contracts`); const all = r ? JSON.parse(r) : []; if (!filter) return all; return all.filter((c: any) => (!filter.script || c.script === filter.script) && (!filter.state || c.state === filter.state) && (!filter.type || c.type === filter.type)); },
+ async saveContract(contract: any) { const all = await this.getContracts(); const idx = all.findIndex((c: any) => c.script === contract.script); if (idx >= 0) all[idx] = contract; else all.push(contract); await redis.set(`${PREFIX}:contracts`, JSON.stringify(all)); },
+ async deleteContract(script: string) { const all = await this.getContracts(); await redis.set(`${PREFIX}:contracts`, JSON.stringify(all.filter((c: any) => c.script !== script))); },
+ async clear() { await redis.del(`${PREFIX}:contracts`); },
+ async [Symbol.asyncDispose]() {},
+};
-const { arkPrivateKey} = config.ark;
-const arkServerUrl = "localhost:7070";
-const esploraUrl = "localhost:3000";
const identity = SingleKey.fromHex(arkPrivateKey);
-const wallet = await Wallet.create({ identity, arkServerUrl, esploraUrl });
+const wallet = await Wallet.create({
+ identity,
+ arkServerUrl,
+ esploraUrl,
+ storage: { walletRepository, contractRepository },
+});
const address = await wallet.getBoardingAddress();
const balance = await wallet.getBalance();
@@ -24,3 +59,6 @@ for (const u of utxos) {
const status = u.status?.confirmed ? "confirmed" : "unconfirmed";
console.log(` ${u.txid}:${u.vout} — ${u.value} sats (${status})`);
}
+
+await redis.quit();
+process.exit(0);