Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
git_hook_setup = cp .githooks/pre-commit .git/hooks/pre-commit
git_diff_to_master = git diff --name-only --diff-filter=ACMRTUXB origin/master > DIFF
create_test_paybutton_json = echo { \"priceAPIURL\": \"foo\", \"networkBlockchainClients\": { \"ecash\": \"chronik\", \"bitcoincash\": \"chronik\" }, \"networkBlockchainURLs\": { \"ecash\": \"https://xec.paybutton.io\", \"bitcoincash\": \"https://bch.paybutton.io\" }, \"wsBaseURL\": \"http://localhost:5000\", \"apiDomain\": \"http://localhost:3000\" } > paybutton-config.json
create_test_paybutton_json = echo { \"priceAPIURL\": \"foo\", \"networkBlockchainClients\": { \"ecash\": \"chronik\", \"bitcoincash\": \"chronik\" }, \"networkBlockchainURLs\": { \"ecash\": [\"https://xec.paybutton.io\"], \"bitcoincash\": [\"https://bch.paybutton.io\"] }, \"wsBaseURL\": \"http://localhost:5000\", \"apiDomain\": \"http://localhost:3000\" } > paybutton-config.json
touch_local_env = touch .env.local

prod:
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ default: false,
#### networkBlockchainURLs
```
type: {
"ecash": "https://chronik.fabien.cash",
"bitcoincash": "https://chronik.pay2stay.com/bch"
"ecash": ["https://xec.paybutton.org", "https://chronik.fabien.cash"],
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be .io.

"bitcoincash": ["https://chronik.pay2stay.com/bch"]
}

```
Expand Down
24 changes: 24 additions & 0 deletions components/Admin/ChronikURLs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { MainNetworkSlugsType } from 'constants/index'

interface IProps {
chronikUrls: Record<MainNetworkSlugsType, string[]>
}
export default function ChronikURLs ({ chronikUrls }: IProps): JSX.Element {
return <>
<h3>Chronik URLs</h3>
<div className="paybutton-table-ctn columns">
<div>
<h4>eCash</h4>
<ol>
{chronikUrls.ecash.map((url, idx) => <li key={idx}>{url}</li>)}
</ol>
</div>
<div>
<h4>Bitcoin Cash</h4>
<ol>
{chronikUrls.bitcoincash.map((url, idx) => <li key={idx}>{url}</li>)}
</ol>
</div>
</div>
</>
}
20 changes: 12 additions & 8 deletions components/Admin/RegisteredUsers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,27 @@ import { UserWithSupertokens } from 'services/userService'
import style from './admin.module.css'
import moment from 'moment'
import TableContainer from '../../components/TableContainer/TableContainer'
import { Cell, CellProps } from 'react-table'

interface IProps {
users: UserWithSupertokens[]
}

export default function RegisteredUsers({ users }: IProps): JSX.Element {
export default function RegisteredUsers ({ users }: IProps): JSX.Element {
if (users === undefined) return <></>

const columns = [
{
Header: 'Registered',
accessor: 'registered',
Cell: ({ cell }: any) => <span>{cell.value}</span>
Cell: ({ cell }: CellProps<UserWithSupertokens>) => <span>{cell.value}</span>
},
{
Header: 'Email',
accessor: 'email',
Cell: ({ cell }: any) => (
Cell: ({ cell }: Cell<UserWithSupertokens>) => (
<a
href={`/api/auth/dashboard/?userid=${cell.row.original.id}&recipeId=emailpassword`}
href={`/api/auth/dashboard/?userid=${cell.row.original.id as string}&recipeId=emailpassword`}
target="_blank"
rel="noopener noreferrer"
>
Expand All @@ -32,18 +33,21 @@ export default function RegisteredUsers({ users }: IProps): JSX.Element {
{
Header: 'Admin',
accessor: 'isAdmin',
Cell: ({ cell }: any) => (
Cell: ({ cell }: CellProps<UserWithSupertokens>) => (
cell.value === true ? <span className={style.admin}>Yes</span> : 'No'
)
}
]
console.log({users})
console.log({ users })
const data = users.map(user => ({
id: (user.stUser?.id === undefined || user.stUser?.id === '') ? user.userProfile?.id : user.stUser?.id,
registered: user.stUser ? moment(user.stUser.timeJoined).fromNow() : 'NO ST USER FOUND',
registered: (user.stUser != null) ? moment(user.stUser.timeJoined).fromNow() : 'NO ST USER FOUND',
email: (user.stUser?.email === undefined || user.stUser?.email === '') ? user.userProfile?.id : user.stUser?.email,
isAdmin: user.userProfile?.isAdmin
}))

return <TableContainer columns={columns} data={data} ssr />
return <>
<h3>Registered Users</h3>
<TableContainer columns={columns} data={data} ssr />
</>
}
51 changes: 51 additions & 0 deletions components/Admin/SubscribedAddresses.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useEffect, useMemo, useState } from 'react'
import Image from 'next/image'
import EyeIcon from 'assets/eye-icon.png'
import TableContainer from 'components/TableContainer/TableContainer'

export default function SubscribedAddresses (): JSX.Element {
const [ecashSubscribedAddresses, setEcashSubscribedAddresses] = useState<string[]>([])
const [bitcoincashSubscribedAddresses, setBitcoincashSubscribedAddresses] = useState<string[]>([])

useEffect(() => {
void (async () => {
const ok = await (await fetch('chronikStatus')).json()
const subscribedEcashAddresses = ok.ecash?.map((value: string) => ({ address: value }))
const subscribedBitcoincashAddresses = ok.bitcoincash?.map((value: string) => ({ address: value }))
setEcashSubscribedAddresses(subscribedEcashAddresses)
setBitcoincashSubscribedAddresses(subscribedBitcoincashAddresses)
})()
}, [])

const columns = useMemo(
() => [
{
Header: 'Subscribed addresses',
accessor: 'address',
Cell: (cellProps: any) => {
return <div className="table-date">{cellProps.cell.value}</div>
}
},
{
Header: 'View',
accessor: 'view',
Cell: (cellProps: any) => {
return <a href={`https://explorer.e.cash/address/${cellProps.cell.row.values.address as string}`} target="_blank" rel="noopener noreferrer" className="table-eye-ctn">
<div className="table-eye">
<Image src={EyeIcon} alt='View on explorer' />
</div>
</a>
}
}
],
[]
)

return <>
<h3>Subscribed Addresses</h3>
<h4> eCash</h4>
<TableContainer columns={columns} data={ecashSubscribedAddresses ?? []} ssr/>
<h4> Bitcoin Cash</h4>
<TableContainer columns={columns} data={bitcoincashSubscribedAddresses ?? []} ssr/>
</>
}
6 changes: 3 additions & 3 deletions components/ButtonGenerator/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import style from '../../styles/landing.module.css'
import { PayButton, Widget as PayButtonWidget } from '@paybutton/react'
import { ChromePicker } from 'react-color'
import CodeBlock from './CodeBlock'
import { decode } from 'ecashaddrjs'
import { decodeCashAddress } from 'ecashaddrjs'
import { generatorFormFields } from './data.js'
import {
PRIMARY_XEC_COLOR,
Expand Down Expand Up @@ -83,7 +83,7 @@ export const initialButtonState: ButtonState = {
onOpen: '',
onClose: '',
wsBaseURL: '',
apiBaseURL: '',
apiBaseURL: ''
}

export default function ButtonGenerator (): JSX.Element {
Expand All @@ -93,7 +93,7 @@ export default function ButtonGenerator (): JSX.Element {

const isValidAddress = (address: string): string => {
try {
return decode(address).prefix
return decodeCashAddress(address).prefix
} catch (err) {
return 'not valid'
}
Expand Down
15 changes: 12 additions & 3 deletions config/example-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,18 @@
"bitcoincash": "chronik"
},
"networkBlockchainURLs": {
"ecash": "https://xec.paybutton.io",
"bitcoincash": "https://bch.paybutton.io"

"ecash": [
"https://xec.paybutton.io",
"https://chronik1.alitayin.com",
"https://chronik2.alitayin.com",
"https://chronik.e.cash",
"https://chronik-native1.fabien.cash",
"https://chronik-native2.fabien.cash",
"https://chronik-native3.fabien.cash",
"https://chronik.pay2stay.com/xec",
"https://chronik.pay2stay.com/xec2"
],
"bitcoincash": ["https://bch.paybutton.io"]
},
"networksUnderMaintenance": {
"bitcoincash": true
Expand Down
6 changes: 3 additions & 3 deletions config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface Config {
priceAPIURL: string
redisURL: string
networkBlockchainClients: KeyValueT<BlockchainClientOptions>
networkBlockchainURLs: KeyValueT<string>
networkBlockchainURLs: KeyValueT<string[]>
networksUnderMaintenance: KeyValueT<boolean>
triggerPOSTTimeout: number
sideshiftAffiliateId: string
Expand All @@ -35,15 +35,15 @@ const readConfig = (): Config => {
if (
(
config.networkBlockchainURLs.ecash === undefined ||
config.networkBlockchainURLs.ecash === ''
config.networkBlockchainURLs.ecash.length === 0
) &&
!config.networksUnderMaintenance.ecash
) {
throw new Error(RESPONSE_MESSAGES.MISSING_BLOCKCHAIN_CLIENT_URL_400('ecash').message)
} else if (
(
config.networkBlockchainURLs.bitcoincash === undefined ||
config.networkBlockchainURLs.bitcoincash === ''
config.networkBlockchainURLs.bitcoincash.length === 0
) &&
!config.networksUnderMaintenance.bitcoincash
) {
Expand Down
3 changes: 3 additions & 0 deletions constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ export const FETCH_N_TIMEOUT = 120000
// When fetching some address transactions, delay (in ms) between each fetch.
export const FETCH_DELAY = 100

// Delay to check if latency test has finished, when the app starts.
export const LATENCY_TEST_CHECK_DELAY = 200

// Wait time (in ms) to see if there are new unsynced addresses
export const SYNC_NEW_ADDRESSES_DELAY = 10000

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"cors": "^2.8.5",
"cross-env": "^7.0.2",
"dotenv-cli": "^5.1.0",
"ecashaddrjs": "^1.5.8",
"ecashaddrjs": "^2.0.0",
"express": "^4.17.1",
"graphql": "^16.3.0",
"helmet": "^4.4.1",
Expand Down Expand Up @@ -97,7 +97,7 @@
"typescript": "^5.7.2"
},
"resolutions": {
"chronik-client-cashtokens/ecashaddrjs": "^1.5.8"
"chronik-client-cashtokens/ecashaddrjs": "^2.0.0"
},
"lint-staged": {
"*.ts?(x)": [
Expand Down
4 changes: 4 additions & 0 deletions pages/admin/admin.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@
border-radius: 5px;
max-width: 600px;
}

.divisor {
margin: 3rem;
}
65 changes: 19 additions & 46 deletions pages/admin/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState, useMemo } from 'react'
import React, { useEffect, useState } from 'react'
import supertokensNode from 'supertokens-node'
import * as SuperTokensConfig from '../../config/backendConfig'
import Session from 'supertokens-node/recipe/session'
Expand All @@ -8,10 +8,11 @@ import style from './admin.module.css'
import { fetchUserWithSupertokens, isUserAdmin, UserWithSupertokens } from 'services/userService'
import { useRouter } from 'next/router'
import RegisteredUsers from 'components/Admin/RegisteredUsers'
import TableContainer from '../../components/TableContainer/TableContainer'
import EyeIcon from 'assets/eye-icon.png'
import Image from 'next/image'
import { removeUnserializableFields } from 'utils'
import { multiBlockchainClient } from 'services/chronikService'
import { MainNetworkSlugsType } from 'constants/index'
import SubscribedAddresses from 'components/Admin/SubscribedAddresses'
import ChronikURLs from 'components/Admin/ChronikURLs'

export const getServerSideProps: GetServerSideProps = async (context) => {
// this runs on the backend, so we must call init on supertokens-node SDK
Expand All @@ -32,13 +33,15 @@ export const getServerSideProps: GetServerSideProps = async (context) => {
const userId = session?.getUserId()
const user = await fetchUserWithSupertokens(userId)
removeUnserializableFields(user.userProfile)
const chronikUrls = multiBlockchainClient.getUrls()

const isAdmin = await isUserAdmin(userId)
return {
props: {
userId,
user,
isAdmin
isAdmin,
chronikUrls
}
}
}
Expand All @@ -47,12 +50,12 @@ interface IProps {
userId: string
isAdmin: boolean
user: supertokensNode.User | undefined
chronikUrls: Record<MainNetworkSlugsType, string[]>

}

export default function Admin ({ user, isAdmin }: IProps): JSX.Element {
export default function Admin ({ user, isAdmin, chronikUrls }: IProps): JSX.Element {
const router = useRouter()
const [ecashSubscribedAddresses, setEcashSubscribedAddresses] = useState<string[]>([])
const [bitcoincashSubscribedAddresses, setBitcoincashSubscribedAddresses] = useState<string[]>([])
const [users, setUsers] = useState<UserWithSupertokens[]>([])

useEffect(() => {
Expand All @@ -63,48 +66,15 @@ export default function Admin ({ user, isAdmin }: IProps): JSX.Element {

useEffect(() => {
void (async () => {
const ok = await (await fetch('chronikStatus')).json()
const subscribedEcashAddresses = ok.ecash?.map((value: string) => ({ address: value }))
const subscribedBitcoincashAddresses = ok.bitcoincash?.map((value: string) => ({ address: value }))
setEcashSubscribedAddresses(subscribedEcashAddresses)
setBitcoincashSubscribedAddresses(subscribedBitcoincashAddresses)
const ok2 = await (await fetch('/api/users')).json()
setUsers(ok2)
const usersJSON = await (await fetch('/api/users')).json()
setUsers(usersJSON)
})()
}, [])

const columns = useMemo(
() => [
{
Header: 'Subscribed addresses',
accessor: 'address',
Cell: (cellProps: any) => {
return <div className="table-date">{cellProps.cell.value}</div>
}
},
{
Header: 'View',
accessor: 'view',
Cell: (cellProps: any) => {
return <a href={`https://explorer.e.cash/address/${cellProps.cell.row.values.address as string}`} target="_blank" rel="noopener noreferrer" className="table-eye-ctn">
<div className="table-eye">
<Image src={EyeIcon} alt='View on explorer' />
</div>
</a>
}
}
],
[]
)

if (user !== null && isAdmin) {
return <>
<h2>Admin Dashboard</h2>
<div className={style.admin_ctn}>
<h3> eCash</h3>
<TableContainer columns={columns} data={ecashSubscribedAddresses ?? []} ssr/>
<h3> Bitcoin Cash</h3>
<TableContainer columns={columns} data={bitcoincashSubscribedAddresses ?? []} ssr/>
<h2>Admin Dashboard</h2>
<a
target="_blank"
rel="noopener noreferrer"
Expand All @@ -113,9 +83,12 @@ export default function Admin ({ user, isAdmin }: IProps): JSX.Element {
>
Go to Supertokens Admin Dashboard
</a>
<h4>Registered Users</h4>
<RegisteredUsers users={users}/>
</div>
<ChronikURLs chronikUrls={chronikUrls}/>
<hr className={style.divisor}/>
<SubscribedAddresses/>
<hr className={style.divisor}/>
<RegisteredUsers users={users}/>
</>
} else {
return <Page/>
Expand Down
Loading