Skip to content

Commit 4a894a6

Browse files
committed
View entire block
1 parent 1264028 commit 4a894a6

File tree

5 files changed

+85
-5
lines changed

5 files changed

+85
-5
lines changed

crates/api/src/routes.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ pub fn router(app: App) -> Router {
3232
.route("/coins/block/{hash}", get(coins_by_block))
3333
.route("/coins/children/{coin_id}", get(coins_by_parent))
3434
.route("/coins/id/{coin_id}", get(coin_by_id))
35-
.route("/spend/{coin_id}", get(spend_by_coin_id))
35+
.route("/spends/block/{hash}", get(spends_by_block))
36+
.route("/spends/id/{coin_id}", get(spend_by_id))
3637
.with_state(app)
3738
.layer(cors)
3839
}
@@ -220,12 +221,52 @@ async fn coin_by_id(
220221
}))
221222
}
222223

224+
#[derive(Serialize)]
225+
pub struct SpendsResponse {
226+
pub spends: Vec<CoinSpendRecord>,
227+
}
228+
229+
async fn spends_by_block(
230+
State(app): State<App>,
231+
Path(hash): Path<Bytes32>,
232+
) -> Result<Json<SpendsResponse>, StatusCode> {
233+
let Some(height) = app.db.block_height(hash).unwrap() else {
234+
return Err(StatusCode::NOT_FOUND);
235+
};
236+
237+
let mut spends = IndexMap::new();
238+
239+
for coin_id in app.db.coins_by_height(height).unwrap() {
240+
if spends.contains_key(&coin_id) {
241+
continue;
242+
}
243+
244+
let Some(coin) = app.db.coin(coin_id).unwrap() else {
245+
continue;
246+
};
247+
248+
if coin.spent_height != Some(height) {
249+
continue;
250+
}
251+
252+
let Some(spend) = app.db.coin_spend(coin_id).unwrap() else {
253+
continue;
254+
};
255+
256+
spends.insert(coin_id, spend);
257+
}
258+
259+
Ok(Json(SpendsResponse {
260+
spends: spends.into_values().collect_vec(),
261+
}))
262+
}
263+
223264
#[derive(Serialize)]
224265
pub struct SpendResponse {
225266
pub spend: CoinSpendRecord,
226267
}
227268

228-
async fn spend_by_coin_id(
269+
async fn spend_by_id(
229270
State(app): State<App>,
230271
Path(coin_id): Path<Bytes32>,
231272
) -> Result<Json<SpendResponse>, StatusCode> {

explorer/src/App.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const router = createBrowserRouter(
1717
<>
1818
<Route path='/' element={<Home />} />
1919
<Route path='/tools' element={<Tools />} />
20+
<Route path='/tools/:hash' element={<Tools />} />
2021
<Route path='/block/:hash' element={<Block />} />
2122
<Route path='/coin/:id' element={<Coin />} />
2223
</>,

explorer/src/lib/api.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ export interface CoinSpendResponse {
107107
spend: CoinSpend | null;
108108
}
109109

110+
export interface CoinSpendsResponse {
111+
spends: CoinSpend[];
112+
}
113+
110114
export async function getBlocks() {
111115
const response = await get<BlocksResponse>('/blocks?reverse=true&limit=50');
112116
return response.blocks;
@@ -133,6 +137,11 @@ export async function getCoin(id: string) {
133137
}
134138

135139
export async function getCoinSpend(id: string) {
136-
const response = await get<CoinSpendResponse>(`/spend/${id}`);
140+
const response = await get<CoinSpendResponse>(`/spends/id/${id}`);
137141
return response.spend;
138142
}
143+
144+
export async function getCoinSpends(hash: string) {
145+
const response = await get<CoinSpendsResponse>(`/spends/block/${hash}`);
146+
return response.spends;
147+
}

explorer/src/pages/Block.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,28 @@ import { External } from '@/components/External';
22
import { Layout } from '@/components/Layout';
33
import { Truncated } from '@/components/Truncated';
44
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
5+
import { Button } from '@/components/ui/button';
56
import { Nft } from '@/contexts/MintGardenContext';
67
import { useDexie } from '@/hooks/useDexie';
78
import { useMintGarden } from '@/hooks/useMintGarden';
89
import { BlockRecord, CoinRecord, getBlock, getCoins } from '@/lib/api';
910
import { Precision, toAddress, toDecimal } from '@/lib/conversions';
1011
import { intlFormat } from 'date-fns';
11-
import { CoinsIcon, DatabaseIcon, HashIcon, LayersIcon } from 'lucide-react';
12+
import {
13+
CoinsIcon,
14+
DatabaseIcon,
15+
EyeIcon,
16+
HashIcon,
17+
LayersIcon,
18+
} from 'lucide-react';
1219
import { PropsWithChildren, useEffect, useState } from 'react';
13-
import { Link, useParams } from 'react-router-dom';
20+
import { Link, useNavigate, useParams } from 'react-router-dom';
1421

1522
export function Block() {
1623
const { hash } = useParams();
1724

25+
const navigate = useNavigate();
26+
1827
const [block, setBlock] = useState<BlockRecord | null>(null);
1928
const [coins, setCoins] = useState<CoinRecord[]>([]);
2029

@@ -119,6 +128,14 @@ export function Block() {
119128
<div className='text-lg text-red-600'>
120129
-{block.transaction_info.removals}
121130
</div>
131+
<Button
132+
variant='outline'
133+
size='sm'
134+
onClick={() => navigate(`/tools/${block.header_hash}`)}
135+
>
136+
<EyeIcon className='w-4 h-4' />
137+
View
138+
</Button>
122139
</div>
123140
<div className='space-y-2'>
124141
{coins

explorer/src/pages/Tools.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Textarea } from '@/components/ui/textarea';
55
import { Nft } from '@/contexts/MintGardenContext';
66
import { useDexie } from '@/hooks/useDexie';
77
import { useMintGarden } from '@/hooks/useMintGarden';
8+
import { getCoinSpends } from '@/lib/api';
89
import { Precision, toDecimal } from '@/lib/conversions';
910
import { parseJson } from '@/lib/json';
1011
import {
@@ -26,11 +27,22 @@ import {
2627
} from 'chia-wallet-sdk-wasm';
2728
import { CoinsIcon, TriangleAlertIcon } from 'lucide-react';
2829
import { useEffect, useMemo, useState } from 'react';
30+
import { useParams } from 'react-router-dom';
2931
import { useLocalStorage } from 'usehooks-ts';
3032

3133
export function Tools() {
34+
const { hash } = useParams();
35+
3236
const [value, setValue] = useLocalStorage('tools-bundle', '');
3337

38+
useEffect(() => {
39+
if (!hash) return;
40+
41+
getCoinSpends(hash).then((coinSpends) => {
42+
setValue(JSON.stringify(coinSpends));
43+
});
44+
}, [hash, setValue]);
45+
3446
const parsedSpendBundle = useMemo(() => {
3547
if (!value) return null;
3648

0 commit comments

Comments
 (0)