• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

blockcoders / kuma-wallet / ebbd3c69-fda1-4bf1-80ea-77bef87d3d87

pending completion
ebbd3c69-fda1-4bf1-80ea-77bef87d3d87

Pull #8

circleci

Ruben
fix tests
Pull Request #8: Milestone 2

876 of 1103 branches covered (79.42%)

Branch coverage included in aggregate %.

3452 of 3452 new or added lines in 44 files covered. (100.0%)

6647 of 7185 relevant lines covered (92.51%)

6.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.56
/src/pages/balance/components/Activity.tsx
1
import { useState, useEffect, useMemo } from "react";
2✔
2
import { useTranslation } from "react-i18next";
2✔
3
import { useToast } from "@src/hooks";
2✔
4
import Extension from "@src/Extension";
2✔
5
import { Loading } from "@src/components/common";
2✔
6
import { RecordData, RecordStatus } from "@src/storage/entities/activity/types";
2✔
7
import { BsArrowUpRight } from "react-icons/bs";
2✔
8
import Contact from "@src/storage/entities/registry/Contact";
2✔
9
import { formatDate } from "@src/utils/utils";
2✔
10
import {
2✔
11
  useNetworkContext,
2✔
12
  useTxContext,
2✔
13
  useAccountContext,
2✔
14
} from "@src/providers";
2✔
15
import Chains from "@src/storage/entities/Chains";
2✔
16
import { AssetIcon } from "@src/components/common/AssetIcon";
2✔
17
import { FaChevronRight } from "react-icons/fa";
2✔
18
import { IAsset } from "@src/types";
2✔
19

2✔
20
const chipColor = {
2✔
21
  [RecordStatus.FAIL]: "bg-red-600",
2✔
22
  [RecordStatus.SUCCESS]: "bg-green-600",
2✔
23
  [RecordStatus.PENDING]: "bg-yellow-600",
2✔
24
};
2✔
25

2✔
26
export const Activity = () => {
2✔
27
  const { t } = useTranslation("activity");
10✔
28

10✔
29
  const {
10✔
30
    state: { type },
10✔
31
  } = useNetworkContext();
10✔
32

10✔
33
  const {
10✔
34
    state: { selectedAccount },
10✔
35
  } = useAccountContext();
10✔
36

10✔
37
  const {
10✔
38
    state: { activity },
10✔
39
  } = useTxContext();
10✔
40

10✔
41
  const { t: tCommon } = useTranslation("common");
10✔
42
  const [isLoading, setIsLoading] = useState(true);
10✔
43
  const [search, setSearch] = useState("" as string);
10✔
44
  const [networks, setNetworks] = useState({} as Chains);
10✔
45
  const [contacts, setContacts] = useState([] as Contact[]);
10✔
46
  const [ownAccounts, setOwnAccounts] = useState([] as Contact[]);
10✔
47
  const { showErrorToast } = useToast();
10✔
48

10✔
49
  useEffect(() => {
10✔
50
    if (selectedAccount) {
4✔
51
      getContacts();
4✔
52
    }
4✔
53
    getNetworks();
4✔
54
  }, [selectedAccount.key]);
10✔
55

10✔
56
  const getNetworks = async () => {
10✔
57
    try {
4✔
58
      setIsLoading(true);
4✔
59
      const networks = await Extension.getAllChains();
4✔
60
      setNetworks(networks);
4✔
61
    } catch (error) {
4!
62
      setNetworks({} as Chains);
×
63
      showErrorToast(tCommon(error as string));
×
64
    } finally {
4✔
65
      setIsLoading(false);
4✔
66
    }
4✔
67
  };
4✔
68

10✔
69
  const getContacts = async () => {
10✔
70
    try {
4✔
71
      setIsLoading(true);
4✔
72
      const { contacts, ownAccounts } = await Extension.getRegistryAddresses();
4✔
73
      setContacts(contacts);
4✔
74
      setOwnAccounts(ownAccounts);
4✔
75
    } catch (error) {
4!
76
      setContacts([]);
×
77
      showErrorToast(tCommon(error as string));
×
78
    } finally {
4✔
79
      setIsLoading(false);
4✔
80
    }
4✔
81
  };
4✔
82

10✔
83
  const getLink = (network: string, hash: string) => {
10✔
84
    const { explorer } =
4✔
85
      networks
4✔
86
        .getAll()
4✔
87
        .find((chain) => chain.name.toLowerCase() === network.toLowerCase()) ||
4!
88
      {};
×
89
    const { evm, wasm } = explorer || {};
4!
90
    if (type.toLowerCase() === "wasm") {
4!
91
      return `${wasm?.url}extrinsic/${hash}`;
×
92
    } else {
4✔
93
      return `${evm?.url}tx/${hash}`;
4✔
94
    }
4✔
95
  };
4✔
96

10✔
97
  const getContactName = (address: string) => {
10✔
98
    const contact = contacts.find((c) => c.address === address);
4✔
99
    const ownAccount = ownAccounts.find((c) => c.address === address);
4✔
100
    return contact || ownAccount
4!
101
      ? contact?.name || ownAccount?.name
×
102
      : address.slice(0, 6) + "..." + address.slice(-4);
4✔
103
  };
4✔
104

10✔
105
  const getValue = (data: RecordData) => {
10✔
106
    if (!data || !data.value) return "$0.0";
4!
107
    return data.symbol ? `${data.value} ${data.symbol}` : `$${data.value}`;
4!
108
  };
4✔
109

10✔
110
  const getStatusColor = (status: RecordStatus) => {
10✔
111
    switch (status) {
4✔
112
      case RecordStatus.PENDING:
4✔
113
        return "goldenrod";
4✔
114
      case RecordStatus.SUCCESS:
4!
115
        return "#469999";
×
116
      case RecordStatus.FAIL:
4!
117
        return "red";
×
118
      default:
4!
119
        return "white";
×
120
    }
4✔
121
  };
4✔
122

10✔
123
  const filteredRecords = useMemo(() => {
10✔
124
    const _search = search.trim().toLocaleLowerCase();
6✔
125

6✔
126
    if (!_search) return activity;
6✔
127

2✔
128
    return activity
2✔
129
      .filter(({ hash, reference, address }) => {
2✔
130
        return (
2✔
131
          hash.toLowerCase().includes(_search) ||
2✔
132
          reference?.toLowerCase().includes(_search) ||
2✔
133
          address.toLowerCase().includes(_search)
2✔
134
        );
2✔
135
      })
2✔
136
      .sort((a, b) => (b.lastUpdated as number) - (a.lastUpdated as number));
2✔
137
  }, [search, activity]);
10✔
138

10✔
139
  if (isLoading) {
10✔
140
    return <Loading />;
4✔
141
  }
4✔
142

6✔
143
  return (
6✔
144
    <>
6✔
145
      <input
6✔
146
        data-testid="search-input"
6✔
147
        id="search"
6✔
148
        placeholder={t("search") || "Search"}
10!
149
        className=" border text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 bg-gray-700 border-gray-600 placeholder-gray-400 text-white"
10✔
150
        onChange={(e) => {
10✔
151
          setSearch(e.target.value);
2✔
152
        }}
2✔
153
      />
10✔
154

10✔
155
      <div className="flex flex-col my-5 overflow-y-auto h-full">
10✔
156
        {activity.length === 0 && (
10!
157
          <div className="flex justify-center items-center mt-5">
×
158
            <p className="text-lg font-medium">{t("empty")}</p>
×
159
          </div>
×
160
        )}
10✔
161
        {filteredRecords.map(
10✔
162
          ({ address, status, lastUpdated, data, network, hash }) => (
10✔
163
            <div
4✔
164
              key={hash}
4✔
165
              className="mb-5 mr-1 bg-[#343A40] flex justify-between rounded-lg py-2 px-2 text-white cursor-pointer items-center gap-3 hover:bg-gray-400 hover:bg-opacity-30 transition overflow-auto"
4✔
166
            >
4✔
167
              <div className="flex items-center justify-between gap-3">
4✔
168
                <a
4✔
169
                  className="text-custom-green-bg hover:bg-custom-green-bg hover:bg-opacity-30 rounded-full p-1"
4✔
170
                  href={getLink(network, hash)}
4✔
171
                  target="_blank"
4✔
172
                  rel="noreferrer"
4✔
173
                >
4✔
174
                  <BsArrowUpRight size={23} color={getStatusColor(status)} />
4✔
175
                </a>
4✔
176
                <div className="overflow-hidden text-ellipsis px-1">
4✔
177
                  <p className="text-xs">{getContactName(address)}</p>
4✔
178
                  <p className="text-xs">{`${formatDate(
4✔
179
                    lastUpdated as number
4✔
180
                  )} - `}</p>
4✔
181
                  {/* <p>
4✔
182
                    
4✔
183
                    <a
4✔
184
                      className="text-custom-green-bg hover:text-white text-sm"
4✔
185
                      href={getLink(network, hash)}
4✔
186
                      target="_blank"
4✔
187
                      rel="noreferrer"
4✔
188
                    >
4✔
189
                      {tCommon("view_in_scanner")}
4✔
190
                    </a>
4✔
191
                  </p> */}
4✔
192
                  <p
4✔
193
                    className={`text-[10px] flex justify-center items-center m-1 font-medium py-1 px-2  rounded-full text-indigo-100  w-fit ${
4✔
194
                      chipColor[status as RecordStatus]
4✔
195
                    }`}
4✔
196
                  >
4✔
197
                    {status}
4✔
198
                  </p>
4✔
199
                </div>
4✔
200
              </div>
4✔
201
              <div className="flex flex-col text-lg px-1">
4✔
202
                <p className="text-sm whitespace-nowrap mb-1 text-center">
4✔
203
                  {getValue(data)}
4✔
204
                </p>
4✔
205
                <div className="flex justify-evenly items-center gap-1">
4✔
206
                  <AssetIcon asset={data.asset as IAsset} width={20} />
4✔
207
                  <FaChevronRight size={16} />
4✔
208

4✔
209
                  <AssetIcon asset={data.asset as IAsset} width={20} />
4✔
210
                </div>
4✔
211
              </div>
4✔
212
            </div>
4✔
213
          )
10✔
214
        )}
10✔
215
      </div>
10✔
216
    </>
10✔
217
  );
10✔
218
};
4✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc