problem: not clear which rockets are testnet at /buymerits

resolve https://github.com/nostrocket/hypergolic/issues/82
This commit is contained in:
Bob
2024-08-21 15:02:55 +08:00
parent 5dda9131e7
commit 7c9c02fee3
2 changed files with 166 additions and 126 deletions

View File

@@ -0,0 +1,89 @@
<script lang="ts">
import { ndk } from '@/ndk';
import type { AMRAuction, Rocket } from '@/event_helpers/rockets';
import { bitcoinTip, txs } from '@/stores/bitcoin';
import BuyAmr from './BuyAMR.svelte';
import Heading from './Heading.svelte';
import { Avatar } from '@nostr-dev-kit/ndk-svelte-components';
import * as Table from '@/components/ui/table';
import * as Card from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
export let rocket: Rocket;
export let amr: AMRAuction[];
export let transactions: Map<string, txs>;
let dev = false;
function getRocketClass(rocket: Rocket): string {
return rocket.Testnet() ? 'dark:border-red-600 mb-2' : 'mb-2';
}
</script>
<Card.Root class={getRocketClass(rocket)}>
<Card.CardHeader>
<div class="flex flex-nowrap place-items-stretch">
<h3 class=" mr-auto text-nowrap text-2xl">
{`ROCKET: ${rocket.Name().toUpperCase()}`}
</h3>
{#if rocket.Testnet()}<Badge
variant="destructive"
class="flex h-8 shrink-0 items-center justify-center rounded-sm"
>
<span
on:click={() => {
dev = true;
alert(
'dev mode enabled, refresh page if this was unintentional or you may lose sats'
);
}}>TESTNET</span
>
</Badge>{/if}
</div>
<Heading></Heading>
<Table.Root>
<Table.Header>
<Table.Row>
<Table.Head class="w-[10px]">Seller</Table.Head>
<Table.Head class="w-[10px]">AMR</Table.Head>
<Table.Head class="w-[10px]">Merits</Table.Head>
<Table.Head class="w-[150px] text-right">Current Price (sats)</Table.Head>
<Table.Head>Status</Table.Head>
<Table.Head>Receiving Address</Table.Head>
<Table.Head></Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{#each amr as p (p.AMRIDs)}
<Table.Row>
<Table.Cell
><Avatar
ndk={$ndk}
pubkey={p.Owner}
class="aspect-square w-10 flex-none rounded-full object-cover"
/></Table.Cell
>
<Table.Cell
>{p.AMRIDs.length > 1 ? 'multiple' : p.AMRIDs[0].substring(0, 12)}</Table.Cell
>
<Table.Cell>{p.Merits}</Table.Cell>
<Table.Cell class="text-right">{p.Merits}</Table.Cell>
<Table.Cell
>{p.Status(rocket, $bitcoinTip.height, transactions.get(p.RxAddress))}</Table.Cell
>
<Table.Cell
on:click={() => {
console.log(transactions.get(p.RxAddress)?.From());
}}>{p.RxAddress}</Table.Cell
>
<Table.Cell
>{#if p.Status(rocket, $bitcoinTip.height, transactions.get(p.RxAddress)) == 'OPEN' && (!rocket.Testnet() || dev)}
<BuyAmr auction={p} />{/if}</Table.Cell
>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
</Card.CardHeader>
</Card.Root>

View File

@@ -1,29 +1,25 @@
<script lang="ts"> <script lang="ts">
import * as Table from '@/components/ui/table';
import { AMRAuction, MeritPurchase, Rocket } from '@/event_helpers/rockets'; import { AMRAuction, MeritPurchase, Rocket } from '@/event_helpers/rockets';
import { ndk } from '@/ndk'; import { ndk } from '@/ndk';
import { bitcoinTip, getIncomingTransactions, txs } from '@/stores/bitcoin'; import { bitcoinTip, getIncomingTransactions, txs } from '@/stores/bitcoin';
import { currentUser } from '@/stores/session'; import { currentUser } from '@/stores/session';
import { NDKEvent } from '@nostr-dev-kit/ndk'; import { NDKEvent } from '@nostr-dev-kit/ndk';
import { Avatar } from '@nostr-dev-kit/ndk-svelte-components';
import { onDestroy } from 'svelte'; import { onDestroy } from 'svelte';
import { derived } from 'svelte/store'; import { derived } from 'svelte/store';
import AssociateBitcoinAddress from '../../components/AssociateBitcoinAddress.svelte'; import AssociateBitcoinAddress from '../../components/AssociateBitcoinAddress.svelte';
import Heading from '../../components/Heading.svelte'; import BuyAmrCard from '../../components/BuyAMRCard.svelte';
import Login from '../../components/Login.svelte'; import Login from '../../components/Login.svelte';
import MeritAuctions from '../../stateupdaters/MeritAuctions.svelte'; import MeritAuctions from '../../stateupdaters/MeritAuctions.svelte';
import BuyAmr from '../../components/BuyAMR.svelte';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { base } from '$app/paths'; import { base } from '$app/paths';
import * as Card from '@/components/ui/card'; import * as Tabs from '$lib/components/ui/tabs/index.js';
import { Badge } from '@/components/ui/badge';
let rocketEvents = $ndk.storeSubscribe([{ kinds: [31108 as number] }], { subId: 'all_rockets' }); let rocketEvents = $ndk.storeSubscribe([{ kinds: [31108 as number] }], { subId: 'all_rockets' });
onDestroy(() => { onDestroy(() => {
rocketEvents?.unsubscribe(); rocketEvents?.unsubscribe();
}); });
let dev = false;
let rockets = derived(rocketEvents, ($rocketEvents) => { let rockets = derived(rocketEvents, ($rocketEvents) => {
let m = new Map<string, NDKEvent>(); let m = new Map<string, NDKEvent>();
for (let e of $rocketEvents) { for (let e of $rocketEvents) {
@@ -40,18 +36,25 @@
}); });
let pendingSales = derived(rockets, ($rockets) => { let pendingSales = derived(rockets, ($rockets) => {
let merits = new Map<Rocket, AMRAuction[]>(); let mainnetMerits = new Map<Rocket, AMRAuction[]>();
let testnetMerits = new Map<Rocket, AMRAuction[]>();
for (let r of $rockets) { for (let r of $rockets) {
let _auctions: AMRAuction[] = r.PendingAMRAuctions(); let _auctions: AMRAuction[] = r.PendingAMRAuctions();
merits.set(r, _auctions); if (r.Testnet()) {
testnetMerits.set(r, _auctions);
} else {
mainnetMerits.set(r, _auctions);
}
} }
return merits; return { mainnet: mainnetMerits, testnet: testnetMerits };
}); });
let _transactions = new Map<string, txs>(); let _transactions = new Map<string, txs>();
let transactions = derived(pendingSales, ($pendingSales) => { let transactions = derived(pendingSales, ($pendingSales) => {
for (let [r, s] of $pendingSales) { for (let network of ['mainnet', 'testnet'] as const) {
for (let [r, s] of $pendingSales[network]) {
for (let amr of s) { for (let amr of s) {
if (!_transactions.get(amr.RxAddress)) { if (!_transactions.get(amr.RxAddress)) {
_transactions.set(amr.RxAddress, new txs(amr.RxAddress)); _transactions.set(amr.RxAddress, new txs(amr.RxAddress));
@@ -76,6 +79,7 @@
} }
} }
} }
}
return _transactions; return _transactions;
}); });
@@ -83,12 +87,16 @@
[pendingSales, transactions, bitcoinTip, currentUser], [pendingSales, transactions, bitcoinTip, currentUser],
([$pendingSales, $transactions, $bitcoinTip, $currentUser]) => { ([$pendingSales, $transactions, $bitcoinTip, $currentUser]) => {
if ($currentUser) { if ($currentUser) {
for (let [r, p] of $pendingSales) { for (let network of ['mainnet', 'testnet'] as const) {
for (let [r, p] of $pendingSales[network]) {
if (r.VotePowerForPubkey($currentUser.pubkey) > 0) { if (r.VotePowerForPubkey($currentUser.pubkey) > 0) {
for (let amrAuction of p) { for (let amrAuction of p) {
if ( if (
amrAuction.Status(r, $bitcoinTip.height, $transactions.get(amrAuction.RxAddress)) == amrAuction.Status(
'SOLD & PENDING RATIFICATION' r,
$bitcoinTip.height,
$transactions.get(amrAuction.RxAddress)
) == 'SOLD & PENDING RATIFICATION'
) { ) {
let txs = $transactions.get(amrAuction.RxAddress); let txs = $transactions.get(amrAuction.RxAddress);
if (txs) { if (txs) {
@@ -106,6 +114,7 @@
} }
} }
} }
}
); );
nextSoldButNotInState.subscribe((t) => { nextSoldButNotInState.subscribe((t) => {
@@ -138,90 +147,32 @@
}); });
transactions.subscribe((t) => {}); transactions.subscribe((t) => {});
function getRocketClass(rocket: Rocket): string {
return rocket.Testnet() ? 'dark:border-red-600' : '';
}
</script> </script>
{#if $nostrocket}<AssociateBitcoinAddress rocket={$nostrocket} /> {#if $nostrocket}
<AssociateBitcoinAddress rocket={$nostrocket} />
{/if} {/if}
{#if $currentUser} {#if $currentUser}
{#each $pendingSales as [rocket, amr] (rocket.Event.id)} <Tabs.Root value="mainnet">
<Tabs.List>
<Tabs.Trigger value="mainnet">Mainnet</Tabs.Trigger>
<Tabs.Trigger value="testnet">Testnet</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="mainnet">
{#each $pendingSales.mainnet as [rocket, amr] (rocket.Event.id)}
{#if amr.length > 0} {#if amr.length > 0}
<Card.Root class={getRocketClass(rocket)}> <BuyAmrCard {rocket} {amr} transactions={$transactions} />
<Card.CardHeader>
<div class="flex flex-nowrap place-items-stretch">
<h3 class=" mr-auto text-nowrap text-2xl">
{`ROCKET: ${rocket.Name().toUpperCase()}`}
</h3>
{#if rocket.Testnet()}<Badge
variant="destructive"
class="flex h-8 shrink-0 items-center justify-center rounded-sm"
>
<span
on:click={() => {
dev = true;
alert(
'dev mode enabled, refresh page if this was unintentional or you may lose sats'
);
}}>TESTNET</span
>
</Badge>{/if}
</div>
<Heading></Heading>
<Table.Root>
<Table.Header>
<Table.Row>
<Table.Head class="w-[10px]">Seller</Table.Head>
<Table.Head class="w-[10px]">AMR</Table.Head>
<Table.Head class="w-[10px]">Merits</Table.Head>
<Table.Head class="w-[150px] text-right">Current Price (sats)</Table.Head>
<Table.Head>Status</Table.Head>
<Table.Head>Receiving Address</Table.Head>
<Table.Head></Table.Head>
</Table.Row>
</Table.Header>
<Table.Body>
{#each amr as p (p.AMRIDs)}
<Table.Row>
<Table.Cell
><Avatar
ndk={$ndk}
pubkey={p.Owner}
class="aspect-square w-10 flex-none rounded-full object-cover"
/></Table.Cell
>
<Table.Cell
>{p.AMRIDs.length > 1 ? 'multiple' : p.AMRIDs[0].substring(0, 12)}</Table.Cell
>
<Table.Cell>{p.Merits}</Table.Cell>
<Table.Cell class="text-right">{p.Merits}</Table.Cell>
<Table.Cell
>{p.Status(
rocket,
$bitcoinTip.height,
$transactions.get(p.RxAddress)
)}</Table.Cell
>
<Table.Cell
on:click={() => {
console.log($transactions.get(p.RxAddress)?.From());
}}>{p.RxAddress}</Table.Cell
>
<Table.Cell
>{#if p.Status(rocket, $bitcoinTip.height, $transactions.get(p.RxAddress)) == 'OPEN' && (!rocket.Testnet() || dev)}<BuyAmr
auction={p}
/>{/if}</Table.Cell
>
</Table.Row>
{/each}
</Table.Body>
</Table.Root>
</Card.CardHeader>
</Card.Root>
{/if} {/if}
{/each} {/each}
</Tabs.Content>
<Tabs.Content value="testnet">
{#each $pendingSales.testnet as [rocket, amr] (rocket.Event.id)}
{#if amr.length > 0}
<BuyAmrCard {rocket} {amr} transactions={$transactions} />
{/if}
{/each}
</Tabs.Content>
</Tabs.Root>
{:else}<Login />{/if} {:else}<Login />{/if}
<MeritAuctions {rockets} /> <MeritAuctions {rockets} />