diff options
| -rw-r--r-- | lib/ark.ts | 14 | ||||
| -rw-r--r-- | lib/payments.ts | 7 | ||||
| -rw-r--r-- | scripts/ark-boarding-address.ts | 48 |
3 files changed, 53 insertions, 16 deletions
@@ -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); |
