Accept multiple cashu tokens encoded together if they're from the same mint

This commit is contained in:
Danny Morabito 2024-11-26 19:41:19 +01:00
parent 04aa38bbe4
commit 8aa8c2752b
Signed by: dannym
GPG key ID: 7CC8056A5A04557E

View file

@ -1,5 +1,5 @@
import {getDecodedToken} from "@cashu/cashu-ts"; import {getDecodedToken, type Proof} from "@cashu/cashu-ts";
import type {Proof, TokenEntry} from "@cashu/cashu-ts"; import type {TokenEntry} from "@cashu/cashu-ts";
import {getMailSubscriptionDurationForSats} from "./general.ts"; import {getMailSubscriptionDurationForSats} from "./general.ts";
class InvalidTokenException extends Error { class InvalidTokenException extends Error {
@ -20,23 +20,31 @@ export class TokenInfo {
] as const; ] as const;
private static readonly MIN_AMOUNT = 21 as const; private static readonly MIN_AMOUNT = 21 as const;
public readonly token: TokenEntry; public readonly tokens: TokenEntry[];
public readonly amount: number; public readonly amount: number;
public readonly mint: string; public readonly mint: string;
public readonly proofs: Proof[]; public readonly proofs: Proof[];
constructor(protected readonly tokenString: string) { constructor(protected readonly tokenString: string) {
const decodedTokenData = getDecodedToken(tokenString); const decodedTokenData = getDecodedToken(tokenString);
if (decodedTokenData.unit !== 'sat' || decodedTokenData.token.length !== 1) const tokens = decodedTokenData.token;
throw new InvalidTokenException('Invalid token format. We only accept a single token denominated in sats'); const amount = tokens.flatMap(t => t.proofs).reduce((c, x) => c + x.amount, 0);
this.token = decodedTokenData.token[0];
this.amount = this.token.proofs.reduce((c, x) => c + x.amount, 0); if (decodedTokenData.unit !== 'sat')
if (this.amount < TokenInfo.MIN_AMOUNT) throw new InvalidTokenException('Invalid token format. We only accept tokens denominated in sats');
throw new InvalidTokenException(`Invalid amount. Minimum required: ${TokenInfo.MIN_AMOUNT} sats`); if(decodedTokenData.token.length === 0)
if (!TokenInfo.ALLOWED_MINTS.includes(this.token.mint)) throw new InvalidTokenException('Invalid token format. We only accept tokens with at least one proof');
if (tokens.slice(1).some(t => t.mint !== tokens[0].mint))
throw new InvalidTokenException('Invalid token format. We only accept tokens with the same mint');
if (!TokenInfo.ALLOWED_MINTS.includes(tokens[0].mint))
throw new InvalidTokenException('Unsupported mint'); throw new InvalidTokenException('Unsupported mint');
this.mint = this.token.mint; if (amount < TokenInfo.MIN_AMOUNT)
this.proofs = this.token.proofs; throw new InvalidTokenException(`Invalid amount. Minimum required: ${TokenInfo.MIN_AMOUNT} sats`);
this.tokens = tokens;
this.amount = amount;
this.mint = tokens[0].mint;
this.proofs = tokens.flatMap(t => t.proofs);
} }
} }