cln-ledger

CLN ledger accounting
git clone git://jb55.com/cln-ledger
Log | Files | Refs

commit cfe738ad31187d969142d6aba5387df15d797a49
parent 0d57df2adef9bccaf2c02858ba0b444de9681213
Author: William Casarin <jb55@jb55.com>
Date:   Wed, 31 May 2023 20:51:37 -0700

commit dist

Diffstat:
M.gitignore | 1-
Adist/index.js | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adist/index.js.map | 2++
Mpackage.json | 1+
Mrun | 2+-
Mtsconfig.json | 2+-
6 files changed, 209 insertions(+), 3 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -5,7 +5,6 @@ .rgignore Makefile events.txt -index.js invoice_events.txt node_modules/ prices.db diff --git a/dist/index.js b/dist/index.js @@ -0,0 +1,203 @@ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __asyncValues = (this && this.__asyncValues) || function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +}; +import fs from 'fs'; +import readline from 'readline'; +import assert from 'assert'; +function description_string(desc) { + switch (desc.type) { + case "generic": + return desc.value; + case "lnurl": + return desc.description; + case "zap": + return "Zap"; + } +} +function determine_zap_type(zap) { + const etag = get_tag(zap.tags, "e"); + const ptag = get_tag(zap.tags, "p"); + if (!ptag) + return null; + if (!etag) { + let profile_zap = { pubkey: ptag, type: "profile" }; + return profile_zap; + } + let zap_ev = { evid: etag, pubkey: ptag, type: "event" }; + return zap_ev; +} +function get_tag(tags, key) { + let v = tags.find(tag => tag[0] === key); + return v && v[1]; +} +function get_lnurl_description(json) { + const description = get_tag(json, "text/plain"); + const address = get_tag(json, "text/identifier"); + return { description, address, type: "lnurl" }; +} +function is_json(str) { + return str[0] === '{' || (str[0] === '[' && str[1] === '['); +} +function create_generic_desc(value) { + return { type: "generic", value }; +} +function determine_description(str, tag) { + if (tag === "routed") { + let desc = { type: "routed" }; + return desc; + } + try { + let json; + if (is_json(str) && (json = JSON.parse(str))) { + if (json.kind === 9734) { + let zaptype = determine_zap_type(json); + let zap_desc = { zap_type: zaptype, zap: json, type: "zap" }; + return zap_desc; + } + else if (json.length > 0) { + return get_lnurl_description(json); + } + return create_generic_desc(str); + } + return create_generic_desc(str); + } + catch (e) { + return create_generic_desc(str); + } +} +function msat(val) { + return `${val} msat`; +} +function classify_account(str, debit) { + if (str.includes("Damus Merch")) + return "merch:tshirt"; + if (str.includes("Damus Hat")) + return "merch:hat"; + if (str.includes("@tipjar")) + return "lnurl:jb55@sendsats.lol:tipjar"; + if (debit === 1971000) + return "zap:1971"; + else if (debit === 420000) + return "zap:420"; + return "unknown"; +} +function determine_postings(credit, debit, desc) { + let postings = []; + const is_credit = credit > 0; + const acct = is_credit ? "income" : "expenses"; + const amount = is_credit ? credit : debit; + switch (desc.type) { + case "routed": + postings.push({ account: `${acct}:routed`, amount: msat(is_credit ? -amount : amount) }); + postings.push({ account: `assets:cln`, amount: msat(is_credit ? amount : -amount) }); + break; + case "generic": + // todo: categorize + const subacct = classify_account(desc.value, debit); + postings.push({ account: `${acct}:${subacct}`, amount: msat(is_credit ? -amount : amount) }); + postings.push({ account: `assets:cln`, amount: msat(is_credit ? amount : -amount) }); + break; + case "lnurl": + assert(debit === 0); + postings.push({ account: `income:lnurl:${desc.address}`, amount: msat(-credit) }); + postings.push({ account: `assets:cln`, amount: msat(credit) }); + break; + case "zap": + assert(debit === 0); + switch (desc.zap_type.type) { + case 'profile': + postings.push({ account: `income:zap:profile:${desc.zap_type.pubkey}`, amount: msat(-credit) }); + break; + case 'event': + // todo: attribute this to profile as well? + let evtype = desc.zap_type; + postings.push({ account: `income:zap:event:${evtype.evid}`, amount: msat(-credit) }); + break; + } + postings.push({ account: `assets:cln`, amount: msat(credit) }); + break; + } + return postings; +} +function process(filePath) { + var _a, e_1, _b, _c; + return __awaiter(this, void 0, void 0, function* () { + const fileStream = fs.createReadStream(filePath); + const rl = readline.createInterface({ + input: fileStream, + crlfDelay: Infinity + }); + console.log("P 2022-07-22 msat 0.00000036 CAD"); + console.log("P 2022-07-22 msat 0.001 sat"); + console.log("P 2022-07-22 msat 0.00001 bit"); + console.log("P 2022-07-22 msat 0.00000000001 btc"); + try { + for (var _d = true, rl_1 = __asyncValues(rl), rl_1_1; rl_1_1 = yield rl_1.next(), _a = rl_1_1.done, !_a;) { + _c = rl_1_1.value; + _d = false; + try { + const line = _c; + let parts = line.split('\t'); + if (parts.length !== 6) { + console.error(`Invalid line: ${line} ${parts.length} !== 5`); + continue; + } + const credit = Number(parts[2]); + const debit = Number(parts[3]); + if (credit === 0 && debit === 0) + continue; + const tag = parts[1]; + if (!(tag === "invoice" || tag === "routed")) + continue; + const timestamp = Number(parts[4]); + const date = new Date(timestamp * 1000); + const description = determine_description(parts[5], tag); + const postings = determine_postings(credit, debit, description); + // type,.tag,.credit_msat,.debit_msat,.timestamp,.description + let transaction = { date, description, postings }; + console.log(transactionToLedger(transaction)); + } + finally { + _d = true; + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (!_d && !_a && (_b = rl_1.return)) yield _b.call(rl_1); + } + finally { if (e_1) throw e_1.error; } + } + }); +} +function format_date(date) { + const year = date.getFullYear(); + const month = (date.getMonth() + 1).toString().padStart(2, '0'); + const day = date.getDate().toString().padStart(2, '0'); + return `${year}-${month}-${day}`; +} +function transactionToLedger(transaction) { + const tx = `${format_date(transaction.date)} ${description_string(transaction.description)}\n`; + return tx + transaction.postings.map(p => ` ${p.account} ${p.amount}`).join("\n") + "\n"; +} +function main() { + return __awaiter(this, void 0, void 0, function* () { + yield process('events.txt'); + }); +} +main().catch(console.error); +//# sourceMappingURL=index.js.map+ \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}+ \ No newline at end of file diff --git a/package.json b/package.json @@ -1,6 +1,7 @@ { "name": "accounting", "description": "damus accounting", + "type": "module", "version": "0.1.0", "repository": { "url": "https://github.com/jb55/accounting" diff --git a/run b/run @@ -1 +1 @@ -npx ts-node index.ts +node dist/index.js diff --git a/tsconfig.json b/tsconfig.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "module": "commonjs", "esModuleInterop": true, "allowSyntheticDefaultImports": true, "target": "es6", @@ -17,6 +16,7 @@ } }, "include": [ + "index.ts", "src/**/*" ] }