@@ -1,4 +1,4 @@
1−import React, { useCallback, useEffect, useState } from 'react';
1+import React, { useCallback, useEffect, useMemo, useState } from 'react';
22
33import * as need from 'lib/need';
44import { useWallet } from 'store/wallet';
@@ -15,6 +15,11 @@ import { RollerTransaction } from '@urbit/roller-api';
1515import './TransactionHistory.scss';
1616import { TransactionRow } from './TransactionRow';
1717import { Box } from '@tlon/indigo-react';
18+import { ShipRow } from './ShipRow';
19+
20+interface GroupedTransactions {
21+ [ship: string]: RollerTransaction[];
22+}
1823
1924const TransactionHistory = () => {
2025 const { pop }: any = useLocalRouter();
@@ -23,10 +28,24 @@ const TransactionHistory = () => {
2328 const address = need.addressFromWallet(wallet);
2429 const [transactions, setTransactions] = useState<RollerTransaction[]>([]);
2530
31+ const txnsByPatp = useMemo(() => {
32+ return transactions.reduce((memo, tx) => {
33+ if (Object.keys(memo).includes(tx.ship)) {
34+ memo[tx.ship].push(tx);
35+ } else {
36+ memo[tx.ship] = [tx];
37+ }
38+ return memo;
39+ }, {} as GroupedTransactions);
40+ }, [transactions]);
41+
42+ const txKeys = useMemo(() => {
43+ return Object.keys(txnsByPatp).sort();
44+ }, [txnsByPatp]);
45+
2646 const fetchTransactions = useCallback(async () => {
2747 const txns = await api.getHistory(address);
28− const sortedTxns = txns.sort((a, b) => a.time - b.time)
29− setTransactions(sortedTxns);
48+ setTransactions(txns);
3049 }, [address, api]);
3150
3251 useEffect(() => {
@@ -46,9 +65,20 @@ const TransactionHistory = () => {
4665 </HeaderPane>
4766 <BodyPane>
4867 <Box className="transaction-container">
49− {transactions.map(tx => (
50− <TransactionRow key={tx.time} {...tx} />
51− ))}
68+ {txKeys.map(patp => {
69+ return (
70+ <>
71+ <ShipRow patp={patp} />
72+ {txnsByPatp[patp]
73+ .sort((a, b) => {
74+ return a.time - b.time;
75+ })
76+ .map(tx => (
77+ <TransactionRow key={tx.time} {...tx} />
78+ ))}
79+ </>
80+ );
81+ })}
5282 </Box>
5383 </BodyPane>
5484 </Window>