Browse Source

add balance to dashdboard

main
matthew 2 years ago
parent
commit
ef05117a60
  1. 2
      searching-front/app/core/components/Footer/Footer.tsx
  2. 5
      searching-front/app/core/components/Link/styles.module.css
  3. 5
      searching-front/app/core/helpers/common.ts
  4. 12
      searching-front/app/core/icons/TonLogoWithoutBg.tsx
  5. 55
      searching-front/app/core/pages/State/State.tsx
  6. 55
      searching-front/app/core/pages/State/styles.module.css
  7. 14
      searching-front/package-lock.json
  8. 2
      searching-front/package.json
  9. 78
      searching-front/services/domain-watcher.ts
  10. 2
      searching-front/services/helpers.ts
  11. 10
      searching-front/services/main.ts

2
searching-front/app/core/components/Footer/Footer.tsx

@ -34,8 +34,8 @@ const Footer = () => {
return (
<div className={s.root}>
<div className={s.contactsWrapper}>
<FooterLink href="https://searching_ton.t.me/" keyLink="footer.linkContacts" />
<FooterLink href="https://searchington.t.me/" keyLink="footer.linkAnnouncments" />
<FooterLink href="https://searching_ton_feedback_bot.t.me/" keyLink="footer.linkFeedback" />
</div>
</div>
)

5
searching-front/app/core/components/Link/styles.module.css

@ -1,6 +1,6 @@
.root {
text-decoration: none;
display: inline-block;
display: inline-flex;
/* size */
font-size: 18px;
@ -8,6 +8,9 @@
}
.root a {
text-decoration: none;
display: inline-flex;
justify-content: center;
align-items: center;
}
.root a.wide::before {

5
searching-front/app/core/helpers/common.ts

@ -9,4 +9,7 @@ export const isNode = () => {
return typeof window !== "object"
}
export const getDomainFromUrl = (url: string) => url.match(/http:\/\/(.*).ton/)?.[1]
export const getDomainFromUrl = (url: string) => url.match(/http:\/\/(.*).ton/)?.[1]
export const getObserverUrlByAddress = (address: string) => `https://tonscan.org/address/${address}`

12
searching-front/app/core/icons/TonLogoWithoutBg.tsx

@ -0,0 +1,12 @@
const TonLogoWithoutBg = () => (
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M3.79243 2.50158C3.80829 2.50053 3.82417 2.5 3.84006 2.5H7.89606C7.90067 2.5 7.90527 2.50004 7.90986 2.50013C7.91445 2.50004 7.91905 2.5 7.92366 2.5H11.9797C11.9955 2.5 12.0114 2.50053 12.0273 2.50158C12.3422 2.52246 12.6472 2.62068 12.9151 2.78756C13.183 2.95443 13.4056 3.18481 13.5633 3.45827C13.7209 3.73174 13.8086 4.03985 13.8187 4.35533C13.8288 4.6708 13.761 4.9839 13.6212 5.2669C13.6144 5.2806 13.6072 5.29409 13.5996 5.30733L8.54758 14.0793C8.41442 14.3105 8.16771 14.4449 7.90986 14.4399C7.652 14.4449 7.4053 14.3105 7.27214 14.0793L2.22014 5.30733C2.21251 5.29409 2.2053 5.2806 2.19853 5.2669C2.05873 4.98391 1.99088 4.67081 2.00098 4.35533C2.01109 4.03985 2.09884 3.73174 2.25646 3.45827C2.41408 3.18481 2.63671 2.95444 2.90463 2.78756C3.17255 2.62068 3.47748 2.52246 3.79243 2.50158ZM8.64366 11.0272L12.3377 4.61302C12.3675 4.54665 12.3818 4.47429 12.3795 4.40143C12.3769 4.32263 12.355 4.24567 12.3157 4.17737C12.2763 4.10907 12.2207 4.05153 12.1538 4.00985C12.0921 3.97143 12.0226 3.94758 11.9504 3.94H8.64366V11.0272ZM7.17606 3.94H3.86928C3.79717 3.94758 3.72763 3.97143 3.66595 4.00985C3.59903 4.05153 3.54342 4.10907 3.50405 4.17737C3.46469 4.24567 3.44277 4.32263 3.44025 4.40143C3.43791 4.47429 3.45223 4.54665 3.48201 4.61303L7.17606 11.0272V3.94Z"
fill="currentColor"
/>
</svg>
)
export default TonLogoWithoutBg

55
searching-front/app/core/pages/State/State.tsx

@ -9,13 +9,14 @@ import "chart.js/auto"
import getActualSitesState from "app/stateSites/queries/getActualSitesState"
import getHistoryOfSitesState from "app/stateSites/queries/getHistoryOfSitesState"
import { InfluxPeriod } from "services/modules/influxdb/types"
import { cn, getDomainFromUrl } from "app/core/helpers/common"
import { cn, getDomainFromUrl, getObserverUrlByAddress } from "app/core/helpers/common"
import s from "./styles.module.css"
import { NftDomain } from "@prisma/client"
import Button from "app/auth/components/Button"
import Link from "app/core/components/Link"
import { count } from "app/core/helpers/metrika"
import TonLogoWithoutBg from "app/core/icons/TonLogoWithoutBg"
interface HistoryOfStateItem {
value: number
@ -89,7 +90,7 @@ const State = ({
historyOfState: historyOfStatePreloaded,
lastWeekNewSites,
}: StatePageProps) => {
const nowDate = format(new Date(),'d MMMM').toLowerCase();
const nowDate = format(new Date(), "d MMMM").toLowerCase()
const [historyPeriod, setHistoryPeriod] = useState(InfluxPeriod.D)
const { t } = useTranslation()
const [historyOfState] = useQuery(getHistoryOfSitesState, historyPeriod, {
@ -115,19 +116,43 @@ const State = ({
</div>
<div className={s.newestListWrapper}>
{lastWeekNewSites.map((i) => (
<Link
target="_blank"
theme="clear"
href={i.address + "?from=Searching.ton"}
wide
className={s.newestListItem}
onClick={()=>count('from_state_page_to_site')}
>
{getDomainFromUrl(i.address)}
<Button className={s.siteButton} theme="primary">
.ton
</Button>
</Link>
<div className={s.newestListItem}>
<Link
className={s.newestListItemLeft}
target="_blank"
theme="clear"
href={i.address + "?from=Searching.ton"}
onClick={() => count("from_state_page_to_site")}
wide
title="Open tonsite"
>
{getDomainFromUrl(i.address)}
<Button className={s.siteButton} theme="primary">
.ton
</Button>
</Link>
{i.walletAddress && i.tonBalance && (
<Link
className={s.newestListItemRight}
target="_blank"
theme="clear"
href={getObserverUrlByAddress(i.walletAddress)}
onClick={() => count("from_state_page_to_tonscan")}
title="Open wallet in tonscan"
wide
>
~
{new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })
.format(+i.tonBalance)
.replace("$", "")
.replace(",", " ")}
<div className={s.tonScanIcon}>
<TonLogoWithoutBg />
</div>
</Link>
)}
</div>
))}
</div>

55
searching-front/app/core/pages/State/styles.module.css

@ -64,16 +64,15 @@
flex-direction: column;
}
.newestListItem {
padding: 24px 34px;
border-radius: var(--border_radius_base);
border: 1px solid var(--border_color_main);
text-transform: capitalize;
font-weight: 700;
font-size: 16px;
line-height: 20px;
cursor: pointer;
position: relative;
box-sizing: border-box;
display: flex;
}
.siteButton.siteButton {
@ -82,16 +81,12 @@
font-size: 20px;
line-height: 25px;
border-radius: 16px;
transition: opacity 0.2s ease-in-out;
padding: 0;
background-color: var(--background_secondary);
margin-left: 8px;
}
.newestListItem:hover .siteButton.siteButton {
background-color: var(--button_primary);
}
.button {
position: absolute;
@ -146,3 +141,49 @@
background: var(--button_primary);
color: white;
}
.newestListItemLeft {
position: relative;
padding: 24px 0 24px 34px;
flex: 1 1 70%;
}
.newestListItemRight {
padding: 24px 34px 24px 0px;
flex: 1 1 30%;
position: relative;
display: flex;
align-items: center;
border-left: 1px solid var(--border_color_main);
justify-content: flex-end;
white-space: nowrap;
font-size: 12px !important;
background: inherit;
}
.newestListItemLeft:hover .siteButton.siteButton {
background-color: var(--button_primary);
}
.newestListItemRight:hover .tonScanIcon{
color: white;
background: var(--button_primary);
transition: all .3s ease-in-out;
}
.tonScanIcon{
width: 24px;
height: 24px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
color: var(--button_primary);
margin-left: 4px;
}
.siteButton, .tonScanIcon {
transition: background-color .2s ease-in-out;
}

14
searching-front/package-lock.json generated

@ -45,7 +45,7 @@
"sanitize-html": "2.7.1",
"textversionjs": "1.1.3",
"tonapi-sdk-js": "0.18.0",
"tonweb": "0.0.55",
"tonweb": "0.0.57",
"ts-node": "10.9.1",
"zod": "3.17.3"
},
@ -15585,9 +15585,9 @@
}
},
"node_modules/tonweb": {
"version": "0.0.55",
"resolved": "https://registry.npmjs.org/tonweb/-/tonweb-0.0.55.tgz",
"integrity": "sha512-C6YUTmHEzAHayUZMh7TWkoPr5lFAuetAO/7CmIumRQm85aeFcTY86TeCsJz0rmf2vmKPlJE2hqjByN5cYFKQfA==",
"version": "0.0.57",
"resolved": "https://registry.npmjs.org/tonweb/-/tonweb-0.0.57.tgz",
"integrity": "sha512-/kqRn3/H1nw2bJ68uOtvwkOj6/9EgYaYpMYAXs93I2pLdJZxVKNwTuZ7weGKVmrn9tOt/nCNooq3OAZDSAVUSg==",
"dependencies": {
"@ledgerhq/hw-transport-web-ble": "5.48.0",
"@ledgerhq/hw-transport-webhid": "5.48.0",
@ -27855,9 +27855,9 @@
}
},
"tonweb": {
"version": "0.0.55",
"resolved": "https://registry.npmjs.org/tonweb/-/tonweb-0.0.55.tgz",
"integrity": "sha512-C6YUTmHEzAHayUZMh7TWkoPr5lFAuetAO/7CmIumRQm85aeFcTY86TeCsJz0rmf2vmKPlJE2hqjByN5cYFKQfA==",
"version": "0.0.57",
"resolved": "https://registry.npmjs.org/tonweb/-/tonweb-0.0.57.tgz",
"integrity": "sha512-/kqRn3/H1nw2bJ68uOtvwkOj6/9EgYaYpMYAXs93I2pLdJZxVKNwTuZ7weGKVmrn9tOt/nCNooq3OAZDSAVUSg==",
"requires": {
"@ledgerhq/hw-transport-web-ble": "5.48.0",
"@ledgerhq/hw-transport-webhid": "5.48.0",

2
searching-front/package.json

@ -64,7 +64,7 @@
"sanitize-html": "2.7.1",
"textversionjs": "1.1.3",
"tonapi-sdk-js": "0.18.0",
"tonweb": "0.0.55",
"tonweb": "0.0.57",
"ts-node": "10.9.1",
"zod": "3.17.3"
},

78
searching-front/services/domain-watcher.ts

@ -1,4 +1,4 @@
import tonweb from "tonweb"
import TonWeb from "tonweb"
import {
JettonApi,
DNSApi,
@ -13,19 +13,30 @@ import db from "../db/index"
import axios from "axios"
import { getTonProxy } from "./helpers"
const dnsApi = new DNSApi()
interface SearchNFTItemsParams {
limit: number
offset: number
}
const getFullUrl = (dmn: string) => `http://${dmn}`
const upsertDmn = async (dmn: string, available: boolean) => {
const domainFromDB = await db.nftDomain.findFirst({where:{address: getFullUrl(dmn)}})
const shouldUpdateFirstAvailableDate = !domainFromDB?.firstAvailableDate && available;
const upsertObj = { available, address: getFullUrl(dmn) };
if(shouldUpdateFirstAvailableDate){
upsertObj.firstAvailableDate = new Date();
interface UpsertDmnParams {
available: boolean
walletAddress?: string
tonBalance?: number
}
const upsertDmn = async (
dmn: string,
{ available, tonBalance, walletAddress }: UpsertDmnParams
) => {
const domainFromDB = await db.nftDomain.findFirst({ where: { address: getFullUrl(dmn) } })
const shouldUpdateFirstAvailableDate = !domainFromDB?.firstAvailableDate && available
const upsertObj = { available, address: getFullUrl(dmn), domainName: dmn, walletAddress, tonBalance }
if (shouldUpdateFirstAvailableDate) {
upsertObj.firstAvailableDate = new Date()
}
return await db.nftDomain.upsert({
where: {
@ -36,7 +47,6 @@ const upsertDmn = async (dmn: string, available: boolean) => {
})
}
const wait = (time: number) => new Promise((resolve) => setTimeout(() => resolve(true), time))
const searchNFTItems = async ({ limit, offset }: SearchNFTItemsParams) => {
@ -53,6 +63,7 @@ const searchNFTItems = async ({ limit, offset }: SearchNFTItemsParams) => {
)
return data.nft_items
} catch (e) {
console.log("error fetch items", e)
return searchNFTItems({ limit, offset })
}
}
@ -71,12 +82,40 @@ const fetchTonSite = async (url: string) => {
}
return url
} catch (e) {
// console.log('restart fetch domains',e)
throw url
}
}
const tonweb = new TonWeb(
new TonWeb.HttpProvider("https://toncenter.com/api/v2/jsonRPC", {
apiKey: "2594e0a460095b81258b639950a16d9718fa3cbb1ba8a2eb87fbb4586a529b8f",
})
)
const fetchDomainInfo = async (url: string) => {
try {
await wait(1)
const address = (await tonweb.dns.getWalletAddress(url))?.toString(true, true, true)
let balance
if (address) {
balance = tonweb.utils.fromNano(await tonweb.getBalance(address))
return {
balance,
address,
}
}
return null
} catch (e) {
return null
}
}
const main = async () =>
new Promise(async (resolve) => {
// const result = await tonweb.dns.getWalletAddress('just-for-test.ton')
// Receive typed array of owner nfts
let count = 0
while (true) {
@ -86,26 +125,25 @@ const main = async () =>
offset: count * portion,
})
if (nftItems.length) {
console.time('fetchDomain')
const promises1: Promise<unknown>[] = []
for (let i = 0; i < nftItems.length; i++) {
const nftDomainItem = nftItems[i]
if (nftDomainItem.dns) {
promises1.push(fetchTonSite(nftDomainItem.dns)
.then(async (dmn) => {
console.log("success dmn", dmn)
upsertDmn(dmn, true)
})
.catch((dmn) => {
upsertDmn(dmn,false)
}))
promises1.push(
fetchTonSite(nftDomainItem.dns)
.then(async (dmn) => {
const domainInfo = await fetchDomainInfo(dmn)
console.log("success dmn", dmn)
upsertDmn(dmn, {available: true, walletAddress:domainInfo?.address,tonBalance:domainInfo?.balance})
})
.catch((dmn) => {
upsertDmn(dmn, {available: false})
})
)
}
}
count++
await Promise.all(promises1)
console.timeEnd('fetchDomain')
continue
}
break

2
searching-front/services/helpers.ts

@ -1,4 +1,4 @@
export const getTonProxy = () => ({
host: "in2.ton.org",
host: "in3.ton.org",
port: 8080,
})

10
searching-front/services/main.ts

@ -10,11 +10,11 @@ const run = async()=>{
console.time('watcher')
await domainWatcher();
console.timeEnd('watcher')
influx()
console.log('Start parser');
console.time('watcher');
await parser();
console.timeEnd('watcher');
// influx()
// console.log('Start parser');
// console.time('watcher');
// await parser();
// console.timeEnd('watcher');
}

Loading…
Cancel
Save