├── .circleci └── config.yml ├── .env.prod ├── .env.stage ├── .env.staging.stash ├── .gitignore ├── .prettierrc.json ├── LICENSE ├── README.md ├── configureLocalEnv.js ├── index.html ├── package-lock.json ├── package.json ├── public ├── favicon.ico └── manifest.json ├── scripts ├── advanceBlocks.js ├── publishScripts.sh ├── pullDevAccounts.js ├── rerouteLegacy.cjs └── updateBuild.cjs ├── src ├── App.module.css ├── App.tsx ├── AppMobile.module.css ├── assets │ ├── animations │ │ └── loadingSpinningGlyph.json │ ├── img │ │ ├── WhatIsAudiusBackground@2x.jpg │ │ ├── apiBanner@2x.png │ │ ├── apiLogo.png │ │ ├── audiusLogoHorizontal.svg │ │ ├── headerImg@2x.jpg │ │ ├── iconAllServices.svg │ │ ├── iconContentNode.svg │ │ ├── iconCopy.svg │ │ ├── iconDeregister.svg │ │ ├── iconDiscoveryProvider.svg │ │ ├── iconPencil.svg │ │ ├── iconRegisterService.svg │ │ ├── iconRemove.svg │ │ ├── iconThumbDown.svg │ │ ├── iconThumbUp.svg │ │ ├── iconTrash.svg │ │ ├── iconValidationCheck.svg │ │ ├── iconValidationX.svg │ │ ├── iconView.svg │ │ ├── iconWarning.svg │ │ ├── iconYourServices.svg │ │ ├── imageBlank2x.png │ │ └── uhOh.svg │ └── styles │ │ ├── colors.css │ │ └── index.css ├── components │ ├── ApiCallsStat │ │ ├── ApiCallsStat.tsx │ │ └── index.tsx │ ├── AppBar │ │ ├── AppBar.module.css │ │ ├── AppBar.tsx │ │ ├── AppBarMobile.module.css │ │ └── index.tsx │ ├── AudioRewardsModal │ │ ├── AudioRewardsModal.module.css │ │ ├── AudioRewardsModal.tsx │ │ └── index.tsx │ ├── BarChart │ │ ├── BarChart.module.css │ │ ├── BarChart.tsx │ │ ├── BarChartMobile.module.css │ │ ├── draw.tsx │ │ └── index.tsx │ ├── Bounds │ │ ├── Bounds.module.css │ │ ├── Bounds.tsx │ │ └── index.tsx │ ├── Button │ │ ├── Button.module.css │ │ ├── Button.tsx │ │ └── index.tsx │ ├── ConfirmTransactionModal │ │ ├── ConfirmTransactionModal.module.css │ │ ├── ConfirmTransactionModal.tsx │ │ └── index.tsx │ ├── ConnectMetaMaskModal │ │ ├── ConnectMetaMaskModal.module.css │ │ ├── ConnectMetaMaskModal.tsx │ │ └── index.tsx │ ├── ContentTable │ │ ├── ContentTable.module.css │ │ ├── ContentTable.tsx │ │ └── index.tsx │ ├── DecreaseStakeModal │ │ ├── DecreaseStakeModal.module.css │ │ ├── DecreaseStakeModal.tsx │ │ └── index.tsx │ ├── Delegate │ │ ├── Delegate.module.css │ │ ├── Delegate.tsx │ │ └── index.tsx │ ├── DelegateStakeModal │ │ ├── DelegateStakeModal.module.css │ │ ├── DelegateStakeModal.tsx │ │ └── index.tsx │ ├── DelegatesModal │ │ ├── DelegatesModal.module.css │ │ ├── DelegatesModal.tsx │ │ └── index.tsx │ ├── DelegatesTable │ │ ├── DelegatesTable.module.css │ │ ├── DelegatesTable.tsx │ │ └── index.tsx │ ├── DelegationStatsChip │ │ ├── DelegationStatsChip.module.css │ │ └── DelegationStatsChip.tsx │ ├── DelegatorsModal │ │ ├── DelegatorsModal.module.css │ │ ├── DelegatorsModal.tsx │ │ └── index.tsx │ ├── DelegatorsTable │ │ ├── DelegatorsTable.module.css │ │ ├── DelegatorsTable.tsx │ │ └── index.tsx │ ├── DeregisterServiceModal │ │ ├── DeregisterServiceModal.module.css │ │ ├── DeregisterServiceModal.tsx │ │ └── index.tsx │ ├── DiscoveryTable │ │ ├── DiscoveryTable.module.css │ │ ├── DiscoveryTable.tsx │ │ └── index.tsx │ ├── DisplayAudio │ │ ├── DisplayAudio.module.css │ │ ├── DisplayAudio.tsx │ │ └── index.tsx │ ├── Dropdown │ │ ├── Dropdown.module.css │ │ ├── Dropdown.tsx │ │ └── index.tsx │ ├── Error │ │ ├── Error.module.css │ │ ├── Error.tsx │ │ └── index.tsx │ ├── ErrorModal │ │ ├── ErrorModal.module.css │ │ ├── ErrorModal.tsx │ │ └── index.tsx │ ├── EstimatedAnnualStat │ │ ├── EstimatedAnnualStat.module.css │ │ ├── EstimatedAnnualStat.tsx │ │ └── index.tsx │ ├── EstimatedWeeklyStat │ │ ├── EstimatedWeeklyStat.tsx │ │ └── index.tsx │ ├── Header │ │ ├── Header.module.css │ │ ├── Header.tsx │ │ ├── HeaderMobile.module.css │ │ └── index.tsx │ ├── InlineStat │ │ ├── InlineStat.module.css │ │ └── InlineStat.tsx │ ├── LineChart │ │ ├── LineChart.module.css │ │ ├── LineChart.tsx │ │ ├── LineChartMobile.module.css │ │ └── index.tsx │ ├── Loading │ │ ├── Loading.module.css │ │ ├── Loading.tsx │ │ └── index.tsx │ ├── ManageService │ │ ├── ManageService.module.css │ │ ├── ManageService.tsx │ │ └── index.tsx │ ├── MinimumDelegationAmountModal │ │ ├── MinimumDelegationAmountModal.module.css │ │ ├── MinimumDelegationAmountModal.tsx │ │ └── index.tsx │ ├── MobileNav │ │ ├── MobileNav.module.css │ │ ├── MobileNav.tsx │ │ └── index.tsx │ ├── Modal │ │ ├── Modal.module.css │ │ ├── Modal.tsx │ │ └── index.tsx │ ├── ModalTable │ │ ├── ModalTable.module.css │ │ ├── ModalTable.tsx │ │ └── index.tsx │ ├── ModifyServiceModal │ │ ├── ModifyServiceModal.module.css │ │ ├── ModifyServiceModal.tsx │ │ └── index.tsx │ ├── MyEstimatedRewards │ │ ├── MyEstimatedRewards.module.css │ │ ├── MyEstimatedRewards.tsx │ │ └── index.tsx │ ├── Nav │ │ ├── Nav.module.css │ │ ├── Nav.tsx │ │ └── index.tsx │ ├── NewProposalModal │ │ ├── NewProposalModal.module.css │ │ ├── NewProposalModal.tsx │ │ └── index.tsx │ ├── NodeOverview │ │ ├── NodeOverview.module.css │ │ ├── NodeOverview.tsx │ │ ├── NodeOverviewMobile.module.css │ │ └── index.tsx │ ├── OperatorCutModal │ │ ├── OperatorCutModal.module.css │ │ ├── OperatorCutModal.tsx │ │ └── index.tsx │ ├── Page │ │ ├── Page.module.css │ │ ├── Page.tsx │ │ ├── PageMobile.module.css │ │ └── index.tsx │ ├── Paper │ │ ├── Paper.module.css │ │ ├── Paper.tsx │ │ └── index.tsx │ ├── PlaysChart │ │ ├── PlaysChart.tsx │ │ └── index.tsx │ ├── Proposal │ │ ├── Proposal.module.css │ │ ├── Proposal.tsx │ │ ├── ProposalMobile.module.css │ │ └── index.tsx │ ├── ProposalHero │ │ ├── ProposalHero.module.css │ │ ├── ProposalHero.tsx │ │ ├── ProposalHeroMobile.module.css │ │ └── index.tsx │ ├── ProposalStatusBadge │ │ ├── ProposalStatusBadge.module.css │ │ ├── ProposalStatusBadge.tsx │ │ └── index.tsx │ ├── ProposalStatusChip │ │ ├── ProposalStatusChip.module.css │ │ ├── ProposalStatusChip.tsx │ │ └── index.tsx │ ├── Proposals │ │ ├── Proposals.module.css │ │ ├── Proposals.tsx │ │ └── index.tsx │ ├── RadarChart │ │ ├── RadarChart.module.css │ │ ├── RadarChart.tsx │ │ ├── RadarChartMobile.module.css │ │ └── index.tsx │ ├── RegisterServiceModal │ │ ├── RegisterServiceModal.module.css │ │ ├── RegisterServiceModal.tsx │ │ └── index.tsx │ ├── RewardStat │ │ ├── RewardStat.module.css │ │ ├── RewardStat.tsx │ │ └── index.tsx │ ├── RewardsCTABanner │ │ ├── RewardsCTABanner.module.css │ │ ├── RewardsCTABanner.tsx │ │ └── index.tsx │ ├── ServiceTable │ │ ├── ServiceTable.module.css │ │ ├── ServiceTable.tsx │ │ └── index.tsx │ ├── StakingStat │ │ ├── StakingStat.module.css │ │ ├── StakingStat.tsx │ │ └── index.tsx │ ├── Stat │ │ ├── Stat.module.css │ │ ├── Stat.tsx │ │ └── index.tsx │ ├── StatsChip │ │ ├── StatsChip.module.css │ │ └── StatsChip.tsx │ ├── Table │ │ ├── Table.module.css │ │ ├── Table.tsx │ │ └── index.tsx │ ├── TextField │ │ ├── TextField.module.css │ │ ├── TextField.tsx │ │ └── index.tsx │ ├── Timeline │ │ ├── Timeline.module.css │ │ ├── Timeline.tsx │ │ ├── TimelineEvent.module.css │ │ ├── TimelineEvent.tsx │ │ ├── TimelineEventMobile.module.css │ │ ├── TimelineModal.module.css │ │ ├── TimelineModal.tsx │ │ └── index.tsx │ ├── Tooltip │ │ ├── Tooltip.module.css │ │ ├── Tooltip.tsx │ │ └── index.tsx │ ├── TopAPIAppsChart │ │ ├── TopAPIAppsChart.module.css │ │ ├── TopAPIAppsChart.tsx │ │ └── index.tsx │ ├── TopAPITable │ │ ├── TopAPITable.module.css │ │ ├── TopAPITable.tsx │ │ └── index.tsx │ ├── TopAddressesTable │ │ ├── TopAddressesTable.module.css │ │ ├── TopAddressesTable.tsx │ │ └── index.tsx │ ├── TopAlbums │ │ ├── TopAlbums.module.css │ │ ├── TopAlbums.tsx │ │ └── index.tsx │ ├── TopAppsChart │ │ ├── TopAppsChart.tsx │ │ └── index.tsx │ ├── TopGenresChart │ │ ├── TopGenresChart.tsx │ │ └── index.tsx │ ├── TopOperatorsTable │ │ ├── TopOperatorsTable.module.css │ │ ├── TopOperatorsTable.tsx │ │ └── index.tsx │ ├── TopPlaylists │ │ ├── TopPlaylists.module.css │ │ ├── TopPlaylists.tsx │ │ └── index.tsx │ ├── TopTracks │ │ ├── TopTracks.module.css │ │ ├── TopTracks.tsx │ │ ├── TopTracksMobile.module.css │ │ └── index.tsx │ ├── TotalApiCallsChart │ │ ├── TotalApiCallsChart.tsx │ │ └── index.tsx │ ├── TotalStakedChart │ │ ├── TotalStakedChart.tsx │ │ └── index.tsx │ ├── TotalStakedStat │ │ ├── TotalStakedStat.module.css │ │ ├── TotalStakedStat.tsx │ │ └── index.tsx │ ├── TransactionStatus │ │ ├── TransactionStatus.module.css │ │ ├── TransactionStatus.tsx │ │ └── index.tsx │ ├── UniqueUsersChart │ │ ├── UniqueUsersChart.tsx │ │ └── index.tsx │ ├── UniqueUsersStat │ │ ├── UniqueUsersStat.tsx │ │ └── index.tsx │ ├── UpdateDelegationModal │ │ ├── UpdateDelegationModal.module.css │ │ ├── UpdateDelegationModal.tsx │ │ └── index.tsx │ ├── UpdateStakeModal │ │ ├── UpdateStakeModal.module.css │ │ ├── UpdateStakeModal.tsx │ │ └── index.tsx │ ├── UserImage │ │ ├── UserImage.module.css │ │ ├── UserImage.tsx │ │ └── index.tsx │ ├── UserInfo │ │ ├── UserInfo.module.css │ │ ├── UserInfo.tsx │ │ ├── UserInfoMobile.module.css │ │ └── index.tsx │ ├── UserName │ │ ├── UserName.module.css │ │ ├── UserName.tsx │ │ └── index.tsx │ ├── UserStakedStat │ │ ├── UserStakedStat.module.css │ │ ├── UserStakedStat.tsx │ │ └── index.tsx │ ├── ValueSlider │ │ ├── ValueSlider.module.css │ │ ├── ValueSlider.tsx │ │ └── index.tsx │ ├── VerticalBarChart │ │ ├── VerticalBarChart.module.css │ │ ├── VerticalBarChart.tsx │ │ ├── VerticalBarChartMobile.module.css │ │ └── index.tsx │ ├── VoteMeter │ │ ├── VoteMeter.module.css │ │ ├── VoteMeter.tsx │ │ ├── VoteMeterMobile.module.css │ │ └── index.tsx │ ├── Voted │ │ ├── Voted.module.css │ │ ├── Voted.tsx │ │ └── index.tsx │ └── VotesTable │ │ ├── VotesTable.module.css │ │ ├── VotesTable.tsx │ │ └── index.tsx ├── containers │ ├── API │ │ ├── API.module.css │ │ ├── API.tsx │ │ ├── APIMobile.module.css │ │ └── index.tsx │ ├── APILeaderboard │ │ ├── APILeaderboard.module.css │ │ ├── APILeaderboard.tsx │ │ └── index.tsx │ ├── Analytics │ │ ├── Analytics.module.css │ │ ├── Analytics.tsx │ │ ├── AnalyticsMobile.module.css │ │ └── index.tsx │ ├── ContentNodes │ │ ├── ContentNodes.module.css │ │ ├── ContentNodes.tsx │ │ └── index.tsx │ ├── DiscoveryProviders │ │ ├── DiscoveryProviders.module.css │ │ ├── DiscoveryProviders.tsx │ │ └── index.tsx │ ├── Governance │ │ ├── Governance.module.css │ │ ├── Governance.tsx │ │ └── index.tsx │ ├── Home │ │ ├── Home.module.css │ │ ├── Home.tsx │ │ ├── HomeMobile.module.css │ │ └── index.tsx │ ├── Node │ │ ├── Node.module.css │ │ ├── Node.tsx │ │ └── index.tsx │ ├── NotFound │ │ ├── NotFound.module.css │ │ ├── NotFound.tsx │ │ └── index.tsx │ ├── Proposal │ │ ├── Proposal.module.css │ │ ├── Proposal.tsx │ │ ├── ProposalMobile.module.css │ │ └── index.tsx │ ├── ServiceOperators │ │ ├── ServiceOperators.module.css │ │ ├── ServiceOperators.tsx │ │ └── index.tsx │ ├── ServiceUsers │ │ ├── ServiceUsers.module.css │ │ ├── ServiceUsers.tsx │ │ └── index.tsx │ ├── Services │ │ ├── Services.module.css │ │ ├── Services.tsx │ │ ├── ServicesMobile.module.css │ │ └── index.tsx │ └── User │ │ ├── User.module.css │ │ ├── User.tsx │ │ ├── UserMobile.module.css │ │ └── index.tsx ├── hooks │ ├── useOpenLink.ts │ ├── useRerouteLegacy.ts │ ├── useRewardRate.ts │ └── useTotalStaked.ts ├── index.css ├── index.tsx ├── models │ └── TimelineEvents.ts ├── serviceWorker.ts ├── services │ ├── Audius │ │ ├── AudiusClient.ts │ │ ├── claim │ │ │ ├── claim.ts │ │ │ └── types.ts │ │ ├── delegate │ │ │ ├── delegate.ts │ │ │ └── types.ts │ │ ├── governance │ │ │ ├── governance.ts │ │ │ └── types.ts │ │ ├── helpers.ts │ │ ├── identity │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── nodeType.ts │ │ ├── service-provider │ │ │ ├── serviceProviderClient.ts │ │ │ └── types.ts │ │ ├── setup.ts │ │ ├── staking │ │ │ └── staking.ts │ │ ├── token │ │ │ └── audiusToken.ts │ │ └── wrappers.ts │ ├── AudiusSubgraph │ │ └── index.ts │ └── SelfId │ │ ├── SelfId.ts │ │ ├── index.ts │ │ └── types.ts ├── store │ ├── account │ │ ├── hooks.ts │ │ └── slice.ts │ ├── actions │ │ ├── cancelTransaction.ts │ │ ├── createProposal.ts │ │ ├── delegateStake.ts │ │ ├── deregisterService.ts │ │ ├── executeProposal.ts │ │ ├── makeClaim.ts │ │ ├── modifyService.ts │ │ ├── registerService.ts │ │ ├── removeDelegator.ts │ │ ├── submitTransaction.ts │ │ ├── submitVote.ts │ │ ├── undelegateStake.ts │ │ ├── updateDelegation.ts │ │ ├── updateMinimumDelegationAmount.ts │ │ ├── updateOperatorCut.ts │ │ ├── updateStake.ts │ │ └── userDelegation.ts │ ├── api │ │ ├── hooks.ts │ │ └── slice.ts │ ├── cache │ │ ├── analytics │ │ │ ├── genres.ts │ │ │ ├── hooks.ts │ │ │ └── slice.ts │ │ ├── claims │ │ │ ├── hooks.ts │ │ │ └── slice.ts │ │ ├── contentNode │ │ │ ├── hooks.ts │ │ │ └── slice.ts │ │ ├── discoveryProvider │ │ │ ├── hooks.ts │ │ │ └── slice.ts │ │ ├── music │ │ │ ├── hooks.ts │ │ │ └── slice.ts │ │ ├── proposals │ │ │ ├── hooks.ts │ │ │ └── slice.ts │ │ ├── protocol │ │ │ ├── hooks.ts │ │ │ └── slice.ts │ │ ├── rewards │ │ │ ├── helpers.ts │ │ │ ├── hooks.ts │ │ │ └── slice.ts │ │ ├── timeline │ │ │ ├── hooks.ts │ │ │ └── slice.ts │ │ ├── user │ │ │ ├── graph │ │ │ │ ├── formatter.ts │ │ │ │ ├── hooks.ts │ │ │ │ ├── queries.ts │ │ │ │ └── types.ts │ │ │ ├── hooks.ts │ │ │ └── slice.ts │ │ └── votes │ │ │ ├── hooks.ts │ │ │ └── slice.ts │ ├── index.ts │ ├── pageHistory │ │ ├── hooks.ts │ │ └── slice.ts │ └── types.ts ├── types.ts └── utils │ ├── activeStake.ts │ ├── consts.ts │ ├── copyToClipboard.ts │ ├── effects.ts │ ├── fetch.ts │ ├── format.ts │ ├── hooks.ts │ ├── identicon.ts │ ├── mobile.ts │ ├── numeric.ts │ └── routes.ts ├── tsconfig.json ├── tsconfig.node.json ├── types ├── 3box │ └── index.d.ts ├── identicon.js │ └── index.d.ts ├── react-custom-scrollbars │ └── index.d.ts ├── react-tippy │ └── index.d.ts ├── simplebar-react │ └── index.d.ts ├── vite-env.d.ts └── web3 │ └── index.d.ts └── vite.config.ts /.env.stage: -------------------------------------------------------------------------------- 1 | VITE_ETH_TOKEN_ADDRESS=0x5375BE4c52fA29b26077B0F15ee5254D779676A6 2 | VITE_ETH_REGISTRY_ADDRESS=0xF27A9c44d7d5DDdA29bC1eeaD94718EeAC1775e3 3 | VITE_ETH_PROVIDER_URL=https://goerli.infura.io/v3/bcb203fe1f8d4eabb7798cf5de1d9097 4 | VITE_ETH_OWNER_WALLET= 5 | VITE_QUERY_PROPOSAL_START_BLOCK = 1 6 | 7 | VITE_ETH_NETWORK_ID=5 8 | 9 | VITE_AUDIUS_URL=https://staging.audius.co 10 | VITE_GQL_URI=https://api.thegraph.com/subgraphs/name/audius-infra/audius-network-goerli 11 | VITE_REGISTRY_ADDRESS=0x793373aBF96583d5eb71a15d86fFE732CD04D452 12 | VITE_ENTITY_MANAGER_ADDRESS=0x1Cd8a543596D499B9b6E7a6eC15ECd2B7857Fd64 13 | 14 | VITE_IDENTITY_SERVICE_ENDPOINT=https://identityservice.staging.audius.co 15 | 16 | VITE_WORMHOLE_ADDRESS=0xf6f45e4d836da1d4ecd43bb1074620bfb0b7e0d7 17 | VITE_CLAIM_DISTRIBUTION_CONTRACT_ADDRESS=0x74b89B916c97d50557E8F944F32662fE52Ce378d 18 | VITE_SOLANA_WEB3_CLUSTER=mainnet-beta 19 | VITE_SOLANA_CLUSTER_ENDPOINT=https://audius.rpcpool.com 20 | VITE_WAUDIO_MINT_ADDRESS=BELGiMZQ34SDE6x2FUaML2UHDAgBLS64xvhXjX5tBBZo 21 | VITE_USDC_MINT_ADDRESS=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v 22 | VITE_SOLANA_TOKEN_PROGRAM_ADDRESS=TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA 23 | VITE_CLAIMABLE_TOKEN_PDA=Aw5AjygeMf9Nvg61BXvFSAzkqxcLqL8koepb14kvfc3W 24 | VITE_SOLANA_FEE_PAYER_ADDRESS=E3CfijtAJwBSHfwFEViAUd3xp7c8TBxwC1eXn1Fgxp8h 25 | VITE_CLAIMABLE_TOKEN_PROGRAM_ADDRESS=2sjQNmUfkV6yKKi4dPR8gWRgtyma5aiymE3aXL2RAZww 26 | VITE_REWARDS_MANAGER_PROGRAM_ID=CDpzvz7DfgbF95jSSCHLX3ERkugyfgn9Fw8ypNZ1hfXp 27 | VITE_REWARDS_MANAGER_PROGRAM_PDA=GaiG9LDYHfZGqeNaoGRzFEnLiwUT7WiC6sA6FDJX9ZPq 28 | VITE_REWARDS_MANAGER_TOKEN_PDA=HJQj8P47BdA7ugjQEn45LaESYrxhiZDygmukt8iumFZJ -------------------------------------------------------------------------------- /.env.staging.stash: -------------------------------------------------------------------------------- 1 | VITE_DATA_REGISTRY_ADDRESS=0x09033761774Fe45F40A47191DdF873F18B62DE05 2 | VITE_DATA_WEB3_PROVIDER=https://sokol.poa.network:443 3 | VITE_DATA_OWNER_WALLET=0xcccc7428648c4AdC0ae262D3547584dDAE25c465 4 | VITE_ETH_REGISTRY_ADDRESS=0xBBeB72177EF2c0ec9fF96453f924a2b9590DF9B2 5 | VITE_ETH_TOKEN_ADDRESS=0x65ca91574256B2c194A964E340e8B0A802E17ec6 6 | VITE_ETH_OWNER_WALLET=0xcccc7428648c4AdC0ae262D3547584dDAE25c465 7 | VITE_ETH_NETWORK_ID=3 8 | VITE_WORMHOLE_ADDRESS=0xf6f45e4d836da1d4ecd43bb1074620bfb0b7e0d7 9 | VITE_CLAIM_DISTRIBUTION_CONTRACT_ADDRESS=0x74b89B916c97d50557E8F944F32662fE52Ce378d 10 | VITE_REGISTRY_ADDRESS=0x793373aBF96583d5eb71a15d86fFE732CD04D452 11 | VITE_ENTITY_MANAGER_ADDRESS=0x1Cd8a543596D499B9b6E7a6eC15ECd2B7857Fd64 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # dev 9 | eth-contracts-ganache-accounts.json 10 | 11 | # testing 12 | /coverage 13 | 14 | # production 15 | /dist 16 | 17 | # misc 18 | .DS_Store 19 | .env.local 20 | .env.development.local 21 | .env.dev.local 22 | .env.test.local 23 | .env.production.local 24 | 25 | npm-debug.log* 26 | yarn-debug.log* 27 | yarn-error.log* 28 | 29 | *.swp 30 | *.swo 31 | *.swn 32 | 33 | .vscode/** 34 | 35 | .idea 36 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": false 4 | } 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2021 Audius 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Audius Service Provider Dashboard 2 | 3 | ## Summary 4 | Audius Service Provider Dashboard allows users to register content nodes and discovery providers, 5 | view their registered services & which ones are out date, and explore all audius services. 6 | 7 | ## Running the Application 8 | The application requires ethereum contracts. 9 | You can run `npm run start:stage` which will use the contracts that are on the staging environment. 10 | If you want to have contracts running locally, you'll also need to run this [setup script](https://github.com/AudiusProject/audius-protocol/blob/master/service-commands/scripts/setup.js) e.g. `node setup.js run eth-contracts up` 11 | 12 | To start: 13 | 1. Install Dependencies `npm install` 14 | 2. Run the Application `npm run start:` 15 | 16 | To Deploy: 17 | Build the application using `npm run build:prod` and serve the static `dist` folder as a simple page app via `npm run serve` 18 | 19 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 22 | 23 | Audius | Protocol Dashboard 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/protocol-dashboard/4bec2b52ae7ab8c9513778c83e318ad9607cb415/public/favicon.ico -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Audius Protocol Dashbaord", 3 | "name": "Audius Protocol Dashboard", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#CC0FE0", 14 | "background_color": "#ffffff" 15 | } -------------------------------------------------------------------------------- /scripts/advanceBlocks.js: -------------------------------------------------------------------------------- 1 | const ethWeb3ProviderEndpoint = 'http://localhost:8546' 2 | require('@openzeppelin/test-helpers/configure')({ 3 | provider: ethWeb3ProviderEndpoint, 4 | }) 5 | 6 | const { time } = require('@openzeppelin/test-helpers') 7 | 8 | const args = process.argv 9 | if (args.length < 3) { 10 | console.log('Need to provide block number arg') 11 | } 12 | 13 | const blockNumber = parseInt(args[2]) 14 | 15 | // Advance blocks to block defined 16 | time.advanceBlockTo(blockNumber).then(res => { 17 | console.log(res) 18 | console.log('Done') 19 | }) -------------------------------------------------------------------------------- /scripts/publishScripts.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # Exposes scripts to client browser and web workers by publishing them to the public folder. 3 | 4 | PUBLISH_DESTINATION="./public/scripts" 5 | 6 | declare -a modules=( 7 | "./node_modules/web3/dist/web3.min.js" 8 | ) 9 | 10 | mkdir -p "$PUBLISH_DESTINATION" 11 | for script in "${modules[@]}" 12 | do 13 | echo "published $script" 14 | cp "$script" "$PUBLISH_DESTINATION" 15 | done 16 | -------------------------------------------------------------------------------- /scripts/pullDevAccounts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * For local development, you may want to grab the public & private keys for available 3 | * funded wallets. 4 | * node ./scripts/pullDevAccounts.js 5 | */ 6 | 7 | const { exec } = require('child_process') 8 | 9 | exec(` 10 | docker cp $(docker ps -q -f "name=audius_ganache_cli_eth_contracts"):/app/eth-contracts-ganache-accounts.json . 11 | `) 12 | 13 | const accounts = require('../eth-contracts-ganache-accounts.json') 14 | const wallets = Object.keys(accounts.addresses).slice(0, 50) 15 | const homedir = require('os').homedir(); 16 | const audConfig = require(`${homedir}/.audius/eth-config.json`) 17 | const tokenAddress = audConfig['audiusTokenAddress'] 18 | 19 | console.log(`Token Address is ${tokenAddress}`) 20 | for (let w in wallets) { 21 | const wallet = wallets[w] 22 | const privateKey = Buffer.from(accounts.addresses[wallet.toLowerCase()].secretKey.data).toString('hex') 23 | console.log(`${w} | Wallet: ${wallet} | Private key: ${privateKey}`) 24 | } -------------------------------------------------------------------------------- /scripts/rerouteLegacy.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path'); 3 | 4 | let getContent = (baseUrl, path) => ` 5 | 6 | 7 | 8 | 9 |

This page has been moved to ${baseUrl}/#/${path}

10 | ` 11 | 12 | const BUILD_PATH = './dist' 13 | 14 | const redirectPaths = [ 15 | 'analytics', 16 | 'governance', 17 | 'services', 18 | './services/discovery-node', 19 | './services/content-node', 20 | './services/service-providers', 21 | './services/users', 22 | 'api', 23 | 'api/leaderboard' 24 | ] 25 | 26 | const getBaseUrl = () => { 27 | if (process.argv.length === 3 && process.argv[2] == 'stage') { 28 | return 'https://dashboard.staging.audius.org' 29 | } 30 | return 'https://dashboard.audius.org' 31 | } 32 | 33 | const writeLegacyPathRedirects = () => { 34 | if (!fs.existsSync(BUILD_PATH)) { 35 | // If the build doesn't exist, return 36 | console.error(`Build path: ${BUILD_PATH} does not exist`) 37 | return 38 | } 39 | for (let pathName of redirectPaths) { 40 | const fileFolder = path.join(__dirname, '../', BUILD_PATH, pathName) 41 | fs.mkdirSync(fileFolder, { recursive: true }) 42 | 43 | const filePath = path.join(fileFolder, 'index.html') 44 | console.log(filePath) 45 | 46 | const baseURL = getBaseUrl() 47 | const file = getContent(baseURL, pathName) 48 | fs.writeFileSync(filePath, file, 'utf8') 49 | } 50 | } 51 | 52 | 53 | if (typeof require !== 'undefined' && require.main === module) { 54 | writeLegacyPathRedirects(); 55 | } -------------------------------------------------------------------------------- /src/App.module.css: -------------------------------------------------------------------------------- 1 | .appContent { 2 | max-width: 992px; 3 | margin: 0px auto 64px; 4 | padding: 0px 16px; 5 | box-sizing: border-box; 6 | } 7 | -------------------------------------------------------------------------------- /src/AppMobile.module.css: -------------------------------------------------------------------------------- 1 | .appContainer { 2 | } 3 | 4 | .appContent { 5 | width: 100%; 6 | padding: 0px 8px; 7 | box-sizing: border-box; 8 | } 9 | -------------------------------------------------------------------------------- /src/assets/img/WhatIsAudiusBackground@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/protocol-dashboard/4bec2b52ae7ab8c9513778c83e318ad9607cb415/src/assets/img/WhatIsAudiusBackground@2x.jpg -------------------------------------------------------------------------------- /src/assets/img/apiBanner@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/protocol-dashboard/4bec2b52ae7ab8c9513778c83e318ad9607cb415/src/assets/img/apiBanner@2x.png -------------------------------------------------------------------------------- /src/assets/img/apiLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/protocol-dashboard/4bec2b52ae7ab8c9513778c83e318ad9607cb415/src/assets/img/apiLogo.png -------------------------------------------------------------------------------- /src/assets/img/headerImg@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/protocol-dashboard/4bec2b52ae7ab8c9513778c83e318ad9607cb415/src/assets/img/headerImg@2x.jpg -------------------------------------------------------------------------------- /src/assets/img/iconDeregister.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iconDeregister 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/assets/img/iconRegisterService.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iconRegisterService 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/assets/img/iconRemove.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iconRemove 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/assets/img/iconThumbDown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/img/iconThumbUp.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/img/iconValidationX.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iconValidationX 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/assets/img/iconView.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iconView 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/assets/img/iconWarning.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iconWarning 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/assets/img/iconYourServices.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iconYourServices 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/assets/img/imageBlank2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/protocol-dashboard/4bec2b52ae7ab8c9513778c83e318ad9607cb415/src/assets/img/imageBlank2x.png -------------------------------------------------------------------------------- /src/assets/img/uhOh.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/styles/colors.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Audius Color Palette 3 | * 4 | */ 5 | :root { 6 | --background: #242438; 7 | 8 | --primary: #C74BD3; 9 | --primary-dark-1: #C556D4; 10 | --primary-dark-2: #C563D6; 11 | --primary-light-1: #B748C6; 12 | --primary-light-2: #A945B9; 13 | 14 | --secondary: #9147CC; 15 | --secondary-transparent: rgba(126, 27, 204, 0.85); 16 | --secondary-dark-1: #975ACD; 17 | --secondary-dark-2: #9A60CF; 18 | --secondary-light-1: #8244B8; 19 | --secondary-light-2: #7440A4; 20 | 21 | --neutral: #BEC5E0; 22 | --neutral-dark-1: #C4CAE1; 23 | --neutral-dark-2: #CBD1E3; 24 | --neutral-dark-3: #E0E6FA; 25 | --neutral-light-1: #A2A8C2; 26 | --neutral-light-2: #9399B3; 27 | --neutral-light-3: #868AA4; 28 | --neutral-light-4: #777C96; 29 | --neutral-light-5: #696D88; 30 | --neutral-light-6: #5A5E78; 31 | --neutral-light-7: #4E4F6A; 32 | --neutral-light-8: #3F415B; 33 | --neutral-light-9: #393A54; 34 | --neutral-light-10: #35364F; 35 | --white: #32334D; 36 | --static-white: #ffffff; 37 | --darkmode-static-white: #ffffff; 38 | 39 | --skeleton: #393A54; 40 | } -------------------------------------------------------------------------------- /src/assets/styles/index.css: -------------------------------------------------------------------------------- 1 | @import './colors.css'; 2 | 3 | #root *, body * { 4 | font-family: var(--font-family); 5 | } 6 | 7 | body, h1, h2, h3, h4, h5, h6 { 8 | color: var(--neutral); 9 | } -------------------------------------------------------------------------------- /src/components/ApiCallsStat/ApiCallsStat.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import Stat from 'components/Stat' 4 | import { useTrailingApiCalls } from 'store/cache/analytics/hooks' 5 | import { Bucket, MetricError } from 'store/cache/analytics/slice' 6 | import { formatNumber } from 'utils/format' 7 | 8 | const messages = { 9 | label: 'API CALLS THIS MONTH' 10 | } 11 | 12 | type OwnProps = {} 13 | 14 | type ApiCallsStatProps = OwnProps 15 | 16 | const ApiCallsStat: React.FC = () => { 17 | const { apiCalls } = useTrailingApiCalls(Bucket.MONTH) 18 | let error, stat 19 | if (apiCalls === MetricError.ERROR) { 20 | error = true 21 | stat = null 22 | } else { 23 | stat = apiCalls?.total_count ?? null 24 | } 25 | return ( 26 | 31 | ) 32 | } 33 | 34 | export default ApiCallsStat 35 | -------------------------------------------------------------------------------- /src/components/ApiCallsStat/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './ApiCallsStat' 2 | -------------------------------------------------------------------------------- /src/components/AppBar/AppBarMobile.module.css: -------------------------------------------------------------------------------- 1 | .left { 2 | display: flex; 3 | flex-direction: column; 4 | width: 100%; 5 | align-items: center; 6 | } 7 | 8 | .logo { 9 | width: 145px; 10 | height: 38px; 11 | margin-bottom: 16px; 12 | } 13 | 14 | .logo path { 15 | fill: var(--static-white); 16 | } 17 | 18 | .name { 19 | flex-wrap: wrap; 20 | font-family: var(--font-family); 21 | font-weight: 800; 22 | font-size: var(--font-s); 23 | letter-spacing: 1px; 24 | text-transform: uppercase; 25 | text-align: center; 26 | color: var(--static-white); 27 | text-shadow: 0px 16px 20px rgba(36, 36, 56, 0.15); 28 | } 29 | -------------------------------------------------------------------------------- /src/components/AppBar/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './AppBar' 2 | -------------------------------------------------------------------------------- /src/components/AudioRewardsModal/AudioRewardsModal.module.css: -------------------------------------------------------------------------------- 1 | .apiLogo { 2 | margin: 24px auto; 3 | opacity: 1; 4 | width: 224px; 5 | filter: brightness(0) invert(1); 6 | } 7 | 8 | .header { 9 | margin: 0px auto 24px; 10 | font-weight: var(--font-bold); 11 | font-size: var(--font-2xl); 12 | line-height: 29px; 13 | text-align: center; 14 | text-transform: capitalize; 15 | color: var(--neutral); 16 | } 17 | 18 | .description { 19 | font-weight: var(--font-bold); 20 | font-size: var(--font-m); 21 | line-height: 160%; 22 | text-align: center; 23 | color: var(--neutral); 24 | margin: 0px auto; 25 | } 26 | 27 | .btn { 28 | margin: 24px auto 8px; 29 | } -------------------------------------------------------------------------------- /src/components/AudioRewardsModal/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './AudioRewardsModal' 2 | -------------------------------------------------------------------------------- /src/components/BarChart/BarChart.module.css: -------------------------------------------------------------------------------- 1 | .chartContainer { 2 | padding: 24px; 3 | display: flex; 4 | flex-direction: column; 5 | user-select: none; 6 | } 7 | 8 | .onClick { 9 | cursor: pointer; 10 | } 11 | 12 | .chart { 13 | flex-grow: 1; 14 | display: flex; 15 | justify-content: center; 16 | align-items: center; 17 | flex-direction: column; 18 | } 19 | 20 | .loading { 21 | margin: 0 auto; 22 | } 23 | 24 | .header { 25 | margin-bottom: 16px; 26 | display: flex; 27 | justify-content: space-between; 28 | align-items: center; 29 | z-index: 1; 30 | } 31 | 32 | .title { 33 | font-weight: bold; 34 | font-size: 20px; 35 | line-height: 25px; 36 | color: var(--neutral); 37 | } 38 | 39 | .columns { 40 | width: 100%; 41 | display: flex; 42 | justify-content: space-between; 43 | font-style: normal; 44 | font-weight: bold; 45 | font-size: 14px; 46 | line-height: 17px; 47 | letter-spacing: 1px; 48 | text-transform: uppercase; 49 | color: var(--neutral-light-4); 50 | margin-top: 20px; 51 | margin-bottom: 16px; 52 | } 53 | -------------------------------------------------------------------------------- /src/components/BarChart/BarChartMobile.module.css: -------------------------------------------------------------------------------- 1 | .header { 2 | margin-bottom: 32px; 3 | display: flex; 4 | flex-direction: column; 5 | justify-content: space-between; 6 | align-items: flex-start; 7 | z-index: 1; 8 | } 9 | 10 | .title { 11 | font-weight: bold; 12 | font-size: 20px; 13 | line-height: 25px; 14 | color: var(--neutral); 15 | margin-bottom: 24px; 16 | } 17 | -------------------------------------------------------------------------------- /src/components/BarChart/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './BarChart' 2 | -------------------------------------------------------------------------------- /src/components/Bounds/Bounds.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: inline-flex; 3 | flex-direction: column; 4 | align-items: center; 5 | padding: 0px; 6 | width: 300px; 7 | min-width: 300px; 8 | margin-bottom: 8px; 9 | } 10 | 11 | .rowContainer { 12 | display: inline-flex; 13 | width: 100%; 14 | justify-content: space-between; 15 | margin-bottom: 2px; 16 | } 17 | 18 | .label { 19 | font-weight: var(--font-bold); 20 | font-size: var(--font-m); 21 | letter-spacing: 0.01em; 22 | text-transform: uppercase; 23 | color: var(--neutral-light-4); 24 | } 25 | 26 | .value { 27 | font-weight: var(--font-bold); 28 | font-size: var(--font-m); 29 | 30 | text-align: right; 31 | letter-spacing: 0.01em; 32 | text-transform: uppercase; 33 | color: var(--neutral); 34 | } -------------------------------------------------------------------------------- /src/components/Bounds/Bounds.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactNode } from 'react' 2 | 3 | import Paper from 'components/Paper' 4 | import styles from './Bounds.module.css' 5 | import { Address } from 'types' 6 | import DisplayAudio from 'components/DisplayAudio' 7 | import { useUser } from 'store/cache/user/hooks' 8 | 9 | const messages = { 10 | minimumTotalStake: 'Min Allowed Stake', 11 | maximumTotalStake: 'Max Allowed Stake' 12 | } 13 | 14 | type RowStatProps = { 15 | label: string 16 | value: ReactNode 17 | } 18 | const RowStat: React.FC = ({ label, value }) => { 19 | return ( 20 |
21 |
{label}
22 |
{value}
23 |
24 | ) 25 | } 26 | 27 | type OwnProps = { 28 | wallet: Address 29 | } 30 | 31 | type BoundsProps = OwnProps 32 | 33 | /** 34 | * Shows stats about staking. Lives on the SP page 35 | */ 36 | const Bounds: React.FC = ({ wallet }) => { 37 | const { user } = useUser({ wallet }) 38 | if (!user || !('serviceProvider' in user)) { 39 | return null 40 | } 41 | const min = 42 | const max = 43 | return ( 44 | 45 | 46 | 47 | 48 | ) 49 | } 50 | 51 | export default Bounds 52 | -------------------------------------------------------------------------------- /src/components/Bounds/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './Bounds' 2 | -------------------------------------------------------------------------------- /src/components/Button/index.tsx: -------------------------------------------------------------------------------- 1 | export { default, ButtonType, ButtonSize } from './Button' 2 | -------------------------------------------------------------------------------- /src/components/ConfirmTransactionModal/index.tsx: -------------------------------------------------------------------------------- 1 | export { 2 | default, 3 | OperatorStaking, 4 | NewService, 5 | OldStake, 6 | NewStake, 7 | Delegating, 8 | ToOperator, 9 | StandaloneBox, 10 | Box 11 | } from './ConfirmTransactionModal' 12 | -------------------------------------------------------------------------------- /src/components/ConnectMetaMaskModal/ConnectMetaMaskModal.module.css: -------------------------------------------------------------------------------- 1 | .description { 2 | font-family: var(--font-family); 3 | font-weight: var(--font-bold); 4 | font-size: var(--font-m); 5 | text-align: center; 6 | color: #BEC5E0; 7 | margin: 27px auto; 8 | } 9 | 10 | .btnContainer { 11 | display: inline-flex; 12 | justify-content: center; 13 | } 14 | 15 | .okayBtn { 16 | margin-right: 8px 17 | } 18 | 19 | .openMetaMaskBtn { 20 | margin-left: 8px 21 | } 22 | -------------------------------------------------------------------------------- /src/components/ConnectMetaMaskModal/ConnectMetaMaskModal.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback } from 'react' 2 | import Modal from 'components/Modal' 3 | import Button, { ButtonType } from 'components/Button' 4 | import styles from './ConnectMetaMaskModal.module.css' 5 | 6 | const messages = { 7 | title: 'Connect MetaMask to Continue', 8 | description: 'Please sign in with MetaMask to continue', 9 | okayBtn: 'OKAY', 10 | openMetaMaskBtn: 'Open MetaMask' 11 | } 12 | 13 | type OwnProps = { 14 | isOpen: boolean 15 | onClose: () => void 16 | } 17 | 18 | type ConnectMetaMaskModalProps = OwnProps 19 | 20 | const ConnectMetaMaskModal: React.FC = ({ 21 | isOpen, 22 | onClose 23 | }: ConnectMetaMaskModalProps) => { 24 | const onOpenMetaMask = useCallback(() => { 25 | if (window.ethereum) { 26 | window.ethereum.request({ method: 'eth_requestAccounts' }) 27 | } 28 | }, []) 29 | return ( 30 | 37 |
{messages.description}
38 |
39 |
52 |
53 | ) 54 | } 55 | 56 | export default ConnectMetaMaskModal 57 | -------------------------------------------------------------------------------- /src/components/ConnectMetaMaskModal/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './ConnectMetaMaskModal' 2 | -------------------------------------------------------------------------------- /src/components/ContentTable/ContentTable.module.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/protocol-dashboard/4bec2b52ae7ab8c9513778c83e318ad9607cb415/src/components/ContentTable/ContentTable.module.css -------------------------------------------------------------------------------- /src/components/ContentTable/ContentTable.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback } from 'react' 2 | import { usePushRoute } from 'utils/effects' 3 | 4 | import { ContentNode, Address, Status } from 'types' 5 | import { SERVICES_CONTENT, contentNodePage } from 'utils/routes' 6 | 7 | import ServiceTable from 'components/ServiceTable' 8 | import { useContentNodes } from 'store/cache/contentNode/hooks' 9 | 10 | const messages = { 11 | title: 'Content Nodes', 12 | viewMore: 'View All Content Nodes' 13 | } 14 | 15 | type OwnProps = { 16 | className?: string 17 | limit?: number 18 | owner?: Address 19 | alwaysShowMore?: boolean 20 | } 21 | 22 | type ContentTableProps = OwnProps 23 | const ContentTable: React.FC = ({ 24 | className, 25 | limit, 26 | owner, 27 | alwaysShowMore 28 | }: ContentTableProps) => { 29 | const { nodes, status } = useContentNodes({ owner }) 30 | const pushRoute = usePushRoute() 31 | 32 | const onClickMore = useCallback(() => { 33 | pushRoute(SERVICES_CONTENT) 34 | }, [pushRoute]) 35 | 36 | const onRowClick = useCallback( 37 | (row: ContentNode) => { 38 | pushRoute(contentNodePage(row.spID)) 39 | }, 40 | [pushRoute] 41 | ) 42 | 43 | return ( 44 | 55 | ) 56 | } 57 | 58 | export default ContentTable 59 | -------------------------------------------------------------------------------- /src/components/ContentTable/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './ContentTable' 2 | -------------------------------------------------------------------------------- /src/components/DecreaseStakeModal/DecreaseStakeModal.module.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/protocol-dashboard/4bec2b52ae7ab8c9513778c83e318ad9607cb415/src/components/DecreaseStakeModal/DecreaseStakeModal.module.css -------------------------------------------------------------------------------- /src/components/DecreaseStakeModal/DecreaseStakeModal.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useCallback } from 'react' 2 | import clsx from 'clsx' 3 | import styles from './DecreaseStakeModal.module.css' 4 | 5 | type OwnProps = { 6 | className?: string 7 | } 8 | 9 | type DecreaseStakeModal = OwnProps 10 | 11 | const DecreaseStakeModal: React.FC = ({ className }) => { 12 | return ( 13 |
14 | decreasde it! 15 |
16 | ) 17 | } 18 | 19 | export default DecreaseStakeModal 20 | -------------------------------------------------------------------------------- /src/components/DecreaseStakeModal/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './DecreaseStakeModal' 2 | -------------------------------------------------------------------------------- /src/components/Delegate/Delegate.module.css: -------------------------------------------------------------------------------- 1 | .title { 2 | font-family: Avenir Next LT Pro; 3 | font-style: normal; 4 | font-weight: var(--font-bold); 5 | font-size: var(--font-xl); 6 | line-height: 25px; 7 | color: #BEC5E0; 8 | padding: 28px 32px; 9 | border-bottom: 1px solid #3F415B; 10 | } 11 | 12 | .content { 13 | width: 100%; 14 | display: inline-flex; 15 | justify-content: space-between; 16 | box-sizing: border-box; 17 | align-items: center; 18 | padding: 16px 32px; 19 | } 20 | 21 | .delegationContainer { 22 | display: inline-flex; 23 | flex-direction: column; 24 | align-items: center; 25 | } 26 | 27 | .delegationValue { 28 | font-family: Avenir Next LT Pro; 29 | font-weight: 800; 30 | font-size: 48px; 31 | background: -webkit-linear-gradient(315deg, #7652CC 2.04%, #B05CE6 100%); 32 | -webkit-background-clip: text; 33 | -webkit-text-fill-color: transparent; 34 | display: inline; 35 | } 36 | 37 | .delegationLabel { 38 | margin-top: 8px; 39 | font-family: Avenir Next LT Pro; 40 | font-weight: var(--font-bold); 41 | font-size: var(--font-s); 42 | line-height: 17px; 43 | letter-spacing: 0.04em; 44 | text-transform: uppercase; 45 | color: #BEC5E0; 46 | } 47 | 48 | .btnContainer { 49 | display: inline-flex; 50 | align-items: center; 51 | } 52 | 53 | /* increase and decrease btns */ 54 | .increaseBtn { 55 | margin-right: 16px; 56 | } 57 | 58 | .increaseIcon { 59 | transform: rotate(270deg); 60 | margin: 0px; 61 | } 62 | 63 | .decreaseIcon { 64 | transform: rotate(90deg); 65 | margin: 0px; 66 | } 67 | 68 | .modifyStakeBtn.disabledBtn .stakeBtnText { 69 | font-size: var(--font-s); 70 | } 71 | -------------------------------------------------------------------------------- /src/components/Delegate/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './Delegate' 2 | -------------------------------------------------------------------------------- /src/components/DelegateStakeModal/DelegateStakeModal.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | 3 | } 4 | 5 | .wrapperClassName { 6 | background: rgba(0,0,0,0.3); 7 | } 8 | 9 | .slider { 10 | max-width: 576px; 11 | margin: 27px auto; 12 | } 13 | 14 | .input { 15 | width: 480px; 16 | width: 480px; 17 | } 18 | 19 | .invalid input { 20 | color: #F15064; 21 | } 22 | -------------------------------------------------------------------------------- /src/components/DelegateStakeModal/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './DelegateStakeModal' 2 | -------------------------------------------------------------------------------- /src/components/DelegatesModal/DelegatesModal.module.css: -------------------------------------------------------------------------------- 1 | .amountHeader { 2 | width: 100%; 3 | text-align: right; 4 | } 5 | 6 | .rowContainer { 7 | height: 79px; 8 | display: inline-flex; 9 | align-items: center; 10 | width: 100%; 11 | } 12 | 13 | .rowCol { 14 | 15 | } 16 | 17 | .colImg { 18 | height: 56px; 19 | width: 56px; 20 | border-radius: 50%; 21 | margin-right: 24px; 22 | } 23 | 24 | .colAddress { 25 | font-family: var(--font-family); 26 | font-style: normal; 27 | font-weight: var(--font-regular); 28 | font-size: var(--font-m); 29 | 30 | color: #BEC5E0; 31 | flex: 1; 32 | overflow-wrap: anywhere; 33 | word-break: break-all; 34 | margin-right: 16px; 35 | } 36 | 37 | .colAmount { 38 | 39 | } 40 | 41 | .modalRow { 42 | cursor: pointer; 43 | padding: 0px 24px; 44 | border-bottom: 1px solid #3F415B; 45 | } 46 | 47 | .modalRow:last-child { 48 | border-bottom: none; 49 | } 50 | 51 | .modalRow:hover, 52 | .modalRow:active { 53 | background: #393A54; 54 | } 55 | -------------------------------------------------------------------------------- /src/components/DelegatesModal/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './DelegatesModal' 2 | -------------------------------------------------------------------------------- /src/components/DelegatesTable/DelegatesTable.module.css: -------------------------------------------------------------------------------- 1 | .amountHeader { 2 | width: 100%; 3 | text-align: right; 4 | } 5 | 6 | .rowContainer { 7 | height: 79px; 8 | display: inline-flex; 9 | align-items: center; 10 | width: 100%; 11 | } 12 | 13 | .rowCol { 14 | 15 | } 16 | 17 | .colImg { 18 | height: 56px; 19 | width: 56px; 20 | border-radius: 50%; 21 | margin-right: 24px; 22 | } 23 | 24 | .colAddress { 25 | font-family: var(--font-family); 26 | font-style: normal; 27 | font-weight: var(--font-regular); 28 | font-size: var(--font-m); 29 | 30 | color: #BEC5E0; 31 | flex: 1; 32 | } 33 | 34 | .colAmount { 35 | 36 | } 37 | 38 | .modalRow { 39 | padding: 0px 24px; 40 | border-bottom: 1px solid #3F415B; 41 | } 42 | 43 | .modalRow:last-child { 44 | border-bottom: none; 45 | } -------------------------------------------------------------------------------- /src/components/DelegatesTable/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './DelegatesTable' 2 | -------------------------------------------------------------------------------- /src/components/DelegationStatsChip/DelegationStatsChip.module.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/protocol-dashboard/4bec2b52ae7ab8c9513778c83e318ad9607cb415/src/components/DelegationStatsChip/DelegationStatsChip.module.css -------------------------------------------------------------------------------- /src/components/DelegationStatsChip/DelegationStatsChip.tsx: -------------------------------------------------------------------------------- 1 | import InlineStat from 'components/InlineStat/InlineStat' 2 | import StatsChip from 'components/StatsChip/StatsChip' 3 | import React from 'react' 4 | import BN from 'bn.js' 5 | import { formatWei } from 'utils/format' 6 | import { TICKER } from 'utils/consts' 7 | import DisplayAudio from 'components/DisplayAudio' 8 | 9 | type DelegationStatsChipProps = { 10 | className?: string 11 | deployerCut: number 12 | minDelegation: BN 13 | delegated: BN 14 | delegators: number 15 | isLoading: boolean 16 | } 17 | 18 | const messages = { 19 | deployerCut: 'Deployer Cut', 20 | delegators: 'Delegators', 21 | minDelegation: 'Min Delegation', 22 | delegated: `Delegated ${TICKER}` 23 | } 24 | 25 | /** 26 | * Shows stats about delegation. Lives on the SP page 27 | */ 28 | const DelegationStatsChip = ({ 29 | className, 30 | deployerCut, 31 | delegated, 32 | delegators, 33 | minDelegation, 34 | isLoading 35 | }: DelegationStatsChipProps) => { 36 | return ( 37 | 44 | 45 | } 48 | /> 49 | 50 | 51 | ) 52 | } 53 | 54 | export default DelegationStatsChip 55 | -------------------------------------------------------------------------------- /src/components/DelegatorsModal/DelegatorsModal.module.css: -------------------------------------------------------------------------------- 1 | .amountHeader { 2 | width: 100%; 3 | text-align: right; 4 | } 5 | 6 | .rowContainer { 7 | height: 79px; 8 | display: inline-flex; 9 | align-items: center; 10 | width: 100%; 11 | } 12 | 13 | .rowCol { 14 | 15 | } 16 | 17 | .colImg { 18 | height: 56px; 19 | width: 56px; 20 | border-radius: 50%; 21 | margin-right: 24px; 22 | } 23 | 24 | .colAddress { 25 | font-family: var(--font-family); 26 | font-style: normal; 27 | font-weight: var(--font-regular); 28 | font-size: var(--font-m); 29 | 30 | color: #BEC5E0; 31 | flex: 1; 32 | } 33 | 34 | .colAmount { 35 | 36 | } 37 | 38 | /* Modal props */ 39 | .modalRow { 40 | padding: 0px 24px; 41 | border-bottom: 1px solid #3F415B; 42 | cursor: pointer; 43 | } 44 | 45 | .modalRow:last-child { 46 | border-bottom: none; 47 | } 48 | 49 | .modalRow:hover, 50 | .modalRow:active { 51 | background: #393A54; 52 | } 53 | 54 | .trashIconContainer { 55 | cursor: pointer; 56 | height: 36px; 57 | width: 36px; 58 | display: flex; 59 | justify-content: center; 60 | align-items: center; 61 | 62 | background: #4E4F6A; 63 | box-shadow: 0px 5px 5px rgba(36, 36, 56, 0.15); 64 | border-radius: 8px; 65 | margin-left: 16px; 66 | } 67 | 68 | .trashIcon { 69 | height: 20px; 70 | width: 20px; 71 | } 72 | 73 | /* */ 74 | .subtext { 75 | margin-top: 4px; 76 | font-weight: 500; 77 | font-size: var(--font-l); 78 | text-align: center; 79 | color: #BEC5E0; 80 | } -------------------------------------------------------------------------------- /src/components/DelegatorsModal/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './DelegatorsModal' 2 | -------------------------------------------------------------------------------- /src/components/DelegatorsTable/DelegatorsTable.module.css: -------------------------------------------------------------------------------- 1 | .amountHeader { 2 | width: 100%; 3 | text-align: right; 4 | } 5 | 6 | .rowContainer { 7 | height: 79px; 8 | display: inline-flex; 9 | align-items: center; 10 | width: 100%; 11 | } 12 | 13 | .rowCol { 14 | 15 | } 16 | 17 | .colImg { 18 | height: 56px; 19 | width: 56px; 20 | border-radius: 50%; 21 | margin-right: 24px; 22 | } 23 | 24 | .colAddress { 25 | font-family: var(--font-family); 26 | font-style: normal; 27 | font-weight: var(--font-regular); 28 | font-size: var(--font-m); 29 | 30 | color: #BEC5E0; 31 | flex: 1; 32 | } 33 | 34 | .colAmount { 35 | 36 | } 37 | 38 | /* Modal props */ 39 | .modalRow { 40 | padding: 0px 24px; 41 | border-bottom: 1px solid #3F415B; 42 | } 43 | 44 | .modalRow:last-child { 45 | border-bottom: none; 46 | } 47 | 48 | .trashIconContainer { 49 | cursor: pointer; 50 | height: 36px; 51 | width: 36px; 52 | display: flex; 53 | justify-content: center; 54 | align-items: center; 55 | 56 | background: #4E4F6A; 57 | box-shadow: 0px 5px 5px rgba(36, 36, 56, 0.15); 58 | border-radius: 8px; 59 | } 60 | 61 | .trashIcon { 62 | height: 20px; 63 | width: 20px; 64 | } -------------------------------------------------------------------------------- /src/components/DelegatorsTable/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './DelegatorsTable' 2 | -------------------------------------------------------------------------------- /src/components/DeregisterServiceModal/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './DeregisterServiceModal' 2 | -------------------------------------------------------------------------------- /src/components/DiscoveryTable/DiscoveryTable.module.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/protocol-dashboard/4bec2b52ae7ab8c9513778c83e318ad9607cb415/src/components/DiscoveryTable/DiscoveryTable.module.css -------------------------------------------------------------------------------- /src/components/DiscoveryTable/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './DiscoveryTable' 2 | -------------------------------------------------------------------------------- /src/components/DisplayAudio/DisplayAudio.module.css: -------------------------------------------------------------------------------- 1 | .tooltip { 2 | cursor: pointer; 3 | } -------------------------------------------------------------------------------- /src/components/DisplayAudio/DisplayAudio.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useState } from 'react' 2 | import BN from 'bn.js' 3 | import clsx from 'clsx' 4 | 5 | import Tooltip, { Position } from 'components/Tooltip' 6 | import AudiusClient from 'services/Audius' 7 | import { formatShortAud, formatWei, formatWeiNumber } from 'utils/format' 8 | 9 | import styles from './DisplayAudio.module.css' 10 | import copyToClipboard from 'utils/copyToClipboard' 11 | 12 | type OwnProps = { 13 | className?: string 14 | amount: BN 15 | position?: Position 16 | label?: string 17 | shortFormat?: boolean 18 | } 19 | 20 | type DisplayAudioProps = OwnProps 21 | 22 | const DisplayAudio: React.FC = ({ 23 | amount, 24 | className, 25 | position, 26 | label, 27 | shortFormat = false 28 | }) => { 29 | const [tooltipText, setTooltipText] = useState(formatWei(amount)) 30 | const formatter = shortFormat ? formatShortAud : AudiusClient.displayShortAud 31 | const onClick = useCallback( 32 | e => { 33 | e.preventDefault() 34 | e.stopPropagation() 35 | copyToClipboard(formatWeiNumber(amount)) 36 | setTooltipText('Copied!') 37 | const timeout = setTimeout(() => { 38 | setTooltipText(formatWei(amount)) 39 | }, 1000) 40 | return () => clearTimeout(timeout) 41 | }, 42 | [amount, setTooltipText] 43 | ) 44 | return ( 45 | 51 | {`${formatter(amount)}${label ? ` ${label}` : ''}`} 52 | 53 | ) 54 | } 55 | 56 | export default DisplayAudio 57 | -------------------------------------------------------------------------------- /src/components/DisplayAudio/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './DisplayAudio' 2 | -------------------------------------------------------------------------------- /src/components/Dropdown/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './Dropdown' 2 | -------------------------------------------------------------------------------- /src/components/Error/Error.module.css: -------------------------------------------------------------------------------- 1 | .error { 2 | height: 100%; 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | justify-content: center; 7 | } 8 | 9 | .error > *{ 10 | height: 100%; 11 | width: 100%; 12 | padding-bottom: 16px; 13 | } 14 | 15 | .icon { 16 | width: 100%; 17 | height: 100%; 18 | } -------------------------------------------------------------------------------- /src/components/Error/Error.tsx: -------------------------------------------------------------------------------- 1 | import Tooltip from 'components/Tooltip' 2 | import React from 'react' 3 | import clsx from 'clsx' 4 | import IconUhOh from 'assets/img/uhOh.svg?react' 5 | 6 | import styles from './Error.module.css' 7 | 8 | const DEFAULT_ERROR_TEXT = 'Incomplete Data' 9 | 10 | const Error = ({ 11 | text = DEFAULT_ERROR_TEXT, 12 | className 13 | }: { 14 | text?: string 15 | className?: string 16 | }) => { 17 | return ( 18 |
19 | 20 | 21 | 22 |
23 | ) 24 | } 25 | 26 | export default Error 27 | -------------------------------------------------------------------------------- /src/components/Error/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from './Error' 2 | -------------------------------------------------------------------------------- /src/components/ErrorModal/ErrorModal.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | min-width: 720px; 3 | width: 720px; 4 | } 5 | 6 | .wrapperClassName { 7 | background-color: rgba(0,0,0,0.4); 8 | } 9 | 10 | .header { 11 | font-family: var(--font-family); 12 | font-weight: var(--font-bold); 13 | font-size: var(--font-m); 14 | text-align: center; 15 | color: #BEC5E0; 16 | margin: 24px auto; 17 | } 18 | 19 | .scrollableMessage { 20 | min-height: 0; 21 | height: 100%; 22 | max-height: 248px; 23 | 24 | width: 480px; 25 | margin: 0px auto 24px; 26 | padding: 24px 20px; 27 | background: #393A54; 28 | border: 1px solid #3F415B; 29 | box-sizing: border-box; 30 | border-radius: 8px; 31 | } 32 | 33 | .scrollableMessage :global(.simplebar-scrollbar) { 34 | width: 6px; 35 | border-radius: 4px; 36 | opacity: 0.5; 37 | } 38 | -------------------------------------------------------------------------------- /src/components/ErrorModal/ErrorModal.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import SimpleBar from 'simplebar-react' 3 | import { ButtonType } from '@audius/stems' 4 | 5 | import Modal from 'components/Modal' 6 | import Button from 'components/Button' 7 | import styles from './ErrorModal.module.css' 8 | 9 | const messages = { 10 | title: 'An Error Has Occured', 11 | header: 12 | 'Actions cannot be taken until pending transactions are completed. Please try again.', 13 | okay: 'OKAY' 14 | } 15 | 16 | type OwnProps = { 17 | isOpen: boolean 18 | onClose: () => void 19 | message: string 20 | } 21 | 22 | type ErrorModalProps = OwnProps 23 | 24 | const ErrorModal: React.FC = ({ 25 | isOpen, 26 | onClose, 27 | message 28 | }: ErrorModalProps) => { 29 | return ( 30 | 39 |
{messages.header}
40 | 41 | {message} 42 |