mirror of
https://github.com/aljazceru/hypergolic.git
synced 2025-12-18 22:14:21 +01:00
problem: bitcoin addresses not added to rocket
This commit is contained in:
46
src/components/AssociateBitcoinAddress.svelte
Normal file
46
src/components/AssociateBitcoinAddress.svelte
Normal file
@@ -0,0 +1,46 @@
|
||||
<script lang="ts">
|
||||
import * as Card from "@/components/ui/card";
|
||||
|
||||
|
||||
import Heading from "./Heading.svelte";
|
||||
import InputBitcoinAddress from "./InputBitcoinAddress.svelte";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ndk } from "@/ndk";
|
||||
import { currentUser } from "@/stores/session";
|
||||
import { NDKEvent } from "@nostr-dev-kit/ndk";
|
||||
import validate from "bitcoin-address-validation";
|
||||
|
||||
let bitcoinAddress:string;
|
||||
|
||||
function publish(address:string) {
|
||||
if (!$ndk.signer) {
|
||||
throw new Error('no ndk signer found');
|
||||
}
|
||||
let author = $currentUser;
|
||||
if (!author) {
|
||||
throw new Error('no current user');
|
||||
}
|
||||
if (!validate(address)) {
|
||||
throw new Error("invalid bitcoin address")
|
||||
}
|
||||
let event = new NDKEvent($ndk)
|
||||
event.kind = 1413
|
||||
event.tags.push(["onchain", address])
|
||||
//todo: let user specify a rocket
|
||||
console.log("todo: let user specify a rocket")
|
||||
event.publish().then((x) => {
|
||||
console.log(x);
|
||||
}).catch(()=>{ console.log("failed to publish", event.rawEvent())});
|
||||
}
|
||||
|
||||
</script>
|
||||
<Heading title="Sponsor a Contributor" />
|
||||
<Card.Root>
|
||||
<Card.Header><Card.Title>Associate Bitcoin Address</Card.Title></Card.Header>
|
||||
<Card.Content>
|
||||
<div class="m-2 flex">
|
||||
You must associate at least one Bitcoin address with your npub before you can pay a Contributor.
|
||||
</div>
|
||||
<div class="flex"><InputBitcoinAddress bind:bitcoinAddress /><Button on:click={()=>publish(bitcoinAddress)} class="mt-3 max-w-xs">Publish</Button></div>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
67
src/components/BitcoinAssociations.svelte
Normal file
67
src/components/BitcoinAssociations.svelte
Normal file
@@ -0,0 +1,67 @@
|
||||
<script lang="ts">
|
||||
import * as Card from '@/components/ui/card';
|
||||
import * as Table from '@/components/ui/table';
|
||||
import { Rocket } from '@/event_helpers/rockets';
|
||||
import { ndk } from '@/ndk';
|
||||
import { NDKKind } from '@nostr-dev-kit/ndk';
|
||||
import { Avatar, Name } from '@nostr-dev-kit/ndk-svelte-components';
|
||||
import { onDestroy } from 'svelte';
|
||||
|
||||
export let rocket: Rocket;
|
||||
|
||||
let _associationRequests = $ndk.storeSubscribe(
|
||||
[{ '#a': [`31108:${rocket.Event.author.pubkey}:${rocket.Name()}`], kinds: [1413 as NDKKind] }],
|
||||
{
|
||||
subId: `${rocket.Name()}_bitcoin_associations`
|
||||
}
|
||||
);
|
||||
|
||||
onDestroy(() => {
|
||||
_associationRequests?.unsubscribe();
|
||||
});
|
||||
</script>
|
||||
|
||||
<Card.Root class="sm:col-span-3">
|
||||
<Card.Header class="px-7">
|
||||
<Card.Title>Registered Bitcoin Addresses</Card.Title>
|
||||
<Card.Description
|
||||
>These people have registered a Bitcoin address and want to sponsor Contributors working on {rocket.Name()}</Card.Description
|
||||
>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
<Table.Root>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.Head>Sponsor</Table.Head>
|
||||
<Table.Head class="hidden text-left md:table-cell">Address</Table.Head>
|
||||
<Table.Head class="table-cell">Amount (Sats)</Table.Head>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
{#each rocket.BitcoinAssociations() as [pubkey, ba], _ (pubkey)}
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
<div class="flex flex-nowrap">
|
||||
<Avatar
|
||||
ndk={$ndk}
|
||||
pubkey={pubkey}
|
||||
class="h-10 w-10 flex-none rounded-full object-cover"
|
||||
/>
|
||||
<Name
|
||||
ndk={$ndk}
|
||||
pubkey={pubkey}
|
||||
class="hidden max-w-32 truncate p-2 md:inline-block"
|
||||
/>
|
||||
</div>
|
||||
</Table.Cell>
|
||||
<Table.Cell class="hidden text-left md:table-cell">
|
||||
{0}
|
||||
</Table.Cell>
|
||||
<Table.Cell class="table-cell">{ba.Address}</Table.Cell>
|
||||
|
||||
</Table.Row>
|
||||
{/each}
|
||||
</Table.Body>
|
||||
</Table.Root>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
32
src/components/InputBitcoinAddress.svelte
Normal file
32
src/components/InputBitcoinAddress.svelte
Normal file
@@ -0,0 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { Input } from '@/components/ui/input';
|
||||
import validate from 'bitcoin-address-validation';
|
||||
|
||||
export let bitcoinAddress: string;
|
||||
$: bitcoinAddressInValid = true;
|
||||
$: bitcoinAddressError = '';
|
||||
|
||||
$: if (bitcoinAddress) {
|
||||
if (!validate(bitcoinAddress)) {
|
||||
bitcoinAddressInValid = true;
|
||||
bitcoinAddressError = 'Bitcoin address is invalid';
|
||||
} else {
|
||||
bitcoinAddressInValid = false;
|
||||
bitcoinAddressError = '';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="m-2 flex flex-col">
|
||||
<div class="flex">
|
||||
<Input
|
||||
bind:value={bitcoinAddress}
|
||||
type="text"
|
||||
placeholder="Bitcoin Address for Payment"
|
||||
class="m-1 max-w-xs"
|
||||
/>
|
||||
</div>
|
||||
{#if bitcoinAddressError}
|
||||
<div class="ml-4 p-0 text-sm text-red-500">{bitcoinAddressError}</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -3,41 +3,40 @@
|
||||
import { base } from '$app/paths';
|
||||
import { Button } from '$lib/components/ui/button/index.js';
|
||||
import * as Card from '$lib/components/ui/card/index.js';
|
||||
import { Name, Avatar } from '@nostr-dev-kit/ndk-svelte-components';
|
||||
import { getMission, getRocketURL } from '@/helpers';
|
||||
import type { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { ChevronRight } from 'lucide-svelte';
|
||||
import type { Rocket } from '@/event_helpers/rockets';
|
||||
import { ndk } from '@/ndk';
|
||||
import { Avatar, Name } from '@nostr-dev-kit/ndk-svelte-components';
|
||||
import { ChevronRight } from 'lucide-svelte';
|
||||
|
||||
export let rocketEvent: NDKEvent;
|
||||
export let rocket: Rocket;
|
||||
//$page.url.searchParams.get("tab")
|
||||
</script>
|
||||
|
||||
<Card.Root class="w-[350px]">
|
||||
<Card.Header>
|
||||
<Card.Title>{rocketEvent.getMatchingTags('d')[0][1]}</Card.Title>
|
||||
<Card.Description>{getMission(rocketEvent)}</Card.Description>
|
||||
<Card.Title>{rocket.Name()}</Card.Title>
|
||||
<Card.Description>{rocket.Mission()}</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
<div class="flex items-center gap-2">
|
||||
<Avatar
|
||||
ndk={$ndk}
|
||||
pubkey={rocketEvent.pubkey}
|
||||
pubkey={rocket.Event.pubkey}
|
||||
class="h-5 w-5 flex-none rounded-full object-cover"
|
||||
/>
|
||||
<Name ndk={$ndk} pubkey={rocketEvent.pubkey} class="inline-block truncate" />
|
||||
<Name ndk={$ndk} pubkey={rocket.Event.pubkey} class="inline-block truncate" />
|
||||
</div>
|
||||
</Card.Content>
|
||||
<Card.Footer class="flex justify-between">
|
||||
<Button
|
||||
on:click={() => {
|
||||
console.log(rocketEvent.rawEvent());
|
||||
console.log(rocket.Event.rawEvent());
|
||||
}}
|
||||
variant="outline">Print to Console</Button
|
||||
>
|
||||
<Button
|
||||
on:click={() => {
|
||||
goto(`${base}/rockets/${getRocketURL(rocketEvent)}`);
|
||||
goto(`${base}/rockets/${rocket.URL()}`);
|
||||
}}>View Full Rocket<ChevronRight class="h-4 w-4" /></Button
|
||||
>
|
||||
</Card.Footer>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
import Todo from './Todo.svelte';
|
||||
import UpdateMission from './UpdateMission.svelte';
|
||||
import { Rocket } from '@/event_helpers/rockets';
|
||||
import BitcoinAssociations from './BitcoinAssociations.svelte';
|
||||
|
||||
export let rocket: NDKEvent;
|
||||
|
||||
@@ -42,6 +43,7 @@
|
||||
<ProposedProducts {rocket} />
|
||||
|
||||
<MeritRequests parsedRocket={new Rocket(rocket)} />
|
||||
<BitcoinAssociations rocket={new Rocket(rocket)}/>
|
||||
<Card.Root class="sm:col-span-3">
|
||||
<Card.Header class="pb-3">
|
||||
<Card.Title>Actions</Card.Title>
|
||||
|
||||
@@ -5,10 +5,68 @@ import validate from 'bitcoin-address-validation';
|
||||
import { BitcoinTipTag } from '@/stores/bitcoin';
|
||||
|
||||
export class Rocket {
|
||||
UpsertBitcoinAssociation(association: BitcoinAssociation): NDKEvent {
|
||||
let event: NDKEvent | undefined = undefined;
|
||||
if (true) { //todo: check if exists
|
||||
this.PrepareForUpdate();
|
||||
event = new NDKEvent(this.Event.ndk, this.Event.rawEvent());
|
||||
event.created_at = Math.floor(new Date().getTime() / 1000);
|
||||
event.tags.push(["address", `${association.Pubkey}:${association.Address}`])
|
||||
event.tags.push(['proof_full', JSON.stringify(association.Event.rawEvent())]);
|
||||
updateIgnitionAndParentTag(event);
|
||||
updateBitcoinTip(event);
|
||||
}
|
||||
return event;
|
||||
}
|
||||
BitcoinAssociations():Map<string, BitcoinAssociation> {
|
||||
let a = new Map<string, BitcoinAssociation>()
|
||||
for (let t of this.Event.getMatchingTags("address")) {
|
||||
if (t.length == 2) {
|
||||
let split = t[1].split(":")
|
||||
if (split.length == 2) {
|
||||
let ba = new BitcoinAssociation()
|
||||
ba.Address = split[1]
|
||||
ba.Pubkey = split[0]
|
||||
if (ba.Validate()) {
|
||||
a.set(ba.Pubkey, ba)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
Event: NDKEvent;
|
||||
|
||||
URL(): string {
|
||||
let ignitionID = undefined;
|
||||
if (
|
||||
this.Event.getMatchingTags('ignition') &&
|
||||
this.Event.getMatchingTags('ignition')[0] &&
|
||||
this.Event.getMatchingTags('ignition')[0][1]
|
||||
) {
|
||||
ignitionID = this.Event.getMatchingTags('ignition')[0][1];
|
||||
}
|
||||
if (!ignitionID) {
|
||||
ignitionID = this.Event.id;
|
||||
}
|
||||
let d = this.Event.getMatchingTags('d')[0][1];
|
||||
let p = this.Event.pubkey;
|
||||
return `${ignitionID}?d=${d}&p=${p}`;
|
||||
}
|
||||
Name(): string {
|
||||
return this.Event.dTag!;
|
||||
}
|
||||
Mission(): string {
|
||||
if (
|
||||
this.Event.getMatchingTags('mission') &&
|
||||
this.Event.getMatchingTags('mission')[0] &&
|
||||
this.Event.getMatchingTags('mission')[0][1]
|
||||
) {
|
||||
return this.Event.getMatchingTags('mission')[0][1];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
Products(): RocketProduct[] {
|
||||
let _products: RocketProduct[] = [];
|
||||
for (let p of this.Event.getMatchingTags('product')) {
|
||||
@@ -118,7 +176,7 @@ export class Rocket {
|
||||
event.tags.push(['merit', `${request.Pubkey}:${request.ID}:0:0:${request.Merits}`]);
|
||||
event.tags.push(['proof_full', JSON.stringify(signedProof.rawEvent())]);
|
||||
updateIgnitionAndParentTag(event);
|
||||
updateBitcionTip(event);
|
||||
updateBitcoinTip(event);
|
||||
}
|
||||
return event;
|
||||
}
|
||||
@@ -133,33 +191,32 @@ export class Rocket {
|
||||
a.StartPrice = parseInt(items[2], 10);
|
||||
a.EndPrice = parseInt(items[3], 10);
|
||||
a.Merits = parseInt(items[4], 10);
|
||||
|
||||
|
||||
let ids = items[5].match(/.{1,64}/g);
|
||||
if (ids) {
|
||||
for (let id of ids) {
|
||||
a.AMRIDs.push(id);
|
||||
}
|
||||
}
|
||||
let amrs = this.ApprovedMeritRequests()
|
||||
let amrs = this.ApprovedMeritRequests();
|
||||
let failed = false;
|
||||
for (let id of a.AMRIDs) {
|
||||
let amr = amrs.get(id)
|
||||
let amr = amrs.get(id);
|
||||
if (!amr) {
|
||||
failed = true
|
||||
failed = true;
|
||||
} else {
|
||||
if (!a.Owner) {
|
||||
a.Owner = amr.Pubkey
|
||||
a.Owner = amr.Pubkey;
|
||||
} else if (a.Owner != amr.Pubkey) {
|
||||
failed = true
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!failed) {
|
||||
auctions.push(a)
|
||||
auctions.push(a);
|
||||
} else {
|
||||
throw new Error("this should not happen, bug!")
|
||||
throw new Error('this should not happen, bug!');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,7 +271,7 @@ export class Rocket {
|
||||
]); //<merit request ID:start price:end price:start height:rx address>
|
||||
event.tags.push(['proof_full', JSON.stringify(request.Event!.rawEvent())]);
|
||||
updateIgnitionAndParentTag(event);
|
||||
updateBitcionTip(event);
|
||||
updateBitcoinTip(event);
|
||||
}
|
||||
if (invalid) {
|
||||
event = undefined;
|
||||
@@ -238,7 +295,7 @@ export class Rocket {
|
||||
purchases
|
||||
]);
|
||||
updateIgnitionAndParentTag(event);
|
||||
updateBitcionTip(event);
|
||||
updateBitcoinTip(event);
|
||||
return event;
|
||||
}
|
||||
UpdateMission(mission: string): NDKEvent {
|
||||
@@ -248,7 +305,7 @@ export class Rocket {
|
||||
event.removeTag('mission');
|
||||
event.tags.push(['mission', mission]);
|
||||
updateIgnitionAndParentTag(event);
|
||||
updateBitcionTip(event);
|
||||
updateBitcoinTip(event);
|
||||
return event;
|
||||
}
|
||||
CurrentProducts(): Map<string, RocketProduct> {
|
||||
@@ -335,7 +392,7 @@ function updateIgnitionAndParentTag(event: NDKEvent) {
|
||||
event.tags.push(['parent', event.id]);
|
||||
}
|
||||
|
||||
function updateBitcionTip(event: NDKEvent) {
|
||||
function updateBitcoinTip(event: NDKEvent) {
|
||||
let existingBitcoinTip = event.getMatchingTags('bitcoin');
|
||||
let existing = [];
|
||||
for (let t of event.tags) {
|
||||
@@ -639,7 +696,7 @@ export class AMRAuction {
|
||||
}
|
||||
for (let pending of rocket.PendingAMRAuctions()) {
|
||||
if (pending.AMRIDs.includes(id)) {
|
||||
valid = false
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -693,3 +750,27 @@ export class AMRAuction {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class BitcoinAssociation {
|
||||
Pubkey: string;
|
||||
Address: string | undefined;
|
||||
Event: NDKEvent;
|
||||
Validate(): boolean {
|
||||
let valid = true;
|
||||
if (this.Pubkey.length != 64) {
|
||||
valid = false;
|
||||
}
|
||||
if ((this.Address && !validate(this.Address)) || !this.Address) {
|
||||
valid = false;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
constructor(event?: NDKEvent) {
|
||||
if (event) {
|
||||
this.Pubkey = event.pubkey;
|
||||
this.Address = event.tagValue('onchain');
|
||||
this.Event = event;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,16 +19,7 @@ export function getRocketURL(e: NDKEvent): string {
|
||||
return `${ignitionID}?d=${d}&p=${p}`;
|
||||
}
|
||||
|
||||
export function getMission(rocketEvent: NDKEvent): string {
|
||||
if (
|
||||
rocketEvent.getMatchingTags('mission') &&
|
||||
rocketEvent.getMatchingTags('mission')[0] &&
|
||||
rocketEvent.getMatchingTags('mission')[0][1]
|
||||
) {
|
||||
return rocketEvent.getMatchingTags('mission')[0][1];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
export function unixTimeNow() {
|
||||
return Math.floor(new Date().getTime() / 1000);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { Avatar } from '@nostr-dev-kit/ndk-svelte-components';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { derived } from 'svelte/store';
|
||||
import AssociateBitcoinAddress from '../../components/AssociateBitcoinAddress.svelte';
|
||||
import Login from '../../components/Login.svelte';
|
||||
import MeritAuctions from '../../stateupdaters/MeritAuctions.svelte';
|
||||
let rocketEvents = $ndk.storeSubscribe([{ kinds: [31108 as number] }], { subId: 'all_rockets' });
|
||||
@@ -40,10 +41,21 @@
|
||||
return merits;
|
||||
});
|
||||
|
||||
|
||||
let noAssociatedBitcoinAddress = derived([currentUser, pendingSales], ([$currentUser, $pendingSales])=>{
|
||||
let show = false
|
||||
if ($currentUser) {
|
||||
for (let [r, _] of $pendingSales) {
|
||||
if (!r.BitcoinAssociations().get($currentUser.pubkey)) {
|
||||
show = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return show
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<h1 class=" m-2 text-nowrap text-center text-xl">Sponsor a Contributor</h1>
|
||||
{#if $noAssociatedBitcoinAddress}<AssociateBitcoinAddress />{/if}
|
||||
|
||||
{#if $currentUser}
|
||||
{#each $pendingSales as [rocket, amr]}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
import Login from '../../components/Login.svelte';
|
||||
import CreateAMRAuction from '../../components/CreateAMRAuction.svelte';
|
||||
import MeritAuctions from '../../stateupdaters/MeritAuctions.svelte';
|
||||
import Heading from '../../components/Heading.svelte';
|
||||
let rocketEvents = $ndk.storeSubscribe([{ kinds: [31108 as number] }], { subId: 'all_rockets' });
|
||||
onDestroy(() => {
|
||||
rocketEvents?.unsubscribe();
|
||||
@@ -101,8 +102,7 @@
|
||||
// return thisRocket
|
||||
// }
|
||||
</script>
|
||||
|
||||
<h1 class=" m-2 text-nowrap text-center text-xl">Trade your Merits for Sats</h1>
|
||||
<Heading title="Trade your Merits for Sats" />
|
||||
|
||||
{#if $currentUser}
|
||||
{#each $myMeritRequests as [rocket, amr]}
|
||||
@@ -122,7 +122,7 @@
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
{#each rocket.PendingAMRAuctions().filter(r=>{return Boolean(r.Owner == $currentUser.pubkey)}) as p}
|
||||
<Table.Row class="bg-purple-500">
|
||||
<Table.Row class="bg-purple-500 hover:bg-purple-600">
|
||||
<Table.Cell><Checkbox /></Table.Cell>
|
||||
<Table.Cell>{p.AMRIDs.length > 1 ? 'multiple' : p.AMRIDs[0].substring(0,12)}</Table.Cell>
|
||||
<Table.Cell>{p.Merits}</Table.Cell>
|
||||
|
||||
63
src/stateupdaters/AssociateBitcoinAddress.svelte
Normal file
63
src/stateupdaters/AssociateBitcoinAddress.svelte
Normal file
@@ -0,0 +1,63 @@
|
||||
<script lang="ts">
|
||||
import { BitcoinAssociation, Rocket } from '@/event_helpers/rockets';
|
||||
import { ndk } from '@/ndk';
|
||||
import { currentUser } from '@/stores/session';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { derived, type Readable } from 'svelte/store';
|
||||
|
||||
let associations = $ndk.storeSubscribe([{ kinds: [1413 as number] }], {
|
||||
subId: 'all_association_requests'
|
||||
});
|
||||
onDestroy(() => {
|
||||
associations?.unsubscribe();
|
||||
});
|
||||
|
||||
export let rockets: Readable<Rocket[]>;
|
||||
|
||||
let validAssociationRequests = derived([associations, rockets], ([$associationEvents, $rockets]) => {
|
||||
let valid = new Map<string, BitcoinAssociation>();
|
||||
for (let e of $associationEvents) {
|
||||
let a = new BitcoinAssociation(e)
|
||||
if (a.Validate()) {
|
||||
valid.set(a.Event.id, a);
|
||||
}
|
||||
}
|
||||
return valid
|
||||
|
||||
});
|
||||
|
||||
let validAgainstMyRocket = derived([currentUser, validAssociationRequests, rockets], ([$currentUser, $associationRequests, $rockets]) => {
|
||||
let valid:{rocket:Rocket, association:BitcoinAssociation}[] = []
|
||||
if ($currentUser) {
|
||||
if ($rockets.length > 0) {
|
||||
for (let [_, a] of $associationRequests) {
|
||||
for (let r of $rockets) {
|
||||
if (r.VotePowerForPubkey($currentUser.pubkey)) {
|
||||
if (!r.BitcoinAssociations().get(a.Pubkey)) { //todo: get current list of Bitcoin associations, if (this is not included)
|
||||
valid.push({rocket:r, association:a})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
})
|
||||
|
||||
validAgainstMyRocket.subscribe((requests) => {
|
||||
if ($rockets && $rockets.length > 0 && currentUser && $currentUser) {
|
||||
for (let {rocket,association} of requests) {
|
||||
if (rocket.VotePowerForPubkey($currentUser.pubkey)) {
|
||||
console.log("todo: check which rocket user has specified")
|
||||
let e = rocket.UpsertBitcoinAssociation(association)
|
||||
if (e) {
|
||||
e.ndk = $ndk
|
||||
e.publish().then(x=>{
|
||||
console.log(x, e)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,27 +1,44 @@
|
||||
<script lang="ts">
|
||||
import type { NDKEventStore } from '@nostr-dev-kit/ndk-svelte';
|
||||
import Heading from '../../components/Heading.svelte';
|
||||
import type { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { Rocket } from '@/event_helpers/rockets';
|
||||
import { ndk } from '@/ndk';
|
||||
import Todo from '../../components/Todo.svelte';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { derived } from 'svelte/store';
|
||||
import Heading from '../../components/Heading.svelte';
|
||||
import RocketCard from '../../components/RocketCard.svelte';
|
||||
import Todo from '../../components/Todo.svelte';
|
||||
import AssociateBitcoinAddress from '../../stateupdaters/AssociateBitcoinAddress.svelte';
|
||||
let _rockets = $ndk.storeSubscribe([{ kinds: [31108 as number] }], { subId: 'rockets' });
|
||||
|
||||
let entries: NDKEventStore<NDKEvent> | undefined;
|
||||
onDestroy(() => {
|
||||
entries?.unsubscribe();
|
||||
_rockets?.unsubscribe();
|
||||
});
|
||||
|
||||
entries = $ndk.storeSubscribe([{ kinds: [31108 as number] }], { subId: 'rockets' });
|
||||
let rockets = derived(_rockets, ($rockets)=>{
|
||||
let _r = new Map<string, Rocket>()
|
||||
for (let e of $rockets) {
|
||||
let existing = _r.get(`${e.pubkey}${e.dTag}`)
|
||||
if (!existing) {
|
||||
console.log(e)
|
||||
existing = new Rocket(e)
|
||||
}
|
||||
if (existing.Event.created_at <= e.created_at) {
|
||||
_r.set(`${e.pubkey}${e.dTag}`, existing)
|
||||
}
|
||||
}
|
||||
return Array.from(_r, ([_, r])=>{return r})
|
||||
})
|
||||
|
||||
|
||||
//todo: until we have namerocket working, just manually dedupe rockets based on my pubkey
|
||||
//todo: write a recognizer/validator for rocket events
|
||||
</script>
|
||||
|
||||
<Heading title="Rockets" />
|
||||
{#if entries && $entries}
|
||||
{#if rockets && $rockets}
|
||||
<AssociateBitcoinAddress {rockets} />
|
||||
<Todo text={['render these in a nicer way, maybe a grid or something']} />
|
||||
|
||||
{#each $entries as rocketEvent (rocketEvent.id)}
|
||||
<RocketCard {rocketEvent} />
|
||||
{#each $rockets as rocket (`${rocket.Event.pubkey}${rocket.Name()}`)}
|
||||
<RocketCard {rocket} />
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user