Merge branch 'MASTER' into fix-style

This commit is contained in:
Angelica Willianto
2024-08-12 14:05:59 +07:00
10 changed files with 559 additions and 145 deletions

View File

@@ -1,18 +1,32 @@
<script lang="ts">
import * as Card from "@/components/ui/card";
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';
import type { Rocket } from '@/event_helpers/rockets';
import { derived } from 'svelte/store';
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;
export let rocket: Rocket;
let bitcoinAddress:string;
let associatedAddresses = derived(currentUser, ($currentUser) => {
let addresses: Set<string> = new Set();
if ($currentUser) {
for (let [_, a] of rocket.BitcoinAssociations()) {
if (a.Pubkey == $currentUser.pubkey && a.Address && validate(a.Address)) {
addresses.add(a.Address);
}
}
}
return addresses;
});
function publish(address:string) {
function publish(address: string) {
if (!$ndk.signer) {
throw new Error('no ndk signer found');
}
@@ -20,27 +34,47 @@
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])
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())});
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" />
Contributors who need Sats are able to list their Merits for sale, to sponsor them simply buy some of
their Merits.
<Card.Root>
<Card.Header><Card.Title>Associate Bitcoin Address</Card.Title></Card.Header>
<Card.Header><Card.Title>Your Bitcoin Addresses</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. Merit purchases from this address will be associated with your pubkey.
</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>
<div class="m-2 flex">
Merit purchases must be conducted with a Bitcoin address that is associated with your pubkey,
otherwise you will not recieve the Merits upon payment.
</div>
{#if $associatedAddresses.size == 0}You do not have any registered addresses{:else}
Your registered addresses:
<ul class="m-2 flex flex-col">
{#each $associatedAddresses as address}<li class="list-item list-disc">{address}</li>{/each}
</ul>
{/if}
Add a new address now
<div class="flex">
<InputBitcoinAddress bind:bitcoinAddress /><Button
on:click={() => publish(bitcoinAddress)}
class="mt-3 max-w-xs">Publish</Button
>
</div>
</Card.Content>
</Card.Root>

View File

@@ -21,17 +21,24 @@
_associationRequests?.unsubscribe();
});
let addresses = new Map<string, BitcoinAssociation>()
let addresses = new Map<string, BitcoinAssociation>();
onMount(()=>{
addresses = rocket.BitcoinAssociations()
addresses.forEach(a => {
onMount(() => {
addresses = rocket.BitcoinAssociations();
addresses.forEach((a) => {
if (a.Address) {
getBalance(a.Address).then(v=>{a.Balance = v; addresses.set(a.Pubkey, a); addresses = addresses}).catch(err=>{console.log(err)})
getBalance(a.Address)
.then((v) => {
a.Balance = v;
addresses.set(a.Address!, a);
addresses = addresses;
})
.catch((err) => {
console.log(err);
});
}
})
})
});
});
</script>
<Card.Root class="sm:col-span-3">
@@ -51,18 +58,18 @@
</Table.Row>
</Table.Header>
<Table.Body>
{#each addresses as [pubkey, ba], _ (pubkey)}
{#each addresses as [address, ba], _ (address)}
<Table.Row>
<Table.Cell>
<div class="flex flex-nowrap">
<Avatar
ndk={$ndk}
pubkey={pubkey}
pubkey={ba.Pubkey}
class="h-10 w-10 flex-none rounded-full object-cover"
/>
<Name
ndk={$ndk}
pubkey={pubkey}
pubkey={ba.Pubkey}
class="hidden max-w-32 truncate p-2 md:inline-block"
/>
</div>
@@ -71,7 +78,6 @@
{ba.Balance.toLocaleString()}
</Table.Cell>
<Table.Cell class="table-cell">{ba.Address}</Table.Cell>
</Table.Row>
{/each}
</Table.Body>

View File

@@ -0,0 +1,71 @@
<script lang="ts">
import { Button, buttonVariants } from '$lib/components/ui/button/index.js';
import * as Dialog from '$lib/components/ui/dialog/index.js';
import * as Alert from '@/components/ui/alert';
import type { AMRAuction } from '@/event_helpers/rockets';
import { ndk } from '@/ndk';
import { currentUser } from '@/stores/session';
import { NDKEvent } from '@nostr-dev-kit/ndk';
import type NDKSvelte from '@nostr-dev-kit/ndk-svelte';
import { Name } from '@nostr-dev-kit/ndk-svelte-components';
import { Terminal } from 'lucide-svelte';
export let auction: AMRAuction;
let o = false;
function publish(ndk: NDKSvelte) {
if (!ndk.signer) {
throw new Error('no ndk signer found');
}
let e = new NDKEvent(ndk);
let author = $currentUser;
if (!author) {
throw new Error('no current user');
}
e.author = author;
e.kind = 1216;
e.created_at = Math.floor(new Date().getTime() / 1000);
//todo validate d tag
// e.publish().then((x) => {
// console.log(x);
// o = false;
// goto(`${base}/rockets/${getRocketURL(rocketEvent)}`);
// });
}
</script>
<Dialog.Root bind:open={o}>
<Dialog.Trigger class={buttonVariants({ variant: 'default' })}>Buy Now</Dialog.Trigger>
<Dialog.Content class="sm:max-w-[425px]">
{#if !currentUser}
<Alert.Root>
<Terminal class="h-4 w-4" />
<Alert.Title>Heads up!</Alert.Title>
<Alert.Description>You need a nostr signing extension to use Nostrocket!</Alert.Description>
</Alert.Root>
{:else}
<Dialog.Header>
<Dialog.Title>Buy Merits from <Name pubkey={auction.Owner} /></Dialog.Title>
</Dialog.Header>
<p>
To buy these merits you MUST send {auction.Merits / 100000000} BTC from one of your registered
addresses to {auction.RxAddress}.
</p>
<p>
Once the transaction has 2 confirmations the Merits will automatically be transferred to
your npub.
</p>
<Dialog.Footer>
Todo: ask user to publish an event before making transaction so that multiple people don't
pay for the same Merits.
<!-- <Button
on:click={() => {
publish($ndk);
}}
type="submit">Publish</Button
> -->
</Dialog.Footer>
{/if}
</Dialog.Content>
</Dialog.Root>

View File

@@ -84,22 +84,25 @@
variant="nostr"
class="flex h-8 shrink-0 items-center justify-center rounded-sm"
>
Tell me via DM when there are updates
Nostrocket is totally not ready yet but whatever
</Badge>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Subscribe for Updates</Dialog.Title>
<Dialog.Description>
Receive notifications about Nostrocket updates via Nostr DM or email.
Subscribe now and we'll ping you when there are new releases/features
</Dialog.Description>
<div class="flex flex-col gap-4 py-4">
{#if $currentUser}
<Button on:click={Subscribe}>Receive DM</Button>
<Button on:click={Subscribe}>DM me with updates</Button>
{:else}
<Login />
{/if}
<Separator />
<span class="ml-auto mr-auto flex"
>If you don't use nostr, you can subscribe to updates with an email address instead</span
>
<div class="grid grid-cols-4 items-center gap-4">
<Label for="email" class="text-right">Email</Label>
<Input bind:value={email} id="email" placeholder="Your email" class="col-span-3" />
@@ -108,7 +111,9 @@
<div class="ml-4 p-0 text-sm text-red-500">{emailError}</div>
{/if}
</div>
<Button disabled={emailInValid} on:click={SubmitEmailAndSubscribe}>Receive Email</Button>
<Button disabled={emailInValid} on:click={SubmitEmailAndSubscribe}
>Please email me with updates</Button
>
</Dialog.Header>
</Dialog.Content>
</Dialog.Root>