Skip to content

Commit

Permalink
Merge pull request #5 from xdevguild/ui-rewrite
Browse files Browse the repository at this point in the history
Rewrite UI
  • Loading branch information
juliancwirko authored May 31, 2024
2 parents da94d1f + 104f4cb commit 7166d00
Show file tree
Hide file tree
Showing 190 changed files with 9,774 additions and 7,050 deletions.
5 changes: 4 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
"singleQuote": true,
"arrowParens": "always",
"trailingComma": "es5",
"endOfLine": "auto"
"endOfLine": "auto",
"plugins": [
"prettier-plugin-tailwindcss"
]
}
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
### [0.14.0](https://github.com/xdevguild/buildo.dev/releases/tag/v0.14.0) (2024-...)
- rebuild the UI. Each operation has separate page now

### [0.13.1](https://github.com/xdevguild/buildo.dev/releases/tag/v0.13.1) (2024-02-28)
- update useElven and implement required changes in code

Expand Down
162 changes: 162 additions & 0 deletions app/(operations)/components/add-burn-sft-meta-quantity.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
'use client';

import * as z from 'zod';
import {
BytesValue,
TypedValue,
ContractCallPayloadBuilder,
ContractFunction,
BigUIntValue,
} from '@multiversx/sdk-core';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Form } from '@/components/ui/form';
import { OperationsInputField } from '@/app/(operations)/components/operations-ui/operations-input-field';
import { OperationsSubmitButton } from '@/app/(operations)/components/operations-ui/operations-submit-button';
import { CommonOpertationContentProps } from '@/app/(operations)/components/operations-ui/operations-common-types';
import { OperationsRadioGroup } from '@/app/(operations)/components/operations-ui/operations-radio-group';
import BigNumber from 'bignumber.js';
import { useAccount, useConfig, useTransaction } from '@useelven/core';
import axios from 'axios';
import { specialOpertationsGasLimit } from '@/app/(operations)/components/operations-ui/constants';
import { useTxStatus } from '@/hooks/use-tx-status';
import { OperationInfoBox } from './operations-ui/operation-info-box';

const formSchema = z.object({
tokenId: z.string().min(1, 'The field is required'),
quantity: z
.string()
.refine(
(value) => !new BigNumber(value).isNaN(),
'Required BigNumber string.'
),
type: z.enum(['add', 'burn'], {
required_error: 'Please choose the type of the operation (add/burn)',
}),
});

export const AddBurnQuantity = ({
tokenType,
}: {
tokenType: CommonOpertationContentProps['tokenType'];
}) => {
const { triggerTx, error, txResult, transaction, pending } = useTransaction();
const { address } = useAccount();
const { apiAddress } = useConfig();

const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
tokenId: '',
quantity: '',
type: 'add',
},
});

useTxStatus({
successHash: txResult?.hash,
pendingHash: transaction?.getHash()?.toString(),
error,
pending,
});

const onSubmit = async ({
tokenId,
quantity,
type,
}: z.infer<typeof formSchema>) => {
try {
// TODO: replace with useElven useApiCall when ready to handle such cases
const tokenOnNetwork = await axios.get<{
nonce: number;
collection: string;
}>(`${apiAddress}/nfts/${tokenId.trim()}`, {
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
});

const nonce = tokenOnNetwork?.data?.nonce;
const collectionId = tokenOnNetwork?.data?.collection;

// TODO: show the error in the transaction status modal
if (!nonce || !collectionId) {
console.error(
"Can't read the nonce or/and collection id of the token, using MultiversX API!"
);
return;
}

const args: TypedValue[] = [
BytesValue.fromUTF8(collectionId.trim()),
new BigUIntValue(new BigNumber(nonce)),
new BigUIntValue(new BigNumber(quantity.trim())),
];

// TODO: replace ContractCallPayloadBuilder
const data = new ContractCallPayloadBuilder()
.setFunction(
new ContractFunction(
type === 'add' ? 'ESDTNFTAddQuantity' : 'ESDTNFTBurn'
)
)
.setArgs(args)
.build();

triggerTx?.({
address,
gasLimit: specialOpertationsGasLimit,
data,
value: 0,
});
} catch (e) {
console.error(
"Can't read the nonce or/and collection id of the token, using MultiversX API!",
e
);
}
};

return (
<>
<OperationInfoBox error={error} txResult={txResult} />
<Form {...form}>
<form
id="add-burn-form"
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8"
>
<div className="flex-1 overflow-auto p-1">
<OperationsRadioGroup
items={[
{ name: 'add', description: 'Add the quantity' },
{ name: 'burn', description: 'Reduce the quantity' },
]}
name="type"
label="Operation type"
description="Please choose the type of the operation. Add or Burn."
/>
<OperationsInputField
name="tokenId"
label="Token id"
placeholder="Example: MyToken-23432-01"
description="Please provide your token id"
/>
<OperationsInputField
name="quantity"
label="Quantity"
placeholder="Example: 10000"
description={
tokenType === 'semi-fungible'
? 'Please provide the quantity.'
: 'Please provide the supply (remember to take into consideration the number of decimals. For example 100.5 with 2 decimal places will be 10050).'
}
/>
</div>
<OperationsSubmitButton formId="add-burn-form" />
</form>
</Form>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use client';

import * as z from 'zod';
import {
BytesValue,
Expand All @@ -8,27 +10,23 @@ import {
import { useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { Form } from '@/components/ui/form';
import {
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import {
esdtTokenProperties,
sftNftTokenProperties,
commonOpertationsGasLimit,
builtInSC,
TokenPropertyOrRole,
} from '@/components/operations/constants';
import { OperationsCheckboxGroup } from '@/components/operations/operations-checkbox-group';
import { OperationsSubmitButton } from '@/components/operations/operations-submit-button';
import { useContext, useEffect } from 'react';
import { OperationsStateDialogContext } from '@/components/operations/operations-status-dialog';
import { CommonOpertationContentProps } from '@/components/operations/operations-common-types';
import { OperationsSelectField } from '@/components/operations/operations-select-field';
} from '@/app/(operations)/components/operations-ui/constants';
import { OperationsCheckboxGroup } from '@/app/(operations)/components/operations-ui/operations-checkbox-group';
import { OperationsSubmitButton } from '@/app/(operations)/components/operations-ui/operations-submit-button';
import { useEffect } from 'react';
import { CommonOpertationContentProps } from '@/app/(operations)/components/operations-ui/operations-common-types';
import { OperationsSelectField } from '@/app/(operations)/components/operations-ui/operations-select-field';
import { useCreatorTokens } from '@/hooks/use-creator-tokens';
import { getTokenIdKey } from '@/lib/get-token-id';
import { useTransaction } from '@useelven/core';
import { OperationInfoBox } from './operations-ui/operation-info-box';
import { useTxStatus } from '@/hooks/use-tx-status';

const formSchema = z.object({
tokenId: z.string().min(1, 'The field is required'),
Expand All @@ -51,13 +49,11 @@ const propertiesMap: Record<
};

export const ChangeProperties = ({
triggerTx,
close,
tokenType,
}: CommonOpertationContentProps) => {
const { setOpen: setTxStatusDialogOpen } = useContext(
OperationsStateDialogContext
);
}: {
tokenType: CommonOpertationContentProps['tokenType'];
}) => {
const { triggerTx, error, txResult, transaction, pending } = useTransaction();

const { tokens } = useCreatorTokens<CreatorTokens>({
tokenType,
Expand All @@ -71,6 +67,13 @@ export const ChangeProperties = ({
},
});

useTxStatus({
successHash: txResult?.hash,
pendingHash: transaction?.getHash()?.toString(),
error,
pending,
});

const watchTokenId = useWatch({ control: form.control, name: 'tokenId' });

const onSubmit = ({ tokenId, properties }: z.infer<typeof formSchema>) => {
Expand All @@ -87,6 +90,7 @@ export const ChangeProperties = ({
args.push(BytesValue.fromUTF8(propertyEnabled.toString()));
}

// TODO: replace ContractCallPayloadBuilder
const data = new ContractCallPayloadBuilder()
.setFunction(new ContractFunction('controlChanges'))
.setArgs(args)
Expand All @@ -98,10 +102,6 @@ export const ChangeProperties = ({
data,
value: 0,
});

setTxStatusDialogOpen(true);
form.reset();
close();
};

useEffect(() => {
Expand All @@ -125,48 +125,45 @@ export const ChangeProperties = ({

return (
<>
<DialogHeader className="p-8 pb-0">
<DialogTitle>Change properties of a {tokenType} ESDT</DialogTitle>
<DialogDescription>
The manager of an ESDT token may individually change any of the
properties of the token, or multiple properties at once. The token
should have the canUpgrade property set to true.
</DialogDescription>
</DialogHeader>
<div className="overflow-y-auto py-0 px-8">
<Form {...form}>
<form
id="change-properties-form"
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8"
>
<div className="flex-1 overflow-auto p-1">
<OperationsSelectField
name="tokenId"
label="Token id"
description="Please provide your token id"
options={
tokens
? tokens?.map((token) => ({
<OperationInfoBox error={error} txResult={txResult} />
<Form {...form}>
<form
id="change-properties-form"
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8"
>
<div className="flex-1 overflow-auto p-1">
<OperationsSelectField
name="tokenId"
label="Token id"
description="Please provide your token id"
options={
tokens
? tokens
?.sort((a, b) => {
const aTokenId = a[getTokenIdKey(tokenType)];
const bTokenId = b[getTokenIdKey(tokenType)];
if (aTokenId < bTokenId) return -1;
if (aTokenId > bTokenId) return 1;
return 0;
})
.map((token) => ({
value: token[getTokenIdKey(tokenType)],
label: token[getTokenIdKey(tokenType)],
}))
: []
}
/>
<OperationsCheckboxGroup
items={propertiesMap[tokenType]}
name="properties"
label="Token properties"
description="Set new properties set for the ESDT token."
/>
</div>
</form>
</Form>
</div>
<DialogFooter className="py-4 px-8">
<OperationsSubmitButton formId="change-properties-form" />
</DialogFooter>
: []
}
/>
<OperationsCheckboxGroup
items={propertiesMap[tokenType]}
name="properties"
label="Token properties"
description="Set new properties set for the ESDT token."
/>
</div>
<OperationsSubmitButton formId="change-properties-form" />
</form>
</Form>
</>
);
};
Loading

0 comments on commit 7166d00

Please sign in to comment.