Build bilingual Astro exchange landing page and brand reference
This commit is contained in:
commit
671a6aea96
34 files changed
+8213
No files matched your search
@@ -0,0 +1,14 @@
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
const tokens = JSON.parse(
|
||||
readFileSync(new URL('../design/tokens.json', import.meta.url), 'utf8'),
|
||||
);
|
||||
const kebab = (name) => name.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
|
||||
const colors = Object.entries(tokens.colors);
|
||||
writeFileSync(
|
||||
new URL('../src/styles/tokens.css', import.meta.url),
|
||||
`/* Generated by npm run tokens. Edit design/tokens.json. */\n:root {\n${colors.map(([k, v]) => ` --${kebab(k)}: ${v};`).join('\n')}\n --radius: ${tokens.website.radius.card}px;\n --font-family: '${tokens.typography.family}', Arial, sans-serif;\n}\n`,
|
||||
);
|
||||
writeFileSync(
|
||||
new URL('../flutter/brand_palette.dart', import.meta.url),
|
||||
`// Generated brand palette reference. Optional for the Flutter application.\n// This is not an application theme: choose component styling independently.\nimport 'dart:ui';\n\nabstract final class SxchngeBrand {\n${colors.map(([k, v]) => ` static const ${k} = Color(0xFF${v.slice(1).toUpperCase()});`).join('\n')}\n static const fontFamily = '${tokens.typography.family}';\n}\n`,
|
||||
);
|
||||
@@ -0,0 +1,45 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { calculateQuote, parseAmount } from '../src/lib/quote.ts';
|
||||
test('demo calculation deducts the example fee in currency cents', () => {
|
||||
assert.deepEqual(calculateQuote(1, 'BTC', 'EUR'), {
|
||||
rate: 57500,
|
||||
fee: 575,
|
||||
receive: 56925,
|
||||
demo: true,
|
||||
});
|
||||
assert.deepEqual(calculateQuote(2, 'ETH', 'USD'), {
|
||||
rate: 2500,
|
||||
fee: 50,
|
||||
receive: 4950,
|
||||
demo: true,
|
||||
});
|
||||
const q = calculateQuote(123.45, 'USDT', 'EUR');
|
||||
assert.equal(q.fee, 1.14);
|
||||
assert.equal(q.receive, 112.43);
|
||||
});
|
||||
test('accepts decimal comma and eight crypto decimal places', () => {
|
||||
assert.equal(parseAmount(' 0,25 '), 0.25);
|
||||
assert.equal(parseAmount('0.00000001'), 0.00000001);
|
||||
assert.equal(
|
||||
calculateQuote(parseAmount('0,25'), 'BTC', 'EUR').receive,
|
||||
14231.25,
|
||||
);
|
||||
});
|
||||
test('rejects ambiguous, malformed, excessive or invalid input', () => {
|
||||
for (const value of [
|
||||
'',
|
||||
'-1',
|
||||
'1e3',
|
||||
'1,2,3',
|
||||
'1.2.3',
|
||||
'<script>',
|
||||
'0.000000001',
|
||||
'1 000',
|
||||
])
|
||||
assert.ok(Number.isNaN(parseAmount(value)));
|
||||
for (const amount of [0, -1, NaN, Infinity, 1000001])
|
||||
assert.throws(() => calculateQuote(amount, 'BTC', 'EUR'), RangeError);
|
||||
assert.throws(() => calculateQuote(1, 'BOGUS', 'EUR'), RangeError);
|
||||
assert.throws(() => calculateQuote(1, 'BTC', 'BOGUS'), RangeError);
|
||||
});
|
||||
Reference in new issue
Block a user