Versie 0.2.0
This commit is contained in:
commit
e77d8fd373
495 files changed
+81026
No files matched your search
@@ -0,0 +1,157 @@
|
||||
// Generated, do not edit. sha256:a4f989c4fcb487fdb8c1ab80d536f8fa5a1a10a2f0357c22596ab060e7b38694
|
||||
import * as db from '../db.js';
|
||||
import { ENUMS } from '../../shared/config.js';
|
||||
import { assertEnum, nowIso } from './_shared.js';
|
||||
|
||||
export async function syncAddressLinks() {
|
||||
const method = 'exact';
|
||||
assertEnum('method', ENUMS.LINK_METHOD, method);
|
||||
db.run(`INSERT OR IGNORE INTO WalletTransactionEventLink (walletTransactionId, eventId, method, createdAt)
|
||||
SELECT w.id, e.id, ?1, ?2
|
||||
FROM WalletTransaction w
|
||||
JOIN Event e ON e.externalAddress = w.address
|
||||
WHERE w.direction = 'in' AND w.address IS NOT NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM ReconcileProposal p
|
||||
WHERE p.walletTransactionId = w.id AND p.resolvedEventId = e.id AND p.status = 'ignored')`,
|
||||
[method, nowIso()]);
|
||||
let n = db.one(`SELECT changes() AS n`).n;
|
||||
db.run(`INSERT OR IGNORE INTO WalletTransactionEventLink (walletTransactionId, eventId, method, createdAt)
|
||||
SELECT w.id, e.id, ?1, ?2
|
||||
FROM WalletTransaction w
|
||||
JOIN Event e ON e.source = 'lightning'
|
||||
AND (e.fromAccountId = w.accountId OR e.toAccountId = w.accountId)
|
||||
AND (e.importReference = 'ln:' || w.txid
|
||||
OR (w.txid LIKE 'fwd:%' AND e.importReference = 'lnfwd:' || w.blockTime))
|
||||
WHERE w.layer = 'lightning'
|
||||
AND NOT EXISTS (SELECT 1 FROM ReconcileProposal p
|
||||
WHERE p.walletTransactionId = w.id AND p.resolvedEventId = e.id AND p.status = 'ignored')`,
|
||||
[method, nowIso()]);
|
||||
n += db.one(`SELECT changes() AS n`).n;
|
||||
db.run(`INSERT OR IGNORE INTO WalletTransactionEventLink (walletTransactionId, eventId, method, createdAt)
|
||||
SELECT w.id, l.eventId, ?1, ?2
|
||||
FROM WalletTransaction w
|
||||
JOIN WalletTransaction twin ON twin.accountId = w.accountId AND twin.txid = w.txid
|
||||
AND twin.layer = 'lightning' AND twin.id <> w.id
|
||||
JOIN WalletTransactionEventLink l ON l.walletTransactionId = twin.id
|
||||
WHERE w.layer = 'lightning'
|
||||
AND NOT EXISTS (SELECT 1 FROM ReconcileProposal p
|
||||
WHERE p.walletTransactionId = w.id AND p.resolvedEventId = l.eventId AND p.status = 'ignored')`,
|
||||
[method, nowIso()]);
|
||||
n += db.one(`SELECT changes() AS n`).n;
|
||||
const asset = onchainAsset();
|
||||
if (asset) {
|
||||
db.run(`INSERT OR IGNORE INTO ReconcileProposal
|
||||
(accountId, assetId, walletTransactionId, transactionHash, amount, direction, suggestedType, status, resolvedEventId, detectedAt)
|
||||
SELECT w.accountId, ?1, w.id, w.txid, w.valueSats, w.direction,
|
||||
CASE WHEN e.type = 'transfer' THEN 'transfer' ELSE 'trade' END,
|
||||
'auto_linked', e.id, ?2
|
||||
FROM WalletTransactionEventLink l
|
||||
JOIN WalletTransaction w ON w.id = l.walletTransactionId
|
||||
JOIN Event e ON e.id = l.eventId
|
||||
WHERE l.method = 'exact'
|
||||
AND NOT EXISTS (SELECT 1 FROM ReconcileProposal p
|
||||
WHERE p.walletTransactionId = w.id AND p.resolvedEventId = e.id)`,
|
||||
[asset.id, nowIso()]);
|
||||
}
|
||||
const changed = n + db.one(`SELECT changes() AS n`).n;
|
||||
if (changed > 0) await db.persist();
|
||||
return n;
|
||||
}
|
||||
export function eventLinkMap() {
|
||||
const m = new Map();
|
||||
for (const r of db.all(`SELECT eventId, method FROM WalletTransactionEventLink`)) m.set(r.eventId, r.method);
|
||||
return m;
|
||||
}
|
||||
export function walletTxEventMap() {
|
||||
const m = new Map();
|
||||
const rows = db.all(`SELECT l.walletTransactionId, l.method, e.id AS eventId, e.type, e.amount, e.unitFee,
|
||||
e.fromAccountId, e.toAccountId, fa.name AS from_name, ta.name AS to_name
|
||||
FROM WalletTransactionEventLink l
|
||||
JOIN Event e ON e.id = l.eventId
|
||||
LEFT JOIN Account fa ON fa.id = e.fromAccountId
|
||||
LEFT JOIN Account ta ON ta.id = e.toAccountId`);
|
||||
for (const r of rows) {
|
||||
if (!m.has(r.walletTransactionId)) m.set(r.walletTransactionId, []);
|
||||
m.get(r.walletTransactionId).push(r);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
export async function linkTxEvent(walletTxId, eventId, method) {
|
||||
assertEnum('method', ENUMS.LINK_METHOD, method);
|
||||
db.run(`INSERT OR IGNORE INTO WalletTransactionEventLink (walletTransactionId, eventId, method, createdAt)
|
||||
VALUES (?,?,?,?)`, [walletTxId, eventId, method, nowIso()]);
|
||||
await db.persist();
|
||||
}
|
||||
export function linkProposalTxSoft(walletTxId, eventId) {
|
||||
const method = 'soft';
|
||||
assertEnum('method', ENUMS.LINK_METHOD, method);
|
||||
db.run(`INSERT OR IGNORE INTO WalletTransactionEventLink (walletTransactionId, eventId, method, createdAt)
|
||||
VALUES (?,?,?,?)`, [walletTxId, eventId, method, nowIso()]);
|
||||
}
|
||||
export async function unlinkTxEvent(walletTxId, eventId) {
|
||||
db.run(`DELETE FROM WalletTransactionEventLink WHERE walletTransactionId = ? AND eventId = ?`, [walletTxId, eventId]);
|
||||
db.run(`UPDATE ReconcileProposal SET status = 'ignored'
|
||||
WHERE walletTransactionId = ? AND resolvedEventId = ? AND status = 'auto_linked'`, [walletTxId, eventId]);
|
||||
await db.persist();
|
||||
}
|
||||
|
||||
export function onchainAsset() {
|
||||
return db.one(`SELECT * FROM Asset WHERE symbol = 'BTC'`)
|
||||
|| db.one(`SELECT * FROM Asset WHERE kind = 'crypto' ORDER BY symbol LIMIT 1`)
|
||||
|| null;
|
||||
}
|
||||
|
||||
export function linksForTx(walletTxId) {
|
||||
return db.all(`
|
||||
SELECT tel.eventId AS id, tel.method,
|
||||
e.type, e.occurredAt, e.amount,
|
||||
a.symbol AS asset_symbol, lf.name AS from_name, lt.name AS to_name
|
||||
FROM WalletTransactionEventLink tel
|
||||
JOIN Event e ON e.id = tel.eventId
|
||||
JOIN Asset a ON a.id = e.assetId
|
||||
LEFT JOIN Account lf ON lf.id = e.fromAccountId
|
||||
LEFT JOIN Account lt ON lt.id = e.toAccountId
|
||||
WHERE tel.walletTransactionId = ?
|
||||
ORDER BY e.occurredAt DESC, e.id DESC`, [walletTxId]);
|
||||
}
|
||||
export function linksForEvent(eventId) {
|
||||
return db.all(`
|
||||
SELECT tel.walletTransactionId AS id, tel.method,
|
||||
t.direction, t.valueSats, t.blockTime, t.txid, t.address, ac.name AS account_name
|
||||
FROM WalletTransactionEventLink tel
|
||||
JOIN WalletTransaction t ON t.id = tel.walletTransactionId
|
||||
LEFT JOIN Account ac ON ac.id = t.accountId
|
||||
WHERE tel.eventId = ?
|
||||
ORDER BY (t.blockTime IS NULL) DESC, t.blockTime DESC, t.id DESC`, [eventId]);
|
||||
}
|
||||
|
||||
export function eventCandidatesForTx(walletTxId, assetId) {
|
||||
return db.all(`
|
||||
SELECT e.id, e.type, e.occurredAt, e.amount,
|
||||
a.symbol AS asset_symbol, lf.name AS from_name, lt.name AS to_name
|
||||
FROM Event e
|
||||
JOIN Asset a ON a.id = e.assetId
|
||||
LEFT JOIN Account lf ON lf.id = e.fromAccountId
|
||||
LEFT JOIN Account lt ON lt.id = e.toAccountId
|
||||
WHERE e.assetId = ?2 AND e.type <> 'reservation'
|
||||
AND e.id NOT IN (SELECT eventId FROM WalletTransactionEventLink WHERE walletTransactionId = ?1)
|
||||
ORDER BY ABS(strftime('%s', e.occurredAt) -
|
||||
strftime('%s', COALESCE((SELECT blockTime FROM WalletTransaction WHERE id = ?1),
|
||||
(SELECT createdAt FROM WalletTransaction WHERE id = ?1)))) ASC,
|
||||
e.id DESC
|
||||
LIMIT 100`, [walletTxId, assetId]);
|
||||
}
|
||||
export function txCandidatesForEvent(eventId) {
|
||||
return db.all(`
|
||||
SELECT t.id, t.direction, t.valueSats, t.blockTime, t.txid, t.address,
|
||||
ac.name AS account_name, l.name AS label_name
|
||||
FROM WalletTransaction t
|
||||
LEFT JOIN Account ac ON ac.id = t.accountId
|
||||
LEFT JOIN Label l ON l.id = t.labelId
|
||||
WHERE t.id NOT IN (SELECT walletTransactionId FROM WalletTransactionEventLink WHERE eventId = ?1)
|
||||
ORDER BY ABS(strftime('%s', COALESCE(t.blockTime, t.createdAt)) -
|
||||
strftime('%s', (SELECT occurredAt FROM Event WHERE id = ?1))) ASC,
|
||||
t.id DESC
|
||||
LIMIT 100`, [eventId]);
|
||||
}
|
||||
Reference in new issue
Block a user