Skip to content

Commit fa21920

Browse files
committed
further improve information layout, add genesis timestamp, fix address calculation nfts
1 parent c73d523 commit fa21920

File tree

3 files changed

+53
-30
lines changed

3 files changed

+53
-30
lines changed

src/pages/index.tsx

+36-29
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import styles from '@/styles/Home.module.css'
44
import { BCMR, utf8ToBin, sha256, binToHex } from 'mainnet-js'
55
import { useEffect, useState } from 'react'
66
import { queryGenesisSupplyFT, queryActiveMinting, querySupplyNFTs, queryAuthchainLength, queryAllTokenHolders } from '../utils/queryChainGraph';
7+
import { formatTimestamp } from '@/utils/utils'
78

89
const inter = Inter({ subsets: ['latin'] })
910

1011
export default function Home() {
1112
interface tokenInfo {
1213
genesisSupplyFT:number;
14+
genesisTxTimestamp:number;
1315
totalSupplyFT:number;
1416
reservedSupplyFT:number;
1517
totalSupplyNFTs:number;
@@ -145,6 +147,7 @@ export default function Home() {
145147
}
146148
// calculate genesisSupplyFT
147149
const genesisTx = respJsonGenesisSupply?.transaction[0]?.hash?.substring(2);
150+
const genesisTxTimestamp = Number(respJsonGenesisSupply.transaction[0].block_inclusions[0].block.timestamp);
148151
let genesisSupplyFT = 0;
149152
if(respJsonGenesisSupply.transaction[0].outputs){
150153
genesisSupplyFT = respJsonGenesisSupply.transaction[0].outputs.reduce(
@@ -157,10 +160,12 @@ export default function Home() {
157160
let totalSupplyNFTs = respJsonSupplyNFTs.output.length;
158161
let indexOffset = 0;
159162
// limit of items returned by chaingraphquery is 5000
163+
let fullListNftHolders = respJsonSupplyNFTs.output
160164
while (totalSupplyNFTs == 5000) {
161165
indexOffset += 1;
162166
const respJsonSupplyNFTs2 = await querySupplyNFTs(tokenId, 5000 * indexOffset);
163167
if(!respJsonSupplyNFTs2) throw new Error("Error in querySupplyNFTs")
168+
fullListNftHolders = fullListNftHolders.concat(respJsonSupplyNFTs2.output);
164169
totalSupplyNFTs += respJsonSupplyNFTs2.output.length;
165170
}
166171
// parse hasActiveMintingToken
@@ -178,13 +183,14 @@ export default function Home() {
178183
total + parseInt(output.fungible_token_amount ?? "0"),
179184
0
180185
);
181-
const uniqueLockingBytecodes = new Set(respJsonAllTokenHolders.output.map(output => output.locking_bytecode.slice(2)));
186+
const listHoldingAddresses = !genesisSupplyFT ? fullListNftHolders : respJsonAllTokenHolders.output
187+
const uniqueLockingBytecodes = new Set(listHoldingAddresses.map(output => output.locking_bytecode.slice(2)));
182188
const numberHolders = Array.from(uniqueLockingBytecodes).filter(locking_bytecode =>
183189
locking_bytecode.startsWith('76a914')
184190
).length;
185191
const numberTokenAddresses = uniqueLockingBytecodes.size;
186192

187-
setTokenInfo({genesisSupplyFT, totalSupplyFT, totalSupplyNFTs, hasActiveMintingToken, genesisTx, authchainLength, authHead, reservedSupplyFT, numberHolders, numberTokenAddresses});
193+
setTokenInfo({genesisSupplyFT, totalSupplyFT, totalSupplyNFTs, hasActiveMintingToken, genesisTx, genesisTxTimestamp, authchainLength, authHead, reservedSupplyFT, numberHolders, numberTokenAddresses});
188194
} catch(error){
189195
console.log(error);
190196
alert("The input is not a valid tokenId!")
@@ -255,14 +261,18 @@ export default function Home() {
255261
<>total amount NFTs: {tokenInfo.totalSupplyNFTs} <br/><br/></>
256262
):null}
257263
description: {metadataInfo?.tokenMetadata?.description} <br/><br/>
258-
genesis transaction: <a href={"https://explorer.electroncash.de/tx/"+tokenInfo.genesisTx} target="_blank" rel="noreferrer">
259-
{tokenInfo.genesisTx}
260-
</a><br/>
261-
{tokenInfo.totalSupplyNFTs? (
262-
<>
263-
has active minting NFT: {tokenInfo.hasActiveMintingToken? "yes":"no"} <br/><br/>
264-
</>
265-
):null}
264+
{metadataInfo?.tokenMetadata?.uris ? <>
265+
web url: {metadataInfo.tokenMetadata.uris?.web? <a href={metadataInfo.tokenMetadata.uris?.web} target='_blank' rel="noreferrer" style={{display: "inline-block", color: "#00E"}}>
266+
{metadataInfo.tokenMetadata.uris?.web}
267+
</a>: "none"}<br/><br/>
268+
other uris: {Object.keys(metadataInfo.tokenMetadata.uris).filter(uri => uri != "icon" && uri != "web").length ?
269+
Object.keys(metadataInfo.tokenMetadata.uris).filter(uri => uri != "icon" && uri != "web").map((uriKey, index, array) =>
270+
<span key={uriKey}>
271+
<a href={metadataInfo?.tokenMetadata?.uris[uriKey]} target='_blank' rel="noreferrer" style={{ display: "inline-block", color: "#00E" }}>{uriKey}</a>
272+
{(index != array.length - 1) ? ", " : null}
273+
</span>
274+
) : "none"} <br /><br />
275+
</>:null}
266276
{metadataInfo && metadataInfo.tokenMetadata? (
267277
<>
268278
{metadataInfo.tokenMetadata.uris?.icon && tokenIconUri ? <>
@@ -294,38 +304,35 @@ export default function Home() {
294304
):null}
295305
</>
296306
):null}
307+
{tokenInfo.totalSupplyNFTs? (
308+
<>
309+
has active minting NFT: {tokenInfo.hasActiveMintingToken? "yes":"no"} <br/><br/>
310+
</>
311+
):null}
297312
{metadataInfo?.httpsUrl ?
298313
(<>
299314
Number of user-addresses holding {metadataInfo?.tokenMetadata?.token?.symbol ?? 'the token'}: {tokenInfo.numberHolders}<br/><br/>
300315
Total number of addresses holding {metadataInfo?.tokenMetadata?.token?.symbol ?? 'the token'} (including smart contracts):
301316
{tokenInfo.numberTokenAddresses}<br/><br/>
302317
</>):null}
303-
{metadataInfo.tokenMetadata.uris ? <>
304-
web url: {metadataInfo.tokenMetadata.uris?.web? <a href={metadataInfo.tokenMetadata.uris?.web} target='_blank' rel="noreferrer" style={{display: "inline-block", color: "#00E"}}>
305-
{metadataInfo.tokenMetadata.uris?.web}
306-
</a>: "none"}<br/><br/>
307-
other uris: {Object.keys(metadataInfo.tokenMetadata.uris).filter(uri => uri != "icon" && uri != "web").length ?
308-
Object.keys(metadataInfo.tokenMetadata.uris).filter(uri => uri != "icon" && uri != "web").map((uriKey, index, array) =>
309-
<span key={uriKey}>
310-
<a href={metadataInfo?.tokenMetadata?.uris[uriKey]} target='_blank' rel="noreferrer" style={{ display: "inline-block", color: "#00E" }}>{uriKey}</a>
311-
{(index != array.length - 1) ? ", " : null}
312-
</span>
313-
) : "none"} <br /><br />
314-
</>:null}
315318
</>):null}
316-
{metadataInfo?.httpsUrl ?
319+
genesis transaction: <a href={"https://explorer.electroncash.de/tx/"+tokenInfo.genesisTx} target="_blank" rel="noreferrer">
320+
{tokenInfo.genesisTx}
321+
</a><br/>
322+
timestamp genesis transaction: {formatTimestamp(tokenInfo.genesisTxTimestamp)} <br/><br/>
323+
{metadataInfo ? <>
324+
authChain length: {tokenInfo.authchainLength} <br/><br/>
325+
authChain metadata updates: {metadataInfo.authchainUpdates} <br/><br/>
326+
authHead txid: <a href={"https://explorer.electroncash.de/tx/"+tokenInfo.authHead} target="_blank" rel="noreferrer">
327+
{tokenInfo.authHead}
328+
</a><br/>
329+
{metadataInfo?.httpsUrl ?
317330
(<>
318331
location metadata:
319332
<a href={metadataInfo.httpsUrl} target="_blank" rel="noreferrer" style={{maxWidth: "570px", wordBreak: "break-all", display: "inline-block", color: "#00E"}}>
320333
{metadataInfo.metaDataLocation}
321334
</a><br/><br/>
322335
</>):null}
323-
{metadataInfo ? <>
324-
authChain length: {tokenInfo.authchainLength} <br/><br/>
325-
authChain metadata updates: {metadataInfo.authchainUpdates} <br/><br/>
326-
authHead txid: <a href={"https://explorer.electroncash.de/tx/"+tokenInfo.authHead} target="_blank" rel="noreferrer">
327-
{tokenInfo.authHead}
328-
</a><br/>
329336
{metadataInfo?.authchainUpdates? <>
330337
metadata hash matches: {metadataInfo.metadataHashMatch? "✅":"❌"} <br/><br/>
331338
</> : null}

src/utils/queryChainGraph.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@ export async function queryGenesisSupplyFT(tokenId:string){
1515
}
1616
}
1717
) {
18-
hash,
18+
hash
1919
outputs(where: { token_category: { _eq: $tokenId } }) {
2020
fungible_token_amount
2121
}
22+
block_inclusions {
23+
block {
24+
timestamp
25+
height
26+
}
27+
}
2228
}
2329
}`);
2430
const variables = { tokenId: `\\x${tokenId}` }

src/utils/utils.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function formatTimestamp(unixTimestampNumber: number){
2+
const date = new Date(unixTimestampNumber * 1000);
3+
const year = date.getUTCFullYear();
4+
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
5+
const day = String(date.getUTCDate()).padStart(2, '0');
6+
const hours = String(date.getUTCHours()).padStart(2, '0');
7+
const minutes = String(date.getUTCMinutes()).padStart(2, '0');
8+
9+
return `${year}-${month}-${day} ${hours}:${minutes}`;
10+
}

0 commit comments

Comments
 (0)