Skip to content

Commit

Permalink
feat: success state for registration
Browse files Browse the repository at this point in the history
  • Loading branch information
hstove committed Aug 10, 2023
1 parent 5c11f8f commit 140b3f0
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 38 deletions.
5 changes: 5 additions & 0 deletions .changeset/blue-phones-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'web': minor
---

Dots now includes a "registration" page, where you can easily register a name on any namespace.
5 changes: 5 additions & 0 deletions .changeset/two-pumas-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@bns-x/api': patch
---

Includes explicit types for `getNameDetails` TRPC endpoint
3 changes: 2 additions & 1 deletion web/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ export function getNetwork(): StacksNetwork {
const netConfig = upstream ? { url: upstream } : undefined;
switch (networkKey) {
case 'devnet':
const devHost = typeof window === 'undefined' ? '127.0.0.1' : 'localhost';
return new StacksMocknet({
url: 'http://127.0.0.1:3999',
url: `http://${devHost}:3999`,
});
case 'testnet':
return new StacksTestnet(netConfig);
Expand Down
25 changes: 13 additions & 12 deletions web/common/hooks/use-name-register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useAtomCallback } from 'jotai/utils';
import { hashFqn, randomSalt } from '@bns-x/core';
import { networkAtom } from '@store/micro-stacks';
import { contractsState } from '@store/index';
import { registerTxAtom, registerTxIdAtom } from '@store/register';
import { registrationTxAtom, registerTxIdAtom, nameBeingRegisteredAtom } from '@store/register';
import { getTxUrl } from '@common/utils';
import { useAccountOpenContractCall } from '@common/hooks/use-account-open-contract-call';
import { stxAddressAtom } from '@store/micro-stacks';
Expand All @@ -17,21 +17,22 @@ import {
import { toast } from 'sonner';

export function useNameRegister(name: string, namespace: string, price: bigint) {
const network = useAtomValue(networkAtom);
const stxAddress = useAtomValue(stxAddressAtom);
const { openContractCall, isRequestPending } = useAccountOpenContractCall();
const stxPostCondition = makeStandardSTXPostCondition(
stxAddress as string,
FungibleConditionCode.Equal,
price
);

const nameRegister = useAtomCallback(
React.useCallback(
async (get, set) => {
try {
const contracts = get(contractsState) as any; // TODO: fix typing: getting a possibly undefined error when pulling in nameRegistrar contract only
set(nameBeingRegisteredAtom, `${name}.${namespace}`);
const contracts = get(contractsState);
const nameRegistrar = contracts.nameRegistrar;
const network = get(networkAtom);
const stxAddress = get(stxAddressAtom);
const stxPostCondition = makeStandardSTXPostCondition(
stxAddress as string,
FungibleConditionCode.Equal,
price
);
await openContractCall({
...nameRegistrar.nameRegister({
name: asciiToBytes(name),
Expand All @@ -42,10 +43,10 @@ export function useNameRegister(name: string, namespace: string, price: bigint)
}),
postConditionMode: PostConditionMode.Deny,
postConditions: [stxPostCondition],
async onCancel() {
onCancel() {
console.log('Cancelled tx');
},
async onFinish(payload) {
onFinish(payload) {
const url = getTxUrl(payload.txId, network);
set(registerTxIdAtom, payload.txId);
toast('Transaction submitted', {
Expand All @@ -67,7 +68,7 @@ export function useNameRegister(name: string, namespace: string, price: bigint)

return {
nameRegister,
registerTxAtom,
registerTxIdAtom,
isRequestPending,
};
}
2 changes: 2 additions & 0 deletions web/common/store/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ export const nameIsPunyState = atom(get => {
});

export const nameInputAtom = atomWithDebounce('');

export const nameBeingRegisteredAtom = hashAtom('registrationName');
2 changes: 1 addition & 1 deletion web/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export function fqn(name: Name) {
export function getTxUrl(txId: string, network: StacksNetwork) {
const coreUrl = network.getCoreApiUrl();
const id = getTxId(txId);
if (coreUrl.includes('http://localhost')) {
if (coreUrl.includes('http://localhost') || coreUrl.includes('127.0.0.1')) {
return `http://localhost:8000/txid/${id}?chain=testnet`;
}
const chain = coreUrl.includes('testnet') ? 'testnet' : 'mainnet';
Expand Down
5 changes: 1 addition & 4 deletions web/components/icons/external-tx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import { getTxUrl } from '@common/utils';
import { ExternalLinkIcon } from './external-link';
import { useTxUrl } from '@common/hooks/use-tx-url';

export const ExternalTx: React.FC<{ txId?: string; btcTxId?: string }> = ({
txId = '',
btcTxId,
}) => {
export const ExternalTx: React.FC<{ txId?: string; btcTxId?: string }> = ({ txId = '' }) => {
const url = useTxUrl(txId);
if (typeof url === 'undefined') return null;
return <ExternalLinkIcon href={url} />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ import { useSwitchAccounts } from '@common/hooks/use-switch-accounts';
import { BnsNameRow } from '@components/bns-name-row';
import { Toaster } from 'sonner';
import { useDeepMemo } from '@common/hooks/use-deep-memo';
import { nameInputAtom, registrationNameState, registrationTxAtom } from '@store/register';
import {
nameInputAtom,
registerTxIdAtom,
registrationNameState,
registrationTxAtom,
} from '@store/register';
import { Text } from '@components/text';
import { Table, TableHeader, TableRow, TableHead, TableBody } from '@components/ui/table';
import { Link } from '@components/link';
import { RegisterNoName } from '@components/p/register/no-name';
import { RegistrationTx } from '@components/p/register/register-tx';

// TODO: success state
// const RegistrationTx: React.FC = () => {
Expand All @@ -30,14 +37,14 @@ import { Link } from '@components/link';
// }

export const Register: React.FC<{ children?: React.ReactNode }> = () => {
const { switchAccounts } = useSwitchAccounts();
const bnsNameValue = useAtomValue(nameInputAtom.currentValueAtom);
const setName = useSetAtom(nameInputAtom.debouncedValueAtom);
const transformedName = useAtomValue(registrationNameState);
const allNames = useAtomValue(currentUserAddressNameStringsState);
const availableNamespaces = useAtomValue(availableNamespacesState);
const v1Name = allNames.coreName;
const noNames = v1Name === null;
const registrationTxid = useAtomValue(registerTxIdAtom);
const registrationTx = useAtomValue(registrationTxAtom);

const emptyInput = bnsNameValue.length === 0;
Expand All @@ -60,7 +67,9 @@ export const Register: React.FC<{ children?: React.ReactNode }> = () => {
<>
<Box flexGrow={1} />
<div className="w-full space-y-6">
{noNames ? (
{registrationTxid ? (
<RegistrationTx />
) : noNames ? (
<>
<div className="space-y-10 text-center">
{/* <div className="max-w-lg mx-auto"> */}
Expand Down Expand Up @@ -102,23 +111,7 @@ export const Register: React.FC<{ children?: React.ReactNode }> = () => {
)}
</>
) : (
<div className="space-y-5 text-center">
<div className="flex flex-col gap-10 items-center">
<div>
<h1 className="text-gray-200 text-7xl font-open-sauce-one font-medium tracking-normal leading-10 max-w-lg">
Register your BNS name
</h1>
</div>
<p className="text-gray-200 text-sm font-inter font-normal tracking-normal leading-6 max-w-lg">
Looks like you registered {v1Name} for this account. Switch to an account that
doesn&apos;t own any names, or{' '}
<Link href="/upgrade">migrate your name to BNSx</Link>.
</p>
<Button className="w-60 text-md" size="lg" onClick={() => switchAccounts()}>
Switch accounts
</Button>
</div>
</div>
<RegisterNoName />
)}
</div>
<Box flexGrow={1} />
Expand Down
30 changes: 30 additions & 0 deletions web/components/p/register/no-name.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { currentUserAddressNameStringsState } from '@store/names';
import { useAtomValue } from 'jotai';
import { Button } from '@components/ui/button';
import { useSwitchAccounts } from '@common/hooks/use-switch-accounts';
import { Link } from '@components/link';

export const RegisterNoName: React.FC<{ children?: React.ReactNode }> = () => {
const { switchAccounts } = useSwitchAccounts();
const allNames = useAtomValue(currentUserAddressNameStringsState);
const v1Name = allNames.coreName;
return (
<div className="space-y-5 text-center">
<div className="flex flex-col gap-10 items-center">
<div>
<h1 className="text-gray-200 text-7xl font-open-sauce-one font-medium tracking-normal leading-10 max-w-lg">
Register your BNS name
</h1>
</div>
<p className="text-gray-200 text-sm font-inter font-normal tracking-normal leading-6 max-w-lg">
Looks like you registered {v1Name} for this account. Switch to an account that
doesn&apos;t own any names, or <Link href="/upgrade">migrate your name to BNSx</Link>.
</p>
<Button className="w-60 text-md" size="lg" onClick={() => switchAccounts()}>
Switch accounts
</Button>
</div>
</div>
);
};
29 changes: 29 additions & 0 deletions web/components/p/register/register-tx.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, { useMemo } from 'react';
import { useAtomValue } from 'jotai';
import { nameBeingRegisteredAtom, registerTxIdAtom, registrationTxAtom } from '@store/register';
import { Text } from '@components/text';
import { CenterBox } from '@components/layout';
import { DoneRow, PendingRow } from '@components/upgrade/rows';

export const RegistrationTx: React.FC<{ children?: React.ReactNode }> = () => {
const registrationTx = useAtomValue(registrationTxAtom);
const name = useAtomValue(nameBeingRegisteredAtom);
const pending = useMemo(() => {
if (typeof registrationTx?.tx_status === 'undefined') return true;
if (registrationTx.tx_status === 'pending') return true;
return false;
}, [registrationTx?.tx_status]);

if (registrationTx === null) return null;
return (
<div className="flex items-center w-full flex-col">
<CenterBox mt="20px" mb="30px">
{pending ? (
<PendingRow txidAtom={registerTxIdAtom}>Registering {name}</PendingRow>
) : (
<DoneRow txidAtom={registerTxIdAtom}>Registered {name}</DoneRow>
)}
</CenterBox>
</div>
);
};

0 comments on commit 140b3f0

Please sign in to comment.