Versie 0.2.0
This commit is contained in:
commit
e77d8fd373
495 files changed
+81026
No files matched your search
@@ -0,0 +1,189 @@
|
||||
// Generated, do not edit. sha256:52135637bc4779b2b5f755ec50fedf41d2fa7b65d90a35f911c4e68f0b093874
|
||||
import { CONFIG, PREFERENCES, SOURCE_CAPABILITIES, SOURCE_ENDPOINTS, DASHBOARD } from '../../shared/config.js';
|
||||
import { toSearchName } from '../../shared/search-name.js';
|
||||
import { run, one, all, lastId } from './conn.mjs';
|
||||
|
||||
function basisMunt() {
|
||||
const r = one(`SELECT baseCurrency FROM Portfolio WHERE id = 1`);
|
||||
if (!r) throw new Error('Seeds need the Portfolio row: write the unit of account first.');
|
||||
return r.baseCurrency;
|
||||
}
|
||||
|
||||
function fiatAssets(basis) {
|
||||
const codes = [...new Set([basis, 'EUR', 'USD'])];
|
||||
const namen = new Intl.DisplayNames(['nl-NL'], { type: 'currency' });
|
||||
return codes.map(code => {
|
||||
const naam = namen.of(code);
|
||||
const decimals = new Intl.NumberFormat('nl-NL', { style: 'currency', currency: code }).resolvedOptions().maximumFractionDigits;
|
||||
return { symbol: code, name: naam.charAt(0).toUpperCase() + naam.slice(1), kind: 'fiat', unit: code,
|
||||
subunit: code === 'EUR' || code === 'USD' ? 'cent' : null, decimals, displayUnit: 'unit' };
|
||||
});
|
||||
}
|
||||
|
||||
function startBron(symbol, basis) {
|
||||
if (symbol === basis) return 'fixed';
|
||||
if (symbol === 'EUR' || symbol === 'USD') return 'frankfurter';
|
||||
return { BTC: 'mempool', ETH: 'bitvavo', XAU: 'goldapi', XAG: 'goldapi' }[symbol] ?? null;
|
||||
}
|
||||
|
||||
export function seedAssets() {
|
||||
for (const a of fiatAssets(basisMunt())) {
|
||||
if (one(`SELECT 1 AS x FROM Asset WHERE symbol = ?`, [a.symbol])) continue;
|
||||
run(
|
||||
`INSERT INTO Asset (symbol, name, searchName, kind, unit, subunit, decimals, displayUnit)
|
||||
VALUES (?,?,?,?,?,?,?,?)`,
|
||||
[a.symbol, a.name, toSearchName(a.name), a.kind, a.unit, a.subunit, a.decimals, a.displayUnit]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const SEED_METAL_PRODUCTS = [
|
||||
{ symbol: 'XAU', name: 'Krugerrand 1 oz', form: 'coin', grams: CONFIG.METALS.GRAMS_PER_TROY_OUNCE },
|
||||
{ symbol: 'XAU', name: 'Maple Leaf 1 oz', form: 'coin', grams: CONFIG.METALS.GRAMS_PER_TROY_OUNCE },
|
||||
{ symbol: 'XAU', name: 'Wiener Philharmoniker 1 oz', form: 'coin', grams: CONFIG.METALS.GRAMS_PER_TROY_OUNCE },
|
||||
{ symbol: 'XAU', name: 'Baar 1 g', form: 'bar', grams: 1 },
|
||||
{ symbol: 'XAU', name: 'Baar 5 g', form: 'bar', grams: 5 },
|
||||
{ symbol: 'XAU', name: 'Baar 10 g', form: 'bar', grams: 10 },
|
||||
{ symbol: 'XAU', name: 'Baar 100 g', form: 'bar', grams: 100 },
|
||||
{ symbol: 'XAU', name: 'Baar 1 kg', form: 'bar', grams: 1000 },
|
||||
{ symbol: 'XAG', name: 'Maple Leaf 1 oz', form: 'coin', grams: CONFIG.METALS.GRAMS_PER_TROY_OUNCE },
|
||||
{ symbol: 'XAG', name: 'Wiener Philharmoniker 1 oz', form: 'coin', grams: CONFIG.METALS.GRAMS_PER_TROY_OUNCE },
|
||||
{ symbol: 'XAG', name: 'Baar 100 g', form: 'bar', grams: 100 },
|
||||
{ symbol: 'XAG', name: 'Baar 1 kg', form: 'bar', grams: 1000 },
|
||||
];
|
||||
export function seedMetalProducts() {
|
||||
const factor = Math.pow(10, CONFIG.METALS.BASE_DECIMALS);
|
||||
for (const p of SEED_METAL_PRODUCTS) {
|
||||
const a = one(`SELECT id FROM Asset WHERE symbol = ?`, [p.symbol]);
|
||||
if (!a) continue;
|
||||
if (one(`SELECT 1 AS x FROM MetalProduct WHERE assetId = ? AND name = ?`, [a.id, p.name])) continue;
|
||||
run(`INSERT INTO MetalProduct (assetId, name, searchName, form, fineGrams) VALUES (?,?,?,?,?)`,
|
||||
[a.id, p.name, toSearchName(p.name), p.form, Math.round(p.grams * factor)]);
|
||||
}
|
||||
}
|
||||
|
||||
const SEED_CONNECTIONS = [
|
||||
{ kind: 'btc_explorer', name: 'mempool.space (publiek)', url: CONFIG.PRICE_SOURCES.MEMPOOL_PUBLIC_BASE, isActive: 1, isSystem: 1 },
|
||||
];
|
||||
export function seedConnections() {
|
||||
const now = new Date().toISOString();
|
||||
for (const c of SEED_CONNECTIONS) {
|
||||
if (one(`SELECT 1 AS x FROM Connection WHERE kind = ? AND name = ?`, [c.kind, c.name])) continue;
|
||||
const hasActive = !!one(`SELECT 1 AS x FROM Connection WHERE kind = ? AND isActive = 1`, [c.kind]);
|
||||
run(`INSERT INTO Connection (name, searchName, url, kind, isActive, isSystem, lastStatus, lastCheckedAt, createdAt, updatedAt)
|
||||
VALUES (?,?,?,?,?,?,NULL,NULL,?,?)`,
|
||||
[c.name, toSearchName(c.name), c.url, c.kind, hasActive ? 0 : c.isActive, c.isSystem, now, now]);
|
||||
}
|
||||
}
|
||||
|
||||
function seedProviderList(basis) {
|
||||
return [
|
||||
{ key: 'manual', name: 'Handmatig', baseUrl: '', authenticationKind: 'none', authenticationRequired: 0, isSystem: true,
|
||||
authenticationHeaderName: null, authenticationParameterName: null, hmac: null,
|
||||
endpoints: [], symbols: [], coverage: [], outputs: [] },
|
||||
|
||||
{ key: CONFIG.MARKET_SERVICE.PROVIDER_KEY, name: 'Atreides Services', baseUrl: '', authenticationKind: 'none',
|
||||
authenticationRequired: 0, isSystem: true, authenticationHeaderName: null, authenticationParameterName: null,
|
||||
hmac: null, endpoints: [], symbols: [], coverage: [], outputs: [] },
|
||||
|
||||
{ key: 'fixed', name: 'Vaste koers', baseUrl: '', authenticationKind: 'none', authenticationRequired: 0, isSystem: true,
|
||||
authenticationHeaderName: null, authenticationParameterName: null, hmac: null,
|
||||
fixedRate: { fiatPrice: 1 },
|
||||
endpoints: [
|
||||
{ capability: 'spot', method: 'GET', pathTemplate: '', queryTemplate: null },
|
||||
{ capability: 'history_point', method: 'GET', pathTemplate: '', queryTemplate: null },
|
||||
],
|
||||
symbols: [], coverage: [basis], outputs: [] },
|
||||
];
|
||||
}
|
||||
|
||||
export function seedProviders() {
|
||||
for (const p of seedProviderList(basisMunt())) {
|
||||
if (one(`SELECT 1 AS x FROM Provider WHERE key = ?`, [p.key])) continue;
|
||||
const isActive = p.authenticationRequired ? 0 : 1;
|
||||
run(`INSERT INTO Provider
|
||||
(key, name, searchName, baseUrl, authenticationHeaderName, authenticationParameterName,
|
||||
authenticationKind, authenticationRequired, isActive, isSeed, isSystem, createdAt)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,1,?,?)`,
|
||||
[p.key, p.name, toSearchName(p.name), p.baseUrl, p.authenticationHeaderName, p.authenticationParameterName,
|
||||
p.authenticationKind, p.authenticationRequired, isActive, p.isSystem ? 1 : 0, new Date().toISOString()]);
|
||||
const pid = lastId();
|
||||
for (const symbool of p.coverage || []) {
|
||||
run(`INSERT INTO ProviderCoverage (providerId, symbol) VALUES (?,?)`, [pid, symbool]);
|
||||
}
|
||||
if (p.fixedRate) {
|
||||
run(`INSERT INTO ProviderFixedRate (providerId, fiatPrice) VALUES (?,?)`, [pid, p.fixedRate.fiatPrice]);
|
||||
}
|
||||
if (p.callsPerMonth) {
|
||||
run(`INSERT INTO ProviderCallLimit (providerId, callsPerMonth, createdAt) VALUES (?,?,?)`,
|
||||
[pid, p.callsPerMonth, new Date().toISOString()]);
|
||||
}
|
||||
if (p.hmac) {
|
||||
const h = p.hmac;
|
||||
run(`INSERT INTO ProviderAuthenticationHmac
|
||||
(providerId, messageParts, hashAlgorithm, encoding, keyHeader, signatureHeader, timestampHeader, windowHeader, windowMs)
|
||||
VALUES (?,?,?,?,?,?,?,?,?)`,
|
||||
[pid, h.messageParts, h.hashAlgorithm, h.encoding, h.keyHeader, h.signatureHeader, h.timestampHeader, h.windowHeader, h.windowMs]);
|
||||
}
|
||||
for (const e of p.endpoints)
|
||||
run(`INSERT INTO ProviderEndpoint (providerId, capability, method, pathTemplate, queryTemplate, quoteCurrency) VALUES (?,?,?,?,?,?)`,
|
||||
[pid, e.capability, e.method, e.pathTemplate, e.queryTemplate, e.quoteCurrency ?? null]);
|
||||
for (const s of p.symbols)
|
||||
run(`INSERT INTO ProviderInputMap (providerId, symbol, externalId, quoteUnit, isCatchAll) VALUES (?,?,?,?,?)`,
|
||||
[pid, s.isCatchAll ? null : s.symbol, s.externalId, s.quoteUnit ?? null, s.isCatchAll ? 1 : 0]);
|
||||
for (const o of p.outputs)
|
||||
run(`INSERT INTO ProviderOutputMap (providerId, capability, internalField, jsonPath, transform) VALUES (?,?,?,?,?)`,
|
||||
[pid, o.capability, o.internalField, o.jsonPath, o.transform]);
|
||||
}
|
||||
}
|
||||
|
||||
export function seedPriceSource(assetId, status) {
|
||||
const assets = assetId
|
||||
? all(`SELECT id, symbol FROM Asset WHERE id = ?`, [assetId])
|
||||
: all(`SELECT id, symbol FROM Asset`);
|
||||
const basis = basisMunt();
|
||||
for (const asset of assets) {
|
||||
const srcKey = startBron(asset.symbol, basis);
|
||||
if (!srcKey) continue;
|
||||
const provider = one(`SELECT id FROM Provider WHERE key = ?`, [srcKey]);
|
||||
if (!provider) continue;
|
||||
for (const capability of SOURCE_CAPABILITIES) {
|
||||
if (one(`SELECT 1 AS x FROM PriceSource WHERE assetId = ? AND capability = ?`,
|
||||
[asset.id, capability])) continue;
|
||||
const eindpunten = SOURCE_ENDPOINTS[capability];
|
||||
if (!one(`SELECT 1 AS x FROM ProviderEndpoint WHERE providerId = ? AND capability IN (${eindpunten.map(() => '?').join(',')})`,
|
||||
[provider.id, ...eindpunten])) continue;
|
||||
run(`INSERT INTO PriceSource (assetId, capability, providerId, rank, status) VALUES (?,?,?,1,?)`,
|
||||
[asset.id, capability, provider.id, status]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function seedDashboardProfile() {
|
||||
if (one(`SELECT 1 AS x FROM DashboardProfile WHERE isSystem = 1`)) return false;
|
||||
const now = new Date().toISOString();
|
||||
const hasActive = !!one(`SELECT 1 AS x FROM DashboardProfile WHERE isActive = 1`);
|
||||
run(`INSERT INTO DashboardProfile (name, searchName, description, sortOrder, isActive, isSystem, createdAt, updatedAt)
|
||||
VALUES (?,?,NULL,0,?,1,?,?)`,
|
||||
['Standaard', toSearchName('Standaard'), hasActive ? 0 : 1, now, now]);
|
||||
const profileId = lastId();
|
||||
for (const w of DASHBOARD.DEFAULT_LAYOUT) {
|
||||
const def = DASHBOARD.WIDGETS[w.type];
|
||||
if (!def) continue;
|
||||
run(`INSERT INTO DashboardWidget (profileId, assetId, instanceKey, gridX, gridY, spanWidth, spanHeight, type, settings)
|
||||
VALUES (?,NULL,?,?,0,?,NULL,?,NULL)`, [profileId, w.instId, w.x || 0, def.defaultSpan, w.type]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const FRESH_VALUES = Object.freeze({ app: Object.freeze({ market_spot: 'first' }) });
|
||||
|
||||
export function seedPreferences() {
|
||||
for (const [scope, keys] of Object.entries(PREFERENCES)) {
|
||||
for (const [key, spec] of Object.entries(keys)) {
|
||||
if (spec.secret) continue;
|
||||
run(`INSERT INTO Preference (scope, key, value) VALUES (?,?,?)`,
|
||||
[scope, key, JSON.stringify(FRESH_VALUES[scope]?.[key] ?? spec.initial)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user