diff --git a/packages/restapi/src/lib/payloads/constants.ts b/packages/restapi/src/lib/payloads/constants.ts index da01fafc7..65d76c858 100644 --- a/packages/restapi/src/lib/payloads/constants.ts +++ b/packages/restapi/src/lib/payloads/constants.ts @@ -32,6 +32,7 @@ export const SOURCE_TYPES = { ARBITRUMONE_MAINNET: "ARBITRUMONE_MAINNET", THE_GRAPH: 'THE_GRAPH', PUSH_VIDEO: 'PUSH_VIDEO', + SIMULATE: 'SIMULATE' }; export enum IDENTITY_TYPE { diff --git a/packages/restapi/src/lib/payloads/sendNotifications.ts b/packages/restapi/src/lib/payloads/sendNotifications.ts index eb262f5f8..091ef1c84 100644 --- a/packages/restapi/src/lib/payloads/sendNotifications.ts +++ b/packages/restapi/src/lib/payloads/sendNotifications.ts @@ -17,9 +17,14 @@ import { isValidCAIP10NFTAddress, isValidETHAddress, } from '../helpers'; -import { IDENTITY_TYPE, DEFAULT_DOMAIN } from './constants'; +import { + IDENTITY_TYPE, + DEFAULT_DOMAIN, + NOTIFICATION_TYPE, + SOURCE_TYPES, +} from './constants'; import { ENV } from '../constants'; - +import { getChannel } from '../channels/getChannel'; /** * Validate options for some scenarios */ @@ -53,6 +58,35 @@ function validateOptions(options: any) { } } +/** + * + * @param payloadOptions channel, recipient and type tp verify whether it is a simulate type + * @returns boolean + */ +async function checkSimulateNotification(payloadOptions: { + channel: string; + recipient: string | string[] | undefined; + type: NOTIFICATION_TYPE; + env: ENV | undefined; +}): Promise { + const { channel, recipient, type, env } = payloadOptions || {}; + // fetch channel info + const channelInfo = await getChannel({ + channel: channel, + env: env, + }); + // check if channel exists, if it does then its not simulate type + if (channelInfo) return false; + else { + // if no channel info found, check if channel address = recipient and notification type is targeted + const convertedRecipient = + typeof recipient == 'string' && recipient?.split(':').length == 3 + ? recipient.split(':')[2] + : recipient; + return channel == convertedRecipient && type == NOTIFICATION_TYPE.TARGETTED; + } +} + export async function sendNotification(options: ISendNotificationInputOptions) { try { const { @@ -133,7 +167,14 @@ export async function sendNotification(options: ISendNotificationInputOptions) { ipfsHash, }); - const source = getSource(chainId, identityType, senderType); + const source = (await checkSimulateNotification({ + channel: options.channel, + recipient: options.recipients, + type: options.type, + env: options.env, + })) + ? SOURCE_TYPES.SIMULATE + : getSource(chainId, identityType, senderType); const apiPayload = { verificationProof, diff --git a/packages/restapi/tests/lib/pushNotification/channel.test.ts b/packages/restapi/tests/lib/pushNotification/channel.test.ts index e3cd1e3f8..bfee0e945 100644 --- a/packages/restapi/tests/lib/pushNotification/channel.test.ts +++ b/packages/restapi/tests/lib/pushNotification/channel.test.ts @@ -14,6 +14,9 @@ describe('PushAPI.channel functionality', () => { let account1: string; let signer2: any; let account2: string; + let userNoChannel: PushAPI; + let noChannelSigner: any; + let noChannelAddress: string; beforeEach(async () => { signer1 = new ethers.Wallet(`0x${process.env['WALLET_PRIVATE_KEY']}`); @@ -29,6 +32,11 @@ describe('PushAPI.channel functionality', () => { provider ); account2 = await signer2.getAddress(); + + const WALLET = ethers.Wallet.createRandom(); + noChannelSigner = new ethers.Wallet(WALLET.privateKey); + noChannelAddress = await noChannelSigner.getAddress(); + enum ENV { PROD = 'prod', STAGING = 'staging', @@ -39,12 +47,14 @@ describe('PushAPI.channel functionality', () => { LOCAL = 'local', } // initialisation with signer and provider - userKate = await PushAPI.initialize(signer2, {env: ENV.DEV}) + userKate = await PushAPI.initialize(signer2, { env: ENV.DEV }); // initialisation with signer userAlice = await PushAPI.initialize(signer2); // TODO: remove signer1 after chat makes signer as optional //initialisation without signer userBob = await PushAPI.initialize(signer1); + // initialisation with a signer that has no channel + userNoChannel = await PushAPI.initialize(noChannelSigner); }); describe('channel :: info', () => { @@ -65,7 +75,7 @@ describe('PushAPI.channel functionality', () => { const res = await userBob.channel.info( 'eip155:5:0x93A829d16DE51745Db0530A0F8E8A9B8CA5370E5' ); - // console.log(res); + // console.log(res); expect(res).not.null; }); }); @@ -73,7 +83,7 @@ describe('PushAPI.channel functionality', () => { describe('channel :: search', () => { it('Without signer and account : Should return response', async () => { const res = await userBob.channel.search(' '); - // console.log(res); + // console.log(res); expect(res).not.null; }); @@ -207,7 +217,7 @@ describe('PushAPI.channel functionality', () => { body: 'testing with random body', cta: 'https://google.com/', embed: 'https://avatars.githubusercontent.com/u/64157541?s=200&v=4', - category: 2 + category: 2, }, } ); @@ -258,6 +268,41 @@ describe('PushAPI.channel functionality', () => { ); expect(res.status).to.equal(204); }); + + it('With signer : subset : Should send notification with title and body along with additional options for alias', async () => { + const res = await userAlice.channel.send( + [ + 'eip155:97:0xD8634C39BBFd4033c0d3289C4515275102423681', + 'eip155:97:0x93A829d16DE51745Db0530A0F8E8A9B8CA5370E5', + ], + { + notification: { + title: 'hi', + body: 'test-subset', + }, + payload: { + title: 'testing first subset notification', + body: 'testing with random body', + cta: 'https://google.com/', + embed: 'https://avatars.githubusercontent.com/u/64157541?s=200&v=4', + }, + channel: 'eip155:97:0xD8634C39BBFd4033c0d3289C4515275102423681', + } + ); + expect(res.status).to.equal(204); + }); + it('With signer : SIMULATED : Should send notification with title and body', async () => { + const res = await userNoChannel.channel.send( + [`eip155:5:${noChannelAddress}`], + { + notification: { + title: 'hi', + body: 'test-targeted-simulated', + }, + } + ); + expect(res.status).to.equal(204); + }); }); describe.skip('channel :: update', () => { @@ -289,9 +334,13 @@ describe('PushAPI.channel functionality', () => { describe('channel :: settings', () => { it('Should create channel', async () => { const res = await userKate.channel.setting([ - {type: 2, default: 5, description: "My notif setting 2", data: {upper:100, lower:5, ticker: 10, enabled: true}}, + { + type: 2, + default: 5, + description: 'My notif setting 2', + data: { upper: 100, lower: 5, ticker: 10, enabled: true }, + }, { type: 1, default: 1, description: 'My Notif Settings' }, - ]); // console.log(res) expect(res).not.null; diff --git a/packages/restapi/tests/lib/pushNotification/notification.test.ts b/packages/restapi/tests/lib/pushNotification/notification.test.ts index 5fd2fb3fd..fe0ab8997 100644 --- a/packages/restapi/tests/lib/pushNotification/notification.test.ts +++ b/packages/restapi/tests/lib/pushNotification/notification.test.ts @@ -24,7 +24,7 @@ describe('PushAPI.notification functionality', () => { `0x${process.env['NFT_HOLDER_WALLET_PRIVATE_KEY_1']}` ); account1 = await signer1.getAddress(); - + const provider = new ethers.providers.JsonRpcProvider( 'https://goerli.blockpi.network/v1/rpc/public' );