This commit is contained in:
2023-03-09 09:57:14 +00:00
parent 1923273f6f
commit ca1bb86036
5 changed files with 134 additions and 2 deletions

View File

@ -6,6 +6,7 @@
"@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@gandlaf21/cashu-ts": "^0.6.0",
"@jukben/emoji-search": "^2.0.1",
"@lightninglabs/lnc-web": "^0.2.3-alpha",
"@noble/hashes": "^1.2.0",

View File

@ -179,3 +179,9 @@ export const MagnetRegex = /(magnet:[\S]+)/i;
*/
export const WavlakeRegex =
/https?:\/\/(?:player\.|www\.)?wavlake\.com\/(?!top|new|artists|account|activity|login|preferences|feed)(?:(?:track|album)\/[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}|[a-z-]+)/i;
/player\.wavlake\.com\/(?!feed\/)(track\/[.a-zA-Z0-9-]+|album\/[.a-zA-Z0-9-]+|[.a-zA-Z0-9-]+)/i;
/*
* Regex to match any base64 string
*/
export const Base64Regex = /([a-zA-Z0-9+/]+={,2})/;

View File

@ -4,9 +4,10 @@ import { Link, useLocation } from "react-router-dom";
import ReactMarkdown from "react-markdown";
import { visit, SKIP } from "unist-util-visit";
import * as unist from "unist";
import base64 from "@protobufjs/base64";
import { HexKey, NostrPrefix } from "@snort/nostr";
import { MentionRegex, InvoiceRegex, HashtagRegex } from "Const";
import { MentionRegex, InvoiceRegex, HashtagRegex, Base64Regex } from "Const";
import { eventLink, hexToBech32, splitByUrl, unwrap, validateNostrLink } from "Util";
import Invoice from "Element/Invoice";
import Hashtag from "Element/Hashtag";
@ -68,6 +69,41 @@ export default function Text({ content, tags, creator, disableMedia, depth }: Te
.flat();
}
function extractBase64Strings(fragments: Fragment[]) {
return fragments
.map(f => {
if (typeof f === "string") {
return f.split(Base64Regex).map(a => {
const parsed = base64.test(a);
if (parsed && a.length > 0) {
const buff = new Uint8Array(3 * (a.length / 4));
const len = base64.decode(a, buff, 0);
const text = new TextDecoder().decode(buff.slice(0, len));
if (text.startsWith("{") && text.endsWith("}") && text.includes("proofs")) {
const data = JSON.parse(text) as {
proofs: [
{
amount: number;
}
];
};
return (
<div className="note-invoice">
<h4>Cashu tokens</h4>
<p>Amount: {data.proofs.reduce((acc, v) => (acc += v.amount), 0)} sats</p>
</div>
);
}
return a;
}
return a;
});
}
return f;
})
.flat();
}
function extractMentions(frag: TextFragment) {
return frag.body
.map(f => {
@ -163,6 +199,7 @@ export default function Text({ content, tags, creator, disableMedia, depth }: Te
fragments = extractLinks(fragments);
fragments = extractInvoices(fragments);
fragments = extractHashtags(fragments);
fragments = extractBase64Strings(fragments);
return fragments;
}

View File

@ -0,0 +1,46 @@
import { CashuMint, CashuWallet as TheCashuWallet, getEncodedProofs, Proof } from "@gandlaf21/cashu-ts";
import { InvoiceRequest, LNWallet, WalletInfo, WalletInvoice } from "Wallet";
export class CashuWallet implements LNWallet {
#mint: string;
#walletPath: string;
#wallet?: TheCashuWallet;
constructor(mint: string, path: string) {
this.#mint = mint;
this.#walletPath = path;
}
isReady(): boolean {
return this.#wallet !== undefined;
}
getInfo: () => Promise<WalletInfo>;
async login(_?: string | undefined): Promise<boolean> {
const m = new CashuMint(this.#mint, this.#walletPath);
const keys = await m.getKeys();
this.#wallet = new TheCashuWallet(keys, m);
return true;
}
close: () => Promise<boolean>;
getBalance: () => Promise<number>;
createInvoice: (req: InvoiceRequest) => Promise<WalletInvoice>;
payInvoice: (pr: string) => Promise<WalletInvoice>;
getInvoices: () => Promise<WalletInvoice[]>;
}
interface NutBank {
proofs: Array<Proof>;
}
export interface NutStashBackup {
proofs: Array<Proof>;
mints: [
{
mintURL: string;
}
];
}