parse tokens
This commit is contained in:
parent
ca1bb86036
commit
4f8f472e84
@ -6,7 +6,7 @@
|
|||||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||||
"@gandlaf21/cashu-ts": "^0.6.0",
|
"@cashu/cashu-ts": "^0.6.1",
|
||||||
"@jukben/emoji-search": "^2.0.1",
|
"@jukben/emoji-search": "^2.0.1",
|
||||||
"@lightninglabs/lnc-web": "^0.2.3-alpha",
|
"@lightninglabs/lnc-web": "^0.2.3-alpha",
|
||||||
"@noble/hashes": "^1.2.0",
|
"@noble/hashes": "^1.2.0",
|
||||||
|
@ -184,4 +184,4 @@ export const WavlakeRegex =
|
|||||||
/*
|
/*
|
||||||
* Regex to match any base64 string
|
* Regex to match any base64 string
|
||||||
*/
|
*/
|
||||||
export const Base64Regex = /([a-zA-Z0-9+/]+={,2})/;
|
export const CashuRegex = /(cashuA[A-Za-z0-9_-]{0,10000}={0,3})/i;
|
||||||
|
@ -4,11 +4,13 @@ import { Link, useLocation } from "react-router-dom";
|
|||||||
import ReactMarkdown from "react-markdown";
|
import ReactMarkdown from "react-markdown";
|
||||||
import { visit, SKIP } from "unist-util-visit";
|
import { visit, SKIP } from "unist-util-visit";
|
||||||
import * as unist from "unist";
|
import * as unist from "unist";
|
||||||
import base64 from "@protobufjs/base64";
|
|
||||||
import { HexKey, NostrPrefix } from "@snort/nostr";
|
import { HexKey, NostrPrefix } from "@snort/nostr";
|
||||||
|
|
||||||
import { MentionRegex, InvoiceRegex, HashtagRegex, Base64Regex } from "Const";
|
import { getDecodedToken } from "@cashu/cashu-ts";
|
||||||
import { eventLink, hexToBech32, splitByUrl, unwrap, validateNostrLink } from "Util";
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
|
import { MentionRegex, InvoiceRegex, HashtagRegex, CashuRegex } from "Const";
|
||||||
|
import { eventLink, hexToBech32, splitByUrl, unwrap } from "Util";
|
||||||
import Invoice from "Element/Invoice";
|
import Invoice from "Element/Invoice";
|
||||||
import Hashtag from "Element/Hashtag";
|
import Hashtag from "Element/Hashtag";
|
||||||
import Mention from "Element/Mention";
|
import Mention from "Element/Mention";
|
||||||
@ -69,33 +71,46 @@ export default function Text({ content, tags, creator, disableMedia, depth }: Te
|
|||||||
.flat();
|
.flat();
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractBase64Strings(fragments: Fragment[]) {
|
function extractCashuTokens(fragments: Fragment[]) {
|
||||||
|
async function copyToken(token: string) {
|
||||||
|
await navigator.clipboard.writeText(token);
|
||||||
|
}
|
||||||
|
async function redeemToken(token: string) {
|
||||||
|
const url = `https://redeem.cashu.me?token=${encodeURIComponent(token)}&lightning=${encodeURIComponent(
|
||||||
|
"callebtc@ln.tips"
|
||||||
|
)}`;
|
||||||
|
window.open(url, "_blank");
|
||||||
|
}
|
||||||
|
|
||||||
return fragments
|
return fragments
|
||||||
.map(f => {
|
.map(f => {
|
||||||
if (typeof f === "string") {
|
if (typeof f === "string" && f.includes("cashuA")) {
|
||||||
return f.split(Base64Regex).map(a => {
|
return f.split(CashuRegex).map(a => {
|
||||||
const parsed = base64.test(a);
|
if (!a.startsWith("cashuA") || a.length < 10) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
const cashu = getDecodedToken(a);
|
||||||
|
if (cashu && cashu.token[0].proofs) {
|
||||||
|
return (
|
||||||
|
<div className="note-invoice">
|
||||||
|
<div className="flex f-between">
|
||||||
|
<div>
|
||||||
|
<h4>Cashu token</h4>
|
||||||
|
<p>Amount: {cashu.token[0].proofs.reduce((acc, v) => (acc += v.amount), 0)} sats</p>
|
||||||
|
<p style={{ fontSize: "0.7em" }}>Mint: {cashu.token[0].mint}</p>
|
||||||
|
</div>
|
||||||
|
<div style={{ marginLeft: "auto" }}>
|
||||||
|
<button type="button" onClick={() => copyToken(a)}>
|
||||||
|
<FormattedMessage defaultMessage="Copy" description="Button: Copy Cashu token" />
|
||||||
|
</button>
|
||||||
|
<button type="button" onClick={() => redeemToken(a)}>
|
||||||
|
<FormattedMessage defaultMessage="Redeem" description="Button: Redeem Cashu token" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
return a;
|
return a;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -199,7 +214,7 @@ export default function Text({ content, tags, creator, disableMedia, depth }: Te
|
|||||||
fragments = extractLinks(fragments);
|
fragments = extractLinks(fragments);
|
||||||
fragments = extractInvoices(fragments);
|
fragments = extractInvoices(fragments);
|
||||||
fragments = extractHashtags(fragments);
|
fragments = extractHashtags(fragments);
|
||||||
fragments = extractBase64Strings(fragments);
|
fragments = extractCashuTokens(fragments);
|
||||||
return fragments;
|
return fragments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
import { CashuMint, CashuWallet as TheCashuWallet, getEncodedProofs, Proof } from "@gandlaf21/cashu-ts";
|
import {
|
||||||
|
InvoiceRequest,
|
||||||
|
LNWallet,
|
||||||
|
prToWalletInvoice,
|
||||||
|
Sats,
|
||||||
|
WalletError,
|
||||||
|
WalletErrorCode,
|
||||||
|
WalletInfo,
|
||||||
|
WalletInvoice,
|
||||||
|
WalletInvoiceState,
|
||||||
|
} from "Wallet";
|
||||||
|
|
||||||
import { InvoiceRequest, LNWallet, WalletInfo, WalletInvoice } from "Wallet";
|
import { CashuMint, CashuWallet as TheCashuWallet, getEncodedToken, Proof } from "@cashu/cashu-ts";
|
||||||
|
|
||||||
export class CashuWallet implements LNWallet {
|
export class CashuWallet implements LNWallet {
|
||||||
#mint: string;
|
#mint: string;
|
||||||
@ -16,7 +26,15 @@ export class CashuWallet implements LNWallet {
|
|||||||
return this.#wallet !== undefined;
|
return this.#wallet !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
getInfo: () => Promise<WalletInfo>;
|
async getInfo(): Promise<WalletInfo> {
|
||||||
|
if (!this.#wallet) {
|
||||||
|
throw new WalletError(WalletErrorCode.GeneralError, "Wallet not initialized");
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
nodePubKey: "asd",
|
||||||
|
alias: "asd",
|
||||||
|
} as WalletInfo;
|
||||||
|
}
|
||||||
|
|
||||||
async login(_?: string | undefined): Promise<boolean> {
|
async login(_?: string | undefined): Promise<boolean> {
|
||||||
const m = new CashuMint(this.#mint, this.#walletPath);
|
const m = new CashuMint(this.#mint, this.#walletPath);
|
||||||
@ -25,11 +43,23 @@ export class CashuWallet implements LNWallet {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
close: () => Promise<boolean>;
|
close(): Promise<boolean> {
|
||||||
getBalance: () => Promise<number>;
|
return Promise.resolve(true);
|
||||||
createInvoice: (req: InvoiceRequest) => Promise<WalletInvoice>;
|
}
|
||||||
payInvoice: (pr: string) => Promise<WalletInvoice>;
|
|
||||||
getInvoices: () => Promise<WalletInvoice[]>;
|
getBalance(): Promise<Sats> {
|
||||||
|
// return dummy balance of 1337 sats
|
||||||
|
return Promise.resolve(1337);
|
||||||
|
}
|
||||||
|
createInvoice(req: InvoiceRequest): Promise<WalletInvoice> {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
payInvoice(pr: string): Promise<WalletInvoice> {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
|
getInvoices(): Promise<WalletInvoice[]> {
|
||||||
|
throw new Error("Method not implemented.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NutBank {
|
interface NutBank {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user