From a104cfe358a5ddfaf15e0c20e9bcd09cf927f238 Mon Sep 17 00:00:00 2001 From: sven Tan Date: Mon, 2 Dec 2024 01:19:31 +0800 Subject: [PATCH 1/7] finish --- .../src/app/faucet/inviter/[address]/page.tsx | 11 + .../src/app/inviter/[address]/page.tsx | 14 +- .../rooch-portal-v2/src/app/inviter/page.tsx | 6 + .../rooch-portal-v2/src/hooks/use-networks.ts | 3 + .../src/layouts/config-nav-dashboard.tsx | 6 + infra/rooch-portal-v2/src/routes/paths.ts | 1 + .../src/sections/faucet/inviter.tsx | 209 ++++++++++++++++++ .../src/sections/faucet/view.tsx | 5 + .../inviter/components/invitation-list.tsx | 84 +++++++ .../inviter/components/lottery-list.tsx | 101 +++++++++ .../src/sections/inviter/index.tsx | 96 ++++++++ infra/rooch-portal-v2/src/utils/inviter.ts | 2 + 12 files changed, 526 insertions(+), 12 deletions(-) create mode 100644 infra/rooch-portal-v2/src/app/faucet/inviter/[address]/page.tsx create mode 100644 infra/rooch-portal-v2/src/app/inviter/page.tsx create mode 100644 infra/rooch-portal-v2/src/sections/faucet/inviter.tsx create mode 100644 infra/rooch-portal-v2/src/sections/inviter/components/invitation-list.tsx create mode 100644 infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx create mode 100644 infra/rooch-portal-v2/src/sections/inviter/index.tsx create mode 100644 infra/rooch-portal-v2/src/utils/inviter.ts diff --git a/infra/rooch-portal-v2/src/app/faucet/inviter/[address]/page.tsx b/infra/rooch-portal-v2/src/app/faucet/inviter/[address]/page.tsx new file mode 100644 index 0000000000..38e136e217 --- /dev/null +++ b/infra/rooch-portal-v2/src/app/faucet/inviter/[address]/page.tsx @@ -0,0 +1,11 @@ +import WalletGuard from 'src/components/guard/WalletGuard'; + +import { InviterFaucetView } from 'src/sections/faucet/inviter'; + +export const metadata = { title: `Faucet` }; + +export default function Page({ params }: { params: { address: string } }) { + return + + +} diff --git a/infra/rooch-portal-v2/src/app/inviter/[address]/page.tsx b/infra/rooch-portal-v2/src/app/inviter/[address]/page.tsx index 5108143092..3bbdb0d0c9 100644 --- a/infra/rooch-portal-v2/src/app/inviter/[address]/page.tsx +++ b/infra/rooch-portal-v2/src/app/inviter/[address]/page.tsx @@ -1,16 +1,6 @@ -import WalletGuard from 'src/components/guard/WalletGuard'; -import { SettingsView } from 'src/sections/settings/view'; +import { InviterView } from 'src/sections/inviter/index'; export default function Page({ params }: { params: { address: string } }) { - // window.localStorage.setItem('inviter', params.address) - console.log(params) - return ( - - - - ); + return ; } - - - diff --git a/infra/rooch-portal-v2/src/app/inviter/page.tsx b/infra/rooch-portal-v2/src/app/inviter/page.tsx new file mode 100644 index 0000000000..ec31ddc548 --- /dev/null +++ b/infra/rooch-portal-v2/src/app/inviter/page.tsx @@ -0,0 +1,6 @@ + +import { InviterView } from 'src/sections/inviter/index'; + +export default function Page() { + return ; +} diff --git a/infra/rooch-portal-v2/src/hooks/use-networks.ts b/infra/rooch-portal-v2/src/hooks/use-networks.ts index 92e5937fc6..94df58c7ab 100644 --- a/infra/rooch-portal-v2/src/hooks/use-networks.ts +++ b/infra/rooch-portal-v2/src/hooks/use-networks.ts @@ -27,6 +27,7 @@ const { networkConfig, useNetworkVariable, useNetworkVariables } = createNetwork faucetObject: '0xd5723eda84f691ae2623da79312c7909b1737c5b3866ecc5dbd6aa21718ff15d', BTCMemPool: 'https://mempool.space/tx/', twitterOracleAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', + inviterCA: ['0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', 'invitation', 'InvitationConf'], }, }, testnet: { @@ -41,6 +42,7 @@ const { networkConfig, useNetworkVariable, useNetworkVariables } = createNetwork faucetObject: '0xd5723eda84f691ae2623da79312c7909b1737c5b3866ecc5dbd6aa21718ff15d', BTCMemPool: 'https://mempool.space/testnet/tx/', twitterOracleAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', + inviterCA: ['0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977', 'invitation', 'InvitationConf'], }, }, localnet: { @@ -55,6 +57,7 @@ const { networkConfig, useNetworkVariable, useNetworkVariables } = createNetwork faucetObject: '0xd5723eda84f691ae2623da79312c7909b1737c5b3866ecc5dbd6aa21718ff15d', BTCMemPool: 'https://mempool.space/testnet/tx/', twitterOracleAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', + inviterCA: ['0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977', 'invitation', 'InvitationConf'], }, }, }); diff --git a/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx b/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx index 38758b2147..46eb9e144f 100644 --- a/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx +++ b/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx @@ -38,6 +38,12 @@ export const navData = [ icon: , // noAddressRequired: true, }, + { + title: 'Invitation', + path: paths.dashboard.inviter, + icon: , + // noAddressRequired: true, + }, { title: 'Settings', path: paths.dashboard.settings, diff --git a/infra/rooch-portal-v2/src/routes/paths.ts b/infra/rooch-portal-v2/src/routes/paths.ts index a1ce4de81e..9a34a25eb7 100644 --- a/infra/rooch-portal-v2/src/routes/paths.ts +++ b/infra/rooch-portal-v2/src/routes/paths.ts @@ -14,6 +14,7 @@ export const paths = { settings: `${ROOTS.DASHBOARD}/settings`, search: `${ROOTS.DASHBOARD}/search`, faucet: `${ROOTS.DASHBOARD}/faucet`, + inviter: `${ROOTS.DASHBOARD}/inviter`, 'gas-swap': `${ROOTS.DASHBOARD}/gas-swap`, }, }; diff --git a/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx b/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx new file mode 100644 index 0000000000..e6a2759ccf --- /dev/null +++ b/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx @@ -0,0 +1,209 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { Args, Transaction } from '@roochnetwork/rooch-sdk'; +import { + useCurrentAddress, useCurrentSession, + useRoochClient, + useRoochClientQuery, +} from "@roochnetwork/rooch-sdk-kit"; + +import { LoadingButton } from '@mui/lab'; +import { Box, Card, Chip, Stack, CardHeader, CardContent } from '@mui/material'; + +import { useRouter } from 'src/routes/hooks'; + +import { useNetworkVariable } from 'src/hooks/use-networks'; + +import { formatCoin } from 'src/utils/format-number'; + +import { DashboardContent } from 'src/layouts/dashboard'; + +import { toast } from 'src/components/snackbar'; + +import { paths } from '../../routes/paths'; +import { INVITER_ADDRESS_KEY } from '../../utils/inviter'; +import SessionKeyGuardButton from "../../components/auth/session-key-guard-button"; + +const FAUCET_NOT_OPEN = 'Faucet Not Open'; +const INVALID_UTXO = 'Invalid UTXO'; +const FAUCET_NOT_ENOUGH_RGAS = 'Faucet Not enough RGas'; +const ALREADY_CLAIMED = 'Already Claimed'; +const UTXO_VALUE_IS_ZERO = 'UTXO Value Is Zero'; + +const ERROR_MSG: Record = { + 1: FAUCET_NOT_OPEN, + 2: INVALID_UTXO, + 3: FAUCET_NOT_ENOUGH_RGAS, + 4: ALREADY_CLAIMED, + 5: UTXO_VALUE_IS_ZERO, +}; + +export function InviterFaucetView({ inviterAddress }: { inviterAddress: string }) { + const router = useRouter(); + + const client = useRoochClient(); + const faucetAddress = useNetworkVariable('faucetAddress'); + const faucetObject = useNetworkVariable('faucetObject'); + const inviterCA = '0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977'; + const inviterConf = `${inviterCA}::invitation::InvitationConf`; + const session = useCurrentSession() + + const viewAddress = useCurrentAddress(); + const [faucetStatus, setFaucetStatus] = useState(false); + const [errorMsg, setErrorMsg] = useState(); + const [claimGas, setClaimGas] = useState(0); + const [UTXOs, setUTXOs] = useState | null>(null); + + const { data: inviter } = useRoochClientQuery('queryObjectStates', { + filter: { + object_type: inviterConf, + }, + }); + + const { data, isPending, refetch } = useRoochClientQuery( + 'getBalance', + { + owner: viewAddress?.genRoochAddress()!, + coinType: '0x3::gas_coin::RGas', + }, + { refetchInterval: 5000 } + ); + + useEffect(() => { + if (!viewAddress) { + return; + } + setFaucetStatus(true); + client + .queryUTXO({ + filter: { + owner: viewAddress.toStr(), + }, + }) + .then(async (result) => { + const utxoIds = result.data.map((item) => item.id); + if (utxoIds) { + setUTXOs(utxoIds); + const result = await client.executeViewFunction({ + target: `${faucetAddress}::gas_faucet::check_claim`, + args: [ + Args.objectId(faucetObject), + Args.address(viewAddress.genRoochAddress()!), + Args.vec('objectId', utxoIds), + ], + }); + + if (result.vm_status === 'Executed') { + const gas = Number(formatCoin(Number(result.return_values![0].decoded_value), 8, 2)); + setClaimGas(gas); + } else if ('MoveAbort' in result.vm_status) { + setErrorMsg(ERROR_MSG[Number(result.vm_status.MoveAbort.abort_code)]); + } + } else { + setErrorMsg('Not found utxo'); + } + }) + .finally(() => { + setFaucetStatus(false); + }); + }, [client, faucetAddress, faucetObject, viewAddress]); + + const fetchFaucet = async () => { + if (errorMsg === ALREADY_CLAIMED) { + router.push(paths.dashboard['gas-swap']); + return; + } + + setFaucetStatus(true); + + if ( + inviterAddress && + inviter && + inviter.data.length > 0 && + inviter.data[0].decoded_value?.value.is_open === true + ) { + try { + const tx = new Transaction(); + tx.callFunction({ + target: `${inviterCA}::invitation::claim_from_faucet`, + args: [ + Args.object({ + address: '0x3', + module: 'gas_coin', + name: 'RGas', + }), + Args.object({ + address: inviterCA, + module: 'invitation', + name: 'InvitationConf', + }), + Args.address(viewAddress?.genRoochAddress()!), + Args.vec('objectId', UTXOs!), + Args.address(inviterAddress), + ], + }); + + const result = await client.signAndExecuteTransaction({ + transaction: tx, + signer: session! + }) + if (result.execution_info.status.type === 'executed') { + refetch() + toast.success('claim success') + window.localStorage.setItem(INVITER_ADDRESS_KEY, '') + } + } catch (e) { + console.log(e); + } finally { + setFaucetStatus(false); + } + } + }; + + return ( + + + + + + + + ({viewAddress?.toStr()}) + + + + + ({viewAddress?.genRoochAddress().toStr()}) + + + + + + {formatCoin(Number(data?.balance || 0), data?.decimals || 0, 2)} + + + {errorMsg + ? errorMsg === ALREADY_CLAIMED + ? 'You Already Claimed RGAS' + : 'You cannot claim gas, Please make sure the current address has a valid utxo and try again' + : ''} + + + {errorMsg === ALREADY_CLAIMED + ? 'Purchase RGas' + : errorMsg || `Claim: ${claimGas} RGas`} + + + + + + + ); +} diff --git a/infra/rooch-portal-v2/src/sections/faucet/view.tsx b/infra/rooch-portal-v2/src/sections/faucet/view.tsx index 11ccd89ca9..81e9627b0b 100644 --- a/infra/rooch-portal-v2/src/sections/faucet/view.tsx +++ b/infra/rooch-portal-v2/src/sections/faucet/view.tsx @@ -20,6 +20,7 @@ import { DashboardContent } from 'src/layouts/dashboard'; import { toast } from 'src/components/snackbar'; import { paths } from '../../routes/paths' +import { INVITER_ADDRESS_KEY } from "../../utils/inviter"; const FAUCET_NOT_OPEN= 'Faucet Not Open' const INVALID_UTXO = 'Invalid UTXO' @@ -50,6 +51,10 @@ export function FaucetView({ address }: { address: string }) { useAddressChanged({ address, path: 'faucet' }); useEffect(() => { + const inviterAddress = window.localStorage.getItem(INVITER_ADDRESS_KEY) + if (inviterAddress && inviterAddress.length > 0) { + router.push(`/faucet/inviter/${inviterAddress}`) + } if (isValidBitcoinAddress(address)) { setViewAddress(address); try { diff --git a/infra/rooch-portal-v2/src/sections/inviter/components/invitation-list.tsx b/infra/rooch-portal-v2/src/sections/inviter/components/invitation-list.tsx new file mode 100644 index 0000000000..9314ff6864 --- /dev/null +++ b/infra/rooch-portal-v2/src/sections/inviter/components/invitation-list.tsx @@ -0,0 +1,84 @@ +import { + Box, + Card, + CardHeader, + CardContent, + Table, + TableBody, + TableRow, + TableCell, + Typography, + Tooltip, +} from '@mui/material'; + +import dayjs from 'dayjs'; +import { AnimateCountUp } from '../../../components/animate'; +import { shortAddress } from '../../../utils/address'; +import { Scrollbar } from '../../../components/scrollbar'; +import { TableHeadCustom, TableNoData } from '../../../components/table'; +import { getUTCOffset } from '../../../utils/format-time'; +import TableSkeleton from '../../../components/skeleton/table-skeleton'; +import { formatCoin } from '../../../utils/format-number'; +import { ROOCH_GAS_COIN_DECIMALS } from '../../../config/constant'; + +const data = [ + { + address: 'tb1q04uaa0mveqtt4y0sltuxtauhlyl8ctstfjazv0', + rgas: 111, + timestamp: 1733064513, + }, +]; + +export function InvitationList() { + return ( + + + + + + Timestamp ({getUTCOffset()}) + + ), + }, + ]} + /> + + {false ? ( + + ) : ( + <> + {data.map((item) => ( + + + + + {shortAddress(item.address, 8, 6)} + + + + + {dayjs(Number(item.timestamp)).format('MMMM DD, YYYY HH:mm:ss')} + + {item.rgas && ( + + {formatCoin(Number(item.rgas), ROOCH_GAS_COIN_DECIMALS, 6)} + + )} + + ))} + + + )} + +
+
+
+ ); +} diff --git a/infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx b/infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx new file mode 100644 index 0000000000..110894f1c2 --- /dev/null +++ b/infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx @@ -0,0 +1,101 @@ +import { + Box, + Button, + Card, + CardHeader, + Table, + TableBody, + TableCell, + TableRow, + Tooltip, + Typography +} from "@mui/material"; +import dayjs from "dayjs"; +import { LoadingButton } from "@mui/lab"; +import { Scrollbar } from "../../../components/scrollbar"; +import { TableHeadCustom, TableNoData } from "../../../components/table"; +import { getUTCOffset } from "../../../utils/format-time"; +import TableSkeleton from "../../../components/skeleton/table-skeleton"; +import { shortAddress } from "../../../utils/address"; +import { formatCoin } from "../../../utils/format-number"; +import { ROOCH_GAS_COIN_DECIMALS } from "../../../config/constant"; + +const data = [{ + address: 'tb1q04uaa0mveqtt4y0sltuxtauhlyl8ctstfjazv0', + rgas: 111, + timestamp: 1733064513 +}] + + +export function InviterLotteryList() { + console.log('hahahh') + return ( + + + Activity History + + + + + + Open Ticket + + + + + + Timestamp ({getUTCOffset()}) + + ), + }, + ]} + /> + + {false ? ( + + ) : ( + <> + {data.map((item) => ( + + + + + {shortAddress(item.address, 8, 6)} + + + + + {dayjs(Number(item.timestamp)).format( + 'MMMM DD, YYYY HH:mm:ss' + )} + + {item.rgas && ( + + {formatCoin( + Number(item.rgas), + ROOCH_GAS_COIN_DECIMALS, + 6 + )} + + )} + + ))} + + + )} + +
+
+
+ ) +} \ No newline at end of file diff --git a/infra/rooch-portal-v2/src/sections/inviter/index.tsx b/infra/rooch-portal-v2/src/sections/inviter/index.tsx new file mode 100644 index 0000000000..3f575950a3 --- /dev/null +++ b/infra/rooch-portal-v2/src/sections/inviter/index.tsx @@ -0,0 +1,96 @@ +'use client'; + +import { useEffect } from 'react'; +import { + useCurrentAddress, + useCurrentNetwork, + useRoochClientQuery, +} from '@roochnetwork/rooch-sdk-kit'; + +import { Tab, Tabs, Stack, Card, CardHeader, CardContent, Box } from "@mui/material"; +import Typography from '@mui/material/Typography'; + +import { Args } from '@roochnetwork/rooch-sdk'; +import { useRouter } from '../../routes/hooks'; +import { useTabs } from '../../hooks/use-tabs'; +import { INVITER_ADDRESS_KEY } from '../../utils/inviter'; +import { DashboardContent } from '../../layouts/dashboard'; +import { useNetworkVariable } from '../../hooks/use-networks'; +import { AnimateCountUp } from "../../components/animate"; +import { InviterLotteryList } from "./components/lottery-list"; +import { InvitationList } from "./components/invitation-list"; + +const TABS = [ + { label: 'Lottery Tickets', value: 'lottery_tickets' }, + { label: 'Invitation List', value: 'invitation_records' }, +]; + +export function InviterView({ inviterAddress }: { inviterAddress?: string }) { + const router = useRouter(); + const [inviterCA, inviterModule, inviterObj] = useNetworkVariable('inviterCA'); + const currentAddress = useCurrentAddress(); + const tabs = useTabs('lottery_tickets'); + + useEffect(() => { + if (inviterAddress && inviterAddress !== currentAddress?.toStr()) { + window.localStorage.setItem(INVITER_ADDRESS_KEY, inviterAddress); + router.push(`/setting`); + } + }, [currentAddress, inviterAddress, router]); + + const { data } = useRoochClientQuery('executeViewFunction', { + target: `${inviterCA}::${inviterModule}::invitation_user_record`, + args: [ + Args.object({ + address: inviterCA, + module: inviterModule, + name: inviterObj, + }), + ], + }); + + console.log(data); + + const renderTabs = ( + + {TABS.map((tab) => ( + + ))} + + ); + + return ( + + + Invitation Overview + + + + + + + + + + + + + + + + + + + + + + + + {renderTabs} + + {tabs.value === 'lottery_tickets' && } + + {tabs.value === 'invitation_records' && } + + ); +} diff --git a/infra/rooch-portal-v2/src/utils/inviter.ts b/infra/rooch-portal-v2/src/utils/inviter.ts new file mode 100644 index 0000000000..eb78cec841 --- /dev/null +++ b/infra/rooch-portal-v2/src/utils/inviter.ts @@ -0,0 +1,2 @@ +export const INVITER_ADDRESS_KEY = 'inviter-address' + From c522803813dc52fc9a4e8d71a8cc9db4087e98a5 Mon Sep 17 00:00:00 2001 From: sven Tan Date: Mon, 2 Dec 2024 17:30:54 +0800 Subject: [PATCH 2/7] fix --- .../inviter/components/invitation-list.tsx | 4 +++- .../inviter/components/lottery-list.tsx | 23 +++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/infra/rooch-portal-v2/src/sections/inviter/components/invitation-list.tsx b/infra/rooch-portal-v2/src/sections/inviter/components/invitation-list.tsx index 9314ff6864..4705dc1c02 100644 --- a/infra/rooch-portal-v2/src/sections/inviter/components/invitation-list.tsx +++ b/infra/rooch-portal-v2/src/sections/inviter/components/invitation-list.tsx @@ -32,7 +32,9 @@ const data = [ export function InvitationList() { return ( - + + Activity History + - - Activity History - - - - - - Open Ticket - + + Activity History + + + + + + Open Ticket +
), }, + { id: 'coin', label: 'RGAS' }, ]} /> @@ -98,4 +97,4 @@ export function InviterLotteryList() { ) -} \ No newline at end of file +} From 9f41d65062780dbff7a861875aa606967edf989e Mon Sep 17 00:00:00 2001 From: sven Tan Date: Mon, 2 Dec 2024 21:12:14 +0800 Subject: [PATCH 3/7] fix ui --- .../src/layouts/config-nav-dashboard.tsx | 2 +- .../assets/components/asset-row-item.tsx | 1 - .../src/sections/faucet/inviter.tsx | 2 +- .../inviter/components/invitation-list.tsx | 7 ++----- .../inviter/components/lottery-list.tsx | 17 ++++++++++------- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx b/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx index 46eb9e144f..58ebbc7115 100644 --- a/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx +++ b/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx @@ -41,7 +41,7 @@ export const navData = [ { title: 'Invitation', path: paths.dashboard.inviter, - icon: , + icon: , // noAddressRequired: true, }, { diff --git a/infra/rooch-portal-v2/src/sections/assets/components/asset-row-item.tsx b/infra/rooch-portal-v2/src/sections/assets/components/asset-row-item.tsx index e67727e3e4..b54af61f4e 100644 --- a/infra/rooch-portal-v2/src/sections/assets/components/asset-row-item.tsx +++ b/infra/rooch-portal-v2/src/sections/assets/components/asset-row-item.tsx @@ -24,7 +24,6 @@ export default function AssetRowItem({ row, isWalletOwner, onOpenTransferModal } - {/* {row.icon_url && } */} {row.icon_url ? ( - + Activity History @@ -40,7 +37,6 @@ export function InvitationList() { ), }, + { id: 'coin', label: 'RGAS' }, ]} /> diff --git a/infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx b/infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx index 02629615ac..358d2a0f01 100644 --- a/infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx +++ b/infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx @@ -2,7 +2,6 @@ import { Box, Button, Card, - CardHeader, Table, TableBody, TableCell, @@ -19,6 +18,7 @@ import TableSkeleton from "../../../components/skeleton/table-skeleton"; import { shortAddress } from "../../../utils/address"; import { formatCoin } from "../../../utils/format-number"; import { ROOCH_GAS_COIN_DECIMALS } from "../../../config/constant"; +import { useState } from "react"; const data = [{ address: 'tb1q04uaa0mveqtt4y0sltuxtauhlyl8ctstfjazv0', @@ -28,16 +28,19 @@ const data = [{ export function InviterLotteryList() { + + const [ticketOption, setTicketOption] = useState(1) return ( - + Activity History - - - - - Open Ticket + + + + + Open Ticket From 9f75c350770eb7ea62b7b2871b4c397921a52e71 Mon Sep 17 00:00:00 2001 From: sven Tan Date: Fri, 6 Dec 2024 10:47:08 +0800 Subject: [PATCH 4/7] fix --- .../src/app/invitation/[address]/page.tsx | 7 + .../src/app/invitation/page..tsx | 8 + .../auth/session-key-guard-button.tsx | 1 + .../rooch-portal-v2/src/hooks/use-networks.ts | 10 +- .../src/layouts/components/nav-upgrade.tsx | 1 + .../src/layouts/config-nav-dashboard.tsx | 2 +- infra/rooch-portal-v2/src/middleware.ts | 1 + infra/rooch-portal-v2/src/routes/paths.ts | 2 +- .../src/sections/faucet/inviter.tsx | 95 +++++---- .../components/invitation-list.tsx | 70 +++++-- .../invitations/components/lottery-list.tsx | 183 ++++++++++++++++++ .../src/sections/invitations/index.tsx | 137 +++++++++++++ .../inviter/components/lottery-list.tsx | 103 ---------- .../src/sections/inviter/index.tsx | 85 +------- .../rooch-sdk/test-e2e/case/session.test.ts | 4 + 15 files changed, 460 insertions(+), 249 deletions(-) create mode 100644 infra/rooch-portal-v2/src/app/invitation/[address]/page.tsx create mode 100644 infra/rooch-portal-v2/src/app/invitation/page..tsx rename infra/rooch-portal-v2/src/sections/{inviter => invitations}/components/invitation-list.tsx (59%) create mode 100644 infra/rooch-portal-v2/src/sections/invitations/components/lottery-list.tsx create mode 100644 infra/rooch-portal-v2/src/sections/invitations/index.tsx delete mode 100644 infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx diff --git a/infra/rooch-portal-v2/src/app/invitation/[address]/page.tsx b/infra/rooch-portal-v2/src/app/invitation/[address]/page.tsx new file mode 100644 index 0000000000..f9d227c635 --- /dev/null +++ b/infra/rooch-portal-v2/src/app/invitation/[address]/page.tsx @@ -0,0 +1,7 @@ +import { InvitationsView } from 'src/sections/invitations/index'; + +export const metadata = { title: `Invitation` }; + +export default function Page({ params }: { params: { address: string } }) { + return ; +} diff --git a/infra/rooch-portal-v2/src/app/invitation/page..tsx b/infra/rooch-portal-v2/src/app/invitation/page..tsx new file mode 100644 index 0000000000..a95260cfd4 --- /dev/null +++ b/infra/rooch-portal-v2/src/app/invitation/page..tsx @@ -0,0 +1,8 @@ + +import { InvitationsView } from 'src/sections/invitations/index'; + +export const metadata = { title: `Invitation` }; + +export default function Page() { + return ; +} diff --git a/infra/rooch-portal-v2/src/components/auth/session-key-guard-button.tsx b/infra/rooch-portal-v2/src/components/auth/session-key-guard-button.tsx index ac92a9ab90..846353019b 100644 --- a/infra/rooch-portal-v2/src/components/auth/session-key-guard-button.tsx +++ b/infra/rooch-portal-v2/src/components/auth/session-key-guard-button.tsx @@ -45,6 +45,7 @@ export default function SessionKeyGuardButton({ children }: { children: ReactNod '0x3::*::*', '0x176214bed3764a1c6a43dc1add387be5578ff8dbc263369f5bdc33a885a501ae::*::*', '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3::*::*', + '0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977::*::*', // remove ], maxInactiveInterval: 60 * 60 * 8, }); diff --git a/infra/rooch-portal-v2/src/hooks/use-networks.ts b/infra/rooch-portal-v2/src/hooks/use-networks.ts index 94df58c7ab..c4e1b826d5 100644 --- a/infra/rooch-portal-v2/src/hooks/use-networks.ts +++ b/infra/rooch-portal-v2/src/hooks/use-networks.ts @@ -20,7 +20,7 @@ const { networkConfig, useNetworkVariable, useNetworkVariables } = createNetwork variables: { roochOperatingAddress: ROOCH_NFT_OPERATING_ADDRESS, mintAddress: ROOCH_MINT_OPERATING_ADDRESS, - btcGasAddress: 'bc1prcajaj9n7e29u4dfp33x3hcf52yqeegspdpcd79pqu4fpr6llx4sugkfjt', + btcGasAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', gasMarketAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', faucetUrl: FAUCET_MAINNET, faucetAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', @@ -35,14 +35,14 @@ const { networkConfig, useNetworkVariable, useNetworkVariables } = createNetwork variables: { roochOperatingAddress: ROOCH_NFT_OPERATING_ADDRESS, mintAddress: ROOCH_MINT_OPERATING_ADDRESS, - btcGasAddress: 'tb1prcajaj9n7e29u4dfp33x3hcf52yqeegspdpcd79pqu4fpr6llx4stqqxgy', + btcGasAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', gasMarketAddress: '0x872502737008ac71c4c008bb3846a688bfd9fa54c6724089ea51b72f813dc71e', - faucetUrl: FAUCET_TESTNET, + faucetUrl: 'http://127.0.0.1:6868', faucetAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', faucetObject: '0xd5723eda84f691ae2623da79312c7909b1737c5b3866ecc5dbd6aa21718ff15d', BTCMemPool: 'https://mempool.space/testnet/tx/', twitterOracleAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', - inviterCA: ['0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977', 'invitation', 'InvitationConf'], + inviterCA: ['0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977', 'invitation3', 'InvitationConf'], }, }, localnet: { @@ -50,7 +50,7 @@ const { networkConfig, useNetworkVariable, useNetworkVariables } = createNetwork variables: { roochOperatingAddress: ROOCH_NFT_OPERATING_ADDRESS, mintAddress: ROOCH_MINT_OPERATING_ADDRESS, - btcGasAddress: 'tb1prcajaj9n7e29u4dfp33x3hcf52yqeegspdpcd79pqu4fpr6llx4stqqxgy', + btcGasAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', gasMarketAddress: '0x872502737008ac71c4c008bb3846a688bfd9fa54c6724089ea51b72f813dc71e', faucetUrl: FAUCET_TESTNET, faucetAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', diff --git a/infra/rooch-portal-v2/src/layouts/components/nav-upgrade.tsx b/infra/rooch-portal-v2/src/layouts/components/nav-upgrade.tsx index 1f37a4e573..8bf31f485f 100644 --- a/infra/rooch-portal-v2/src/layouts/components/nav-upgrade.tsx +++ b/infra/rooch-portal-v2/src/layouts/components/nav-upgrade.tsx @@ -63,6 +63,7 @@ export function NavUpgrade({ sx, ...other }: StackProps) { '0x3::*::*', '0x176214bed3764a1c6a43dc1add387be5578ff8dbc263369f5bdc33a885a501ae::*::*', '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3::*::*', + '0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977::*::*', // remove ], maxInactiveInterval: 60 * 60 * 8, }); diff --git a/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx b/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx index 58ebbc7115..72a15de5da 100644 --- a/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx +++ b/infra/rooch-portal-v2/src/layouts/config-nav-dashboard.tsx @@ -40,7 +40,7 @@ export const navData = [ }, { title: 'Invitation', - path: paths.dashboard.inviter, + path: paths.dashboard.invitation, icon: , // noAddressRequired: true, }, diff --git a/infra/rooch-portal-v2/src/middleware.ts b/infra/rooch-portal-v2/src/middleware.ts index c38cb320ce..f42d2811c6 100644 --- a/infra/rooch-portal-v2/src/middleware.ts +++ b/infra/rooch-portal-v2/src/middleware.ts @@ -16,6 +16,7 @@ const apiDomains = [ getRoochNodeUrl('testnet'), 'https://test-faucet.rooch.network', 'https://main-faucet.rooch.network', + 'http://127.0.0.1:6868', ]; const isProduction = process.env.NODE_ENV === 'production'; diff --git a/infra/rooch-portal-v2/src/routes/paths.ts b/infra/rooch-portal-v2/src/routes/paths.ts index 9a34a25eb7..808a08a97c 100644 --- a/infra/rooch-portal-v2/src/routes/paths.ts +++ b/infra/rooch-portal-v2/src/routes/paths.ts @@ -14,7 +14,7 @@ export const paths = { settings: `${ROOTS.DASHBOARD}/settings`, search: `${ROOTS.DASHBOARD}/search`, faucet: `${ROOTS.DASHBOARD}/faucet`, - inviter: `${ROOTS.DASHBOARD}/inviter`, + invitation: `${ROOTS.DASHBOARD}/invitation`, 'gas-swap': `${ROOTS.DASHBOARD}/gas-swap`, }, }; diff --git a/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx b/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx index e2612d6239..22932c4a4a 100644 --- a/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx +++ b/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx @@ -1,12 +1,13 @@ 'use client'; import { useState, useEffect } from 'react'; -import { Args, Transaction } from '@roochnetwork/rooch-sdk'; +import { Args, stringToBytes, toHEX, Bytes } from '@roochnetwork/rooch-sdk'; import { - useCurrentAddress, useCurrentSession, + useCurrentAddress, useRoochClient, useRoochClientQuery, -} from "@roochnetwork/rooch-sdk-kit"; + useCurrentWallet, +} from '@roochnetwork/rooch-sdk-kit'; import { LoadingButton } from '@mui/lab'; import { Box, Card, Chip, Stack, CardHeader, CardContent } from '@mui/material'; @@ -22,8 +23,6 @@ import { DashboardContent } from 'src/layouts/dashboard'; import { toast } from 'src/components/snackbar'; import { paths } from '../../routes/paths'; -import { INVITER_ADDRESS_KEY } from '../../utils/inviter'; -import SessionKeyGuardButton from "../../components/auth/session-key-guard-button"; const FAUCET_NOT_OPEN = 'Faucet Not Open'; const INVALID_UTXO = 'Invalid UTXO'; @@ -45,9 +44,10 @@ export function InviterFaucetView({ inviterAddress }: { inviterAddress: string } const client = useRoochClient(); const faucetAddress = useNetworkVariable('faucetAddress'); const faucetObject = useNetworkVariable('faucetObject'); - const inviterCA = '0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977'; - const inviterConf = `${inviterCA}::invitation::InvitationConf`; - const session = useCurrentSession() + const [inviterCA, inviterName] = useNetworkVariable('inviterCA') + const inviterConf = `${inviterCA}::${inviterName}::InvitationConf`; + const faucetUrl = useNetworkVariable('faucetUrl'); + const wallet = useCurrentWallet(); const viewAddress = useCurrentAddress(); const [faucetStatus, setFaucetStatus] = useState(false); @@ -59,6 +59,9 @@ export function InviterFaucetView({ inviterAddress }: { inviterAddress: string } filter: { object_type: inviterConf, }, + queryOption: { + decode: true, + }, }); const { data, isPending, refetch } = useRoochClientQuery( @@ -123,38 +126,56 @@ export function InviterFaucetView({ inviterAddress }: { inviterAddress: string } inviter.data.length > 0 && inviter.data[0].decoded_value?.value.is_open === true ) { + let sign: Bytes | undefined + const pk = wallet.wallet!.getPublicKey().toBytes() + try { + sign = await wallet.wallet?.sign(stringToBytes('utf8', 'hello, rooch')) + } catch (e) { + toast.error(e.message) + } + + if (!sign) { + return; + } + try { - const tx = new Transaction(); - tx.callFunction({ - target: `${inviterCA}::invitation::claim_from_faucet`, - args: [ - Args.object({ - address: '0x3', - module: 'gas_coin', - name: 'RGas', - }), - Args.object({ - address: inviterCA, - module: 'invitation', - name: 'InvitationConf', - }), - Args.address(viewAddress?.genRoochAddress()!), - Args.vec('objectId', UTXOs!), - Args.address(inviterAddress), - ], + const payload = JSON.stringify({ + claimer: viewAddress!.toStr(), + inviter: inviterAddress, + claimer_sign: toHEX(sign), + public_key: toHEX(pk), + message: 'hello, rooch', + }); + const response = await fetch(`${faucetUrl}/faucet-inviter`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: payload, }); - const result = await client.signAndExecuteTransaction({ - transaction: tx, - signer: session! - }) - if (result.execution_info.status.type === 'executed') { - refetch() - toast.success('claim success') - window.localStorage.setItem(INVITER_ADDRESS_KEY, '') + if (!response.ok) { + const data = await response.json(); + console.log(data); + if (response.status === 500 && data.error.includes('UTXO value is zero')) { + const msg = 'Claim failed, Not found UTXO'; + setErrorMsg(msg); + toast.error(msg); + return; + } + + toast.error('Network response was not ok'); + return; } - } catch (e) { - console.log(e); + + const d = await response.json(); + await refetch(); + toast.success( + `Faucet Success! RGas: ${formatCoin(Number(d.gas || 0), data?.decimals || 0, 2)}` + ); + } catch (error) { + console.error('Error:', error); + toast.error(`faucet error: ${error}`); } finally { setFaucetStatus(false); } @@ -188,7 +209,6 @@ export function InviterFaucetView({ inviterAddress }: { inviterAddress: string } ? 'You Already Claimed RGAS' : 'You cannot claim gas, Please make sure the current address has a valid utxo and try again' : ''} - - diff --git a/infra/rooch-portal-v2/src/sections/inviter/components/invitation-list.tsx b/infra/rooch-portal-v2/src/sections/invitations/components/invitation-list.tsx similarity index 59% rename from infra/rooch-portal-v2/src/sections/inviter/components/invitation-list.tsx rename to infra/rooch-portal-v2/src/sections/invitations/components/invitation-list.tsx index 2bb9ccb555..1bf17c3d23 100644 --- a/infra/rooch-portal-v2/src/sections/inviter/components/invitation-list.tsx +++ b/infra/rooch-portal-v2/src/sections/invitations/components/invitation-list.tsx @@ -1,32 +1,62 @@ +import dayjs from 'dayjs'; +import { useState, useEffect } from "react"; +import { useRoochClient } from "@roochnetwork/rooch-sdk-kit"; + import { Box, Card, Table, - TableBody, + Tooltip, TableRow, + TableBody, TableCell, Typography, - Tooltip, } from '@mui/material'; -import dayjs from 'dayjs'; import { shortAddress } from '../../../utils/address'; import { Scrollbar } from '../../../components/scrollbar'; -import { TableHeadCustom, TableNoData } from '../../../components/table'; import { getUTCOffset } from '../../../utils/format-time'; -import TableSkeleton from '../../../components/skeleton/table-skeleton'; import { formatCoin } from '../../../utils/format-number'; import { ROOCH_GAS_COIN_DECIMALS } from '../../../config/constant'; +import TableSkeleton from '../../../components/skeleton/table-skeleton'; +import { TableNoData, TableHeadCustom } from '../../../components/table'; + +type ListType = { + address: string + reward: number + timestamp: number +} + +export function InvitationList({ table }: { table?: string }) { + const client = useRoochClient() + const [loading, setLoading] = useState(false) + const [data, setData] = useState>() + + useEffect(() => { + if (!table) { + return + } -const data = [ - { - address: 'tb1q04uaa0mveqtt4y0sltuxtauhlyl8ctstfjazv0', - rgas: 111, - timestamp: 1733064513, - }, -]; + setLoading(true) + client.listStates({ + accessPath: `/table/${table}`, + stateOption: { + decode: true + } + }).then((result) => { + setData(result.data.map((item) => { + const view = ((item.state.decoded_value!.value) as any).value.value + return { + address: view.address, + reward: view.reward_amount, + timestamp: view.timestamp, + } + })) + }).catch((e) => { + console.log(e) + }).finally(() => setLoading(false)) + }, [table, client]); -export function InvitationList() { return ( @@ -49,11 +79,11 @@ export function InvitationList() { ]} /> - {false ? ( - + {loading ? ( + ) : ( <> - {data.map((item) => ( + {data?.map((item) => ( @@ -63,16 +93,16 @@ export function InvitationList() { - {dayjs(Number(item.timestamp)).format('MMMM DD, YYYY HH:mm:ss')} + {dayjs(Number(item.timestamp * 1000)).format('MMMM DD, YYYY HH:mm:ss')} - {item.rgas && ( + {item.reward && ( - {formatCoin(Number(item.rgas), ROOCH_GAS_COIN_DECIMALS, 6)} + {formatCoin(Number(item.reward), ROOCH_GAS_COIN_DECIMALS, 6)} )} ))} - + )} diff --git a/infra/rooch-portal-v2/src/sections/invitations/components/lottery-list.tsx b/infra/rooch-portal-v2/src/sections/invitations/components/lottery-list.tsx new file mode 100644 index 0000000000..4aaeef0e86 --- /dev/null +++ b/infra/rooch-portal-v2/src/sections/invitations/components/lottery-list.tsx @@ -0,0 +1,183 @@ +import dayjs from 'dayjs'; +import { useState, useEffect, useCallback } from "react"; +import { Args, Transaction } from '@roochnetwork/rooch-sdk'; +import { useRoochClient, useCurrentSession } from '@roochnetwork/rooch-sdk-kit'; + +import { LoadingButton } from '@mui/lab'; +import { + Box, + Card, + Table, + Button, + TableRow, + TableBody, + TableCell, + Typography, +} from '@mui/material'; + +import { Scrollbar } from '../../../components/scrollbar'; +import { getUTCOffset } from '../../../utils/format-time'; +import { formatCoin } from '../../../utils/format-number'; +import { useNetworkVariable } from '../../../hooks/use-networks'; +import { ROOCH_GAS_COIN_DECIMALS } from '../../../config/constant'; +import TableSkeleton from '../../../components/skeleton/table-skeleton'; +import { TableNoData, TableHeadCustom } from '../../../components/table'; + +const options = [1, 5, 10, 0]; + +type ListType = { + reward: number; + timestamp: number; +}; + +export function InvitationLotteryList({ table, ticket = 0, openCallback }: { table?: string, ticket: number, openCallback: () => void }) { + const client = useRoochClient(); + const [data, setData] = useState>(); + const [loading, setLoading] = useState(false); + const [opening, setOpening] = useState(false); + const [ticketOption, setTicketOption] = useState(1); + const session = useCurrentSession(); + const [inviterCA, inviterModule, inviterObj] = useNetworkVariable('inviterCA'); + + const fetch = useCallback(() => { + setLoading(true); + client + .listStates({ + accessPath: `/table/${table}`, + stateOption: { + decode: true, + }, + }) + .then((result) => { + console.log(result); + setData( + result.data.map((item) => { + console.log(result) + const view = (item.state.decoded_value!.value as any).value.value; + return { + address: view.address, + reward: view.reward_amount, + timestamp: view.timestamp, + }; + }) + ); + }) + .catch((e) => { + console.log(e); + }) + .finally(() => setLoading(false)); + }, [client, table]) + + useEffect(() => { + if (!table) { + return; + } + + fetch() + + }, [fetch, table]); + + const openTicket = async () => { + setOpening(true) + const tx = new Transaction(); + tx.callFunction({ + target: `${inviterCA}::${inviterModule}::lottery`, + args: [Args.object({ + address: inviterCA, + module: inviterModule, + name: inviterObj, + }), Args.u64(BigInt(ticketOption === 0 ? ticket : ticketOption))], + }); + + const result = await client.signAndExecuteTransaction({ + transaction: tx, + signer: session!, + }); + + if (result.execution_info.status.type === 'executed') { + openCallback() + fetch() + } + setOpening(false) + console.log(result); + }; + + return ( + + + Activity History + {ticket === 0 || ( + + {options.map((item) => ( + + ))} + + Open Ticket + + + )} + + +
+ + Timestamp ({getUTCOffset()}) + + ), + }, + { id: 'coin', label: 'RGAS' }, + ]} + /> + + {loading ? ( + + ) : ( + <> + {data?.map((item) => ( + + + {dayjs(Number(item.timestamp * 1000)).format('MMMM DD, YYYY HH:mm:ss')} + + {item.reward && ( + + {formatCoin(Number(item.reward), ROOCH_GAS_COIN_DECIMALS, 6)} + + )} + + ))} + + + )} + +
+
+
+ ); +} diff --git a/infra/rooch-portal-v2/src/sections/invitations/index.tsx b/infra/rooch-portal-v2/src/sections/invitations/index.tsx new file mode 100644 index 0000000000..33775c3b8e --- /dev/null +++ b/infra/rooch-portal-v2/src/sections/invitations/index.tsx @@ -0,0 +1,137 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { Args } from '@roochnetwork/rooch-sdk'; +import { + useCurrentAddress, + useRoochClientQuery, +} from '@roochnetwork/rooch-sdk-kit'; + +import Typography from '@mui/material/Typography'; +import { Tab, Box, Tabs, Card, Stack, CardHeader, CardContent } from '@mui/material'; + +import { useTabs } from '../../hooks/use-tabs'; +import { fromDustToPrecision } from '../../utils/number'; +import { AnimateCountUp } from '../../components/animate'; +import { DashboardContent } from '../../layouts/dashboard'; +import { useNetworkVariable } from '../../hooks/use-networks'; +import { InvitationList } from './components/invitation-list'; +import { InvitationLotteryList } from './components/lottery-list'; + +const TABS = [ + { label: 'Lottery Tickets', value: 'lottery_tickets' }, + { label: 'Invitation List', value: 'invitation_records' }, +]; + +type inviterDataType = { + invitationCount: number; + invitationReward: number; + lotteryTable: string; + invitationTable: string; + lotteryReward: number; + remainingLotteryTicket: number; +}; + +export function InvitationsView() { + const [inviterCA, inviterModule, inviterObj] = useNetworkVariable('inviterCA'); + const currentAddress = useCurrentAddress(); + const tabs = useTabs('lottery_tickets'); + const [inviterData, setInviterData] = useState(); + + const { data, refetch } = useRoochClientQuery('executeViewFunction', { + target: `${inviterCA}::${inviterModule}::invitation_user_record`, + args: [ + Args.object({ + address: inviterCA, + module: inviterModule, + name: inviterObj, + }), + Args.address(currentAddress?.genRoochAddress().toHexAddress() || ''), + ], + }); + + useEffect(() => { + if (!data || data.vm_status !== 'Executed') { + return; + } + + const dataView = (data.return_values![0].decoded_value as any).value; + + setInviterData({ + invitationCount: Number(dataView.total_invitations), + invitationReward: Number(dataView.invitation_reward_amount), + invitationTable: dataView.invitation_records.value.contents.value.handle.value.id as string, + lotteryTable: dataView.lottery_records.value.contents.value.handle.value.id as string, + remainingLotteryTicket: Number(dataView.remaining_luckey_ticket), + lotteryReward: Number(dataView.lottery_reward_amount), + }); + }, [data]); + + const renderTabs = ( + + {TABS.map((tab) => ( + + ))} + + ); + + return ( + + + Invitation Overview + + + + + + + {inviterData && ( + + )} + + + + + + {inviterData && ( + + )} + + + + + + {inviterData && ( + + )} + + + + + {renderTabs} + + {tabs.value === 'lottery_tickets' && ( + refetch()} + /> + )} + + {tabs.value === 'invitation_records' && ( + + )} + + ); +} diff --git a/infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx b/infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx deleted file mode 100644 index 358d2a0f01..0000000000 --- a/infra/rooch-portal-v2/src/sections/inviter/components/lottery-list.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { - Box, - Button, - Card, - Table, - TableBody, - TableCell, - TableRow, - Tooltip, - Typography -} from "@mui/material"; -import dayjs from "dayjs"; -import { LoadingButton } from "@mui/lab"; -import { Scrollbar } from "../../../components/scrollbar"; -import { TableHeadCustom, TableNoData } from "../../../components/table"; -import { getUTCOffset } from "../../../utils/format-time"; -import TableSkeleton from "../../../components/skeleton/table-skeleton"; -import { shortAddress } from "../../../utils/address"; -import { formatCoin } from "../../../utils/format-number"; -import { ROOCH_GAS_COIN_DECIMALS } from "../../../config/constant"; -import { useState } from "react"; - -const data = [{ - address: 'tb1q04uaa0mveqtt4y0sltuxtauhlyl8ctstfjazv0', - rgas: 111, - timestamp: 1733064513 -}] - - -export function InviterLotteryList() { - - const [ticketOption, setTicketOption] = useState(1) - return ( - - - Activity History - - - - - - Open Ticket - - - - - - Timestamp ({getUTCOffset()}) - - ), - }, - { id: 'coin', label: 'RGAS' }, - ]} - /> - - {false ? ( - - ) : ( - <> - {data.map((item) => ( - - - - - {shortAddress(item.address, 8, 6)} - - - - - {dayjs(Number(item.timestamp)).format( - 'MMMM DD, YYYY HH:mm:ss' - )} - - {item.rgas && ( - - {formatCoin( - Number(item.rgas), - ROOCH_GAS_COIN_DECIMALS, - 6 - )} - - )} - - ))} - - - )} - -
-
-
- ) -} diff --git a/infra/rooch-portal-v2/src/sections/inviter/index.tsx b/infra/rooch-portal-v2/src/sections/inviter/index.tsx index 3f575950a3..3c389e966e 100644 --- a/infra/rooch-portal-v2/src/sections/inviter/index.tsx +++ b/infra/rooch-portal-v2/src/sections/inviter/index.tsx @@ -1,96 +1,19 @@ 'use client'; import { useEffect } from 'react'; -import { - useCurrentAddress, - useCurrentNetwork, - useRoochClientQuery, -} from '@roochnetwork/rooch-sdk-kit'; -import { Tab, Tabs, Stack, Card, CardHeader, CardContent, Box } from "@mui/material"; -import Typography from '@mui/material/Typography'; - -import { Args } from '@roochnetwork/rooch-sdk'; import { useRouter } from '../../routes/hooks'; -import { useTabs } from '../../hooks/use-tabs'; import { INVITER_ADDRESS_KEY } from '../../utils/inviter'; -import { DashboardContent } from '../../layouts/dashboard'; -import { useNetworkVariable } from '../../hooks/use-networks'; -import { AnimateCountUp } from "../../components/animate"; -import { InviterLotteryList } from "./components/lottery-list"; -import { InvitationList } from "./components/invitation-list"; - -const TABS = [ - { label: 'Lottery Tickets', value: 'lottery_tickets' }, - { label: 'Invitation List', value: 'invitation_records' }, -]; export function InviterView({ inviterAddress }: { inviterAddress?: string }) { const router = useRouter(); - const [inviterCA, inviterModule, inviterObj] = useNetworkVariable('inviterCA'); - const currentAddress = useCurrentAddress(); - const tabs = useTabs('lottery_tickets'); useEffect(() => { - if (inviterAddress && inviterAddress !== currentAddress?.toStr()) { + if (inviterAddress) { window.localStorage.setItem(INVITER_ADDRESS_KEY, inviterAddress); - router.push(`/setting`); + router.push(`/settings`); } - }, [currentAddress, inviterAddress, router]); - - const { data } = useRoochClientQuery('executeViewFunction', { - target: `${inviterCA}::${inviterModule}::invitation_user_record`, - args: [ - Args.object({ - address: inviterCA, - module: inviterModule, - name: inviterObj, - }), - ], - }); - - console.log(data); - - const renderTabs = ( - - {TABS.map((tab) => ( - - ))} - - ); - - return ( - - - Invitation Overview - - - - - - - - - - - - - - - - - - - - - - - - {renderTabs} - - {tabs.value === 'lottery_tickets' && } + }, [inviterAddress, router]); - {tabs.value === 'invitation_records' && } - - ); + return <>; } diff --git a/sdk/typescript/rooch-sdk/test-e2e/case/session.test.ts b/sdk/typescript/rooch-sdk/test-e2e/case/session.test.ts index a9ad6cd71d..b4bf31b1e8 100644 --- a/sdk/typescript/rooch-sdk/test-e2e/case/session.test.ts +++ b/sdk/typescript/rooch-sdk/test-e2e/case/session.test.ts @@ -4,6 +4,7 @@ import { beforeAll, describe, expect, it, afterAll } from 'vitest' import { TestBox } from '../setup.js' import { Transaction } from '../../src/transactions/index.js' +import { BitcoinAddress } from "../../src"; describe('Checkpoints Session API', () => { let testBox: TestBox @@ -17,6 +18,9 @@ describe('Checkpoints Session API', () => { }) it('Create session should be success', async () => { + + const s = new BitcoinAddress('bc1q04uaa0mveqtt4y0sltuxtauhlyl8ctstr5x3hu').genRoochAddress().toHexAddress() + console.log(s) const session = await testBox.getClient().createSession({ sessionArgs: { appName: 'sdk-e2e-test', From 3a7dfa217176c29cb34bd7efd699377796650d32 Mon Sep 17 00:00:00 2001 From: sven Tan Date: Fri, 6 Dec 2024 12:11:23 +0800 Subject: [PATCH 5/7] switch testnet --- .../auth/session-key-guard-button-v1.tsx | 49 +++++++++++-------- .../auth/session-key-guard-button.tsx | 1 - .../rooch-portal-v2/src/hooks/use-networks.ts | 6 +-- .../src/layouts/components/nav-upgrade.tsx | 1 - .../invitations/components/lottery-list.tsx | 11 +---- 5 files changed, 33 insertions(+), 35 deletions(-) diff --git a/infra/rooch-portal-v2/src/components/auth/session-key-guard-button-v1.tsx b/infra/rooch-portal-v2/src/components/auth/session-key-guard-button-v1.tsx index a0b305677a..72d5581a26 100644 --- a/infra/rooch-portal-v2/src/components/auth/session-key-guard-button-v1.tsx +++ b/infra/rooch-portal-v2/src/components/auth/session-key-guard-button-v1.tsx @@ -9,7 +9,15 @@ import { isSessionExpired } from 'src/utils/common'; import { toast } from 'src/components/snackbar'; -export default function SessionKeyGuardButtonV1({ children, desc, callback }: { children?: ReactNode, desc?: string, callback?: () => Promise }) { +export default function SessionKeyGuardButtonV1({ + children, + desc, + callback, +}: { + children?: ReactNode; + desc?: string; + callback?: () => Promise; +}) { const sessionKey = useCurrentSession(); const { mutateAsync: createSessionKey } = useCreateSessionKey(); const [loading, setLoading] = useState(false); @@ -27,13 +35,14 @@ export default function SessionKeyGuardButtonV1({ children, desc, callback }: { }, [sessionKey]); const handle = async () => { - setLoading(true) - if (sessionKey && !isCurrentSessionExpired) { - if (callback) { - await callback() - } - } else { - try { + setLoading(true); + + try { + if (sessionKey && !isCurrentSessionExpired) { + if (callback) { + await callback(); + } + } else { await createSessionKey({ appName: 'rooch-portal', appUrl: 'portal.rooch.network', @@ -46,19 +55,19 @@ export default function SessionKeyGuardButtonV1({ children, desc, callback }: { maxInactiveInterval: 60 * 60 * 8, }); if (callback) { - await callback() + await callback(); } - } catch (error) { - if (error.message) { - toast.error(error.message); - return; - } - toast.error(String(error)); } + } catch (error) { + if (error.message) { + toast.error(error.message); + return; + } + toast.error(String(error)); + } finally { + setLoading(false); } - - setLoading(false) - } + }; return sessionKey && !isCurrentSessionExpired && children ? ( children @@ -70,9 +79,7 @@ export default function SessionKeyGuardButtonV1({ children, desc, callback }: { loading={loading} onClick={handle} > - { - desc || 'Create Session Key' - } + {desc || 'Create Session Key'} ); } diff --git a/infra/rooch-portal-v2/src/components/auth/session-key-guard-button.tsx b/infra/rooch-portal-v2/src/components/auth/session-key-guard-button.tsx index 846353019b..ac92a9ab90 100644 --- a/infra/rooch-portal-v2/src/components/auth/session-key-guard-button.tsx +++ b/infra/rooch-portal-v2/src/components/auth/session-key-guard-button.tsx @@ -45,7 +45,6 @@ export default function SessionKeyGuardButton({ children }: { children: ReactNod '0x3::*::*', '0x176214bed3764a1c6a43dc1add387be5578ff8dbc263369f5bdc33a885a501ae::*::*', '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3::*::*', - '0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977::*::*', // remove ], maxInactiveInterval: 60 * 60 * 8, }); diff --git a/infra/rooch-portal-v2/src/hooks/use-networks.ts b/infra/rooch-portal-v2/src/hooks/use-networks.ts index c4e1b826d5..a4b983daf4 100644 --- a/infra/rooch-portal-v2/src/hooks/use-networks.ts +++ b/infra/rooch-portal-v2/src/hooks/use-networks.ts @@ -37,12 +37,12 @@ const { networkConfig, useNetworkVariable, useNetworkVariables } = createNetwork mintAddress: ROOCH_MINT_OPERATING_ADDRESS, btcGasAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', gasMarketAddress: '0x872502737008ac71c4c008bb3846a688bfd9fa54c6724089ea51b72f813dc71e', - faucetUrl: 'http://127.0.0.1:6868', + faucetUrl: FAUCET_TESTNET, faucetAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', faucetObject: '0xd5723eda84f691ae2623da79312c7909b1737c5b3866ecc5dbd6aa21718ff15d', BTCMemPool: 'https://mempool.space/testnet/tx/', twitterOracleAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', - inviterCA: ['0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977', 'invitation3', 'InvitationConf'], + inviterCA: ['0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', 'invitation', 'InvitationConf'], }, }, localnet: { @@ -57,7 +57,7 @@ const { networkConfig, useNetworkVariable, useNetworkVariables } = createNetwork faucetObject: '0xd5723eda84f691ae2623da79312c7909b1737c5b3866ecc5dbd6aa21718ff15d', BTCMemPool: 'https://mempool.space/testnet/tx/', twitterOracleAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', - inviterCA: ['0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977', 'invitation', 'InvitationConf'], + inviterCA: ['0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', 'invitation', 'InvitationConf'], }, }, }); diff --git a/infra/rooch-portal-v2/src/layouts/components/nav-upgrade.tsx b/infra/rooch-portal-v2/src/layouts/components/nav-upgrade.tsx index 8bf31f485f..1f37a4e573 100644 --- a/infra/rooch-portal-v2/src/layouts/components/nav-upgrade.tsx +++ b/infra/rooch-portal-v2/src/layouts/components/nav-upgrade.tsx @@ -63,7 +63,6 @@ export function NavUpgrade({ sx, ...other }: StackProps) { '0x3::*::*', '0x176214bed3764a1c6a43dc1add387be5578ff8dbc263369f5bdc33a885a501ae::*::*', '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3::*::*', - '0x1d6f6657fc996008a1e43b8c13805e969a091560d4cea57b1db9f3ce4450d977::*::*', // remove ], maxInactiveInterval: 60 * 60 * 8, }); diff --git a/infra/rooch-portal-v2/src/sections/invitations/components/lottery-list.tsx b/infra/rooch-portal-v2/src/sections/invitations/components/lottery-list.tsx index 4aaeef0e86..083b0b80ef 100644 --- a/infra/rooch-portal-v2/src/sections/invitations/components/lottery-list.tsx +++ b/infra/rooch-portal-v2/src/sections/invitations/components/lottery-list.tsx @@ -22,6 +22,7 @@ import { useNetworkVariable } from '../../../hooks/use-networks'; import { ROOCH_GAS_COIN_DECIMALS } from '../../../config/constant'; import TableSkeleton from '../../../components/skeleton/table-skeleton'; import { TableNoData, TableHeadCustom } from '../../../components/table'; +import SessionKeyGuardButtonV1 from "../../../components/auth/session-key-guard-button-v1"; const options = [1, 5, 10, 0]; @@ -49,7 +50,6 @@ export function InvitationLotteryList({ table, ticket = 0, openCallback }: { tab }, }) .then((result) => { - console.log(result); setData( result.data.map((item) => { console.log(result) @@ -126,14 +126,7 @@ export function InvitationLotteryList({ table, ticket = 0, openCallback }: { tab {item === 0 ? 'All' : item} ))} - - Open Ticket - + )} From 6b9c10002750619362d2b3a9aa0a64b7aafee279 Mon Sep 17 00:00:00 2001 From: sven Date: Fri, 6 Dec 2024 19:28:23 +0800 Subject: [PATCH 6/7] fix --- .../rooch-portal-v2/src/hooks/use-networks.ts | 6 +- .../src/sections/faucet/inviter.tsx | 16 +- .../components/invitation-list.tsx | 2 +- .../src/sections/settings/view.tsx | 163 +++++++++++++----- 4 files changed, 135 insertions(+), 52 deletions(-) diff --git a/infra/rooch-portal-v2/src/hooks/use-networks.ts b/infra/rooch-portal-v2/src/hooks/use-networks.ts index a4b983daf4..61056f7de3 100644 --- a/infra/rooch-portal-v2/src/hooks/use-networks.ts +++ b/infra/rooch-portal-v2/src/hooks/use-networks.ts @@ -36,8 +36,8 @@ const { networkConfig, useNetworkVariable, useNetworkVariables } = createNetwork roochOperatingAddress: ROOCH_NFT_OPERATING_ADDRESS, mintAddress: ROOCH_MINT_OPERATING_ADDRESS, btcGasAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', - gasMarketAddress: '0x872502737008ac71c4c008bb3846a688bfd9fa54c6724089ea51b72f813dc71e', - faucetUrl: FAUCET_TESTNET, + gasMarketAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e 744c13f2d9998bf76cc3', + faucetUrl: 'http://192.168.31.134', faucetAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', faucetObject: '0xd5723eda84f691ae2623da79312c7909b1737c5b3866ecc5dbd6aa21718ff15d', BTCMemPool: 'https://mempool.space/testnet/tx/', @@ -51,7 +51,7 @@ const { networkConfig, useNetworkVariable, useNetworkVariables } = createNetwork roochOperatingAddress: ROOCH_NFT_OPERATING_ADDRESS, mintAddress: ROOCH_MINT_OPERATING_ADDRESS, btcGasAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', - gasMarketAddress: '0x872502737008ac71c4c008bb3846a688bfd9fa54c6724089ea51b72f813dc71e', + gasMarketAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', faucetUrl: FAUCET_TESTNET, faucetAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', faucetObject: '0xd5723eda84f691ae2623da79312c7909b1737c5b3866ecc5dbd6aa21718ff15d', diff --git a/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx b/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx index 22932c4a4a..7117c300dd 100644 --- a/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx +++ b/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx @@ -23,6 +23,7 @@ import { DashboardContent } from 'src/layouts/dashboard'; import { toast } from 'src/components/snackbar'; import { paths } from '../../routes/paths'; +import { INVITER_ADDRESS_KEY } from 'src/utils/inviter'; const FAUCET_NOT_OPEN = 'Faucet Not Open'; const INVALID_UTXO = 'Invalid UTXO'; @@ -64,6 +65,15 @@ export function InviterFaucetView({ inviterAddress }: { inviterAddress: string } }, }); + useEffect(() => { + + // invite close + if (inviter && inviter.data.length > 0 && inviter.data[0].decoded_value?.value.is_open === false) { + router.push(paths.dashboard.faucet); + } + + }, [inviter]) + const { data, isPending, refetch } = useRoochClientQuery( 'getBalance', { @@ -128,8 +138,9 @@ export function InviterFaucetView({ inviterAddress }: { inviterAddress: string } ) { let sign: Bytes | undefined const pk = wallet.wallet!.getPublicKey().toBytes() + const signMsg = 'Welcome to use Rooch! Hold BTC Claim your Rgas.' try { - sign = await wallet.wallet?.sign(stringToBytes('utf8', 'hello, rooch')) + sign = await wallet.wallet?.sign(stringToBytes('utf8', signMsg)) } catch (e) { toast.error(e.message) } @@ -144,7 +155,7 @@ export function InviterFaucetView({ inviterAddress }: { inviterAddress: string } inviter: inviterAddress, claimer_sign: toHEX(sign), public_key: toHEX(pk), - message: 'hello, rooch', + message: signMsg, }); const response = await fetch(`${faucetUrl}/faucet-inviter`, { method: 'POST', @@ -169,6 +180,7 @@ export function InviterFaucetView({ inviterAddress }: { inviterAddress: string } } const d = await response.json(); + window.localStorage.setItem(INVITER_ADDRESS_KEY, '') await refetch(); toast.success( `Faucet Success! RGas: ${formatCoin(Number(d.gas || 0), data?.decimals || 0, 2)}` diff --git a/infra/rooch-portal-v2/src/sections/invitations/components/invitation-list.tsx b/infra/rooch-portal-v2/src/sections/invitations/components/invitation-list.tsx index 1bf17c3d23..0d1683082f 100644 --- a/infra/rooch-portal-v2/src/sections/invitations/components/invitation-list.tsx +++ b/infra/rooch-portal-v2/src/sections/invitations/components/invitation-list.tsx @@ -102,7 +102,7 @@ export function InvitationList({ table }: { table?: string }) { )} ))} - + )} diff --git a/infra/rooch-portal-v2/src/sections/settings/view.tsx b/infra/rooch-portal-v2/src/sections/settings/view.tsx index 3116ee6027..9375d41cbd 100644 --- a/infra/rooch-portal-v2/src/sections/settings/view.tsx +++ b/infra/rooch-portal-v2/src/sections/settings/view.tsx @@ -3,13 +3,14 @@ import axios from 'axios' import { useState, useEffect, useCallback } from 'react' import { CopyToClipboard } from 'react-copy-to-clipboard' -import { Args, Transaction, stringToBytes } from '@roochnetwork/rooch-sdk' +import { Args, Transaction, stringToBytes, toHEX } from '@roochnetwork/rooch-sdk' import { useRoochClient, useCurrentAddress, useCurrentNetwork, useCurrentSession, - useRoochClientQuery + useRoochClientQuery, + useCurrentWallet } from '@roochnetwork/rooch-sdk-kit' import { LoadingButton } from '@mui/lab' @@ -25,6 +26,7 @@ import { Iconify } from 'src/components/iconify' import { useNetworkVariable } from '../../hooks/use-networks' import SessionKeysTableCard from './components/session-keys-table-card' import SessionKeyGuardButtonV1 from '../../components/auth/session-key-guard-button-v1' +import { INVITER_ADDRESS_KEY } from 'src/utils/inviter' export function SettingsView() { const address = useCurrentAddress() @@ -34,6 +36,8 @@ export function SettingsView() { const network = useCurrentNetwork() const faucetUrl = useNetworkVariable('faucetUrl') const twitterOracleAddress = useNetworkVariable('twitterOracleAddress') + const [inviterCA, inviterModule, inviterConf] = useNetworkVariable('inviterCA'); + const wallet = useCurrentWallet() const [tweetStatus, setTweetStatus] = useState('') const [twitterId, setTwitterId] = useState() const [verifying, setVerifying] = useState(false) @@ -104,6 +108,116 @@ export function SettingsView() { } } + const bindTwitter = async (pureTweetId: string) => { + await axios.post( + `${faucetUrl}/verify-and-binding-twitter-account`, + { + tweet_id: pureTweetId, + }, + { + headers: { + 'Content-Type': 'application/json', + }, + }, + ) + } + + const bindWithInviter = async (inviterAddr: string, pureTweetId: string) => { + const signMsg = 'Welcome to use Rooch! Connect with Twitter and claim your Rgas.' + const sign = await wallet.wallet?.sign(stringToBytes('utf8', signMsg)) + const pk = wallet.wallet!.getPublicKey().toBytes() + + const payload = JSON.stringify({ + inviter: inviterAddr, + tweet_id: pureTweetId, + claimer_sign: toHEX(sign!), + public_key: toHEX(pk), + message: signMsg, + }); + await axios.post( + `${faucetUrl}/binding-twitter-with-inviter`, + payload, + { + headers: { + 'Content-Type': 'application/json', + }, + }, + ) + + window.localStorage.setItem(INVITER_ADDRESS_KEY, '') + } + + const handleBindTwitter = async () => { + + // setp 1, check twitter + const match = tweetStatus.match(/status\/(\d+)/) + + if (!match) { + toast.error('twitter invald') + return + } + setVerifying(true) + const pureTweetId = match[1] + + try { + const pureTweetId = match[1] + const res = await axios.post( + `${faucetUrl}/fetch-tweet`, + { + tweet_id: pureTweetId, + }, + { + headers: { + 'Content-Type': 'application/json', + }, + }, + ) + + if (!res.data.ok) { + toast.error('fetch twitter failed') + return + } + + // step 2, check inviter + const inviterAddr = window.localStorage.getItem(INVITER_ADDRESS_KEY) + if (inviterAddr && inviterAddr !== '') { + // check invite is open + const result = await client.queryObjectStates({ + filter: { + object_type: `${inviterCA}::${inviterModule}::${inviterConf}`, + }, + queryOption: { + decode: true, + }, + }); + + if (result && result.data.length > 0 && result.data[0].decoded_value?.value.is_open === true) { + await bindWithInviter(inviterAddr, pureTweetId) + } else { + await bindTwitter(pureTweetId) + } + + await sleep(3000) + const checkRes = await fetchTwitterId() + if (checkRes) { + toast.success('Binding success') + } + } + } catch(error) { + if ('response' in error) { + if ('error' in error.response.data) { + toast.error(error.response.data.error) + } else { + toast.error(error.response.data) + } + } else { + toast.error(error.message) + } + } finally { + setVerifying(false) + } + } + const networkText = network === 'mainnet' ? 'Pre-mainnet' : 'Testnet' const XText = `BTC:${address?.toStr()} @@ -216,50 +330,7 @@ https://${network === 'mainnet' ? '':'test-'}portal.rooch.network/inviter/${addr loading={verifying} className="mt-2 w-fit" variant="contained" - onClick={async () => { - try { - setVerifying(true) - const match = tweetStatus.match(/status\/(\d+)/) - if (match) { - const pureTweetId = match[1] - const res = await axios.post( - `${faucetUrl}/fetch-tweet`, - { - tweet_id: pureTweetId, - }, - { - headers: { - 'Content-Type': 'application/json', - }, - }, - ) - console.log('🚀 ~ file: view.tsx:190 ~ onClick={ ~ res:', res) - if (res?.data?.ok) { - await axios.post( - `${faucetUrl}/verify-and-binding-twitter-account`, - { - tweet_id: pureTweetId, - }, - { - headers: { - 'Content-Type': 'application/json', - }, - }, - ) - } - await sleep(3000) - const checkRes = await fetchTwitterId() - if (checkRes) { - toast.success('Binding success') - } - } - } catch (error) { - console.log('🚀 ~ file: view.tsx:211 ~ onClick={ ~ error:', error) - toast.error(error.response.data.error) - } finally { - setVerifying(false) - } - }} + onClick={handleBindTwitter} > Verify and bind Twitter account From cf02cec9e6830337e893388fa5886c6da2e1b3b6 Mon Sep 17 00:00:00 2001 From: sven Tan Date: Fri, 6 Dec 2024 22:07:22 +0800 Subject: [PATCH 7/7] fix build --- infra/rooch-portal-v2/src/hooks/use-networks.ts | 2 +- infra/rooch-portal-v2/src/sections/faucet/inviter.tsx | 4 ++-- infra/rooch-portal-v2/src/sections/settings/view.tsx | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/infra/rooch-portal-v2/src/hooks/use-networks.ts b/infra/rooch-portal-v2/src/hooks/use-networks.ts index 61056f7de3..d45ebd04c2 100644 --- a/infra/rooch-portal-v2/src/hooks/use-networks.ts +++ b/infra/rooch-portal-v2/src/hooks/use-networks.ts @@ -37,7 +37,7 @@ const { networkConfig, useNetworkVariable, useNetworkVariables } = createNetwork mintAddress: ROOCH_MINT_OPERATING_ADDRESS, btcGasAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', gasMarketAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e 744c13f2d9998bf76cc3', - faucetUrl: 'http://192.168.31.134', + faucetUrl: FAUCET_TESTNET, faucetAddress: '0x701c21bf1c8cd5af8c42983890d8ca55e7a820171b8e744c13f2d9998bf76cc3', faucetObject: '0xd5723eda84f691ae2623da79312c7909b1737c5b3866ecc5dbd6aa21718ff15d', BTCMemPool: 'https://mempool.space/testnet/tx/', diff --git a/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx b/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx index 7117c300dd..394b7bfb31 100644 --- a/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx +++ b/infra/rooch-portal-v2/src/sections/faucet/inviter.tsx @@ -22,8 +22,8 @@ import { DashboardContent } from 'src/layouts/dashboard'; import { toast } from 'src/components/snackbar'; -import { paths } from '../../routes/paths'; import { INVITER_ADDRESS_KEY } from 'src/utils/inviter'; +import { paths } from '../../routes/paths'; const FAUCET_NOT_OPEN = 'Faucet Not Open'; const INVALID_UTXO = 'Invalid UTXO'; @@ -72,7 +72,7 @@ export function InviterFaucetView({ inviterAddress }: { inviterAddress: string } router.push(paths.dashboard.faucet); } - }, [inviter]) + }, [inviter, router]) const { data, isPending, refetch } = useRoochClientQuery( 'getBalance', diff --git a/infra/rooch-portal-v2/src/sections/settings/view.tsx b/infra/rooch-portal-v2/src/sections/settings/view.tsx index 9375d41cbd..00e5414da0 100644 --- a/infra/rooch-portal-v2/src/sections/settings/view.tsx +++ b/infra/rooch-portal-v2/src/sections/settings/view.tsx @@ -26,7 +26,7 @@ import { Iconify } from 'src/components/iconify' import { useNetworkVariable } from '../../hooks/use-networks' import SessionKeysTableCard from './components/session-keys-table-card' import SessionKeyGuardButtonV1 from '../../components/auth/session-key-guard-button-v1' -import { INVITER_ADDRESS_KEY } from 'src/utils/inviter' +import { INVITER_ADDRESS_KEY } from "../../utils/inviter"; export function SettingsView() { const address = useCurrentAddress()