feat: improve error reporting for wallet payments
This commit is contained in:
parent
202b9933e0
commit
167f1c5e65
@ -1,6 +1,7 @@
|
|||||||
|
import { ReactNode, useSyncExternalStore } from "react";
|
||||||
|
import { v4 as uuid } from "uuid";
|
||||||
import ExternalStore from "ExternalStore";
|
import ExternalStore from "ExternalStore";
|
||||||
import Icon from "Icons/Icon";
|
import Icon from "Icons/Icon";
|
||||||
import { ReactNode, useSyncExternalStore } from "react";
|
|
||||||
import { unixNow } from "Util";
|
import { unixNow } from "Util";
|
||||||
|
|
||||||
import "./Toaster.css";
|
import "./Toaster.css";
|
||||||
@ -9,6 +10,7 @@ interface ToastNotification {
|
|||||||
element: ReactNode;
|
element: ReactNode;
|
||||||
expire?: number;
|
expire?: number;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ToasterSlots extends ExternalStore<Array<ToastNotification>> {
|
class ToasterSlots extends ExternalStore<Array<ToastNotification>> {
|
||||||
@ -17,6 +19,7 @@ class ToasterSlots extends ExternalStore<Array<ToastNotification>> {
|
|||||||
|
|
||||||
push(n: ToastNotification) {
|
push(n: ToastNotification) {
|
||||||
n.expire ??= unixNow() + 3;
|
n.expire ??= unixNow() + 3;
|
||||||
|
n.id ??= uuid();
|
||||||
this.#stack.push(n);
|
this.#stack.push(n);
|
||||||
this.notifyChange();
|
this.notifyChange();
|
||||||
}
|
}
|
||||||
@ -43,7 +46,7 @@ export default function Toaster() {
|
|||||||
return (
|
return (
|
||||||
<div className="toaster">
|
<div className="toaster">
|
||||||
{toast.map(a => (
|
{toast.map(a => (
|
||||||
<div className="card flex">
|
<div className="card flex" key={a.id}>
|
||||||
<Icon name={a.icon ?? "bell"} className="mr5" />
|
<Icon name={a.icon ?? "bell"} className="mr5" />
|
||||||
{a.element}
|
{a.element}
|
||||||
</div>
|
</div>
|
||||||
|
@ -123,7 +123,7 @@ export default class LNDHubWallet implements LNWallet {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const json = await rsp.json();
|
const json = await rsp.json();
|
||||||
if ("error" in json) {
|
if ("code" in json && !rsp.ok) {
|
||||||
const err = json as ErrorResponse;
|
const err = json as ErrorResponse;
|
||||||
throw new WalletError(err.code, err.message);
|
throw new WalletError(err.code, err.message);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Connection, RawEvent } from "@snort/nostr";
|
import { Connection, RawEvent } from "@snort/nostr";
|
||||||
import { EventBuilder } from "System";
|
import { EventBuilder } from "System";
|
||||||
import { EventExt } from "System/EventExt";
|
import { EventExt } from "System/EventExt";
|
||||||
import { LNWallet, WalletError, WalletErrorCode, WalletInfo, WalletInvoice } from "Wallet";
|
import { LNWallet, WalletError, WalletErrorCode, WalletInfo, WalletInvoice, WalletInvoiceState } from "Wallet";
|
||||||
|
|
||||||
interface WalletConnectConfig {
|
interface WalletConnectConfig {
|
||||||
relayUrl: string;
|
relayUrl: string;
|
||||||
@ -14,6 +14,23 @@ interface QueueObj {
|
|||||||
reject: (e: Error) => void;
|
reject: (e: Error) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface WalletConnectResponse<T> {
|
||||||
|
result_type?: string;
|
||||||
|
result?: T;
|
||||||
|
error?: {
|
||||||
|
code:
|
||||||
|
| "RATE_LIMITED"
|
||||||
|
| "NOT_IMPLEMENTED"
|
||||||
|
| "INSUFFICIENT_BALANCE"
|
||||||
|
| "QUOTA_EXCEEDED"
|
||||||
|
| "RESTRICTED"
|
||||||
|
| "UNAUTHORIZED"
|
||||||
|
| "INTERNAL"
|
||||||
|
| "OTHER";
|
||||||
|
message: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export class NostrConnectWallet implements LNWallet {
|
export class NostrConnectWallet implements LNWallet {
|
||||||
#config: WalletConnectConfig;
|
#config: WalletConnectConfig;
|
||||||
#conn?: Connection;
|
#conn?: Connection;
|
||||||
@ -83,9 +100,18 @@ export class NostrConnectWallet implements LNWallet {
|
|||||||
|
|
||||||
async payInvoice(pr: string) {
|
async payInvoice(pr: string) {
|
||||||
await this.login();
|
await this.login();
|
||||||
return await this.#rpc<WalletInvoice>("pay_invoice", {
|
const rsp = await this.#rpc<WalletConnectResponse<WalletInvoice>>("pay_invoice", {
|
||||||
invoice: pr,
|
invoice: pr,
|
||||||
});
|
});
|
||||||
|
if (!rsp.error) {
|
||||||
|
return {
|
||||||
|
...rsp.result,
|
||||||
|
pr,
|
||||||
|
state: WalletInvoiceState.Paid,
|
||||||
|
} as WalletInvoice;
|
||||||
|
} else {
|
||||||
|
throw new WalletError(WalletErrorCode.GeneralError, rsp.error.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getInvoices() {
|
getInvoices() {
|
||||||
|
@ -47,6 +47,7 @@ class ZapPool extends ExternalStore<Array<ZapPoolRecipient>> {
|
|||||||
const invoice = await svc.getInvoice(amtSend, `SnortZapPool: ${x.split}%`);
|
const invoice = await svc.getInvoice(amtSend, `SnortZapPool: ${x.split}%`);
|
||||||
if (invoice.pr) {
|
if (invoice.pr) {
|
||||||
const result = await wallet.payInvoice(invoice.pr);
|
const result = await wallet.payInvoice(invoice.pr);
|
||||||
|
console.debug("ZPC", invoice, result);
|
||||||
if (result.state === WalletInvoiceState.Paid) {
|
if (result.state === WalletInvoiceState.Paid) {
|
||||||
x.sum -= amtSend;
|
x.sum -= amtSend;
|
||||||
Toastore.push({
|
Toastore.push({
|
||||||
@ -58,13 +59,23 @@ class ZapPool extends ExternalStore<Array<ZapPoolRecipient>> {
|
|||||||
icon: "zap",
|
icon: "zap",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Payment failed");
|
throw new Error(`Failed to pay invoice, unknown reason`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error(invoice.reason ?? "Failed to get invoice");
|
throw new Error(invoice.reason ?? "Failed to get invoice");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
if (e instanceof Error) {
|
||||||
|
const profile = UserCache.getFromCache(x.pubkey);
|
||||||
|
Toastore.push({
|
||||||
|
element: `Failed to send sats to ${getDisplayName(profile, x.pubkey)} (${
|
||||||
|
e.message
|
||||||
|
}), please try again later`,
|
||||||
|
expire: unixNow() + 10,
|
||||||
|
icon: "close",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.#save();
|
this.#save();
|
||||||
|
Loading…
Reference in New Issue
Block a user