From bda613f89b3c99ae6d4ba608bb4024753b90aab9 Mon Sep 17 00:00:00 2001
From: PLANKTON <68655454+kieled@users.noreply.github.com>
Date: Sun, 18 Aug 2024 03:06:26 +0300
Subject: [PATCH] 0.2.6 | Custom HD path (#100)
* fix send for many utxos
* fix , refactoring, redesign
* styles
* fix bug with loading trasactions, better styles, clear transactions on create new wallet
* update version
---
package.json | 2 +-
.../controllers/provider/controller.ts | 1 +
src/shared/constant/index.ts | 14 +-
src/shared/locales/languages/en.json | 14 +-
src/shared/utils/transactions.ts | 78 ++----
.../inscription-card/components.tsx | 4 +-
src/ui/components/layout/component.tsx | 224 +++++++++---------
src/ui/components/select-hint/component.tsx | 18 +-
src/ui/components/select/component.tsx | 34 ++-
.../settings-layout/styles.module.scss | 2 +-
.../switch-address-type/component.tsx | 17 +-
.../switch-address-type/styles.module.scss | 2 +-
src/ui/components/switch/component.tsx | 26 +-
src/ui/components/switch/styles.module.scss | 9 +
src/ui/components/tile/component.tsx | 40 +++-
src/ui/components/tile/styles.module.scss | 36 ++-
src/ui/hooks/transactions.ts | 16 +-
src/ui/hooks/wallet.ts | 6 +-
src/ui/index.global.scss | 6 +-
.../inscription-details/components.tsx | 28 ++-
src/ui/pages/main/new-wallet/component.tsx | 5 -
.../new-wallet/new-mnemonic/component.tsx | 6 +-
.../restore-mnemonic-ordinals/component.tsx | 113 ---------
.../styles.module.scss | 27 ---
.../new-wallet/restore-mnemonic/component.tsx | 95 ++++++--
.../restore-mnemonic/styles.module.scss | 6 +-
.../new-wallet/restore-priv-key/component.tsx | 1 -
.../pages/main/new-wallet/styles.module.scss | 4 +-
.../main/settings/change-addr-type/index.ts | 1 -
src/ui/pages/main/settings/component.tsx | 10 +-
.../main/settings/language/component.tsx | 34 +--
.../main/settings/language/styles.module.scss | 10 +-
.../change-addr-type/component.tsx | 3 +-
.../wallet/change-addr-type}/index.ts | 0
.../change-addr-type/styles.module.scss | 0
.../pages/main/settings/wallet/component.tsx | 12 +-
.../settings/wallet/network/component.tsx | 18 +-
.../wallet/network/styles.module.scss | 2 +-
src/ui/pages/main/switch-wallet/component.tsx | 9 +-
.../pages/main/transaction-info/component.tsx | 53 ++---
.../main/transaction-info/styles.module.scss | 15 +-
src/ui/pages/main/wallet/styles.module.scss | 2 +-
.../wallet/transactions-list/component.tsx | 26 +-
src/ui/pages/router.tsx | 12 +-
src/ui/utils/index.ts | 30 +--
src/ui/utils/tx-ctx.tsx | 18 +-
tailwind.config.js | 2 +-
47 files changed, 510 insertions(+), 581 deletions(-)
create mode 100644 src/ui/components/switch/styles.module.scss
delete mode 100644 src/ui/pages/main/new-wallet/restore-mnemonic-ordinals/component.tsx
delete mode 100644 src/ui/pages/main/new-wallet/restore-mnemonic-ordinals/styles.module.scss
delete mode 100644 src/ui/pages/main/settings/change-addr-type/index.ts
rename src/ui/pages/main/settings/{ => wallet}/change-addr-type/component.tsx (93%)
rename src/ui/pages/main/{new-wallet/restore-mnemonic-ordinals => settings/wallet/change-addr-type}/index.ts (100%)
rename src/ui/pages/main/settings/{ => wallet}/change-addr-type/styles.module.scss (100%)
diff --git a/package.json b/package.json
index 4ac0430b..8c7db40b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "nintondo-extension",
- "version": "0.2.5.5",
+ "version": "0.2.6",
"private": true,
"scripts": {
"dev": "bun build.ts --watch",
diff --git a/src/background/controllers/provider/controller.ts b/src/background/controllers/provider/controller.ts
index 003233c2..406afb0d 100644
--- a/src/background/controllers/provider/controller.ts
+++ b/src/background/controllers/provider/controller.ts
@@ -22,6 +22,7 @@ type Payload
= {
approvalRes?: any;
};
+// @ts-ignore
class ProviderController implements IProviderController {
connect = async () => {
if (
diff --git a/src/shared/constant/index.ts b/src/shared/constant/index.ts
index a588515d..381bd952 100644
--- a/src/shared/constant/index.ts
+++ b/src/shared/constant/index.ts
@@ -24,18 +24,18 @@ export const ADDRESS_TYPES: {
name: string;
hdPath: string;
}[] = [
- {
- value: AddressType.P2PKH,
- label: "P2PKH",
- name: "Legacy (P2PKH)",
- hdPath: "m/44'/0'/0'/0",
- },
{
value: AddressType.P2WPKH,
label: "P2WPKH",
name: "Native Segwit (P2WPKH)",
hdPath: "m/84'/0'/0'/0",
},
+ {
+ value: AddressType.P2PKH,
+ label: "P2PKH",
+ name: "Legacy (P2PKH)",
+ hdPath: "m/44'/0'/0'/0",
+ },
{
value: AddressType.P2TR,
label: "P2TR",
@@ -95,3 +95,5 @@ export const DEFAULT_FEES = {
};
export const DEFAULT_SERVICE_FEE = 1_000_000;
+
+export const DEFAULT_HD_PATH = "m/44'/0'/0'/0";
diff --git a/src/shared/locales/languages/en.json b/src/shared/locales/languages/en.json
index 3cdc7a72..dad96143 100644
--- a/src/shared/locales/languages/en.json
+++ b/src/shared/locales/languages/en.json
@@ -115,7 +115,6 @@
"new_wallet": {
"new_mnemonic_label": "New mnemonic",
"restore_mnemonic_label": "Restore mnemonic",
- "restore_ordinals_label": "Restore ordinals mnemonic",
"restore_from_private_key_label": "Restore from private key",
"restore_from_label": "Restore from",
"step_1": "Step 1",
@@ -136,7 +135,8 @@
"private_key": "Private key",
"recover": "Recover",
"invalid_private_key_error": "Invalid private key"
- }
+ },
+ "hd_path": "Hd path"
},
"receive": {
"click_to_copy": "Click to copy",
@@ -211,20 +211,22 @@
},
"transaction_info": {
"txid": "TxId",
- "confirmations_label": "Confirmations:",
+ "confirmations_label": "Confirmations",
"fee_label": "Fee",
- "value_label": "Value:",
+ "value_label": "Value",
"open_in_explorer": "Open in explorer",
"copied": "Copied",
"inputs": "Inputs",
"outputs": "Outputs",
- "details": "Details"
+ "details": "Details",
+ "your_address": "You"
},
"hooks": {
"transaction": {
"insufficient_balance_0": "Insufficient balance. Non-Inscription balance",
"insufficient_balance_1": "BEL) is lower than",
- "insufficient_balance_2": "BEL"
+ "insufficient_balance_2": "BEL",
+ "too_many_utxos": "Too many UTXOs. You must consolidate them in order to send"
},
"wallet": {
"last_wallet_error": "You cannot delete your last wallet"
diff --git a/src/shared/utils/transactions.ts b/src/shared/utils/transactions.ts
index 69f7276f..e21d6b1b 100644
--- a/src/shared/utils/transactions.ts
+++ b/src/shared/utils/transactions.ts
@@ -3,80 +3,38 @@ import { payments } from "belcoinjs-lib";
import Big from "big.js";
import { AddressType } from "bellhdw/src/hd/types";
-export enum TxDirection {
- out = 0,
- in = 1,
-}
-
-export const getTxDirection = (
- transaction: ITransaction,
- targetAddress: string
-): TxDirection => {
- const includesIn = transaction.vin
- .map((i) => i.prevout?.scriptpubkey_address)
- .includes(targetAddress);
-
- if (includesIn) {
- return TxDirection.out;
- }
- return TxDirection.in;
-};
-
export const getTransactionValue = (
transaction: ITransaction,
targetAddress: string,
fixed: number = 2
) => {
- const direction = getTxDirection(transaction, targetAddress);
- let value: number;
- switch (direction) {
- case TxDirection.in:
- value =
- transaction.vout.reduce(
- (acc, cur) =>
- cur.scriptpubkey_address === targetAddress ? acc + cur.value : acc,
- 0
- ) /
- 10 ** 8;
- break;
- case TxDirection.out:
- value =
- (transaction.vin.reduce(
- (acc, cur) =>
- cur.prevout?.scriptpubkey_address === targetAddress
- ? acc - cur.prevout?.value
- : acc,
- 0
- ) +
- transaction.vout.reduce(
- (acc, cur) =>
- cur.scriptpubkey_address === targetAddress
- ? cur.value + acc
- : acc,
- 0
- )) /
- 10 ** 8;
- break;
- }
+ const outputsSum = transaction.vout
+ .filter((i) => i.scriptpubkey_address === targetAddress)
+ .reduce((acc, cur) => acc + cur.value, 0);
+ const inputsSum = transaction.vin
+ .filter((i) => i.prevout?.scriptpubkey_address === targetAddress)
+ .reduce((acc, cur) => acc + cur.prevout!.value, 0);
- // return value;
+ const value = Math.abs(outputsSum - inputsSum) / 10 ** 8;
- if (typeof fixed !== "undefined") {
- if (value < 100) {
- return Math.abs(value).toFixed(fixed + 1);
- }
- return Math.abs(value).toFixed(fixed);
+ if (value < 1) return parseFloat(value.toFixed(5)).toString();
+ if (value < 100) {
+ return value.toFixed(fixed + 1);
}
-
- return Math.abs(value);
+ return value.toFixed(fixed);
};
export const isIncomeTx = (
transaction: ITransaction,
targetAddress: string
) => {
- const direction = getTxDirection(transaction, targetAddress);
- return direction === TxDirection.in;
+ const outputsSum = transaction.vout
+ .filter((i) => i.scriptpubkey_address === targetAddress)
+ .reduce((acc, cur) => acc + cur.value, 0);
+ const inputsSum = transaction.vin
+ .filter((i) => i.prevout?.scriptpubkey_address === targetAddress)
+ .reduce((acc, cur) => acc + cur.prevout!.value, 0);
+ return outputsSum - inputsSum > 0;
};
export const getScriptForAddress = (
diff --git a/src/ui/components/inscription-card/components.tsx b/src/ui/components/inscription-card/components.tsx
index bf07e4c3..4975f86b 100644
--- a/src/ui/components/inscription-card/components.tsx
+++ b/src/ui/components/inscription-card/components.tsx
@@ -40,7 +40,9 @@ const InscriptionCard: FC = ({ inscriptionId }) => {
{
- navigate("/pages/inscription-details", { state: inscriptionId });
+ navigate("/pages/inscription-details", {
+ state: { inscription_id: inscriptionId },
+ });
}}
>
diff --git a/src/ui/components/layout/component.tsx b/src/ui/components/layout/component.tsx
index da01e34b..6634e525 100644
--- a/src/ui/components/layout/component.tsx
+++ b/src/ui/components/layout/component.tsx
@@ -4,7 +4,7 @@ import cn from "classnames";
import {
ChevronLeftIcon,
PlusCircleIcon,
- ArrowsUpDownIcon
+ ArrowsUpDownIcon,
} from "@heroicons/react/24/outline";
import { useMemo } from "react";
import { useGetCurrentAccount, useWalletState } from "@/ui/states/walletState";
@@ -36,106 +36,103 @@ export default function PagesLayout() {
const currentAccount = useGetCurrentAccount();
const defaultTitles = useMemo(
- () => [
- {
- route: "/pages/change-addr-type",
- title: t("components.layout.change_address_type"),
- },
- {
- route: "/pages/create-new-account",
- title: t("components.layout.create_new_account"),
- },
- {
- route: "/pages/change-password",
- title: t("components.layout.change_password"),
- },
- {
- backAction: () => {
- navigate("/home");
+ () =>
+ [
+ {
+ route: "/pages/change-addr-type",
+ title: t("components.layout.change_address_type"),
},
- route: "/pages/finalle-send/@",
- title: t("components.layout.send"),
- },
- {
- route: "/pages/security",
- title: t("components.layout.security"),
- },
- {
- route: "/pages/receive",
- title: currentAccount?.name ?? "Account",
- },
- {
- route: "/pages/switch-wallet",
- title: t("components.layout.switch_wallet"),
- action: {
- icon:
,
- link: "/pages/create-new-wallet",
+ {
+ route: "/pages/create-new-account",
+ title: t("components.layout.create_new_account"),
},
- },
- {
- route: "/pages/restore-mnemonic",
- title: t("components.layout.restore_from_mnemonic"),
- },
- {
- route: "/pages/restore-ordinals",
- title: t("components.layout.restore_from_mnemonic"),
- },
- {
- route: "/pages/restore-priv-key",
- title: t("components.layout.restore_from_private_key"),
- },
- {
- route: "/pages/send",
- title: t("components.layout.send"),
- },
- {
- route: "/pages/transaction-info/@",
- title: t("components.layout.transaction_info"),
- },
- {
- route: "/pages/settings",
- title: t("components.layout.settings"),
- },
- {
- route: "/pages/advanced",
- title: t("components.layout.advanced"),
- },
- {
- route: "/pages/show-mnemonic/@",
- title: t("components.layout.show_mnemonic"),
- },
- {
- route: "/pages/show-pk/@",
- title: t("components.layout.show_private_key"),
- },
- {
- route: "/pages/discover",
- title: t("components.layout.discover"),
- },
- {
- route: "/pages/connected-sites",
- title: t("components.layout.connected_sites"),
- },
- {
- route: "/pages/language",
- title: t("components.layout.change_language"),
- },
- {
- route: "/pages/wallet-settings",
- title: t("components.layout.wallet_settings"),
- },
- {
- route: "/pages/network-settings",
- title: t("components.layout.network_settings"),
- },
- {
- route: "/pages/create-send",
- title: t("components.layout.send"),
- backAction: () => {
- navigate("/home");
+ {
+ route: "/pages/change-password",
+ title: t("components.layout.change_password"),
+ },
+ {
+ backAction: () => {
+ navigate("/home");
+ },
+ route: "/pages/finalle-send/@",
+ title: t("components.layout.send"),
+ },
+ {
+ route: "/pages/security",
+ title: t("components.layout.security"),
+ },
+ {
+ route: "/pages/receive",
+ title: currentAccount?.name ?? "Account",
+ },
+ {
+ route: "/pages/switch-wallet",
+ title: t("components.layout.switch_wallet"),
+ action: {
+ icon:
,
+ link: "/pages/create-new-wallet",
+ },
},
- },
- ] as IRouteTitle[],
+ {
+ route: "/pages/restore-mnemonic",
+ title: t("components.layout.restore_from_mnemonic"),
+ },
+ {
+ route: "/pages/restore-priv-key",
+ title: t("components.layout.restore_from_private_key"),
+ },
+ {
+ route: "/pages/send",
+ title: t("components.layout.send"),
+ },
+ {
+ route: "/pages/transaction-info/@",
+ title: t("components.layout.transaction_info"),
+ },
+ {
+ route: "/pages/settings",
+ title: t("components.layout.settings"),
+ },
+ {
+ route: "/pages/advanced",
+ title: t("components.layout.advanced"),
+ },
+ {
+ route: "/pages/show-mnemonic/@",
+ title: t("components.layout.show_mnemonic"),
+ },
+ {
+ route: "/pages/show-pk/@",
+ title: t("components.layout.show_private_key"),
+ },
+ {
+ route: "/pages/discover",
+ title: t("components.layout.discover"),
+ },
+ {
+ route: "/pages/connected-sites",
+ title: t("components.layout.connected_sites"),
+ },
+ {
+ route: "/pages/language",
+ title: t("components.layout.change_language"),
+ },
+ {
+ route: "/pages/wallet-settings",
+ title: t("components.layout.wallet_settings"),
+ },
+ {
+ route: "/pages/network-settings",
+ title: t("components.layout.network_settings"),
+ },
+ {
+ route: "/pages/create-send",
+ title: t("components.layout.send"),
+ backAction: () => {
+ navigate("/home");
+ },
+ },
+ ] as IRouteTitle[],
[currentAccount?.name, navigate]
);
@@ -171,7 +168,7 @@ export default function PagesLayout() {
route: "/pages/inscription-details",
title:
t("inscription_details.title") +
- ` #${currentRoute.state?.inscription_number}`,
+ ` #${currentRoute.state?.inscription_number ?? ""}`,
},
{
route: "/pages/switch-account",
@@ -191,16 +188,25 @@ export default function PagesLayout() {
},
{
route: /\/pages\/(inscriptions|bel-20)/,
- title:
{
- if (currentRoute.pathname === "/pages/inscriptions") {
- navigate("/pages/bel-20");
- } else {
- navigate("/pages/inscriptions");
- }
- }}>
-
{currentRoute.pathname === "/pages/inscriptions" ? "Inscriptions" : "BEL-20"}
-
-
,
+ title: (
+
{
+ if (currentRoute.pathname === "/pages/inscriptions") {
+ navigate("/pages/bel-20");
+ } else {
+ navigate("/pages/inscriptions");
+ }
+ }}
+ >
+
+ {currentRoute.pathname === "/pages/inscriptions"
+ ? "Inscriptions"
+ : "BEL-20"}
+
+
+
+ ),
action: {
icon:
,
},
diff --git a/src/ui/components/select-hint/component.tsx b/src/ui/components/select-hint/component.tsx
index e700a19f..be3d5d9f 100644
--- a/src/ui/components/select-hint/component.tsx
+++ b/src/ui/components/select-hint/component.tsx
@@ -1,4 +1,10 @@
-import { Combobox, Transition } from "@headlessui/react";
+import {
+ Combobox,
+ ComboboxInput,
+ ComboboxOption,
+ ComboboxOptions,
+ Transition,
+} from "@headlessui/react";
import { FC, Fragment, useEffect, useState } from "react";
import englishWords from "nintondo-bip39/src/wordlists/english.json";
import cn from "classnames";
@@ -54,7 +60,7 @@ const SelectWithHint: FC
= ({ selected, setSelected }) => {
-
= ({ selected, setSelected }) => {
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
-
+
{filtered.length === 0 && query !== "" ? (
<>>
) : (
filtered.map((word) => (
-
cn(s.options, { [s.optionsActive]: active })
@@ -94,10 +100,10 @@ const SelectWithHint: FC = ({ selected, setSelected }) => {
>
)}
-
+
))
)}
-
+
diff --git a/src/ui/components/select/component.tsx b/src/ui/components/select/component.tsx
index 8ad31b3e..5e6caa04 100644
--- a/src/ui/components/select/component.tsx
+++ b/src/ui/components/select/component.tsx
@@ -1,4 +1,10 @@
-import { Listbox, Transition } from "@headlessui/react";
+import {
+ Listbox,
+ ListboxButton,
+ ListboxOption,
+ ListboxOptions,
+ Transition,
+} from "@headlessui/react";
import { ChevronUpDownIcon, CheckIcon } from "@heroicons/react/24/outline";
import { Fragment } from "react";
@@ -9,6 +15,7 @@ interface Props
{
label?: string;
displayCheckIcon?: boolean;
className?: string;
+ anchor?: "bottom" | "top";
}
const Select = ({
@@ -18,15 +25,16 @@ const Select = ({
label,
displayCheckIcon = true,
className,
+ anchor,
}: Props) => {
return (
-
+
{label !== undefined ? (
) : undefined}
-
+
{selected.name}
({
aria-hidden="true"
/>
-
+
-
+
{values.map((value, valueIdx) => (
-
`relative cursor-default select-none py-2 ${
active ? "bg-input-bg text-text" : "text-text"
- } ${
- displayCheckIcon ? "pl-10 pr-4" : "flex justify-center"
- }`
+ } ${displayCheckIcon ? "pl-4 pr-4" : "flex justify-center"}`
}
value={value}
>
@@ -70,9 +82,9 @@ const Select = ({
) : null}
>
)}
-
+
))}
-
+
diff --git a/src/ui/components/settings-layout/styles.module.scss b/src/ui/components/settings-layout/styles.module.scss
index 295674ae..ca93c55a 100644
--- a/src/ui/components/settings-layout/styles.module.scss
+++ b/src/ui/components/settings-layout/styles.module.scss
@@ -1,5 +1,5 @@
.settings {
- @apply w-full grid grid-cols-2 grid-rows-2;
+ @apply w-full flex flex-col gap-3;
}
.wrapper {
diff --git a/src/ui/components/switch-address-type/component.tsx b/src/ui/components/switch-address-type/component.tsx
index 9a47d6dc..5f49ed38 100644
--- a/src/ui/components/switch-address-type/component.tsx
+++ b/src/ui/components/switch-address-type/component.tsx
@@ -1,8 +1,8 @@
import s from "./styles.module.scss";
import { ADDRESS_TYPES } from "@/shared/constant";
import { FC } from "react";
-import cn from "classnames";
import { AddressType } from "bellhdw";
+import Tile from "../tile";
interface Props {
handler: (type: AddressType) => void;
@@ -13,18 +13,13 @@ const SwitchAddressType: FC
= ({ handler, selectedType }) => {
return (
{ADDRESS_TYPES.map((i) => (
-
handler(i.value)}
- >
-
-
{i.name.replace(/ \(.*\)$/, "")}
-
{i.label}
-
-
+ selected={selectedType === i.value}
+ />
))}
);
diff --git a/src/ui/components/switch-address-type/styles.module.scss b/src/ui/components/switch-address-type/styles.module.scss
index d09ca07b..4b2436b6 100644
--- a/src/ui/components/switch-address-type/styles.module.scss
+++ b/src/ui/components/switch-address-type/styles.module.scss
@@ -1,5 +1,5 @@
.allTypes {
- @apply w-full h-full grid grid-rows-2 grid-cols-2 gap-3 pt-8 max-h-60;
+ @apply w-full flex flex-col gap-3 pt-8;
}
.addressType {
diff --git a/src/ui/components/switch/component.tsx b/src/ui/components/switch/component.tsx
index 0b93c57e..92535058 100644
--- a/src/ui/components/switch/component.tsx
+++ b/src/ui/components/switch/component.tsx
@@ -1,6 +1,7 @@
-import { Switch } from "@headlessui/react";
+import { Field, Label, Switch } from "@headlessui/react";
import { FC } from "react";
import cn from "classnames";
+import s from "./styles.module.scss";
interface Props {
locked?: boolean;
@@ -8,6 +9,7 @@ interface Props {
onChange: (value: boolean) => void;
label: string;
className?: string;
+ disabled?: boolean;
}
const SwitchComponent: FC = ({
@@ -16,34 +18,40 @@ const SwitchComponent: FC = ({
value,
label,
className,
+ disabled,
}) => {
return (
-
+
{
if (locked) return;
onChange(v);
}}
- className={`${value ? "bg-orange-600" : "bg-gray-500"}
- relative inline-flex h-6 w-12 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75`}
+ className={cn(
+ { "bg-orange-600": value, "bg-gray-500": !value },
+ s.switch
+ )}
>
-
+
+
-
+
);
};
diff --git a/src/ui/components/switch/styles.module.scss b/src/ui/components/switch/styles.module.scss
new file mode 100644
index 00000000..9fdcf5cf
--- /dev/null
+++ b/src/ui/components/switch/styles.module.scss
@@ -0,0 +1,9 @@
+.switch {
+ @apply relative inline-flex h-6 w-12 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors
+ duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75
+ disabled:opacity-50;
+}
+
+.toggle {
+ @apply pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out;
+}
diff --git a/src/ui/components/tile/component.tsx b/src/ui/components/tile/component.tsx
index 17d8a547..11f0c05c 100644
--- a/src/ui/components/tile/component.tsx
+++ b/src/ui/components/tile/component.tsx
@@ -8,23 +8,47 @@ export interface TileProps {
onClick?: () => void;
label: string;
link?: string;
- icon: React.ReactNode;
+ description?: string;
+ icon?: React.ReactNode;
+ selected?: boolean;
}
-const Tile: FC = ({ label, className, link, onClick, icon }) => {
+const Tile: FC = ({
+ label,
+ className,
+ link,
+ onClick,
+ icon,
+ description,
+ selected,
+}) => {
+ const content = (
+ <>
+ {icon && {icon}
}
+
+
{label}
+ {description &&
{description}
}
+
+ >
+ );
+
if (!link && onClick) {
return (
-
- {icon}
-
{label}
+
+ {content}
);
}
return (
-
- {icon}
-
{label}
+
+ {content}
);
};
diff --git a/src/ui/components/tile/styles.module.scss b/src/ui/components/tile/styles.module.scss
index 02ada70c..73726fa1 100644
--- a/src/ui/components/tile/styles.module.scss
+++ b/src/ui/components/tile/styles.module.scss
@@ -1,21 +1,35 @@
.card {
- @apply cursor-pointer h-28 flex items-center justify-center flex-col gap-4 px-3 odd:border-r border-b even:border-l last:border-b-0 border-neutral-800;
-
- &:nth-last-child(2) {
- @apply border-b-0;
- }
+ @apply cursor-pointer flex items-center gap-4 px-3 border rounded-xl bg-neutral-950 border-neutral-800 transition-colors text-lg py-3;
&:hover {
- > * {
- @apply scale-110;
+ @apply bg-neutral-900 border-orange-400/50;
+
+ .iconContainer {
+ @apply bg-orange-400/90 text-black;
}
}
+}
- > div {
- @apply text-xs text-center font-medium;
- }
+.label {
+ @apply text-sm font-medium;
+}
+
+.description {
+ @apply text-xs text-neutral-500;
+}
+
+.content {
+ @apply flex gap-1.5 flex-col;
+}
+
+.iconContainer {
+ @apply bg-neutral-900 rounded-lg p-1;
> * {
- @apply transition-transform;
+ @apply p-1;
}
}
+
+.selected {
+ @apply bg-orange-400/5 border-orange-400;
+}
diff --git a/src/ui/hooks/transactions.ts b/src/ui/hooks/transactions.ts
index e2e243c9..5c3a139b 100644
--- a/src/ui/hooks/transactions.ts
+++ b/src/ui/hooks/transactions.ts
@@ -34,10 +34,22 @@ export function useCreateBellsTxCallback() {
)
throw new Error("Failed to get current wallet or account");
const fromAddress = currentAccount.address;
- const utxos = await apiController.getUtxos(fromAddress, {
- amount: toAmount,
+ let utxos = await apiController.getUtxos(fromAddress, {
+ amount:
+ toAmount + (receiverToPayFee ? 0 : gptFeeCalculate(2, 2, feeRate)),
});
+
+ if ((utxos?.length ?? 0) > 5) {
+ utxos = await apiController.getUtxos(fromAddress, {
+ amount: toAmount + gptFeeCalculate(1 + utxos!.length, 2, feeRate),
+ });
+ }
+
if (!utxos) return;
+
+ if (utxos.length > 1000)
+ throw new Error(t("hooks.transaction.too_many_utxos"));
+
const safeBalance = (utxos ?? []).reduce((pre, cur) => pre + cur.value, 0);
if (safeBalance < toAmount) {
throw new Error(
diff --git a/src/ui/hooks/wallet.ts b/src/ui/hooks/wallet.ts
index fc0dcee6..cf5d6254 100644
--- a/src/ui/hooks/wallet.ts
+++ b/src/ui/hooks/wallet.ts
@@ -48,12 +48,12 @@ export const useCreateNewWallet = () => {
);
const clearSelected = useClearSelectedAccountStats();
const navigate = useNavigate();
+ const { clearTransactions } = useTransactionManagerContext();
return async (props: INewWalletProps) => {
const wallet = await walletController.createNewWallet(props);
const keyring = await keyringController.serializeKeyringById(wallet.id);
- let newWallets = [...wallets, wallet];
- newWallets = (await clearSelected(newWallets))!;
+ let newWallets = (await clearSelected([...wallets, wallet]))!;
await walletController.saveWallets({
phrases: [{ id: wallet.id, phrase: props.payload, data: keyring }],
@@ -64,7 +64,9 @@ export const useCreateNewWallet = () => {
wallets: newWallets,
selectedAccount: 0,
selectedWallet: newWallets.length - 1,
+ vaultIsEmpty: false,
});
+ clearTransactions();
await notificationController.changedAccount();
navigate("/");
diff --git a/src/ui/index.global.scss b/src/ui/index.global.scss
index 31b4db64..dcff9f5c 100644
--- a/src/ui/index.global.scss
+++ b/src/ui/index.global.scss
@@ -87,7 +87,7 @@ input[type="number"] {
}
.app {
- @apply h-full min-h-screen flex justify-center items-center w-full standard:bg-input-bg standard:rounded-2xl overflow-x-hidden standard:min-h-max standard:pb-6 max-standard:max-w-[355px];
+ @apply h-full min-h-screen flex justify-center items-center w-full standard:bg-input-bg standard:rounded-2xl overflow-x-hidden standard:min-h-max standard:pb-6 max-standard:max-w-full;
.main-route {
@apply w-full flex justify-center;
@@ -115,11 +115,11 @@ input[type="number"] {
}
::-webkit-scrollbar-thumb {
- background: #888;
+ @apply bg-neutral-500 rounded-xl;
}
::-webkit-scrollbar-thumb:hover {
- background: #555;
+ @apply bg-neutral-100;
}
.profile-card {
diff --git a/src/ui/pages/main/inscriptions/inscription-details/components.tsx b/src/ui/pages/main/inscriptions/inscription-details/components.tsx
index b58c9902..d5390ab4 100644
--- a/src/ui/pages/main/inscriptions/inscription-details/components.tsx
+++ b/src/ui/pages/main/inscriptions/inscription-details/components.tsx
@@ -87,12 +87,14 @@ const InscriptionDetails = () => {
}));
const convertToCompletedInscription = useCallback(
- async (
- inscriptionId: string
- ): Promise
=> {
+ async ({
+ inscription_id,
+ }: {
+ inscription_id: string;
+ }): Promise => {
const [data, location] = await Promise.all([
- apiController.searchContentInscriptionByInscriptionId(inscriptionId),
- apiController.getLocationByInscriptionId(inscriptionId),
+ apiController.searchContentInscriptionByInscriptionId(inscription_id),
+ apiController.getLocationByInscriptionId(inscription_id),
]);
if (!data || !location) return;
const parsedLocation = parseLocation(location.location);
@@ -102,17 +104,17 @@ const InscriptionDetails = () => {
return {
content_length: data.file_size,
content_type: data.file_type,
- inscription_id: inscriptionId,
+ inscription_id: inscription_id,
inscription_number: data.number,
- content: inscriptionId,
- preview: inscriptionId,
+ content: inscription_id,
+ preview: inscription_id,
value: value ? value[0] : 0,
owner: location.owner,
txid: parsedLocation.txid,
vout: parsedLocation.vout,
offset: parsedLocation.offset,
outpoint: `${parsedLocation.txid}i${parsedLocation.vout}`,
- genesis: inscriptionId,
+ genesis: inscription_id,
status: {
block_hash: "",
block_height: data.creation_block,
@@ -126,10 +128,18 @@ const InscriptionDetails = () => {
useEffect(() => {
if (!location.state) return navigate(-1);
+ if (location.state?.txid) {
+ setInscription(location.state);
+ return;
+ }
convertToCompletedInscription(location.state)
.then((completeInscription) => {
if (completeInscription) {
setInscription(completeInscription);
+ navigate(location.pathname, {
+ state: completeInscription,
+ replace: true,
+ });
} else {
navigate(-1);
}
diff --git a/src/ui/pages/main/new-wallet/component.tsx b/src/ui/pages/main/new-wallet/component.tsx
index 60de9311..8470e89a 100644
--- a/src/ui/pages/main/new-wallet/component.tsx
+++ b/src/ui/pages/main/new-wallet/component.tsx
@@ -24,11 +24,6 @@ const NewWallet = () => {
label: t("new_wallet.restore_from_private_key_label"),
link: "/pages/restore-priv-key",
},
- {
- icon: ,
- label: t("new_wallet.restore_ordinals_label"),
- link: "/pages/restore-ordinals",
- },
];
return (
diff --git a/src/ui/pages/main/new-wallet/new-mnemonic/component.tsx b/src/ui/pages/main/new-wallet/new-mnemonic/component.tsx
index 96632957..2b41ce92 100644
--- a/src/ui/pages/main/new-wallet/new-mnemonic/component.tsx
+++ b/src/ui/pages/main/new-wallet/new-mnemonic/component.tsx
@@ -14,6 +14,7 @@ import { t } from "i18next";
import { AddressType } from "bellhdw";
import Switch from "@/ui/components/switch";
import { ss } from "@/ui/utils";
+import { ADDRESS_TYPES } from "@/shared/constant";
const NewMnemonic = () => {
const location = useLocation();
@@ -32,7 +33,7 @@ const NewMnemonic = () => {
undefined
);
const [addressType, setAddressType] = useState
(
- AddressType.P2PKH
+ ADDRESS_TYPES[0].value
);
const createNewWallet = useCreateNewWallet();
@@ -73,7 +74,6 @@ const NewMnemonic = () => {
hideRoot: true,
network,
});
- await updateWalletState({ vaultIsEmpty: false });
} catch (e) {
console.error(e);
if (e instanceof Error) toast.error(e.message);
@@ -116,7 +116,7 @@ const NewMnemonic = () => {
{
- const [step, setStep] = useState(1);
- const { updateWalletState } = useWalletState(ss(["updateWalletState"]));
- const [addressType, setAddressType] = useState(AddressType.P2PKH);
- const [mnemonicPhrase, setMnemonicPhrase] = useState<(string | undefined)[]>(
- new Array(12).fill("")
- );
- const createNewWallet = useCreateNewWallet();
- const navigate = useNavigate();
- const [loading, setLoading] = useState(false);
- const { network } = useAppState(ss(["network"]));
-
- const setMnemonic = (v: string, index: number) => {
- if (!v) {
- return;
- }
- const phrase = v.split(" ");
- if (phrase.length === 12) setMnemonicPhrase(phrase);
- else
- setMnemonicPhrase((prev) => {
- prev[index] = v;
- return prev;
- });
- };
-
- const onNextStep = () => {
- if (mnemonicPhrase.findIndex((f) => f === undefined) !== -1)
- toast.error(t("new_wallet.restore_mnemonic.incomplete_phrase_error"));
- else setStep(2);
- };
-
- const onRestore = async () => {
- setLoading(true);
- try {
- await createNewWallet({
- payload: mnemonicPhrase.join(" "),
- walletType: "root",
- addressType,
- hideRoot: false,
- hdPath: "m/44'/3'/0'/0/0",
- passphrase: "",
- network,
- });
- await updateWalletState({ vaultIsEmpty: false });
- navigate("/");
- } catch (e) {
- toast.error(t("new_wallet.restore_mnemonic.invalid_words_error"));
- setStep(1);
- } finally {
- setLoading(false);
- }
- };
-
- if (loading) return ;
-
- return (
-
-
-
{t("new_wallet.step_1")}
-
{t("new_wallet.step_2")}
-
- {step === 1 ? (
-
-
- {new Array(12).fill("").map((_, index) => (
-
-
{index + 1}.
-
setMnemonic(v, index)}
- />
-
- ))}
-
-
-
-
-
- ) : (
-
-
-
-
-
-
- )}
-
- );
-};
-
-export default RestoreMnemonicOrdinals;
diff --git a/src/ui/pages/main/new-wallet/restore-mnemonic-ordinals/styles.module.scss b/src/ui/pages/main/new-wallet/restore-mnemonic-ordinals/styles.module.scss
deleted file mode 100644
index 33cf9362..00000000
--- a/src/ui/pages/main/new-wallet/restore-mnemonic-ordinals/styles.module.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-.restoreMnemonic {
- @apply w-full h-full flex flex-col items-center gap-6 text-base p-4 pb-0;
-}
-
-.phrase {
- @apply grid grid-cols-2 text-sm;
-}
-
-.stepTitle {
- @apply flex justify-between w-1/2;
-}
-
-.active {
- color: red;
-}
-
-.word {
- @apply flex justify-between items-center p-2.5 gap-2;
-
- .wordInput {
- @apply w-4/5;
- }
-}
-
-.step {
- @apply h-full w-full flex flex-col justify-between;
-}
diff --git a/src/ui/pages/main/new-wallet/restore-mnemonic/component.tsx b/src/ui/pages/main/new-wallet/restore-mnemonic/component.tsx
index 1229e020..81d947e8 100644
--- a/src/ui/pages/main/new-wallet/restore-mnemonic/component.tsx
+++ b/src/ui/pages/main/new-wallet/restore-mnemonic/component.tsx
@@ -1,7 +1,7 @@
import s from "./styles.module.scss";
import { useCreateNewWallet } from "@/ui/hooks/wallet";
import { useWalletState } from "@/ui/states/walletState";
-import { useState } from "react";
+import { useMemo, useState } from "react";
import cn from "classnames";
import { useNavigate } from "react-router-dom";
import toast from "react-hot-toast";
@@ -13,11 +13,32 @@ import { TailSpin } from "react-loading-icons";
import Switch from "@/ui/components/switch";
import { useAppState } from "@/ui/states/appState";
import { ss } from "@/ui/utils";
+import { ADDRESS_TYPES, DEFAULT_HD_PATH } from "@/shared/constant";
+import Select from "@/ui/components/select";
+
+const selectOptions = [
+ {
+ label: "Default",
+ value: DEFAULT_HD_PATH,
+ lecacyDerivation: false,
+ },
+ {
+ label: "Ordinals",
+ value: "m/44'/3'/0'/0/0",
+ lecacyDerivation: true,
+ isLegacySwitchLocked: true,
+ },
+ {
+ label: "Custom",
+ value: "",
+ },
+];
const RestoreMnemonic = () => {
const [step, setStep] = useState(1);
const { updateWalletState } = useWalletState(ss(["updateWalletState"]));
- const [addressType, setAddressType] = useState(AddressType.P2PKH);
+ const [addressType, setAddressType] = useState(ADDRESS_TYPES[0].value);
+ const [hdPath, setHdPath] = useState(DEFAULT_HD_PATH);
const [mnemonicPhrase, setMnemonicPhrase] = useState<(string | undefined)[]>(
new Array(12).fill("")
);
@@ -57,7 +78,6 @@ const RestoreMnemonic = () => {
hideRoot: !showRootAcc,
network,
});
- await updateWalletState({ vaultIsEmpty: false });
navigate("/home");
} catch (e) {
console.error(e);
@@ -68,9 +88,13 @@ const RestoreMnemonic = () => {
}
};
- const onSwitch = () => {
- setShowRootAcc((p) => !p);
- };
+ const selectedOption = useMemo(() => {
+ const v = selectOptions.find((i) => i.value === hdPath)?.label;
+
+ if (v) return { name: v };
+
+ return { name: selectOptions[selectOptions.length - 1].label };
+ }, [hdPath]);
if (loading) return ;
@@ -93,14 +117,6 @@ const RestoreMnemonic = () => {
))}
-
-
-