Back to APIs list

Currency API examples & templates

Use these vals as a playground to view and fork Currency API examples and templates on Val Town. Run any example below or find templates that can be used as a pre-built solution.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { type Static, Type } from "npm:@sinclair/typebox";
const currencyCode = Type.Union([
Type.Literal("USD"),
Type.Literal("EUR"),
]);
const currency = Type.Object({
code: currencyCode,
rate: Type.Optional(Type.Number()),
});
const language = Type.Union([
Type.Literal("fr-FR"),
Type.Literal("en-US"),
]);
const textfield = Type.Union([
Type.String(),
Type.Object({}, {
additionalProperties: Type.String(),
}),
]);
const entity = Type.Object({
name: textfield,
email: Type.Optional(textfield),
address: Type.Optional(textfield),
phone: Type.Optional(textfield),
website: Type.Optional(textfield),
});
const item = Type.Object({
title: textfield,
quantity: Type.Number(),
price: Type.Number(),
});
export const schema = Type.Object({
id: Type.String(),
issued: Type.String({
format: "date",
}),
due: Type.String({
format: "date",
}),
currencies: Type.Array(currency),
logo: Type.Optional(Type.String({ description: "Your logo." })),
from: entity,
to: entity,
tax: Type.Optional(Type.Number()),
items: Type.Array(item),
note: Type.Optional(textfield),
});
export type Invoice = Static<typeof schema>;
type InvoiceItem = Static<typeof item>;
export type Language = Static<typeof language>;
type Entity = Static<typeof entity>;
export type Currency = Static<typeof currency>;
type RenderParams = {
to: string[];
from: string[];
title: string;
note: string;
details: string[][];
table: Table;
};
type Table = {
columns: string[];
rows: string[][];
summary: string[][];
};
function extractTitle(id: string, lang: Language) {
switch (lang) {
case "fr-FR":
return `Facture ${id}`;
case "en-US":
return `Invoice ${id}`;
}
}
function getTableColumns(lang: Language) {
switch (lang) {
case "fr-FR":
return [];
case "en-US":
return [];
}
}
function formatPrice(price: Number, currency: Currency) {
switch (currency.code) {
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { parseArgs } from "jsr:@std/cli/parse-args";
import { Base64 } from "npm:js-base64";
import open from "npm:open";
function printHelp() {
console.log("help");
}
const { _, language, currency } = parseArgs(Deno.args, {
boolean: ["help"],
string: ["language", "currency"],
});
if (_.length == 0 || !language || !currency) {
printHelp();
Deno.exit(1);
}
const content = Deno.readTextFileSync(_[0]);
const url = new URL(`https://jsoninvoice.pomdtr.me/invoice/${Base64.encode(content)}`);
url.searchParams.set("language", language);
url.searchParams.set("currency", currency);
console.log(url.toString());
await open(url.toString());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/** @jsxImportSource npm:hono/jsx */
import codeOnValTown from "https://esm.town/v/andreterron/codeOnValTown?v=50";
import { honoMiddleware } from "https://esm.town/v/pomdtr/codeOnValTown";
import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo";
import * as basicTheme from "https://esm.town/v/pomdtr/invoice_basic_theme";
import { extractParams, Invoice, Language, schema } from "https://esm.town/v/pomdtr/invoice_schema";
import { Editor } from "https://esm.town/v/pomdtr/jsoninvoice_editor";
import { HomePage } from "https://esm.town/v/pomdtr/jsoninvoice_homepage";
import { Hono } from "npm:hono";
import { Base64 } from "npm:js-base64";
const app = new Hono();
const val = extractValInfo(import.meta.url);
app.use(
"/",
honoMiddleware({
val: {
handle: val.author,
name: val.name,
},
}),
);
app.get("/", c => {
return c.html(
<HomePage />,
);
});
app.get("/editor", c => {
return c.html(
<Editor />,
);
});
app.get("/invoice/:code", async c => {
try {
let invoice: Invoice = JSON.parse(Base64.decode(c.req.param("code")));
const currencyCode = c.req.query("currency");
const currency = invoice.currencies.find(currency => currency.code == currencyCode);
if (!currency) {
return new Response(`${currencyCode} not available in currencies array`, {
status: 400,
});
}
const language = c.req.query("language") as Language;
const params = extractParams(invoice, {
currency,
language,
});
const rendered = await basicTheme.render(params);
return c.html(rendered);
} catch (e) {
return new Response(e.stack, {
status: 500,
});
}
});
app.get("/schema.json", () => {
return new Response(JSON.stringify(schema, null, 2), {
"headers": {
"Content-Type": "application/json",
},
});
});
app.get("/TODO", (c) => {
return c.text("TODO");
});
export default app.fetch;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { Base64 } from "https://cdn.jsdelivr.net/npm/js-base64@3.7.7/base64.mjs";
import { debounce } from "https://esm.sh/lodash-es";
const editor = document.getElementById("editor");
const preview = document.getElementById("preview") as HTMLIFrameElement;
const printBtn = document.getElementById("print-btn") as HTMLButtonElement;
const copyBtn = document.getElementById("copy-btn") as HTMLButtonElement;
const formatBtn = document.getElementById("format-btn") as HTMLButtonElement;
const languageSelector = document.getElementById("languages") as HTMLSelectElement;
const currencySelector = document.getElementById("currencies") as HTMLSelectElement;
async function updatePreview() {
try {
const code = JSON.parse(editor.code);
const language = languageSelector.value;
const currency = currencySelector.value;
const encoded = Base64.encode(JSON.stringify(code));
preview.src = `${window.location.origin}/invoice/${encoded}?language=${language}&currency=${currency}`;
} catch (_) {
}
}
const debouncedUpdatePreview = debounce(updatePreview, 500, {});
editor.addEventListener("code-change", (e: CustomEvent) => {
debouncedUpdatePreview();
});
currencySelector.addEventListener("change", () => {
debouncedUpdatePreview();
});
languageSelector.addEventListener("change", () => {
debouncedUpdatePreview();
});
printBtn.addEventListener("click", (e: CustomEvent) => {
window.open(preview.src);
});
copyBtn.addEventListener("click", async (e: CustomEvent) => {
await navigator.clipboard.writeText(editor.code);
});
formatBtn.addEventListener("click", async (e: CustomEvent) => {
const invoice = JSON.parse(editor.code);
editor.code = JSON.stringify(invoice, null, 2);
});
updatePreview();

BTC Price Alert

This val monitors the price of Bitcoin (BTC) and sends an email alert if the price fluctuates significantly. Specifically, it checks the current BTC price against the last recorded price and triggers an email notification if the change exceeds 20%. The email includes the new price, formatted as currency.

Fork this val to get these notifications on your inbox.

Readme
Runs every 1 hrs
Fork
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { formatAsCurrency } from "https://esm.town/v/panphora/formatAsCurrency?v=5";
import { blob } from "https://esm.town/v/std/blob?v=11";
import { email } from "https://esm.town/v/std/email?v=9";
import { currency } from "https://esm.town/v/stevekrouse/currency";
export async function btcPriceAlert() {
const lastBtcPrice: number = await blob.getJSON("lastBtcPrice");
let btcPrice = await currency("usd", "btc");
let change = Math.abs(btcPrice - lastBtcPrice);
if (change / lastBtcPrice > .2) {
await blob.setJSON("lastBtcPrice", btcPrice);
let formattedBtcPrice = formatAsCurrency(btcPrice);
await email({
text: formattedBtcPrice,
subject: "BTC PRICE ALERT: " + formattedBtcPrice,
});
}
return btcPrice;
}

Donations that people have declared as being on my behalf.

Readme
1
2
// set at Mon Apr 08 2024 21:15:15 GMT+0000 (Coordinated Universal Time)
export let donations = {"totalGBP":103.3558,"currencyCount":2,"individual":[{"timestamp":1689933934.276,"amount":"50","currency":"USD"},{"timestamp":1689936862.918,"amount":"62.50","currency":"GBP"},{"timestamp":1708422075.09,"amount":"1.00","currency":"GB

BTC Price Alert

This val monitors the price of Bitcoin (BTC) and sends an email alert if the price fluctuates significantly. Specifically, it checks the current BTC price against the last recorded price and triggers an email notification if the change exceeds 20%. The email includes the new price, formatted as currency.

Fork this val to get these notifications on your inbox.

Readme
Runs every 1 hrs
Fork
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { formatAsCurrency } from "https://esm.town/v/panphora/formatAsCurrency?v=5";
import { blob } from "https://esm.town/v/std/blob?v=11";
import { email } from "https://esm.town/v/std/email?v=9";
import { currency } from "https://esm.town/v/stevekrouse/currency";
export async function btcPriceAlert() {
const lastBtcPrice: number = await blob.getJSON("lastBtcPrice");
let btcPrice = await currency("usd", "btc");
let change = Math.abs(btcPrice - lastBtcPrice);
if (change / lastBtcPrice > .2) {
await blob.setJSON("lastBtcPrice", btcPrice);
let formattedBtcPrice = formatAsCurrency(btcPrice);
await email({
text: formattedBtcPrice,
subject: "BTC PRICE ALERT: " + formattedBtcPrice,
});
}
return btcPrice;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { generateInvoicePDF } from "https://esm.town/v/vtdocs/generateInvoicePDF?v=1";
export const examplePDF = async (req: Request) => {
const invoicePDF = await generateInvoicePDF({
invoiceNumber: "001",
date: new Date().toDateString(),
customerName: "Alice Bar",
customerEmail: "alice@bar.com",
items: [{ description: "Arabica Beans 500g", quantity: 2, price: 10 }, {
description: "Robusta Beans 500g",
quantity: 1,
price: 11,
}],
currencySymbol: "$",
});
return new Response(invoicePDF, {
headers: { "Content-Type": "application/pdf" },
});
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import Craftgate from "npm:@craftgate/craftgate";
const craftgate = new Craftgate.Client({
apiKey: "sandbox-YEhueLgomBjqsnvBlWVVuFsVhlvJlMHE",
secretKey: "sandbox-tBdcdKVGmGupzfaWcULcwDLMoglZZvTz",
baseUrl: "https://sandbox-api.craftgate.io",
});
const request = {
price: 100.0,
paidPrice: 100.0,
walletPrice: 0.0,
installment: 1,
conversationId: "456d1297-908e-4bd6-a13b-4be31a6e47d5",
currency: Craftgate.Model.Currency.TRY,
paymentGroup: Craftgate.Model.PaymentGroup.ListingOrSubscription,
card: {
cardHolderName: "Haluk Demir",
cardNumber: "5258640000000001",
expireYear: "2044",
expireMonth: "07",
cvc: "000",
},
items: [
{
name: "Item 1",
price: 30.0,
externalId: "123d1297-839e-4bd6-a13b-4be31a6e12a8",
},
{
name: "Item 2",
price: 50.0,
externalId: "789d1297-839e-4bd6-a13b-4be31a6e13f7",
},
{
name: "Item 3",
price: 20.0,
externalId: "3a1d1297-839e-4bd6-a13b-4be31a6e18e6",
},
],
};
craftgate.payment().createPayment(request)
.then(result => console.info("Payment successful", result))
.catch(err => console.error("Payment failed", err));

BTC Price Alert

This val monitors the price of Bitcoin (BTC) and sends an email alert if the price fluctuates significantly. Specifically, it checks the current BTC price against the last recorded price and triggers an email notification if the change exceeds 20%. The email includes the new price, formatted as currency.

Fork this val to get these notifications on your inbox.

Readme
Runs every 1 hrs
Fork
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { formatAsCurrency } from "https://esm.town/v/panphora/formatAsCurrency?v=5";
import { blob } from "https://esm.town/v/std/blob?v=11";
import { email } from "https://esm.town/v/std/email?v=9";
import { currency } from "https://esm.town/v/stevekrouse/currency";
export async function btcPriceAlert() {
const lastBtcPrice: number = await blob.getJSON("lastBtcPrice");
let btcPrice = await currency("usd", "btc");
console.log(lastBtcPrice, btcPrice);
let change = Math.abs(btcPrice - lastBtcPrice);
if (change / lastBtcPrice > .2) {
await blob.setJSON("lastBtcPrice", btcPrice);
let formattedBtcPrice = formatAsCurrency(btcPrice);
await email({
text: formattedBtcPrice,
subject: "BTC PRICE ALERT: " + formattedBtcPrice,
});
}
return btcPrice;
}

BTC Price Alert

This val monitors the price of Bitcoin (BTC) and sends an email alert if the price fluctuates significantly. Specifically, it checks the current BTC price against the last recorded price and triggers an email notification if the change exceeds 20%. The email includes the new price, formatted as currency.

Fork this val to get these notifications on your inbox.

Readme
Runs every 1 hrs
Fork
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { formatAsCurrency } from "https://esm.town/v/panphora/formatAsCurrency?v=5";
import { blob } from "https://esm.town/v/std/blob?v=11";
import { email } from "https://esm.town/v/std/email?v=9";
import { currency } from "https://esm.town/v/stevekrouse/currency";
export async function btcPriceAlert() {
const lastBtcPrice: number = await blob.getJSON("lastBtcPrice");
let btcPrice = await currency("usd", "btc");
let change = Math.abs(btcPrice - lastBtcPrice);
if (change / lastBtcPrice > .1) {
await blob.setJSON("lastBtcPrice", btcPrice);
let formattedBtcPrice = formatAsCurrency(btcPrice);
await email({
text: formattedBtcPrice,
subject: "BTC PRICE ALERT: " + formattedBtcPrice,
});
}
return btcPrice;
}

BTC Price Alert

This val monitors the price of Bitcoin (BTC) and sends an email alert if the price fluctuates significantly. Specifically, it checks the current BTC price against the last recorded price and triggers an email notification if the change exceeds 20%. The email includes the new price, formatted as currency.

Fork this val to get these notifications on your inbox.

Readme
Runs every 1 hrs
Fork
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { formatAsCurrency } from "https://esm.town/v/panphora/formatAsCurrency?v=5";
import { blob } from "https://esm.town/v/std/blob?v=11";
import { email } from "https://esm.town/v/std/email?v=9";
import { currency } from "https://esm.town/v/stevekrouse/currency";
export async function btcPriceAlert() {
const lastBtcPrice: number = await blob.getJSON("lastBtcPrice");
let btcPrice = await currency("usd", "btc");
let change = Math.abs(btcPrice - lastBtcPrice);
if (change / lastBtcPrice > .2) {
await blob.setJSON("lastBtcPrice", btcPrice);
let formattedBtcPrice = formatAsCurrency(btcPrice);
await email({
text: formattedBtcPrice,
subject: "BTC PRICE ALERT: " + formattedBtcPrice,
});
}
return btcPrice;
}

An example of how to render an invoice using @vtdocs.generateInvoicePDF

Readme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { generateInvoicePDF } from "https://esm.town/v/vtdocs/generateInvoicePDF";
// View me at https://andreterron-examplePDF.web.val.run!
export const examplePDF = async (req: Request): Promise<Response> => {
const invoicePDF = generateInvoicePDF({
invoiceNumber: "001",
date: new Date().toDateString(),
customerName: "Alice Bar",
customerEmail: "alice@bar.com",
items: [{ description: "Arabica Beans 500g", quantity: 2, price: 10 }, {
description: "Robusta Beans 500g",
quantity: 1,
price: 11,
}],
currencySymbol: "$",
});
return new Response(await invoicePDF, {
headers: {
"Content-Type": "application/pdf",
},
});
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
export const rssFeeds: RssFeed[] = [
{
name: "A beautiful site",
url: "https://www.abeautifulsite.net/feed/feed.xml",
type: "blog",
},
{
name: "Addy Osmani",
url: "https://addyosmani.com/feed.xml",
type: "blog",
},
{
name: "Adrian Roselli",
url: "https://adrianroselli.com/feed",
type: "blog",
},
{
name: "And a dinosaur",
url: "https://andadinosaur.com/home.rss",
type: "blog",
},
{
name: "Andy Bell",
url: "https://andy-bell.co.uk/feed.xml",
type: "blog",
},
{
name: "Anil Dash",
url: "https://www.anildash.com/feed.xml",
type: "blog",
},
{
name: "Brad Frost",
url: "https://feeds.feedburner.com/brad-frosts-blog",
type: "blog",
},
{
name: "Bruce Schneier",
url: "https://www.schneier.com/blog/atom.xml",
type: "security",
},
{
name: "Chris Coyer",
url: "https://chriscoyier.net/feed/",
type: "blog",
},
{
name: "Codrops",
url: "https://tympanus.net/codrops/feed/",
type: "blog",
},
{
name: "Dave Rupert",
url: "https://daverupert.com/atom.xml",
type: "blog",
},
{
name: "Dmitri Pavlutin",
url: "https://dmitripavlutin.com/rss.xml",
type: "blog",
},
{
name: "Heather Buchel",
url: "https://heather-buchel.com/feed/feed.xml",
type: "blog",
},
{
name: "Hidde de Vries",
url: "https://hidde.blog/feed",
type: "blog",
},
{
name: "Kent C. Dodds",
url: "https://kentcdodds.com/blog/rss.xml",
type: "blog",
},
{
name: "LeadDev",
url: "https://leaddev.com/content-piece-and-series/rss.xml",
type: "blog",
},
{
name: "Jake Lazaroff",
url: "https://jakelazaroff.com/rss.xml",
type: "blog",
},
{
name: "Jason Rodriguez",
url: "https://rodriguezcommaj.com/feed.xml",
type: "blog",
},
{
name: "Jeremy Keith",
url: "https://adactio.com/articles/rss",
type: "blog",
},
{
name: "Jim Nielsen",
url: "https://blog.jim-nielsen.com/feed.xml",
type: "blog",
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { formatAsCurrency } from "https://esm.town/v/panphora/formatAsCurrency?v=5";
import { email } from "https://esm.town/v/std/email?v=9";
import { set } from "https://esm.town/v/std/set?v=11";
import { currency } from "https://esm.town/v/stevekrouse/currency";
import { lastBtcPrice } from "https://esm.town/v/stevekrouse/lastBtcPrice";
export async function btcPriceAlert() {
let btcPrice = await currency("usd", "btc");
let change = Math.abs(btcPrice - lastBtcPrice);
if (change / lastBtcPrice > .2) {
await set("lastBtcPrice", btcPrice);
let formattedBtcPrice = formatAsCurrency(btcPrice);
await email({
text: formattedBtcPrice,
subject: "BTC PRICE ALERT: " + formattedBtcPrice,
});
}
return btcPrice;
}