diff --git a/.env.example b/.env.example index f3fdf3b21..cd8e553c8 100644 --- a/.env.example +++ b/.env.example @@ -109,4 +109,5 @@ BEEHIIV_PUBLICATION_ID= # Notifications NOTIFICATIONS_SERVICE_ENABLED=false PUSH_API_URL=https://backend-staging.epns.io -PUSH_CHANNEL_OWNER_PK= \ No newline at end of file +PUSH_CHANNEL_OWNER_PK= +GATSBY_PUSH_CHANNEL_ID= \ No newline at end of file diff --git a/src/back/routes/notification.ts b/src/back/routes/notification.ts index 6fd7f1dca..81e7fdd7a 100644 --- a/src/back/routes/notification.ts +++ b/src/back/routes/notification.ts @@ -4,7 +4,8 @@ import handleAPI from 'decentraland-gatsby/dist/entities/Route/handle' import routes from 'decentraland-gatsby/dist/entities/Route/routes' import { Request } from 'express' -import { NotificationCustomType, NotificationType } from '../../utils/notifications' +import { NotificationCustomType } from '../../shared/types/notifications' +import { NotificationType } from '../../utils/notifications' import { NotificationService } from '../services/notification' import { validateDebugAddress } from '../utils/validations' diff --git a/src/back/services/notification.ts b/src/back/services/notification.ts index 586e0fd23..131129f84 100644 --- a/src/back/services/notification.ts +++ b/src/back/services/notification.ts @@ -1,3 +1,4 @@ +import { ChainId } from '@dcl/schemas/dist/dapps/chain-id' import { ethers } from 'ethers' import isEthereumAddress from 'validator/lib/isEthereumAddress' @@ -5,9 +6,10 @@ import { NOTIFICATIONS_SERVICE_ENABLED } from '../../constants' import { ProposalAttributes } from '../../entities/Proposal/types' import { proposalUrl } from '../../entities/Proposal/utils' import { ErrorService } from '../../services/ErrorService' +import { NotificationCustomType } from '../../shared/types/notifications' import { ErrorCategory } from '../../utils/errorCategories' import { isProdEnv } from '../../utils/governanceEnvs' -import { NotificationCustomType, NotificationType, getCaipAddress } from '../../utils/notifications' +import { NotificationType, PUSH_CHANNEL_ID, getCaipAddress } from '../../utils/notifications' import { CoauthorService } from './coauthor' @@ -18,8 +20,7 @@ enum ENV { STAGING = 'staging', } -const CHAIN_ID = 5 -const CHANNEL_ADDRESS = '0xBf363AeDd082Ddd8DB2D6457609B03f9ee74a2F1' +const chainId = isProdEnv() ? ChainId.ETHEREUM_MAINNET : ChainId.ETHEREUM_GOERLI const PUSH_CHANNEL_OWNER_PK = process.env.PUSH_CHANNEL_OWNER_PK const PUSH_API_URL = process.env.PUSH_API_URL const pkAddress = `0x${PUSH_CHANNEL_OWNER_PK}` @@ -27,6 +28,8 @@ const signer = NOTIFICATIONS_SERVICE_ENABLED ? new ethers.Wallet(pkAddress) : un const NotificationIdentityType = { DIRECT_PAYLOAD: 2, } +const ADDITIONAL_META_CUSTOM_TYPE = 0 +const ADDITIONAL_META_CUSTOM_TYPE_VERSION = 1 const areValidAddresses = (addresses: string[]) => Array.isArray(addresses) && addresses.every((item) => isEthereumAddress(item)) @@ -65,7 +68,7 @@ export class NotificationService { cta: url, img: '', additionalMeta: { - type: `0+${1}`, // TODO: Check what this means with Push team. + type: `${ADDITIONAL_META_CUSTOM_TYPE}+${ADDITIONAL_META_CUSTOM_TYPE_VERSION}`, data: JSON.stringify({ customType, }), @@ -73,7 +76,7 @@ export class NotificationService { }, recipients: this.getRecipients(recipient), - channel: getCaipAddress(CHANNEL_ADDRESS, CHAIN_ID), + channel: getCaipAddress(PUSH_CHANNEL_ID, chainId), env: isProdEnv() ? ENV.PROD : ENV.STAGING, }) @@ -102,18 +105,18 @@ export class NotificationService { } if (Array.isArray(recipient)) { - return recipient.map((item: string) => getCaipAddress(item, CHAIN_ID)) + return recipient.map((item: string) => getCaipAddress(item, chainId)) } - return getCaipAddress(recipient, CHAIN_ID) + return getCaipAddress(recipient, chainId) } static async getUserFeed(address: string) { try { const response = await fetch( - `${PUSH_API_URL}/apis/v1/users/${getCaipAddress(address, CHAIN_ID)}/channels/${getCaipAddress( - CHANNEL_ADDRESS, - CHAIN_ID + `${PUSH_API_URL}/apis/v1/users/${getCaipAddress(address, chainId)}/channels/${getCaipAddress( + PUSH_CHANNEL_ID, + chainId )}/feeds` ) diff --git a/src/clients/Governance.ts b/src/clients/Governance.ts index 0ffa24f07..dd0ff9377 100644 --- a/src/clients/Governance.ts +++ b/src/clients/Governance.ts @@ -36,8 +36,8 @@ import { Topic } from '../entities/SurveyTopic/types' import { ProjectHealth, UpdateAttributes, UpdateResponse } from '../entities/Updates/types' import { Vote, VotedProposal, Voter } from '../entities/Votes/types' import { NewsletterSubscriptionResult } from '../shared/types/newsletter' +import { Notification } from '../shared/types/notifications' import Time from '../utils/date/Time' -import { Notification } from '../utils/notifications' import { TransparencyBudget } from './DclData' import { diff --git a/src/components/Notifications/NotificationItem.tsx b/src/components/Notifications/NotificationItem.tsx index 94abf971b..ba91341f5 100644 --- a/src/components/Notifications/NotificationItem.tsx +++ b/src/components/Notifications/NotificationItem.tsx @@ -1,5 +1,5 @@ +import { Notification, NotificationCustomType } from '../../shared/types/notifications' import Time from '../../utils/date/Time' -import { Notification, NotificationCustomType } from '../../utils/notifications' import Link from '../Common/Typography/Link' import Markdown from '../Common/Typography/Markdown' import Text from '../Common/Typography/Text' diff --git a/src/components/Notifications/NotificationsFeed.tsx b/src/components/Notifications/NotificationsFeed.tsx index 5d0420c68..d1c92c076 100644 --- a/src/components/Notifications/NotificationsFeed.tsx +++ b/src/components/Notifications/NotificationsFeed.tsx @@ -1,5 +1,6 @@ import { useEffect, useMemo, useState } from 'react' +import { ChainId } from '@dcl/schemas/dist/dapps/chain-id' import { Web3Provider } from '@ethersproject/providers' import * as PushAPI from '@pushprotocol/restapi' import { useQuery } from '@tanstack/react-query' @@ -13,7 +14,8 @@ import { isSameAddress } from '../../entities/Snapshot/utils' import { DEFAULT_QUERY_STALE_TIME } from '../../hooks/constants' import { useClickOutside } from '../../hooks/useClickOutside' import useFormatMessage from '../../hooks/useFormatMessage' -import { CHAIN_ID, CHANNEL_ADDRESS, ENV, Notification, getCaipAddress } from '../../utils/notifications' +import { ENV, Notification } from '../../shared/types/notifications' +import { PUSH_CHANNEL_ID, getCaipAddress } from '../../utils/notifications' import FullWidthButton from '../Common/FullWidthButton' import Heading from '../Common/Typography/Heading' import Text from '../Common/Typography/Text' @@ -38,6 +40,7 @@ export default function NotificationsFeed({ isOpen, onClose }: Props) { const [filteredNotifications, setFilteredNotifications] = useState([]) useClickOutside('.NotificationsFeed', isOpen, onClose) + const chainId = userState.chainId || ChainId.ETHEREUM_GOERLI const { data: subscriptions, @@ -47,13 +50,18 @@ export default function NotificationsFeed({ isOpen, onClose }: Props) { } = useQuery({ queryKey: [`subscriptions#${user}`], queryFn: () => - user ? PushAPI.user.getSubscriptions({ user: getCaipAddress(user, CHAIN_ID), env: ENV.STAGING }) : null, + user + ? PushAPI.user.getSubscriptions({ + user: getCaipAddress(user, chainId), + env: ENV.STAGING, + }) + : null, enabled: !!user, staleTime: DEFAULT_QUERY_STALE_TIME, }) const isSubscribed = useMemo( - () => !!subscriptions?.find((item: { channel: string }) => isSameAddress(item.channel, CHANNEL_ADDRESS)), + () => !!subscriptions?.find((item: { channel: string }) => isSameAddress(item.channel, PUSH_CHANNEL_ID)), [subscriptions] ) @@ -78,8 +86,8 @@ export default function NotificationsFeed({ isOpen, onClose }: Props) { await PushAPI.channels.subscribe({ signer, - channelAddress: getCaipAddress(CHANNEL_ADDRESS, CHAIN_ID), - userAddress: getCaipAddress(user, CHAIN_ID), + channelAddress: getCaipAddress(PUSH_CHANNEL_ID, chainId), + userAddress: getCaipAddress(user, chainId), onSuccess: () => { refetchSubscriptions() }, @@ -98,8 +106,8 @@ export default function NotificationsFeed({ isOpen, onClose }: Props) { await PushAPI.channels.unsubscribe({ signer, - channelAddress: getCaipAddress(CHANNEL_ADDRESS, CHAIN_ID), - userAddress: getCaipAddress(user, CHAIN_ID), + channelAddress: getCaipAddress(PUSH_CHANNEL_ID, chainId), + userAddress: getCaipAddress(user, chainId), onSuccess: () => refetchSubscriptions(), env: ENV.STAGING, }) diff --git a/src/config/env/dev.json b/src/config/env/dev.json index 36866c031..4d65b490a 100644 --- a/src/config/env/dev.json +++ b/src/config/env/dev.json @@ -41,5 +41,6 @@ "GATSBY_VOTING_POWER_TO_PASS_HIRING": "99", "GATSBY_DURATION_HIRING": "1200", "GATSBY_SUBMISSION_THRESHOLD_HIRING": "99", - "GATSBY_SSO_URL": "https://id.decentraland.zone" + "GATSBY_SSO_URL": "https://id.decentraland.zone", + "GATSBY_PUSH_CHANNEL_ID": "0xBf363AeDd082Ddd8DB2D6457609B03f9ee74a2F1" } diff --git a/src/config/env/local.json b/src/config/env/local.json index 3579e9c51..cae065d00 100644 --- a/src/config/env/local.json +++ b/src/config/env/local.json @@ -38,5 +38,6 @@ "GATSBY_VOTING_POWER_TO_PASS_HIRING": "99", "GATSBY_DURATION_HIRING": "1200", "GATSBY_SUBMISSION_THRESHOLD_HIRING": "99", - "GATSBY_SSO_URL": "https://id.decentraland.zone" + "GATSBY_SSO_URL": "https://id.decentraland.zone", + "GATSBY_PUSH_CHANNEL_ID": "0xBf363AeDd082Ddd8DB2D6457609B03f9ee74a2F1" } diff --git a/src/config/env/prd.json b/src/config/env/prd.json index a0d8f4bf5..abdda9bd8 100644 --- a/src/config/env/prd.json +++ b/src/config/env/prd.json @@ -37,5 +37,6 @@ "GATSBY_VOTING_POWER_TO_PASS_PITCH": "2000000", "GATSBY_VOTING_POWER_TO_PASS_TENDER": "4000000", "GATSBY_VOTING_POWER_TO_PASS_HIRING": "6000000", - "GATSBY_SSO_URL": "https://id.decentraland.org" + "GATSBY_SSO_URL": "https://id.decentraland.org", + "GATSBY_PUSH_CHANNEL_ID": "" } diff --git a/src/shared/types/notifications.ts b/src/shared/types/notifications.ts new file mode 100644 index 000000000..82223a654 --- /dev/null +++ b/src/shared/types/notifications.ts @@ -0,0 +1,25 @@ +export type Notification = { + payload_id: number + epoch: string + payload: { + data: { + acta: string + asub: string + amsg: string + additionalMeta: { + data: string + } + } + } +} + +export enum ENV { + PROD = 'prod', + STAGING = 'staging', +} + +export enum NotificationCustomType { + Announcement = 'announcement', + Proposal = 'proposal', + Grant = 'grant', +} diff --git a/src/utils/notifications.ts b/src/utils/notifications.ts index c64a4f166..6375b1877 100644 --- a/src/utils/notifications.ts +++ b/src/utils/notifications.ts @@ -1,29 +1,4 @@ -// TODO: Move types to notification types file -export type Notification = { - payload_id: number - epoch: string - payload: { - data: { - acta: string - asub: string - amsg: string - additionalMeta: { - data: string - } - } - } -} - -export enum ENV { - PROD = 'prod', - STAGING = 'staging', -} - -export enum NotificationCustomType { - Announcement = 'announcement', - Proposal = 'proposal', - Grant = 'grant', -} +import { clientEnv } from './clientEnv' export const NotificationType = { BROADCAST: 1, @@ -35,6 +10,4 @@ export function getCaipAddress(address: string, chainId: number) { return `eip155:${chainId}:${address}` } -// TODO: Move to env vars -export const CHAIN_ID = 5 -export const CHANNEL_ADDRESS = '0xBf363AeDd082Ddd8DB2D6457609B03f9ee74a2F1' +export const PUSH_CHANNEL_ID = process.env.GATSBY_PUSH_CHANNEL_ID || clientEnv('GATSBY_PUSH_CHANNEL_ID')