diff --git a/components/FA2Transfer.tsx b/components/FA2Transfer.tsx
index 75468121..2610f8c7 100644
--- a/components/FA2Transfer.tsx
+++ b/components/FA2Transfer.tsx
@@ -109,25 +109,25 @@ const FA2Transfer = ({
onTokenChange?.(newToken);
setCurrentToken(newToken);
- if (autoSetField) {
- const previousValue = getFieldProps(
- `transfers.${proposalIndex}.values.${localIndex}`
- ).value;
-
- if (
- Array.isArray(previousValue) ||
- (!!previousValue && "balance" in previousValue)
- ) {
- throw new Error("Expect previous value to be formValue");
- }
-
- setFieldValue(`transfers.${proposalIndex}.values.${localIndex}`, {
- ...(previousValue ?? {}),
- token: newToken ?? "",
- tokenId: newToken?.token.tokenId ?? "",
- fa2Address: newToken?.token.contract.address ?? "",
- });
+ if (!autoSetField) return;
+
+ const previousValue = getFieldProps(
+ `transfers.${proposalIndex}.values.${localIndex}`
+ ).value;
+
+ if (
+ Array.isArray(previousValue) ||
+ (!!previousValue && "balance" in previousValue)
+ ) {
+ throw new Error("Expect previous value to be formValue");
}
+
+ setFieldValue(`transfers.${proposalIndex}.values.${localIndex}`, {
+ ...(previousValue ?? {}),
+ token: newToken ?? "",
+ tokenId: newToken?.token.tokenId ?? "",
+ fa2Address: newToken?.token.contract.address ?? "",
+ });
};
const fetchTokens = useCallback(
@@ -345,7 +345,19 @@ const FA2TransferGroup = ({ proposalIndex, remove }: props) => {
remove={remove}
autoSetField={false}
onTokenChange={token => {
+ const previousValue = getFieldProps(
+ `transfers.${proposalIndex}.values.0`
+ ).value;
+
+ if (
+ Array.isArray(previousValue) ||
+ (!!previousValue && "balance" in previousValue)
+ ) {
+ throw new Error("Expect previous value to be formValue");
+ }
+
const data = {
+ ...previousValue,
token,
fa2Address: token.token.contract.address,
tokenId: token.token.tokenId,
diff --git a/components/HistoryFaToken.tsx b/components/HistoryFaToken.tsx
new file mode 100644
index 00000000..f1f37029
--- /dev/null
+++ b/components/HistoryFaToken.tsx
@@ -0,0 +1,97 @@
+import { TriangleDownIcon } from "@radix-ui/react-icons";
+import BigNumber from "bignumber.js";
+import { useMemo, useState } from "react";
+import { TransferType } from "../types/display";
+import Alias from "./Alias";
+import { fa1_2Token } from "./FA1_2";
+import { fa2Token } from "./FA2Transfer";
+
+type props = {
+ transferType: TransferType;
+ token: {
+ timestamp: string;
+ from: {
+ address: string;
+ };
+ amount: string;
+ token: fa1_2Token["token"] | fa2Token["token"];
+ };
+};
+
+const HistoryFaToken = ({ transferType, token }: props) => {
+ const [isOpen, setIsOpen] = useState(false);
+
+ const { tzDate, tzHours, tzMinutes } = useMemo(
+ () => ({
+ tzDate: new Date(token.timestamp).toLocaleDateString(),
+ tzHours: new Date(token.timestamp).getHours().toString().padStart(2, "0"),
+ tzMinutes: new Date(token.timestamp)
+ .getMinutes()
+ .toString()
+ .padStart(2, "0"),
+ }),
+ [token.timestamp]
+ );
+
+ return (
+
+
+
+
+ -
+ Full name:{" "}
+ {token.token.metadata.name}
+
+ -
+ Token ID:{" "}
+ {token.token.tokenId}
+
+ -
+ Contract address:{" "}
+
+
+
+
+
+ );
+};
+
+export default HistoryFaToken;
diff --git a/context/proposals.ts b/context/proposals.ts
index 46a6ebb5..ee2b5721 100644
--- a/context/proposals.ts
+++ b/context/proposals.ts
@@ -1,4 +1,4 @@
-import { mutezTransfer } from "../types/display";
+import { mutezTransfer, tokenTransfer } from "../types/display";
import { API_URL } from "./config";
async function getProposals(bigmap: string) {
@@ -7,14 +7,27 @@ async function getProposals(bigmap: string) {
return json;
}
async function getTransfers(address: string): Promise {
- try {
- let res = await fetch(
- `${API_URL}/v1/operations/transactions?target=${address}&status=applied&amount.gt=0`
- );
- return await res.json();
- } catch (e) {
- console.log(e);
- return [];
- }
+ return fetch(
+ `${API_URL}/v1/operations/transactions?target=${address}&status=applied&amount.gt=0`
+ )
+ .then(res => res.json())
+ .catch(e => {
+ console.log(e);
+
+ return Promise.resolve([]);
+ });
}
-export { getProposals, getTransfers };
+
+function getTokenTransfers(address: string): Promise {
+ return fetch(
+ `${API_URL}/v1/tokens/transfers?anyof.to_.to=${address}&sort.desc=id`
+ )
+ .then(res => res.json())
+ .catch(e => {
+ console.log(e);
+
+ return Promise.resolve([]);
+ });
+}
+
+export { getProposals, getTransfers, getTokenTransfers };
diff --git a/pages/history.tsx b/pages/history.tsx
index c1d6b252..c367e6f9 100644
--- a/pages/history.tsx
+++ b/pages/history.tsx
@@ -1,20 +1,32 @@
import { tzip16 } from "@taquito/tzip16";
import { validateContractAddress } from "@taquito/utils";
+import BigNumber from "bignumber.js";
import { useContext, useEffect, useMemo, useState } from "react";
import Alias from "../components/Alias";
+import HistoryFaToken from "../components/HistoryFaToken";
import ProposalCard from "../components/ProposalCard";
import Spinner from "../components/Spinner";
import Meta from "../components/meta";
import Modal from "../components/modal";
import ProposalSignForm from "../components/proposalSignForm";
import fetchVersion from "../context/metadata";
-import { getProposals, getTransfers } from "../context/proposals";
+import {
+ getProposals,
+ getTokenTransfers,
+ getTransfers,
+} from "../context/proposals";
import {
AppDispatchContext,
AppStateContext,
contractStorage,
} from "../context/state";
-import { mutezTransfer, proposal, version } from "../types/display";
+import {
+ TransferType,
+ mutezTransfer,
+ proposal,
+ tokenTransfer,
+ version,
+} from "../types/display";
import { mutezToTez } from "../utils/tez";
import useWalletTokens from "../utils/useWalletTokens";
import { getProposalsId, toProposal, toStorage } from "../versioned/apis";
@@ -38,7 +50,9 @@ const History = () => {
state.contracts[state.currentContract ?? ""]
);
const [proposals, setProposals] = useState(emptyProps);
- const [transfers, setTransfers] = useState([] as mutezTransfer[]);
+ const [transfers, setTransfers] = useState<
+ [mutezTransfer[], tokenTransfer[]]
+ >([[], []]);
const [openModal, setCloseModal] = useState<{
state: number;
proposal: [boolean | undefined, number];
@@ -59,11 +73,16 @@ const History = () => {
setIsLoading(true);
if (!state.currentContract) return;
- let c = await state.connection.contract.at(state.currentContract, tzip16);
- let balance = await state.connection.tz.getBalance(state.currentContract);
+ const c = await state.connection.contract.at(
+ state.currentContract,
+ tzip16
+ );
+ const balance = await state.connection.tz.getBalance(
+ state.currentContract
+ );
- let cc = await c.storage();
- let version = await (state.contracts[state.currentContract]
+ const cc = await c.storage();
+ const version = await (state.contracts[state.currentContract]
? Promise.resolve(
state.contracts[state.currentContract].version
)
@@ -78,16 +97,19 @@ const History = () => {
},
})
: null;
- let bigmap: { key: string; value: any }[] = await getProposals(
+ const bigmap: { key: string; value: any }[] = await getProposals(
getProposalsId(version, cc)
);
- let transfers = await getTransfers(state.currentContract);
- let proposals: [number, any][] = bigmap.map(({ key, value }) => [
+ const response = await Promise.all([
+ getTransfers(state.currentContract),
+ getTokenTransfers(state.currentContract),
+ ]);
+ const proposals: [number, any][] = bigmap.map(({ key, value }) => [
Number.parseInt(key),
{ ui: toProposal(version, value), og: value },
]);
setContract(updatedContract);
- setTransfers(transfers);
+ setTransfers(response);
setProposals(proposals);
setIsLoading(false);
})();
@@ -103,8 +125,25 @@ const History = () => {
),
]
.concat(
- transfers.map(
- x => [-1, { ui: { timestamp: x.timestamp }, ...x }] as any
+ transfers[0].map(
+ x =>
+ [
+ TransferType.MUTEZ,
+ { ui: { timestamp: x.timestamp }, ...x },
+ ] as any
+ )
+ )
+ .concat(
+ transfers[1].map(
+ x =>
+ [
+ x.token.standard === "fa2"
+ ? TransferType.FA2
+ : x.token.standard === "fa1.2"
+ ? TransferType.FA1_2
+ : TransferType.UNKNOWN,
+ { ui: { timestamp: x.timestamp }, ...x },
+ ] as any
)
)
.sort((a, b) => {
@@ -167,58 +206,81 @@ const History = () => {
filteredProposals.length > 0 && (
{filteredProposals.map((x, i) => {
- return x[0] == -1 ? (
-
-
- Received Tez
- Received
-
-
- From:{" "}
-
-
-
- Amount:{" "}
- {mutezToTez((x[1] as any).amount)} Tez
-
-
- {new Date((x[1] as any).timestamp).toLocaleDateString()}{" "}
- -{" "}
- {`${new Date((x[1] as any).timestamp)
- .getHours()
- .toString()
- .padStart(2, "0")}:${new Date((x[1] as any).timestamp)
- .getMinutes()
- .toString()
- .padStart(2, "0")}`}
-
-
- ) : (
-
({
- hasApproved: result,
- signer,
- })
- )}
- content={x[1].ui.content}
- proposer={x[1].og.proposer}
- resolver={x[1].og.resolver}
- walletTokens={walletTokens}
- />
- );
+ switch (x[0]) {
+ case TransferType.MUTEZ:
+ return (
+
+
+
+ Received Tez
+
+ Received
+
+
+ From:{" "}
+
+
+
+ Amount:{" "}
+ {mutezToTez((x[1] as any).amount)} Tez
+
+
+ {new Date(
+ (x[1] as any).timestamp
+ ).toLocaleDateString()}{" "}
+ -{" "}
+ {`${new Date((x[1] as any).timestamp)
+ .getHours()
+ .toString()
+ .padStart(2, "0")}:${new Date(
+ (x[1] as any).timestamp
+ )
+ .getMinutes()
+ .toString()
+ .padStart(2, "0")}`}
+
+
+ );
+ case TransferType.FA2:
+ case TransferType.FA1_2:
+ return (
+
+ );
+
+ case TransferType.UNKNOWN:
+ return null;
+ default:
+ return (
+ ({
+ hasApproved: result,
+ signer,
+ })
+ )}
+ content={x[1].ui.content}
+ proposer={x[1].og.proposer}
+ resolver={x[1].og.resolver}
+ walletTokens={walletTokens}
+ />
+ );
+ break;
+ }
})}
)
diff --git a/types/display.ts b/types/display.ts
index d299c5a2..8348bc8d 100644
--- a/types/display.ts
+++ b/types/display.ts
@@ -29,6 +29,34 @@ type mutezTransfer = {
address: string;
};
};
+export type tokenTransfer = {
+ id: number;
+ level: number;
+ timestamp: string;
+ token: {
+ id: number;
+ contract: {
+ address: string;
+ };
+ tokenId: string;
+ standard: string;
+ totalSupply: string;
+ metadata: {
+ name: string;
+ symbol: string;
+ decimals: string;
+ };
+ };
+ from: {
+ address: string;
+ };
+ to: {
+ address: string;
+ };
+ amount: number;
+ transactionId: number;
+};
+
type status = "Proposing" | "Executed" | "Rejected" | "Expired";
type proposal = {
author: string;
@@ -46,6 +74,14 @@ type version =
| "0.0.11"
| "0.1.1"
| "unknown version";
+
+export enum TransferType {
+ MUTEZ = -1,
+ FA2 = -2,
+ FA1_2 = -3,
+ UNKNOWN = -9999,
+}
+
export {
type proposal,
type changeThreshold,