mirror of
https://github.com/PrimalHQ/primal-web-app.git
synced 2024-10-01 17:31:13 +00:00
Compare commits
No commits in common. "a69f7d59506d5e8c219f4b66354f411304099639" and "40bc2ec8a764aa3db38071c63bd76f370b046a84" have entirely different histories.
a69f7d5950
...
40bc2ec8a7
@ -55,6 +55,7 @@
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|
||||||
>button {
|
>button {
|
||||||
|
color: var(--text-primary);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
@ -53,13 +53,11 @@ const AuthoreSubscribe: Component<{
|
|||||||
getAuthorData();
|
getAuthorData();
|
||||||
});
|
});
|
||||||
|
|
||||||
const doSubscription = async (tier: Tier, cost: TierCost, exchangeRate?: Record<string, Record<string, number>>) => {
|
const doSubscription = async (tier: Tier, cost: TierCost) => {
|
||||||
const a = author();
|
const a = author();
|
||||||
|
|
||||||
if (!a || !account || !cost) return;
|
if (!a || !account || !cost) return;
|
||||||
|
|
||||||
if (cost.unit === 'USD' && (!exchangeRate || !exchangeRate['USD'])) return;
|
|
||||||
|
|
||||||
const subEvent = {
|
const subEvent = {
|
||||||
kind: Kind.Subscribe,
|
kind: Kind.Subscribe,
|
||||||
content: '',
|
content: '',
|
||||||
@ -74,38 +72,13 @@ const AuthoreSubscribe: Component<{
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const { success, note } = await sendEvent(subEvent, account.relays, account.relaySettings);
|
const { success, note } = await sendEvent(subEvent, account.relays, account.relaySettings);
|
||||||
|
|
||||||
if (success && note) {
|
if (success && note) {
|
||||||
const isZapped = await zapSubscription(note, a, account.publicKey, account.relays, exchangeRate);
|
await zapSubscription(note, a, account.publicKey, account.relays);
|
||||||
|
|
||||||
if (!isZapped) {
|
|
||||||
unsubscribe(note.id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsubscribe = async (eventId: string) => {
|
|
||||||
const a = author();
|
|
||||||
|
|
||||||
if (!a || !account) return;
|
|
||||||
|
|
||||||
const unsubEvent = {
|
|
||||||
kind: Kind.Unsubscribe,
|
|
||||||
content: '',
|
|
||||||
created_at: Math.floor((new Date()).getTime() / 1_000),
|
|
||||||
|
|
||||||
tags: [
|
|
||||||
['p', a.pubkey],
|
|
||||||
['e', eventId],
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
await sendEvent(unsubEvent, account.relays, account.relaySettings);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const openSubscribe = () => {
|
const openSubscribe = () => {
|
||||||
app?.actions.openAuthorSubscribeModal(author(), doSubscription);
|
app?.actions.openAuthorSubscribeModal(author(), doSubscription);
|
||||||
};
|
};
|
||||||
|
@ -65,34 +65,24 @@ const ReedSelect: Component<{ isPhone?: boolean, id?: string, big?: boolean}> =
|
|||||||
}
|
}
|
||||||
|
|
||||||
const options:() => SelectionOption[] = () => {
|
const options:() => SelectionOption[] = () => {
|
||||||
let opts = [];
|
return [
|
||||||
|
{
|
||||||
if (account?.publicKey) {
|
label: 'My Reads',
|
||||||
opts.push(
|
value: account?.publicKey || '',
|
||||||
{
|
},
|
||||||
label: 'My Reads',
|
|
||||||
value: account?.publicKey || '',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
opts.push(
|
|
||||||
{
|
{
|
||||||
label: 'All Reads',
|
label: 'All Reads',
|
||||||
value: 'none',
|
value: 'none',
|
||||||
}
|
},
|
||||||
);
|
|
||||||
|
|
||||||
return [ ...opts ];
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialValue = () => {
|
const initialValue = () => {
|
||||||
const selected = reeds?.selectedFeed;
|
const selected = reeds?.selectedFeed;
|
||||||
|
|
||||||
if (!selected) {
|
if (!selected) {
|
||||||
const feed = options()[0];
|
return options()[0];
|
||||||
selectFeed(feed);
|
|
||||||
return feed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -20,7 +20,7 @@ import { createStore } from 'solid-js/store';
|
|||||||
import { APP_ID } from '../../App';
|
import { APP_ID } from '../../App';
|
||||||
import { subsTo } from '../../sockets';
|
import { subsTo } from '../../sockets';
|
||||||
import { getArticleThread, getReadsTopics, getUserArticleFeed } from '../../lib/feed';
|
import { getArticleThread, getReadsTopics, getUserArticleFeed } from '../../lib/feed';
|
||||||
import { fetchUserArticles } from '../../handleNotes';
|
import { fetchArticles, fetchUserArticles } from '../../handleNotes';
|
||||||
import { getParametrizedEvent, getParametrizedEvents } from '../../lib/notes';
|
import { getParametrizedEvent, getParametrizedEvents } from '../../lib/notes';
|
||||||
import { decodeIdentifier } from '../../lib/keys';
|
import { decodeIdentifier } from '../../lib/keys';
|
||||||
import ArticleShort from '../ArticlePreview/ArticleShort';
|
import ArticleShort from '../ArticlePreview/ArticleShort';
|
||||||
|
@ -164,13 +164,13 @@ const ReadsSidebar: Component< { id?: string } > = (props) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const getRecomendedArticles = async (ids: string[]) => {
|
const getRecomendedArticles = async (ids: string[]) => {
|
||||||
// if (!account?.publicKey) return;
|
if (!account?.publicKey) return;
|
||||||
|
|
||||||
const subId = `reads_picks_${APP_ID}`;
|
const subId = `reads_picks_${APP_ID}`;
|
||||||
|
|
||||||
setIsFetching(() => true);
|
setIsFetching(() => true);
|
||||||
|
|
||||||
const articles = await fetchArticles(ids,subId);
|
const articles = await fetchArticles(account.publicKey, ids,subId);
|
||||||
|
|
||||||
setIsFetching(() => false);
|
setIsFetching(() => false);
|
||||||
|
|
||||||
@ -180,23 +180,22 @@ const ReadsSidebar: Component< { id?: string } > = (props) => {
|
|||||||
return (
|
return (
|
||||||
<div id={props.id} class={styles.readsSidebar}>
|
<div id={props.id} class={styles.readsSidebar}>
|
||||||
<Show when={account?.isKeyLookupDone}>
|
<Show when={account?.isKeyLookupDone}>
|
||||||
<Show when={account?.publicKey}>
|
<div class={styles.headingPicks}>
|
||||||
<div class={styles.headingPicks}>
|
Featured Author
|
||||||
Featured Author
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<Show
|
<Show
|
||||||
when={!isFetchingAuthors()}
|
when={!isFetchingAuthors()}
|
||||||
fallback={
|
fallback={
|
||||||
<Loader />
|
<Loader />
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div class={styles.section}>
|
<div class={styles.section}>
|
||||||
<AuthorSubscribe pubkey={featuredAuthor()} />
|
<AuthorSubscribe pubkey={featuredAuthor()} />
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
|
|
||||||
<div class={styles.headingPicks}>
|
<div class={styles.headingPicks}>
|
||||||
Featured Reads
|
Featured Reads
|
||||||
</div>
|
</div>
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modalBody {
|
.body {
|
||||||
.tiers {
|
.tiers {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
@ -94,7 +94,11 @@
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
width: 400px;
|
width: 400px;
|
||||||
|
|
||||||
.tierTitle {
|
&.selected {
|
||||||
|
border: 1px solid var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title: {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@ -153,10 +157,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.selected {
|
|
||||||
border: 1px solid var(--accent);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,17 +13,11 @@ import { userName } from '../../stores/profile';
|
|||||||
import Avatar from '../Avatar/Avatar';
|
import Avatar from '../Avatar/Avatar';
|
||||||
import VerificationCheck from '../VerificationCheck/VerificationCheck';
|
import VerificationCheck from '../VerificationCheck/VerificationCheck';
|
||||||
import { APP_ID } from '../../App';
|
import { APP_ID } from '../../App';
|
||||||
import { subsTo, subTo } from '../../sockets';
|
import { subsTo } from '../../sockets';
|
||||||
import { getAuthorSubscriptionTiers } from '../../lib/feed';
|
import { getAuthorSubscriptionTiers } from '../../lib/feed';
|
||||||
import ButtonSecondary from '../Buttons/ButtonSecondary';
|
import ButtonSecondary from '../Buttons/ButtonSecondary';
|
||||||
import { Select } from '@kobalte/core';
|
import { Select } from '@kobalte/core';
|
||||||
import Loader from '../Loader/Loader';
|
import Loader from '../Loader/Loader';
|
||||||
import { logInfo } from '../../lib/logger';
|
|
||||||
import { getExchangeRate, getMembershipStatus } from '../../lib/membership';
|
|
||||||
import { useAccountContext } from '../../contexts/AccountContext';
|
|
||||||
|
|
||||||
|
|
||||||
export const satsInBTC = 100_000_000;
|
|
||||||
|
|
||||||
export type TierCost = {
|
export type TierCost = {
|
||||||
amount: string,
|
amount: string,
|
||||||
@ -48,29 +42,23 @@ export type TierStore = {
|
|||||||
selectedTier: Tier | undefined,
|
selectedTier: Tier | undefined,
|
||||||
selectedCost: TierCost | undefined,
|
selectedCost: TierCost | undefined,
|
||||||
isFetchingTiers: boolean,
|
isFetchingTiers: boolean,
|
||||||
exchangeRate: Record<string, Record<string, number>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const payUnits = ['sats', 'sat', 'msat', 'msats', 'USD', 'usd', ''];
|
export const payUnits = ['sats', 'msat', ''];
|
||||||
|
|
||||||
const SubscribeToAuthorModal: Component<{
|
const SubscribeToAuthorModal: Component<{
|
||||||
id?: string,
|
id?: string,
|
||||||
author: PrimalUser | undefined,
|
author: PrimalUser | undefined,
|
||||||
onClose: () => void,
|
onClose: () => void,
|
||||||
onSubscribe: (tier: Tier, cost: TierCost, exchangeRate?: Record<string, Record<string, number>>) => void,
|
onSubscribe: (tier: Tier, cost: TierCost) => void,
|
||||||
}> = (props) => {
|
}> = (props) => {
|
||||||
|
|
||||||
const account = useAccountContext();
|
|
||||||
|
|
||||||
const [store, updateStore] = createStore<TierStore>({
|
const [store, updateStore] = createStore<TierStore>({
|
||||||
tiers: [],
|
tiers: [],
|
||||||
selectedTier: undefined,
|
selectedTier: undefined,
|
||||||
selectedCost: undefined,
|
selectedCost: undefined,
|
||||||
isFetchingTiers: false,
|
isFetchingTiers: false,
|
||||||
exchangeRate: {},
|
})
|
||||||
});
|
|
||||||
|
|
||||||
let walletSocket: WebSocket | undefined;
|
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const author = props.author;
|
const author = props.author;
|
||||||
@ -80,55 +68,6 @@ const SubscribeToAuthorModal: Component<{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
createEffect(() => {
|
|
||||||
if (props.author && (!walletSocket || walletSocket.readyState === WebSocket.CLOSED)) {
|
|
||||||
openWalletSocket(() => {
|
|
||||||
if (!walletSocket || walletSocket.readyState !== WebSocket.OPEN) return;
|
|
||||||
|
|
||||||
const subId = `er_${APP_ID}`;
|
|
||||||
|
|
||||||
const unsub = subTo(walletSocket, subId, (type, _, content) => {
|
|
||||||
if (type === 'EVENT') {
|
|
||||||
const response: { rate: string } = JSON.parse(content?.content || '{ "rate": 1 }');
|
|
||||||
|
|
||||||
const BTCForTarget = parseFloat(response.rate) || 1;
|
|
||||||
|
|
||||||
const satsToTarget = BTCForTarget / satsInBTC;
|
|
||||||
const targetToBTC = 1 / BTCForTarget;
|
|
||||||
const targetToSats = 1 / satsToTarget;
|
|
||||||
|
|
||||||
updateStore('exchangeRate', () => ({
|
|
||||||
USD: {
|
|
||||||
sats: targetToSats,
|
|
||||||
BTC: targetToBTC,
|
|
||||||
USD: 1,
|
|
||||||
},
|
|
||||||
sats: {
|
|
||||||
sats: 1,
|
|
||||||
USD: satsToTarget,
|
|
||||||
BTC: 1 / satsInBTC,
|
|
||||||
},
|
|
||||||
BTC: {
|
|
||||||
sats: satsInBTC,
|
|
||||||
USD: BTCForTarget,
|
|
||||||
BTC: 1,
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type === 'EOSE') {
|
|
||||||
unsub();
|
|
||||||
walletSocket?.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
getExchangeRate(account?.publicKey, subId, "USD", walletSocket);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
walletSocket?.close();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const getTiers = (author: PrimalUser) => {
|
const getTiers = (author: PrimalUser) => {
|
||||||
if (!author) return;
|
if (!author) return;
|
||||||
|
|
||||||
@ -145,7 +84,7 @@ const SubscribeToAuthorModal: Component<{
|
|||||||
if (content.kind === Kind.Tier) {
|
if (content.kind === Kind.Tier) {
|
||||||
const t = content as NostrTier;
|
const t = content as NostrTier;
|
||||||
|
|
||||||
let costs = t.tags?.filter((t: string[]) => t[0] === 'amount').map((t: string[]) => (
|
const costs = t.tags?.filter((t: string[]) => t[0] === 'amount').map((t: string[]) => (
|
||||||
{
|
{
|
||||||
amount: t[1],
|
amount: t[1],
|
||||||
unit: t[2],
|
unit: t[2],
|
||||||
@ -198,39 +137,9 @@ const SubscribeToAuthorModal: Component<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
const displayCost = (cost: TierCost | undefined) => {
|
const displayCost = (cost: TierCost | undefined) => {
|
||||||
let text = '';
|
return `${cost?.unit === 'msat' ? Math.ceil(parseInt(cost?.amount || '0') / 1_000) : cost?.amount} sats`;
|
||||||
|
|
||||||
switch(cost?.unit) {
|
|
||||||
case 'msat':
|
|
||||||
case 'msats':
|
|
||||||
case '':
|
|
||||||
text = `${Math.ceil(parseInt(cost?.amount || '0') / 1_000)} sats`;
|
|
||||||
break;
|
|
||||||
case 'sats':
|
|
||||||
case 'sat':
|
|
||||||
text = `${cost.amount} sats`;
|
|
||||||
break;
|
|
||||||
case 'USD':
|
|
||||||
case 'usd':
|
|
||||||
text = `${cost.amount} USD`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const openWalletSocket = (onOpen: () => void) => {
|
|
||||||
walletSocket = new WebSocket('wss://wallet.primal.net/v1');
|
|
||||||
|
|
||||||
walletSocket.addEventListener('close', () => {
|
|
||||||
logInfo('WALLET SOCKET CLOSED');
|
|
||||||
});
|
|
||||||
|
|
||||||
walletSocket.addEventListener('open', () => {
|
|
||||||
logInfo('WALLET SOCKET OPENED');
|
|
||||||
onOpen();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={props.author !== undefined} onClose={props.onClose}>
|
<Modal open={props.author !== undefined} onClose={props.onClose}>
|
||||||
<div id={props.id} class={styles.subscribeToAuthor}>
|
<div id={props.id} class={styles.subscribeToAuthor}>
|
||||||
@ -251,7 +160,7 @@ const SubscribeToAuthorModal: Component<{
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class={styles.modalBody}>
|
<div class={styles.body}>
|
||||||
<div class={styles.tiers}>
|
<div class={styles.tiers}>
|
||||||
<Show
|
<Show
|
||||||
when={!store.isFetchingTiers}
|
when={!store.isFetchingTiers}
|
||||||
@ -270,7 +179,7 @@ const SubscribeToAuthorModal: Component<{
|
|||||||
class={`${styles.tier} ${isSelectedTier(tier) ? styles.selected : ''}`}
|
class={`${styles.tier} ${isSelectedTier(tier) ? styles.selected : ''}`}
|
||||||
onClick={() => selectTier(tier)}
|
onClick={() => selectTier(tier)}
|
||||||
>
|
>
|
||||||
<div class={styles.tierTitle}>{tier.title}</div>
|
<div class={styles.title}>{tier.title}</div>
|
||||||
|
|
||||||
<Show
|
<Show
|
||||||
when={costOptions(tier).length > 1 && store.selectedTier?.id === tier.id}
|
when={costOptions(tier).length > 1 && store.selectedTier?.id === tier.id}
|
||||||
@ -368,7 +277,7 @@ const SubscribeToAuthorModal: Component<{
|
|||||||
<Show when={store.selectedTier}>
|
<Show when={store.selectedTier}>
|
||||||
<div class={styles.payAction}>
|
<div class={styles.payAction}>
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
onClick={() => store.selectedTier && store.selectedCost && props.onSubscribe(store.selectedTier, store.selectedCost, store.exchangeRate)}
|
onClick={() => store.selectedTier && store.selectedCost && props.onSubscribe(store.selectedTier, store.selectedCost)}
|
||||||
>
|
>
|
||||||
subscribe
|
subscribe
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
|
@ -492,6 +492,7 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
|
|||||||
if (content.kind === Kind.NoteStats) {
|
if (content.kind === Kind.NoteStats) {
|
||||||
const statistic = content as NostrStatsContent;
|
const statistic = content as NostrStatsContent;
|
||||||
const stat = JSON.parse(statistic.content);
|
const stat = JSON.parse(statistic.content);
|
||||||
|
console.log('READS STATS: ', stat)
|
||||||
|
|
||||||
if (scope) {
|
if (scope) {
|
||||||
updateStore(scope, 'page', 'postStats',
|
updateStore(scope, 'page', 'postStats',
|
||||||
@ -526,6 +527,7 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
|
|||||||
const noteActionContent = content as NostrNoteActionsContent;
|
const noteActionContent = content as NostrNoteActionsContent;
|
||||||
const noteActions = JSON.parse(noteActionContent.content) as NoteActions;
|
const noteActions = JSON.parse(noteActionContent.content) as NoteActions;
|
||||||
|
|
||||||
|
console.log('READS ACTIONS: ', content)
|
||||||
if (scope) {
|
if (scope) {
|
||||||
updateStore(scope, 'page', 'noteActions',
|
updateStore(scope, 'page', 'noteActions',
|
||||||
(actions) => ({ ...actions, [noteActions.event_id]: { ...noteActions } })
|
(actions) => ({ ...actions, [noteActions.event_id]: { ...noteActions } })
|
||||||
|
@ -184,8 +184,9 @@ export const fetchNotes = (pubkey: string | undefined, noteIds: string[], subId:
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchArticles = (noteIds: string[], subId: string) => {
|
export const fetchArticles = (pubkey: string | undefined, noteIds: string[], subId: string) => {
|
||||||
return new Promise<PrimalArticle[]>((resolve, reject) => {
|
return new Promise<PrimalArticle[]>((resolve, reject) => {
|
||||||
|
if (!pubkey) reject('Missing pubkey');
|
||||||
|
|
||||||
let page: FeedPage = {
|
let page: FeedPage = {
|
||||||
users: {},
|
users: {},
|
||||||
|
@ -36,39 +36,3 @@ export const getMembershipStatus = async (pubkey: string | undefined, subId: str
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const getExchangeRate = async (pubkey: string | undefined, subId: string, currency: string, socket: WebSocket) => {
|
|
||||||
if (!pubkey) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const content = JSON.stringify(
|
|
||||||
["exchange_rate", { target_currency: currency }],
|
|
||||||
);
|
|
||||||
|
|
||||||
const event = {
|
|
||||||
content,
|
|
||||||
kind: Kind.WALLET_OPERATION,
|
|
||||||
created_at: Math.ceil((new Date()).getTime() / 1000),
|
|
||||||
tags: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
const signedEvent = await signEvent(event);
|
|
||||||
|
|
||||||
const message = JSON.stringify([
|
|
||||||
"REQ",
|
|
||||||
subId,
|
|
||||||
{cache: ["wallet", { operation_event: signedEvent }]},
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (socket) {
|
|
||||||
const e = new CustomEvent('send', { detail: { message, ws: socket }});
|
|
||||||
|
|
||||||
socket.send(message);
|
|
||||||
socket.dispatchEvent(e);
|
|
||||||
} else {
|
|
||||||
throw('no_socket');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -140,7 +140,7 @@ export const zapProfile = async (profile: PrimalUser, sender: string | undefined
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const zapSubscription = async (subEvent: NostrRelaySignedEvent, recipient: PrimalUser, sender: string | undefined, relays: Relay[], exchangeRate?: Record<string, Record<string, number>>) => {
|
export const zapSubscription = async (subEvent: NostrRelaySignedEvent, recipient: PrimalUser, sender: string | undefined, relays: Relay[]) => {
|
||||||
if (!sender || !recipient) {
|
if (!sender || !recipient) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -164,11 +164,6 @@ export const zapSubscription = async (subEvent: NostrRelaySignedEvent, recipient
|
|||||||
sats = parseInt(costTag[1]);
|
sats = parseInt(costTag[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (costTag[2] === 'USD' && exchangeRate && exchangeRate['USD']) {
|
|
||||||
let usd = parseFloat(costTag[1]);
|
|
||||||
sats = Math.ceil(exchangeRate['USD'].sats * usd * 1_000);
|
|
||||||
}
|
|
||||||
|
|
||||||
let payload = {
|
let payload = {
|
||||||
profile: recipient.pubkey,
|
profile: recipient.pubkey,
|
||||||
event: subEvent.id,
|
event: subEvent.id,
|
||||||
|
@ -390,7 +390,7 @@ const Longform: Component< { naddr: string } > = (props) => {
|
|||||||
getAuthorSubscriptionTiers(author.pubkey, subId)
|
getAuthorSubscriptionTiers(author.pubkey, subId)
|
||||||
}
|
}
|
||||||
|
|
||||||
const doSubscription = async (tier: Tier, cost: TierCost, exchangeRate?: Record<string, Record<string, number>>) => {
|
const doSubscription = async (tier: Tier, cost: TierCost) => {
|
||||||
const a = store.article?.user;
|
const a = store.article?.user;
|
||||||
|
|
||||||
if (!a || !account || !cost) return;
|
if (!a || !account || !cost) return;
|
||||||
@ -412,34 +412,10 @@ const Longform: Component< { naddr: string } > = (props) => {
|
|||||||
const { success, note } = await sendEvent(subEvent, account.relays, account.relaySettings);
|
const { success, note } = await sendEvent(subEvent, account.relays, account.relaySettings);
|
||||||
|
|
||||||
if (success && note) {
|
if (success && note) {
|
||||||
const isZapped = await zapSubscription(note, a, account.publicKey, account.relays, exchangeRate);
|
await zapSubscription(note, a, account.publicKey, account.relays);
|
||||||
|
|
||||||
if (!isZapped) {
|
|
||||||
unsubscribe(note.id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsubscribe = async (eventId: string) => {
|
|
||||||
const a = store.article?.user;
|
|
||||||
|
|
||||||
if (!a || !account) return;
|
|
||||||
|
|
||||||
const unsubEvent = {
|
|
||||||
kind: Kind.Unsubscribe,
|
|
||||||
content: '',
|
|
||||||
created_at: Math.floor((new Date()).getTime() / 1_000),
|
|
||||||
|
|
||||||
tags: [
|
|
||||||
['p', a.pubkey],
|
|
||||||
['e', eventId],
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
await sendEvent(unsubEvent, account.relays, account.relaySettings);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const openSubscribe = () => {
|
const openSubscribe = () => {
|
||||||
app?.actions.openAuthorSubscribeModal(store.article?.user, doSubscription);
|
app?.actions.openAuthorSubscribeModal(store.article?.user, doSubscription);
|
||||||
};
|
};
|
||||||
@ -626,6 +602,8 @@ const Longform: Component< { naddr: string } > = (props) => {
|
|||||||
getArticleThread(account?.publicKey, pubkey, identifier, kind, subId);
|
getArticleThread(account?.publicKey, pubkey, identifier, kind, subId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePage = (content: NostrEventContent) => {
|
const updatePage = (content: NostrEventContent) => {
|
||||||
if (content.kind === Kind.Metadata) {
|
if (content.kind === Kind.Metadata) {
|
||||||
const user = content as NostrUserContent;
|
const user = content as NostrUserContent;
|
||||||
|
@ -547,7 +547,7 @@ const Profile: Component = () => {
|
|||||||
getAuthorSubscriptionTiers(author.pubkey, subId);
|
getAuthorSubscriptionTiers(author.pubkey, subId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const doSubscription = async (tier: Tier, cost: TierCost, exchangeRate?: Record<string, Record<string, number>>) => {
|
const doSubscription = async (tier: Tier, cost: TierCost) => {
|
||||||
const a = profile?.userProfile;
|
const a = profile?.userProfile;
|
||||||
|
|
||||||
if (!a || !account || !cost) return;
|
if (!a || !account || !cost) return;
|
||||||
@ -569,35 +569,10 @@ const Profile: Component = () => {
|
|||||||
const { success, note } = await sendEvent(subEvent, account.relays, account.relaySettings);
|
const { success, note } = await sendEvent(subEvent, account.relays, account.relaySettings);
|
||||||
|
|
||||||
if (success && note) {
|
if (success && note) {
|
||||||
const isZapped = await zapSubscription(note, a, account.publicKey, account.relays, exchangeRate);
|
await zapSubscription(note, a, account.publicKey, account.relays);
|
||||||
|
|
||||||
if (!isZapped) {
|
|
||||||
unsubscribe(note.id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsubscribe = async (eventId: string) => {
|
|
||||||
const a = profile?.userProfile;;
|
|
||||||
|
|
||||||
if (!a || !account) return;
|
|
||||||
|
|
||||||
const unsubEvent = {
|
|
||||||
kind: Kind.Unsubscribe,
|
|
||||||
content: '',
|
|
||||||
created_at: Math.floor((new Date()).getTime() / 1_000),
|
|
||||||
|
|
||||||
tags: [
|
|
||||||
['p', a.pubkey],
|
|
||||||
['e', eventId],
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
await sendEvent(unsubEvent, account.relays, account.relaySettings);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const openSubscribe = () => {
|
const openSubscribe = () => {
|
||||||
app?.actions.openAuthorSubscribeModal(profile?.userProfile, doSubscription);
|
app?.actions.openAuthorSubscribeModal(profile?.userProfile, doSubscription);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user