ray-finance 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -29
- package/dist/cli/commands.d.ts +2 -0
- package/dist/cli/commands.js +135 -0
- package/dist/cli/index.js +41 -0
- package/dist/daily-sync.js +10 -0
- package/dist/demo/data.d.ts +252 -0
- package/dist/demo/data.js +272 -0
- package/dist/demo/logos.d.ts +8 -0
- package/dist/demo/logos.js +58 -0
- package/dist/demo/seed.d.ts +1 -0
- package/dist/demo/seed.js +125 -0
- package/dist/property.d.ts +23 -0
- package/dist/property.js +80 -0
- package/dist/public/link.html +11 -18
- package/dist/queries/index.js +4 -4
- package/dist/server.js +25 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src=".github/ray-logo.png" alt="Ray" width="
|
|
2
|
+
<img src=".github/ray-logo.png" alt="Ray" width="108" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<p align="center">
|
|
@@ -14,40 +14,17 @@
|
|
|
14
14
|
|
|
15
15
|
<br />
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
net worth $45,230 +$120
|
|
21
|
-
|
|
22
|
-
spending $2,340 this month · $340 less vs last month
|
|
23
|
-
Dining -$114 · Shopping -$142 · Groceries -$73
|
|
24
|
-
|
|
25
|
-
▓▓▓▓▓▓▓░ Dining 92%
|
|
26
|
-
|
|
27
|
-
▓▓▓▓░░░░ Emergency fund $18,200/$40,000
|
|
28
|
-
|
|
29
|
-
upcoming Netflix $16 in 3d · Comcast $142 in 6d
|
|
30
|
-
|
|
31
|
-
score 72/100 · 5d no dining · 3d on pace
|
|
32
|
-
|
|
33
|
-
──────────────────────────────────────────────────
|
|
34
|
-
|
|
35
|
-
❯ if I quit my job to freelance, how long can I survive?
|
|
36
|
-
|
|
37
|
-
Based on your last 3 months: you burn $4,820/mo after
|
|
38
|
-
fixed costs. With $18,200 in savings, that's
|
|
39
|
-
3.8 months of runway at current spend.
|
|
40
|
-
|
|
41
|
-
Cut dining and shopping to last-month levels and
|
|
42
|
-
you stretch to 5.1 months. Land one $8k contract
|
|
43
|
-
in that window and you never dip below $10k.
|
|
44
|
-
```
|
|
17
|
+
<p align="center">
|
|
18
|
+
<img src=".github/ray-demo.png" alt="Ray demo" />
|
|
19
|
+
</p>
|
|
45
20
|
|
|
46
21
|
Open Ray and it shows your net worth, spending vs last month, budget pacing, and upcoming bills — before you type a word. Ask a question and it answers from your real data, not guesses. Local-first. Encrypted. Open source.
|
|
47
22
|
|
|
48
23
|
## Features
|
|
49
24
|
|
|
50
25
|
- **It already knows** — Every conversation starts with a real-time financial briefing. Net worth, spending velocity, budget alerts, goal pace, upcoming bills, and your daily score. No "let me look that up."
|
|
26
|
+
- **Persistent context** — Ray maintains a financial profile that evolves with you: income, goals, strategy, key decisions, and open items. It updates this context as your situation changes, so every conversation picks up where the last one left off.
|
|
27
|
+
- **Long-term memory** — Important details from conversations are saved as memories. Mention you're saving for a house or switching jobs and Ray remembers — without you repeating yourself.
|
|
51
28
|
- **Bank sync via Plaid** — Connect checking, savings, credit cards, investments, and loans
|
|
52
29
|
- **Encrypted local database** — All data stays on your machine in an AES-256 encrypted SQLite database
|
|
53
30
|
- **Daily scoring** — A 0-100 behavior score with streaks and 14 unlockable achievements. No restaurants for a week? That's Kitchen Hero. Five zero-spend days? Monk Mode.
|
|
@@ -65,6 +42,26 @@ Open Ray and it shows your net worth, spending vs last month, budget pacing, and
|
|
|
65
42
|
npm install -g ray-finance
|
|
66
43
|
```
|
|
67
44
|
|
|
45
|
+
## Try It
|
|
46
|
+
|
|
47
|
+
Explore Ray with realistic fake data — no bank accounts needed.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
ray demo # seed a demo database
|
|
51
|
+
ray --demo status # financial overview
|
|
52
|
+
ray --demo accounts # linked accounts with balances
|
|
53
|
+
ray --demo spending # spending breakdown by category
|
|
54
|
+
ray --demo budgets # budget tracking
|
|
55
|
+
ray --demo goals # financial goal progress
|
|
56
|
+
ray --demo score # daily score, streaks, achievements
|
|
57
|
+
ray --demo alerts # financial alerts
|
|
58
|
+
ray --demo transactions # recent transactions
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The dashboard commands work with no setup at all. To also try the AI chat with demo data, run `ray setup` first and add an [Anthropic API key](https://console.anthropic.com) or Ray API key — then `ray --demo` will start an interactive session where you can ask questions about the fake portfolio.
|
|
62
|
+
|
|
63
|
+
When you're ready to connect real accounts, run `ray link`.
|
|
64
|
+
|
|
68
65
|
## Quick Start
|
|
69
66
|
|
|
70
67
|
```bash
|
|
@@ -98,6 +95,8 @@ Run `ray --help` to see all available commands.
|
|
|
98
95
|
| Command | Description |
|
|
99
96
|
|---------|-------------|
|
|
100
97
|
| `ray` | Interactive AI chat with your financial advisor |
|
|
98
|
+
| `ray demo` | Seed a demo database with realistic fake data |
|
|
99
|
+
| `ray --demo <cmd>` | Run any command against demo data |
|
|
101
100
|
| `ray setup` | Configure API keys and preferences |
|
|
102
101
|
| `ray link` | Connect a new bank account |
|
|
103
102
|
| `ray sync` | Pull latest transactions and balances |
|
|
@@ -155,6 +154,7 @@ Ray stores everything in `~/.ray/`:
|
|
|
155
154
|
context.md # Persistent financial context for AI
|
|
156
155
|
data/
|
|
157
156
|
finance.db # Encrypted SQLite database
|
|
157
|
+
demo.db # Demo database (created by `ray demo`)
|
|
158
158
|
sync.log # Daily sync output
|
|
159
159
|
```
|
|
160
160
|
|
|
@@ -174,6 +174,7 @@ RAY_API_KEY= # Ray API key (managed mode, replaces the above)
|
|
|
174
174
|
|
|
175
175
|
## Roadmap
|
|
176
176
|
|
|
177
|
+
- [ ] Bring your own model — use any LLM provider (OpenAI, Ollama, open-source models, etc.)
|
|
177
178
|
- [ ] Daily digest email — morning summary of your finances
|
|
178
179
|
|
|
179
180
|
Have an idea? [Open a PR](https://github.com/cdinnison/ray-finance/pulls).
|
package/dist/cli/commands.d.ts
CHANGED
|
@@ -11,4 +11,6 @@ export declare function showSpending(period?: string): Promise<void>;
|
|
|
11
11
|
export declare function showBudgets(): void;
|
|
12
12
|
export declare function showGoals(): void;
|
|
13
13
|
export declare function showScore(): void;
|
|
14
|
+
export declare function runAdd(): Promise<void>;
|
|
15
|
+
export declare function runRemove(): Promise<void>;
|
|
14
16
|
export declare function showAlerts(): void;
|
package/dist/cli/commands.js
CHANGED
|
@@ -5,6 +5,7 @@ import { getLatestScore, getAchievements, getMonthlySavings } from "../scoring/i
|
|
|
5
5
|
import { generateAlerts } from "../alerts/index.js";
|
|
6
6
|
import { runDailySync } from "../daily-sync.js";
|
|
7
7
|
import { startLinkServer } from "../server.js";
|
|
8
|
+
import { addManualAccount, getManualAccounts, removeManualAccount, scrapeRedfinEstimate } from "../property.js";
|
|
8
9
|
import { heading, progressBar, formatMoney, formatMoneyColored, dim, formatDuration, formatError, renderLogo, institutionName } from "./format.js";
|
|
9
10
|
export async function runSync() {
|
|
10
11
|
const ora = (await import("ora")).default;
|
|
@@ -26,6 +27,7 @@ export async function runSync() {
|
|
|
26
27
|
export async function runLink() {
|
|
27
28
|
const open = (await import("open")).default;
|
|
28
29
|
const ora = (await import("ora")).default;
|
|
30
|
+
const readline = await import("readline");
|
|
29
31
|
const { url, waitForComplete, stop } = startLinkServer();
|
|
30
32
|
console.log(`\n${heading("Link Account")}\n`);
|
|
31
33
|
console.log(`Opening Plaid Link in your browser...\n`);
|
|
@@ -35,6 +37,37 @@ export async function runLink() {
|
|
|
35
37
|
await waitForComplete();
|
|
36
38
|
stop();
|
|
37
39
|
spinner.succeed("Bank account linked successfully!");
|
|
40
|
+
// Check if a mortgage was linked and we don't already have a property account
|
|
41
|
+
const db = getDb();
|
|
42
|
+
const hasMortgage = db.prepare(`SELECT 1 FROM accounts WHERE type = 'loan' AND subtype = 'mortgage' LIMIT 1`).get();
|
|
43
|
+
const hasProperty = db.prepare(`SELECT 1 FROM accounts WHERE type = 'other' AND subtype = 'property' LIMIT 1`).get();
|
|
44
|
+
if (hasMortgage && !hasProperty) {
|
|
45
|
+
console.log(`\n${dim("Mortgage detected.")} Track your home value for accurate net worth.`);
|
|
46
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
47
|
+
const ask = (q) => new Promise(resolve => rl.question(q, resolve));
|
|
48
|
+
const listingUrl = (await ask(`${dim("Paste a Redfin URL (or press Enter to skip):")} `)).trim();
|
|
49
|
+
if (listingUrl) {
|
|
50
|
+
const name = (await ask(`${dim("Name (e.g. Primary Residence):")} `)).trim() || "Primary Residence";
|
|
51
|
+
rl.close();
|
|
52
|
+
const propSpinner = ora("Fetching home value...").start();
|
|
53
|
+
try {
|
|
54
|
+
const value = await scrapeRedfinEstimate(listingUrl);
|
|
55
|
+
if (value) {
|
|
56
|
+
addManualAccount(db, name, "asset", value, listingUrl);
|
|
57
|
+
propSpinner.succeed(`${name}: ${rawFormatMoney(value)} — updates automatically on sync.`);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
propSpinner.fail("Could not determine home value from that URL. Try 'ray add' later.");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
propSpinner.fail("Failed to fetch home value. Try 'ray add' later.");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
rl.close();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
38
71
|
}
|
|
39
72
|
export async function showAccounts() {
|
|
40
73
|
const db = getDb();
|
|
@@ -239,6 +272,108 @@ export function showScore() {
|
|
|
239
272
|
}
|
|
240
273
|
console.log();
|
|
241
274
|
}
|
|
275
|
+
export async function runAdd() {
|
|
276
|
+
const ora = (await import("ora")).default;
|
|
277
|
+
const inquirer = (await import("inquirer")).default;
|
|
278
|
+
const db = getDb();
|
|
279
|
+
const theme = {
|
|
280
|
+
prefix: { idle: " ", done: chalk.green(" ✓") },
|
|
281
|
+
style: { highlight: (text) => chalk.yellowBright(text) },
|
|
282
|
+
};
|
|
283
|
+
console.log(`\n${heading("Add Account")}`);
|
|
284
|
+
console.log(dim(" Track something not linked via Plaid — a home, car, crypto, loan, etc.\n"));
|
|
285
|
+
const { name } = await inquirer.prompt([{ theme,
|
|
286
|
+
type: "input",
|
|
287
|
+
name: "name",
|
|
288
|
+
message: "Name",
|
|
289
|
+
validate: (v) => v.trim() ? true : "Required",
|
|
290
|
+
}]);
|
|
291
|
+
const { type } = await inquirer.prompt([{ theme,
|
|
292
|
+
type: "list",
|
|
293
|
+
name: "type",
|
|
294
|
+
message: "Type",
|
|
295
|
+
choices: [
|
|
296
|
+
{ name: "Asset — something you own (adds to net worth)", value: "asset" },
|
|
297
|
+
{ name: "Liability — something you owe (subtracts from net worth)", value: "liability" },
|
|
298
|
+
],
|
|
299
|
+
}]);
|
|
300
|
+
let finalBalance = 0;
|
|
301
|
+
let listingUrl;
|
|
302
|
+
// For assets: offer Redfin auto-tracking
|
|
303
|
+
if (type === "asset") {
|
|
304
|
+
const { redfin } = await inquirer.prompt([{ theme,
|
|
305
|
+
type: "input",
|
|
306
|
+
name: "redfin",
|
|
307
|
+
message: `Redfin URL ${dim("(optional — auto-tracks home value)")}`,
|
|
308
|
+
}]);
|
|
309
|
+
const url = redfin.trim();
|
|
310
|
+
if (url) {
|
|
311
|
+
try {
|
|
312
|
+
const parsed = new URL(url);
|
|
313
|
+
if (!parsed.hostname.includes("redfin")) {
|
|
314
|
+
console.log(chalk.yellow(" Only Redfin URLs are supported."));
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
listingUrl = url;
|
|
318
|
+
const spinner = ora("Fetching Redfin Estimate...").start();
|
|
319
|
+
const scraped = await scrapeRedfinEstimate(url);
|
|
320
|
+
if (scraped) {
|
|
321
|
+
finalBalance = scraped;
|
|
322
|
+
spinner.succeed(`Redfin Estimate: ${chalk.bold(rawFormatMoney(scraped))} ${dim("— updates on each sync")}`);
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
spinner.warn("Could not fetch estimate.");
|
|
326
|
+
listingUrl = undefined;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
console.log(chalk.yellow(" Invalid URL."));
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
// Manual value if no Redfin
|
|
336
|
+
if (!listingUrl) {
|
|
337
|
+
const { balance } = await inquirer.prompt([{ theme,
|
|
338
|
+
type: "input",
|
|
339
|
+
name: "balance",
|
|
340
|
+
message: "Current value ($)",
|
|
341
|
+
validate: (v) => {
|
|
342
|
+
const n = parseFloat(v.replace(/[$,]/g, ""));
|
|
343
|
+
return isNaN(n) ? "Enter a number" : true;
|
|
344
|
+
},
|
|
345
|
+
}]);
|
|
346
|
+
finalBalance = parseFloat(balance.replace(/[$,]/g, ""));
|
|
347
|
+
}
|
|
348
|
+
addManualAccount(db, name.trim(), type, finalBalance, listingUrl);
|
|
349
|
+
const label = type === "asset" ? chalk.green("asset") : chalk.red("liability");
|
|
350
|
+
console.log(`\n ${chalk.green("+")} ${chalk.bold(name.trim())} ${rawFormatMoney(finalBalance)} ${label}\n`);
|
|
351
|
+
}
|
|
352
|
+
export async function runRemove() {
|
|
353
|
+
const readline = await import("readline");
|
|
354
|
+
const db = getDb();
|
|
355
|
+
const accounts = getManualAccounts(db);
|
|
356
|
+
if (accounts.length === 0) {
|
|
357
|
+
console.log("\nNo manual accounts. Use 'ray add' to create one.");
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
console.log(`\n${heading("Manual Accounts")}\n`);
|
|
361
|
+
for (let i = 0; i < accounts.length; i++) {
|
|
362
|
+
const a = accounts[i];
|
|
363
|
+
const typeLabel = a.type === "loan" || a.type === "credit" ? "liability" : "asset";
|
|
364
|
+
const url = a.listing_url ? dim(` — ${a.listing_url}`) : "";
|
|
365
|
+
console.log(` ${dim(`${i + 1}.`)} ${a.name} ${rawFormatMoney(a.current_balance)} (${typeLabel})${url}`);
|
|
366
|
+
}
|
|
367
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
368
|
+
const answer = (await new Promise(resolve => rl.question(`\n Remove which? (number, or Enter to cancel): `, resolve))).trim();
|
|
369
|
+
rl.close();
|
|
370
|
+
const idx = parseInt(answer, 10) - 1;
|
|
371
|
+
if (isNaN(idx) || idx < 0 || idx >= accounts.length)
|
|
372
|
+
return;
|
|
373
|
+
removeManualAccount(db, accounts[idx].account_id);
|
|
374
|
+
console.log(chalk.green(`\n Removed ${accounts[idx].name}.`));
|
|
375
|
+
console.log();
|
|
376
|
+
}
|
|
242
377
|
export function showAlerts() {
|
|
243
378
|
const db = getDb();
|
|
244
379
|
const alerts = generateAlerts(db);
|
package/dist/cli/index.js
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
// --demo flag: use dedicated demo database (must run before config import)
|
|
5
|
+
const isDemoMode = process.argv.includes("--demo");
|
|
6
|
+
if (isDemoMode) {
|
|
7
|
+
process.argv = process.argv.filter(a => a !== "--demo");
|
|
8
|
+
}
|
|
2
9
|
import { Command } from "commander";
|
|
3
10
|
import { createRequire } from "module";
|
|
4
11
|
import { config, isConfigured, useManaged, RAY_PROXY_BASE } from "../config.js";
|
|
5
12
|
import { helpScreen } from "./format.js";
|
|
13
|
+
// Override config for demo mode (demo DB is unencrypted)
|
|
14
|
+
if (isDemoMode) {
|
|
15
|
+
config.dbPath = resolve(homedir(), ".ray", "data", "demo.db");
|
|
16
|
+
config.dbEncryptionKey = "";
|
|
17
|
+
}
|
|
6
18
|
const require = createRequire(import.meta.url);
|
|
7
19
|
const { version } = require("../../package.json");
|
|
8
20
|
const program = new Command();
|
|
@@ -48,6 +60,22 @@ program
|
|
|
48
60
|
const { runLink } = await import("./commands.js");
|
|
49
61
|
await runLink();
|
|
50
62
|
});
|
|
63
|
+
program
|
|
64
|
+
.command("add")
|
|
65
|
+
.description("Add a manual account (home, car, crypto, etc.)")
|
|
66
|
+
.action(async () => {
|
|
67
|
+
ensureConfigured();
|
|
68
|
+
const { runAdd } = await import("./commands.js");
|
|
69
|
+
await runAdd();
|
|
70
|
+
});
|
|
71
|
+
program
|
|
72
|
+
.command("remove")
|
|
73
|
+
.description("Remove a manual account")
|
|
74
|
+
.action(async () => {
|
|
75
|
+
ensureConfigured();
|
|
76
|
+
const { runRemove } = await import("./commands.js");
|
|
77
|
+
await runRemove();
|
|
78
|
+
});
|
|
51
79
|
program
|
|
52
80
|
.command("accounts")
|
|
53
81
|
.description("Show linked accounts and balances")
|
|
@@ -181,6 +209,14 @@ program
|
|
|
181
209
|
const { runDoctor } = await import("./doctor.js");
|
|
182
210
|
await runDoctor();
|
|
183
211
|
});
|
|
212
|
+
program
|
|
213
|
+
.command("demo")
|
|
214
|
+
.description("Seed a demo database with realistic fake data")
|
|
215
|
+
.action(async () => {
|
|
216
|
+
const demoPath = resolve(homedir(), ".ray", "data", "demo.db");
|
|
217
|
+
const { seedDemoDb } = await import("../demo/seed.js");
|
|
218
|
+
seedDemoDb(demoPath);
|
|
219
|
+
});
|
|
184
220
|
program
|
|
185
221
|
.command("completions")
|
|
186
222
|
.description("Install shell completions")
|
|
@@ -189,6 +225,8 @@ program
|
|
|
189
225
|
installCompletions();
|
|
190
226
|
});
|
|
191
227
|
function ensureConfigured() {
|
|
228
|
+
if (isDemoMode)
|
|
229
|
+
return;
|
|
192
230
|
if (!isConfigured()) {
|
|
193
231
|
console.error("Ray is not configured. Run 'ray setup' first.");
|
|
194
232
|
process.exit(1);
|
|
@@ -199,6 +237,8 @@ program.configureHelp({
|
|
|
199
237
|
formatHelp: () => helpScreen([
|
|
200
238
|
{ name: "setup", desc: "Configure Ray (API keys, preferences)" },
|
|
201
239
|
{ name: "link", desc: "Link a new financial account via Plaid" },
|
|
240
|
+
{ name: "add", desc: "Add a manual account (home, car, crypto, etc.)" },
|
|
241
|
+
{ name: "remove", desc: "Remove a manual account" },
|
|
202
242
|
{ name: "sync", desc: "Sync transactions from linked banks" },
|
|
203
243
|
{ name: "accounts", desc: "Show linked accounts and balances" },
|
|
204
244
|
{ name: "status", desc: "Show financial overview" },
|
|
@@ -213,6 +253,7 @@ program.configureHelp({
|
|
|
213
253
|
{ name: "billing", desc: "Manage your Ray subscription" },
|
|
214
254
|
{ name: "update", desc: "Update Ray to the latest version" },
|
|
215
255
|
{ name: "doctor", desc: "Check system health" },
|
|
256
|
+
{ name: "demo", desc: "Seed a demo database with fake data" },
|
|
216
257
|
{ name: "completions", desc: "Install shell completions" },
|
|
217
258
|
]),
|
|
218
259
|
});
|
package/dist/daily-sync.js
CHANGED
|
@@ -3,6 +3,7 @@ import { calculateDailyScore, checkAchievements } from "./scoring/index.js";
|
|
|
3
3
|
import { decryptPlaidToken } from "./db/encryption.js";
|
|
4
4
|
import { config } from "./config.js";
|
|
5
5
|
import { institutionName } from "./cli/format.js";
|
|
6
|
+
import { refreshPropertyValues, hasListingUrls } from "./property.js";
|
|
6
7
|
/** Run the daily sync for a single database */
|
|
7
8
|
export async function runDailySync(db) {
|
|
8
9
|
const institutions = db
|
|
@@ -98,6 +99,15 @@ export async function runDailySync(db) {
|
|
|
98
99
|
console.error(` Error syncing ${inst.name}: ${err.message}`);
|
|
99
100
|
}
|
|
100
101
|
}
|
|
102
|
+
// Refresh property values from listing URLs if configured
|
|
103
|
+
if (hasListingUrls(db)) {
|
|
104
|
+
try {
|
|
105
|
+
await refreshPropertyValues(db);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Non-fatal
|
|
109
|
+
}
|
|
110
|
+
}
|
|
101
111
|
// Snapshot net worth
|
|
102
112
|
const assets = db
|
|
103
113
|
.prepare(`SELECT COALESCE(SUM(current_balance), 0) as total FROM accounts WHERE type IN ('depository', 'investment', 'other')`)
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
export declare const institutions: {
|
|
2
|
+
item_id: string;
|
|
3
|
+
access_token: string;
|
|
4
|
+
name: string;
|
|
5
|
+
products: string;
|
|
6
|
+
logo: string;
|
|
7
|
+
primary_color: string;
|
|
8
|
+
}[];
|
|
9
|
+
export declare const accounts: ({
|
|
10
|
+
account_id: string;
|
|
11
|
+
item_id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
official_name: string;
|
|
14
|
+
type: string;
|
|
15
|
+
subtype: string;
|
|
16
|
+
mask: string;
|
|
17
|
+
current_balance: number;
|
|
18
|
+
available_balance: number;
|
|
19
|
+
currency: string;
|
|
20
|
+
balance_limit: null;
|
|
21
|
+
} | {
|
|
22
|
+
account_id: string;
|
|
23
|
+
item_id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
official_name: string;
|
|
26
|
+
type: string;
|
|
27
|
+
subtype: string;
|
|
28
|
+
mask: string;
|
|
29
|
+
current_balance: number;
|
|
30
|
+
available_balance: null;
|
|
31
|
+
currency: string;
|
|
32
|
+
balance_limit: null;
|
|
33
|
+
} | {
|
|
34
|
+
account_id: string;
|
|
35
|
+
item_id: string;
|
|
36
|
+
name: string;
|
|
37
|
+
official_name: string;
|
|
38
|
+
type: string;
|
|
39
|
+
subtype: string;
|
|
40
|
+
mask: string;
|
|
41
|
+
current_balance: number;
|
|
42
|
+
available_balance: number;
|
|
43
|
+
currency: string;
|
|
44
|
+
balance_limit: number;
|
|
45
|
+
} | {
|
|
46
|
+
account_id: string;
|
|
47
|
+
item_id: string;
|
|
48
|
+
name: string;
|
|
49
|
+
official_name: null;
|
|
50
|
+
type: string;
|
|
51
|
+
subtype: string;
|
|
52
|
+
mask: null;
|
|
53
|
+
current_balance: number;
|
|
54
|
+
available_balance: null;
|
|
55
|
+
currency: string;
|
|
56
|
+
balance_limit: null;
|
|
57
|
+
})[];
|
|
58
|
+
export declare const transactions: ({
|
|
59
|
+
transaction_id: string;
|
|
60
|
+
account_id: string;
|
|
61
|
+
amount: number;
|
|
62
|
+
date: string;
|
|
63
|
+
name: string;
|
|
64
|
+
merchant_name: string;
|
|
65
|
+
category: string;
|
|
66
|
+
subcategory: string;
|
|
67
|
+
pending: number;
|
|
68
|
+
payment_channel: string;
|
|
69
|
+
} | {
|
|
70
|
+
transaction_id: string;
|
|
71
|
+
account_id: string;
|
|
72
|
+
amount: number;
|
|
73
|
+
date: string;
|
|
74
|
+
name: string;
|
|
75
|
+
merchant_name: null;
|
|
76
|
+
category: string;
|
|
77
|
+
subcategory: string;
|
|
78
|
+
pending: number;
|
|
79
|
+
payment_channel: string;
|
|
80
|
+
})[];
|
|
81
|
+
export declare const securities: {
|
|
82
|
+
security_id: string;
|
|
83
|
+
name: string;
|
|
84
|
+
ticker: string;
|
|
85
|
+
type: string;
|
|
86
|
+
close_price: number;
|
|
87
|
+
close_price_as_of: string;
|
|
88
|
+
}[];
|
|
89
|
+
export declare const holdings: ({
|
|
90
|
+
account_id: string;
|
|
91
|
+
security_id: string;
|
|
92
|
+
quantity: number;
|
|
93
|
+
value: number;
|
|
94
|
+
cost_basis: number;
|
|
95
|
+
price: number;
|
|
96
|
+
price_as_of: string;
|
|
97
|
+
vested_value: null;
|
|
98
|
+
vested_quantity: null;
|
|
99
|
+
} | {
|
|
100
|
+
account_id: string;
|
|
101
|
+
security_id: string;
|
|
102
|
+
quantity: number;
|
|
103
|
+
value: number;
|
|
104
|
+
cost_basis: number;
|
|
105
|
+
price: number;
|
|
106
|
+
price_as_of: string;
|
|
107
|
+
vested_value: number;
|
|
108
|
+
vested_quantity: number;
|
|
109
|
+
})[];
|
|
110
|
+
export declare const liabilities: ({
|
|
111
|
+
account_id: string;
|
|
112
|
+
type: string;
|
|
113
|
+
interest_rate: number;
|
|
114
|
+
origination_date: null;
|
|
115
|
+
original_balance: null;
|
|
116
|
+
current_balance: number;
|
|
117
|
+
minimum_payment: number;
|
|
118
|
+
next_payment_due: string;
|
|
119
|
+
last_payment_amount: number;
|
|
120
|
+
last_payment_date: string;
|
|
121
|
+
credit_limit: number;
|
|
122
|
+
last_statement_issue_date: string;
|
|
123
|
+
is_overdue: number;
|
|
124
|
+
apr_type: string;
|
|
125
|
+
maturity_date: null;
|
|
126
|
+
loan_type: null;
|
|
127
|
+
property_address: null;
|
|
128
|
+
escrow_balance: null;
|
|
129
|
+
loan_status: null;
|
|
130
|
+
loan_name: null;
|
|
131
|
+
repayment_plan: null;
|
|
132
|
+
expected_payoff_date: null;
|
|
133
|
+
ytd_interest_paid: null;
|
|
134
|
+
ytd_principal_paid: null;
|
|
135
|
+
} | {
|
|
136
|
+
account_id: string;
|
|
137
|
+
type: string;
|
|
138
|
+
interest_rate: number;
|
|
139
|
+
origination_date: string;
|
|
140
|
+
original_balance: number;
|
|
141
|
+
current_balance: number;
|
|
142
|
+
minimum_payment: number;
|
|
143
|
+
next_payment_due: string;
|
|
144
|
+
last_payment_amount: number;
|
|
145
|
+
last_payment_date: string;
|
|
146
|
+
credit_limit: null;
|
|
147
|
+
last_statement_issue_date: null;
|
|
148
|
+
is_overdue: number;
|
|
149
|
+
apr_type: string;
|
|
150
|
+
maturity_date: string;
|
|
151
|
+
loan_type: string;
|
|
152
|
+
property_address: string;
|
|
153
|
+
escrow_balance: number;
|
|
154
|
+
loan_status: string;
|
|
155
|
+
loan_name: string;
|
|
156
|
+
repayment_plan: null;
|
|
157
|
+
expected_payoff_date: string;
|
|
158
|
+
ytd_interest_paid: number;
|
|
159
|
+
ytd_principal_paid: number;
|
|
160
|
+
})[];
|
|
161
|
+
export declare const recurring: ({
|
|
162
|
+
stream_id: string;
|
|
163
|
+
account_id: string;
|
|
164
|
+
merchant_name: string;
|
|
165
|
+
description: string;
|
|
166
|
+
frequency: string;
|
|
167
|
+
category: string;
|
|
168
|
+
subcategory: string;
|
|
169
|
+
avg_amount: number;
|
|
170
|
+
last_amount: number;
|
|
171
|
+
first_date: string;
|
|
172
|
+
last_date: string;
|
|
173
|
+
is_active: number;
|
|
174
|
+
status: string;
|
|
175
|
+
stream_type: string;
|
|
176
|
+
} | {
|
|
177
|
+
stream_id: string;
|
|
178
|
+
account_id: string;
|
|
179
|
+
merchant_name: null;
|
|
180
|
+
description: string;
|
|
181
|
+
frequency: string;
|
|
182
|
+
category: string;
|
|
183
|
+
subcategory: string;
|
|
184
|
+
avg_amount: number;
|
|
185
|
+
last_amount: number;
|
|
186
|
+
first_date: string;
|
|
187
|
+
last_date: string;
|
|
188
|
+
is_active: number;
|
|
189
|
+
status: string;
|
|
190
|
+
stream_type: string;
|
|
191
|
+
})[];
|
|
192
|
+
export declare const budgets: {
|
|
193
|
+
category: string;
|
|
194
|
+
monthly_limit: number;
|
|
195
|
+
period: string;
|
|
196
|
+
}[];
|
|
197
|
+
export declare const goals: {
|
|
198
|
+
name: string;
|
|
199
|
+
target_amount: number;
|
|
200
|
+
current_amount: number;
|
|
201
|
+
target_date: string;
|
|
202
|
+
status: string;
|
|
203
|
+
}[];
|
|
204
|
+
export declare const dailyScores: {
|
|
205
|
+
date: string;
|
|
206
|
+
score: number;
|
|
207
|
+
restaurant_count: number;
|
|
208
|
+
shopping_count: number;
|
|
209
|
+
food_spend: number;
|
|
210
|
+
total_spend: number;
|
|
211
|
+
zero_spend: number;
|
|
212
|
+
no_restaurant_streak: number;
|
|
213
|
+
no_shopping_streak: number;
|
|
214
|
+
on_pace_streak: number;
|
|
215
|
+
}[];
|
|
216
|
+
export declare const achievements: {
|
|
217
|
+
key: string;
|
|
218
|
+
name: string;
|
|
219
|
+
description: string;
|
|
220
|
+
unlocked_at: string;
|
|
221
|
+
}[];
|
|
222
|
+
export declare const netWorthHistory: {
|
|
223
|
+
date: string;
|
|
224
|
+
total_assets: number;
|
|
225
|
+
total_liabilities: number;
|
|
226
|
+
net_worth: number;
|
|
227
|
+
}[];
|
|
228
|
+
export declare const investmentTransactions: {
|
|
229
|
+
investment_transaction_id: string;
|
|
230
|
+
account_id: string;
|
|
231
|
+
security_id: string;
|
|
232
|
+
date: string;
|
|
233
|
+
name: string;
|
|
234
|
+
quantity: number;
|
|
235
|
+
amount: number;
|
|
236
|
+
price: number;
|
|
237
|
+
fees: number;
|
|
238
|
+
type: string;
|
|
239
|
+
subtype: string;
|
|
240
|
+
iso_currency_code: string;
|
|
241
|
+
}[];
|
|
242
|
+
export declare const recurringBills: {
|
|
243
|
+
name: string;
|
|
244
|
+
amount: number;
|
|
245
|
+
day_of_month: number;
|
|
246
|
+
type: string;
|
|
247
|
+
account_id: string;
|
|
248
|
+
}[];
|
|
249
|
+
export declare const memories: {
|
|
250
|
+
content: string;
|
|
251
|
+
category: string;
|
|
252
|
+
}[];
|