diff --git a/src/app/App.tsx b/src/app/App.tsx
index ddfe106..de92113 100644
--- a/src/app/App.tsx
+++ b/src/app/App.tsx
@@ -41,49 +41,11 @@ import OuterConfirmation from "./components/OuterConfirmation/OuterConfirmation"
import Formatters from "./utils/formatters";
import Big from "big.js";
import swapModalStyles from "./styles/SwapModal.module.scss";
-import useGetAsset from "./hooks/useGetAsset";
-
-// Types
-type dispatchType = () => void;
-type destinationsType = { address: string, amount: number }[];
-type transferType = { transfer: { sender: string, destination: string, destinations: destinationsType, amount: string, asset: { ticker: string }, comment?: string }, id: number };
-type RequestType = { method: string; assetId: string, amount: string, destinationAddress: string, destinationChainId: string };
-type SwapRequest = {
- id: string;
- swap: {
- destinationAddress: string;
- destinationAsset: string;
- destinationAssetAmount: string;
- currentAsset: string;
- currentAssetAmount: string;
- };
-};
-type SwapProposal = {
- to_finalizer: { amount: Big }[];
- to_initiator: { amount: Big }[];
-};
-type Asset = {
- decimal_point: number;
- [key: string]: any;
-};
-type AcceptSwapReq = {
- id: string;
- hex_raw_proposal: string;
- swapProposal: SwapProposal;
- receivingAsset: Asset;
- sendingAsset: Asset;
-};
-
-type AssetWhitelistReq = {
- id: string;
- asset_id: string;
- asset_name: string;
-}
+import { AcceptSwapReq, AssetWhitelistReq, dispatchType, RequestType, SwapRequest, transferType } from "../types";
function App() {
const { state, dispatch } = useContext(Store);
const [confirmationModalOpen, setConfirmationModalOpen] = useState(false);
- const { getAssetById } = useGetAsset();
const [incorrectPassword, setIncorrectPassword] = useState(false);
const [loggedIn, setLoggedIn] = useState(false);
@@ -92,11 +54,6 @@ function App() {
const [connectOpened, setConnectOpened] = useState(false);
- // Flags of display
- // creatingPassword flag has an effect only in case of loggedIn flag is false.
- // creatingPassword flag means whether to show the password create screen or existing password enter screen.
- // const creatingPassword = !passwordExists();
-
useEffect(() => {
async function loadLogin() {
const password = await getSessionPassword();
@@ -560,6 +517,29 @@ function App() {
}
}
+ async function getBurnAssetRequests() {
+ const response = await fetchBackground({ method: "GET_BURN_ASSET_REQUESTS" });
+ const burnRequests = response.data;
+
+ const pageReqs = burnRequests.map((e: any) => {
+ const data = e.burn;
+
+ return {
+ id: e.id,
+ method: "FINALIZE_BURN_ASSET_REQUEST",
+ name: "BURN_ASSET",
+ params: [
+ data
+ ],
+ };
+ });
+
+ if (pageReqs.length > 0) {
+ goTo(OuterConfirmation, { reqs: pageReqs });
+ }
+ }
+
+ await getBurnAssetRequests();
await getAliasCreationRequests();
await getIonicSwapRequests();
await getSignRequests();
diff --git a/src/app/components/OuterConfirmation/OuterConfirmation.tsx b/src/app/components/OuterConfirmation/OuterConfirmation.tsx
index 5892e72..f6580e2 100644
--- a/src/app/components/OuterConfirmation/OuterConfirmation.tsx
+++ b/src/app/components/OuterConfirmation/OuterConfirmation.tsx
@@ -2,7 +2,7 @@ import React from "react";
import Button, { ButtonThemes } from "../UI/Button/Button";
import styles from "./OuterConfirmation.module.scss";
import { useState, useEffect } from "react";
-import { fetchBackground } from "../../utils/utils";
+import { fetchBackground, shortenAddress } from "../../utils/utils";
import customTokenIcon from "../../assets/tokens-svg/custom-token.svg";
import banditIcon from "../../assets/tokens-svg/bandit-icon.svg";
import zanoIcon from "../../assets/tokens-svg/zano.svg";
@@ -11,6 +11,8 @@ import ethIcon from "../../assets/tokens-svg/eth.svg";
import arrowIcon from "../../assets/svg/arrow-blue.svg";
import InfoTooltip from "../UI/InfoTooltip";
import { getCurrent, goBack } from "react-chrome-extension-router";
+import { BurnAssetDataType } from "../../../types";
+import { BANDIT_ASSET_ID, ZANO_ASSET_ID } from "../../../constants";
interface ParamsType {
key: number;
@@ -29,13 +31,14 @@ const OuterConfirmation = () => {
const [reqIndex, setReqIndex] = useState(0);
const [accepting, setAccepting] = useState(false);
const [denying, setDenying] = useState(false);
- const [showFullAddresses, setShowFullAddresses] = useState(false);
+ const [showFullItems, setShowFullItems] = useState(false);
const [showFullComment, setShowFullComment] = useState(false);
const req = reqs[reqIndex] || {};
const { id, name, params, method, destinations } = req;
const isTransferMethod = name?.toLowerCase() === "transfer";
+ const isBurnMethod = name?.toLowerCase() === "burn_asset";
const isMultipleDestinations = destinations && destinations.length > 0;
@@ -56,7 +59,6 @@ const OuterConfirmation = () => {
}
}
-
async function acceptClick() {
setAccepting(true);
await fetchBackground({ method, id, success: true });
@@ -88,7 +90,188 @@ const OuterConfirmation = () => {
const disabled = accepting || denying;
- console.log("FINALIZA TRANSACTION", req);
+ const getConfirmationName = () => {
+ if (isTransferMethod) {
+ return "Please confirm the transfer details";
+ } else if (isBurnMethod) {
+ return "BURN ASSET"
+ } else {
+ return name
+ }
+ }
+
+ const getConfirmationContent = () => {
+ if (isTransferMethod) {
+ return (
+ <>
+
+
+
From
+
{transactionParams?.F}
+
+
+
Asset
+
{getAssetIcon(transactionParams?.Asset)} {transactionParams?.Asset}
+
+
+
Amount
+
{totalAmount}
+
+
+
+
Comment
+
{(transactionParams?.Comment?.length > 60 && !showFullComment) ?
+ <>
+ {transactionParams?.Comment?.slice(0, 60)}...
+
+ >
+ :
+ <>
+ {transactionParams?.Comment}
+ {showFullComment && }
+ >
+ }
+
+
+
+
+
+
To
+
{isMultipleDestinations ? <>{destinations?.length} addresses> : transactionParams?.To}
+
+
+ {!isMultipleDestinations &&
+
Amount
+
{totalAmount}
+
}
+
+
+ {isMultipleDestinations && (
+ <>
+
+
+ {showFullItems && destinations?.map((item: DestionationType, idx: number) => (
+
+
RECIPIENT {idx + 1}
+
+
+
+
+
+
Amount
+
{item.amount}
+
+
+
+ ))}
+ >
+ )}
+ >
+ )
+ } else if (isBurnMethod) {
+ const {
+ assetId,
+ burnAmount,
+ nativeAmount,
+ pointTxToAddress,
+ serviceEntries
+ }: BurnAssetDataType = params[0];
+ const getIconByAsseetId = () => {
+ if (assetId === ZANO_ASSET_ID) {
+ return "ZANO"
+ } else if (assetId === BANDIT_ASSET_ID) {
+ return "BANDIT"
+ } else {
+ return assetId
+ }
+ }
+
+ return (
+ <>
+
+
+
Asset
+
{getAssetIcon(getIconByAsseetId())} {shortenAddress(assetId, 6, 6)}
+
+
+
Burn Amount
+
{burnAmount}
+
+ {nativeAmount &&
+
Native Amount
+
{nativeAmount}
+
}
+ {pointTxToAddress &&
+
Send Tx To
+
{shortenAddress(pointTxToAddress, 6, 6)}
+
}
+
+
+ {serviceEntries && }
+
+ {showFullItems && serviceEntries?.map((item, idx) => {
+ const dataLength = serviceEntries?.length || 1;
+
+ return
+ {dataLength > 1 &&
+ Service Entries {idx + 1}
+
}
+
+
+
+
Body
+
{shortenAddress(item.body, 6, 6)}
+
+
+
+
Instruction
+
{item.instruction}
+
+ {item.security &&
+
Security
+
{shortenAddress(item.security, 6, 6)}
+
}
+
+
Service Id
+
{item.service_id}
+
+
+
+ })}
+ >
+ );
+ } else {
+ return (
+
+
+ {Array.isArray(params) && params?.map((item: ParamsType, idx: number) => (
+
+
{item.key}
+
{item.value}
+
+ ))}
+
+
+ )
+ }
+ }
+
if (!req) {
return No request found.
;
@@ -98,99 +281,15 @@ const OuterConfirmation = () => {
Request Confirmation
- {isTransferMethod ? "Please confirm the transfer details" : name}
+ {getConfirmationName()}
- {isTransferMethod ? (
- <>
-
-
-
From
-
{transactionParams?.From}
-
-
-
Asset
-
{getAssetIcon(transactionParams?.Asset)} {transactionParams?.Asset}
-
-
-
Amount
-
{totalAmount}
-
-
-
-
Comment
-
{(transactionParams?.Comment?.length > 60 && !showFullComment) ?
- <>
- {transactionParams?.Comment?.slice(0, 60)}...
-
- >
- :
- <>
- {transactionParams?.Comment}
- {showFullComment && }
- >
- }
-
-
-
-
-
-
To
-
{isMultipleDestinations ? <>{destinations?.length} addresses> : transactionParams?.To}
-
-
- {!isMultipleDestinations &&
-
Amount
-
{totalAmount}
-
}
-
-
- {isMultipleDestinations && (
- <>
-
-
- {showFullAddresses && destinations?.map((item: DestionationType, idx: number) => (
-
-
RECIPIENT {idx + 1}
-
-
-
-
-
-
Amount
-
{item.amount}
-
-
-
- ))}
- >
- )}
- >
- ) : (
-
-
- {Array.isArray(params) && params?.map((item: ParamsType, idx: number) => (
-
-
{item.key}
-
{item.value}
-
- ))}
-
-
- )}
+ {getConfirmationContent()}
- {isTransferMethod && <>
+ {isTransferMethod || isBurnMethod && <>
Transaction fee
@@ -198,12 +297,14 @@ const OuterConfirmation = () => {
0.01 ZANO
-
+ {isTransferMethod && <>
+
-
-
Total
-
{totalAmount}
-
+
+
Total
+
{totalAmount}
+
+ >}
>}
diff --git a/src/app/utils/utils.ts b/src/app/utils/utils.ts
index b9493a4..c04426e 100644
--- a/src/app/utils/utils.ts
+++ b/src/app/utils/utils.ts
@@ -12,12 +12,12 @@ interface ValidationResult {
error?: string;
}
-export async function fetchBackground(data: {
- method: string;
- password?: string;
- id?: number;
- success?: boolean;
- credentials?: { port: string };
+export async function fetchBackground(data: {
+ method: string;
+ password?: string;
+ id?: number;
+ success?: boolean;
+ credentials?: { port: string };
alias?: string;
}): Promise
{
return new Promise((resolve, reject) => {
@@ -107,7 +107,7 @@ export function validateTokensInput(input: string | number, decimal_point: numbe
const roundedInput = new Decimal(dotInput).toFixed(1);
if (roundedInput.replace(/./g, '').length <= 20) {
- return roundedInput;
+ return roundedInput;
}
}
@@ -144,3 +144,15 @@ export function validateTokensInput(input: string | number, decimal_point: numbe
valid: true
};
}
+
+
+export const shortenAddress = (
+ address: string | undefined,
+ startAmount: number = 5,
+ endAmount: number = 3
+) => {
+ if (!address) {
+ return "";
+ }
+ return address.slice(0, startAmount) + "..." + address.slice(-endAmount);
+};
\ No newline at end of file
diff --git a/src/background/background.ts b/src/background/background.ts
index b25b9bf..ccaf701 100644
--- a/src/background/background.ts
+++ b/src/background/background.ts
@@ -15,7 +15,8 @@ import {
getWhiteList,
getAssetInfo,
createAlias,
- addAssetToWhitelist
+ addAssetToWhitelist,
+ burnAsset
} from "./wallet";
import JSONbig from "json-bigint";
@@ -232,14 +233,15 @@ const signReqFinalizers: SignReqFinalizer = {};
const signReqs: unknown[] = [];
const savedRequests: Record<
- "IONIC_SWAP" | "ACCEPT_IONIC_SWAP" | "CREATE_ALIAS" | "TRANSFER" | "ASSETS_WHITELIST_ADD",
+ "IONIC_SWAP" | "ACCEPT_IONIC_SWAP" | "CREATE_ALIAS" | "TRANSFER" | "ASSETS_WHITELIST_ADD" | "BURN_ASSET",
Record
> = {
IONIC_SWAP: {},
ACCEPT_IONIC_SWAP: {},
CREATE_ALIAS: {},
TRANSFER: {},
- ASSETS_WHITELIST_ADD: {}
+ ASSETS_WHITELIST_ADD: {},
+ BURN_ASSET: {},
};
const allPopupIds: number[] = [];
@@ -280,7 +282,9 @@ const SELF_ONLY_REQUESTS = [
"GET_WALLETS",
"FINALIZE_TRANSFER_REQUEST",
"GET_ASSETS_WHITELIST_ADD_REQUESTS",
- "FINALIZE_ASSETS_WHITELIST_ADD_REQUESTS"
+ "FINALIZE_ASSETS_WHITELIST_ADD_REQUESTS",
+ "GET_BURN_ASSET_REQUESTS",
+ "FINALIZE_BURN_ASSET_REQUEST",
];
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
@@ -321,6 +325,10 @@ interface RequestType {
asset_id?: string;
asset_name?: string;
comment: string;
+ burnAmount: number;
+ nativeAmount?: number;
+ pointTxToAddress?: string;
+ serviceEntries?: any[];
}
interface Sender {
@@ -877,6 +885,45 @@ async function processRequest(request: RequestType, sender: Sender, sendResponse
)
break
}
+ case "BURN_ASSET":
+ PopupRequestsMethods.onRequestCreate(
+ "BURN_ASSET",
+ request,
+ sendResponse,
+ {
+ method: "FINALIZE_BURN_ASSET_REQUEST",
+ name: "Burn asset",
+ burn: request,
+ } as any
+ );
+ break;
+
+ case "GET_BURN_ASSET_REQUESTS":
+ PopupRequestsMethods.getRequestsList("BURN_ASSET", sendResponse);
+ break;
+
+ case "FINALIZE_BURN_ASSET_REQUEST":
+ PopupRequestsMethods.onRequestFinalize(
+ "BURN_ASSET",
+ request,
+ sendResponse,
+ async (req) => {
+ const burnReq = req.burn as any;
+ return burnAsset({
+ assetId: burnReq.assetId,
+ burnAmount: burnReq.burnAmount,
+ nativeAmount: burnReq.nativeAmount,
+ pointTxToAddress: burnReq.pointTxToAddress,
+ serviceEntries: burnReq.serviceEntries,
+ });
+ },
+ {
+ console: "Burn asset error:",
+ response: "Failed to burn asset",
+ reqNotFound: "Burn asset request not found",
+ }
+ );
+ break;
default:
diff --git a/src/background/wallet.ts b/src/background/wallet.ts
index 48e9625..beb164d 100644
--- a/src/background/wallet.ts
+++ b/src/background/wallet.ts
@@ -511,4 +511,52 @@ export async function addAssetToWhitelist(assetId: string) {
const data = await response.json();
return data;
-}
\ No newline at end of file
+}
+
+export const burnAsset = async ({
+ assetId,
+ burnAmount,
+ decimalPoint = 12,
+ nativeAmount = 0,
+ pointTxToAddress,
+ serviceEntries = [],
+}: {
+ assetId: string;
+ burnAmount: number;
+ decimalPoint?: number;
+ nativeAmount?: number;
+ pointTxToAddress?: string;
+ serviceEntries?: {
+ body: string;
+ flags: number;
+ instruction: string;
+ security?: string;
+ service_id: string;
+ }[];
+}) => {
+ const params: any = {
+ asset_id: assetId,
+ burn_amount: addZeros(burnAmount, decimalPoint).toFixed(0),
+ };
+
+ if (nativeAmount) {
+ params.native_amount = nativeAmount;
+ }
+
+ if (pointTxToAddress) {
+ params.point_tx_to_address = pointTxToAddress;
+ }
+
+ if (serviceEntries.length > 0) {
+ params.service_entries = serviceEntries;
+ }
+
+ const response = await fetchData("burn_asset", params);
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+
+ const data = await response.json();
+ return data;
+};
\ No newline at end of file
diff --git a/src/constants/index.ts b/src/constants/index.ts
index 8f720b4..6cdc915 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -1 +1,2 @@
-export const ZANO_ASSET_ID = "d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a";
\ No newline at end of file
+export const ZANO_ASSET_ID = "d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a";
+export const BANDIT_ASSET_ID = "55a8e0a730b133fb83915ba0e4335a680ae9d07a99642b17774460560f3b003d";
\ No newline at end of file
diff --git a/src/types/index.ts b/src/types/index.ts
new file mode 100644
index 0000000..f1600fd
--- /dev/null
+++ b/src/types/index.ts
@@ -0,0 +1,96 @@
+// Types
+export type dispatchType = () => void;
+export type destinationsType = { address: string, amount: number }[];
+
+export type transferType = {
+ transfer:
+ {
+ sender: string,
+ destination: string,
+ destinations: destinationsType,
+ amount: string,
+ asset: {
+ ticker: string
+ },
+ comment?: string,
+ }, id: number
+};
+
+export type RequestType = {
+ method: string;
+ assetId: string,
+ amount: string,
+ destinationAddress: string,
+ destinationChainId: string,
+ burnAmount: string;
+ nativeAmount?: number;
+ pointTxToAddress?: string;
+ serviceEntries?: any[];
+};
+
+export type SwapRequest = {
+ id: string;
+ swap: {
+ destinationAddress: string;
+ destinationAsset: string;
+ destinationAssetAmount: string;
+ currentAsset: string;
+ currentAssetAmount: string;
+ };
+};
+
+export type SwapProposal = {
+ to_finalizer: { amount: Big }[];
+ to_initiator: { amount: Big }[];
+};
+
+export type Asset = {
+ decimal_point: number;
+ [key: string]: any;
+};
+
+export type AcceptSwapReq = {
+ id: string;
+ hex_raw_proposal: string;
+ swapProposal: SwapProposal;
+ receivingAsset: Asset;
+ sendingAsset: Asset;
+};
+
+export type AssetWhitelistReq = {
+ id: string;
+ asset_id: string;
+ asset_name: string;
+}
+
+export interface BurnAssetRequest {
+ params: {
+ assetId: string;
+ burnAmount: number;
+ nativeAmount?: number;
+ pointTxToAddress?: string;
+ serviceEntries?: {
+ body: string;
+ flags: number;
+ instruction: string;
+ security?: string;
+ service_id: string;
+ }[];
+ };
+ [key: string]: any;
+}
+
+export interface BurnAssetDataType {
+ assetId: string;
+ burnAmount: number;
+ decimalPoint?: number;
+ nativeAmount?: number;
+ pointTxToAddress?: string;
+ serviceEntries?: {
+ service_id: string;
+ instruction: string;
+ body: string;
+ flags: number;
+ security?: string;
+ }[];
+}
\ No newline at end of file