diff --git a/README.md b/README.md index 6cc5ea396..fe14fdc1b 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@

- + discord @@ -177,7 +177,7 @@ node main - **[Website](https://push.org)** To checkout our Product. - **[Docs](https://docs.push.org/developers/)** For comprehensive documentation. - **[Blog](https://medium.com/push-protocol)** To learn more about our partners, new launches, etc. -- **[Discord](discord.gg/pushprotocol)** for support and discussions with the community and the team. +- **[Discord](https://discord.com/invite/pushprotocol)** for support and discussions with the community and the team. - **[GitHub](https://github.com/ethereum-push-notification-service)** for source code, project board, issues, and pull requests. - **[Twitter](https://twitter.com/pushprotocol)** for the latest updates on the product and published blogs. @@ -196,7 +196,7 @@ Read how you can contribute Discord +Discord ## License Check out our License HERE diff --git a/packages/examples/sdk-backend-node/.env.sample b/packages/examples/sdk-backend-node/.env.sample index 550450212..a444eee26 100644 --- a/packages/examples/sdk-backend-node/.env.sample +++ b/packages/examples/sdk-backend-node/.env.sample @@ -43,8 +43,8 @@ VIDEO_CHAIN_ID=your_video_chain_id # VIDEO SENDER ADDRESS VIDEO_SENDER_ADDRESS=your_video_sender_address -# VIDEO RECIPEINT ADDRESS -VIDEO_RECIPEINT_ADDRESS=your_video_recipeint_address +# VIDEO RECIPIENT ADDRESS +VIDEO_RECIPIENT_ADDRESS=your_video_recipient_address # VIDEO CHAT ID VIDEO_CHAT_ID=your_video_chat_id \ No newline at end of file diff --git a/packages/examples/sdk-backend-node/chat/chat.lowlevel.ts b/packages/examples/sdk-backend-node/chat/chat.lowlevel.ts new file mode 100644 index 000000000..852b62153 --- /dev/null +++ b/packages/examples/sdk-backend-node/chat/chat.lowlevel.ts @@ -0,0 +1,667 @@ +import * as PushAPI from '@pushprotocol/restapi'; +import { createSocketConnection, EVENTS } from '@pushprotocol/socket'; +import { ethers } from 'ethers'; +import { + adjectives, + animals, + colors, + uniqueNamesGenerator, +} from 'unique-names-generator'; +import { ENV } from '../types'; +import { config } from '../config'; +import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; +import { createWalletClient, http } from 'viem'; +import { goerli } from 'viem/chains'; + +// CONFIGS +const { env, showAPIResponse } = config; + +/***************** SAMPLE SIGNER GENERATION *********************/ +/** + * USING VIEM + */ +// Random Wallet Signers +const signer = createWalletClient({ + account: privateKeyToAccount(generatePrivateKey()), + chain: goerli, + transport: http(), +}); +const signerAddress = signer.account.address; +const secondSigner = createWalletClient({ + account: privateKeyToAccount(generatePrivateKey()), + chain: goerli, + transport: http(), +}); +const secondSignerAddress = secondSigner.account.address; +// Dummy Wallet Addresses +const randomWallet1 = privateKeyToAccount(generatePrivateKey()).address; +const randomWallet2 = privateKeyToAccount(generatePrivateKey()).address; +const randomWallet3 = privateKeyToAccount(generatePrivateKey()).address; + +/** + * USING ETHERS + */ +// // Random Wallet Signers +// const signer = ethers.Wallet.createRandom(); +// const signerAddress = signer.address; +// const secondSigner = ethers.Wallet.createRandom(); +// const secondSignerAddress = secondSigner.address; +// // Dummy Wallet Addresses +// const randomWallet1 = ethers.Wallet.createRandom().address; +// const randomWallet2 = ethers.Wallet.createRandom().address; +// const randomWallet3 = ethers.Wallet.createRandom().address; + +/************************************************************* */ + +// Group Chat Data +const groupName = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], +}); +const groupDescription = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], +}); +const groupImage = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; + +// Push Chat - Run Chat Use cases +export const runChatLowlevelUseCases = async (): Promise => { + console.log('PushAPI.user.create'); + await PushAPI_user_create(); + + console.log('PushAPI.user.get'); + await PushAPI_user_get(); + + console.log('PushAPI_chat_decryptPGPKey'); + await PushAPI_chat_decryptPGPKey(); + + console.log('PushAPI.chat.chats'); + await PushAPI_chat_chats(); + + console.log('PushAPI.chat.requests'); + await PushAPI_chat_requests(); + + console.log('PushAPI.chat.send'); + const TargetChatId = await PushAPI_chat_send(); + + console.log('PushAPI.chat.approve'); + await PushAPI_chat_approve(); + + console.log('PushAPI chat Video call Notification'); + await PushAPI_chat_video_call_notification(TargetChatId); + + console.log('PushAPI.chat.createGroup'); + const { chatId, name } = await PushAPI_chat_createGroup(); + + console.log('PushAPI.chat.conversationHash'); + await PushAPI_chat_conversationHash(); + + console.log('PushAPI_chat_history'); + await PushAPI_chat_history(); + + console.log('PushAPI.chat.latest'); + await PushAPI_chat_latest(); + + console.log('PushAPI.chat.updateGroup'); + await PushAPI_chat_updateGroup(chatId); + + console.log('PushAPI.chat.getGroupByName'); + await PushAPI_chat_getGroupByName(name); + + console.log('PushAPI.chat.getGroup'); + await PushAPI_chat_getGroup(chatId); + + console.log('PushAPI.chat.decryptConversation'); + await PushAPI_chat_decryptConversation(); + + console.log('Push Chat - PushSDKSocket()'); + await PushChatSDKSocket(); +}; + +// Push Chat - PushAPI.user.create +async function PushAPI_user_create(silent = !showAPIResponse) { + const user = await PushAPI.user.create({ + signer: signer, + env: env as ENV, + }); + + const user_2 = await PushAPI.user.create({ + signer: secondSigner, + env: env as ENV, + }); + + console.log('PushAPI_user_create | Response - 200 OK'); + if (!silent) { + console.log(user); + console.log(user_2); + } + + return user; +} + +// Push Chat - PushAPI.user.get +async function PushAPI_user_get(silent = !showAPIResponse) { + const user = await PushAPI.user.get({ + account: `eip155:${signerAddress}`, + env: env as ENV, + }); + + console.log('PushAPI_user_get | Response - 200 OK'); + + if (!silent) { + console.log(user); + } +} + +// Push Chat - PushAPI.chat.decryptPGPKey +async function PushAPI_chat_decryptPGPKey(silent = !showAPIResponse) { + // get user and derive encrypted PGP key + const user = await PushAPI.user.get({ + account: `eip155:${signerAddress}`, + env: env as ENV, + }); + + // decrypt the PGP Key + const pgpKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + console.log('PushAPI_chat_decryptPGPKey | Response - 200 OK'); + if (!silent) { + console.log(pgpKey); + } +} + +// Push Chat - PushAPI.chat.chats +async function PushAPI_chat_chats(silent = !showAPIResponse) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signerAddress}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + // Actual api + const response = await PushAPI.chat.chats({ + account: `eip155:${signerAddress}`, + toDecrypt: true, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_chat_chats | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Chat - PushAPI.chat.requests +async function PushAPI_chat_requests(silent = !showAPIResponse) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signerAddress}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + // Actual api + const response = await PushAPI.chat.requests({ + account: `eip155:${signerAddress}`, + toDecrypt: true, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_chat_requests | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Chat - PushAPI.chat.conversationHash +async function PushAPI_chat_conversationHash(silent = !showAPIResponse) { + // conversation hash are also called link inside chat messages + const conversationHash = await PushAPI.chat.conversationHash({ + account: `eip155:${signerAddress}`, + conversationId: `eip155:${secondSignerAddress}`, // 2nd address + env: env as ENV, + }); + + console.log('PushAPI_chat_conversationHash | Response - 200 OK'); + if (!silent) { + console.log(conversationHash); + } +} + +// Push Chat - PushAPI.chat.latest +async function PushAPI_chat_latest(silent = !showAPIResponse) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signerAddress}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + // Fetch conversation hash + // conversation hash are also called link inside chat messages + const conversationHash = await PushAPI.chat.conversationHash({ + account: `eip155:${signerAddress}`, + conversationId: `eip155:${secondSignerAddress}`, // 2nd address + env: env as ENV, + }); + + // Actual API + const response = await PushAPI.chat.latest({ + threadhash: conversationHash.threadHash, // get conversation hash from conversationHash function and send the response threadhash here + account: `eip155:${signerAddress}`, + toDecrypt: true, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_chat_latest | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Chat - PushAPI.chat.history +async function PushAPI_chat_history(silent = !showAPIResponse) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signerAddress}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + // Fetch conversation hash + // conversation hash are also called link inside chat messages + const conversationHash = await PushAPI.chat.conversationHash({ + account: `eip155:${signerAddress}`, + conversationId: `eip155:${secondSignerAddress}`, // 2nd address + env: env as ENV, + }); + + // Actual API + const response = await PushAPI.chat.history({ + threadhash: conversationHash.threadHash, // get conversation hash from conversationHash function and send the response threadhash here + account: `eip155:${signerAddress}`, + limit: 5, + toDecrypt: true, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_chat_history | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Chat - PushAPI.chat.send +// // Will send a message to the user or chat request in case user hasn't approved them +async function PushAPI_chat_send(silent = !showAPIResponse) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signerAddress}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + // Actual api + const response = await PushAPI.chat.send({ + messageObj: { + content: "Gm gm! It's me... Mario", + }, + messageType: 'Text', // can be "Text" | "Image" | "File" | "GIF" + receiverAddress: secondSignerAddress, + + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_chat_send | Response - 200 OK'); + if (!silent) { + console.log(response); + } + return response.chatId; +} + +// Push Chat - Approve +async function PushAPI_chat_approve(silent = !showAPIResponse) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${secondSignerAddress}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: secondSigner, + }); + + // Actual api + const approve = await PushAPI.chat.approve({ + status: 'Approved', + senderAddress: signerAddress, // receiver's address or chatId of a group + + signer: secondSigner, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_chat_approve | Response - 200 OK'); + if (!silent) { + console.log(approve); + } +} + +// Push Chat - PushAPI.chat.createGroup +async function PushAPI_chat_createGroup( + silent = !showAPIResponse +): Promise<{ chatId: string; name: string }> { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signerAddress}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + // Actual API + // Convert image to base 64 and pass + const response = await PushAPI.chat.createGroup({ + groupName, + groupDescription, + members: [`eip155:${randomWallet1}`, `eip155:${randomWallet2}`], + groupImage, + admins: [], // takes signer as admin automatically, add more if you want to + isPublic: true, + + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_chat_createGroup | Response - 200 OK'); + if (!silent) { + console.log(response); + } + return { chatId: response.chatId, name: response.groupName }; +} + +// Push Chat - PushAPI.chat.updateGroup +async function PushAPI_chat_updateGroup( + chatId: string, + silent = !showAPIResponse +) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signerAddress}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + // Actual API + // Convert image to base 64 and pass + // This is an idempotent operation, meaning it requires all group info to be passed no matter if only few things change + // Why so? To ensure that verificationProof always is able to replicate the current group info (trustless since signature is stored with the info) + const response = await PushAPI.chat.updateGroup({ + chatId, + groupName, + groupDescription, + members: [ + `eip155:${randomWallet1}`, + `eip155:${randomWallet2}`, + `eip155:${randomWallet3}`, + `eip155:${signerAddress}`, + ], + groupImage, + admins: [`eip155:${signerAddress}`], // takes signer as admin automatically, add more if you want to + + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + console.log('PushAPI_chat_updateGroup | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Chat - PushAPI.chat.getGroupByName +async function PushAPI_chat_getGroupByName( + name: string, + silent = !showAPIResponse +) { + const response = await PushAPI.chat.getGroupByName({ + groupName: name, + env: env as ENV, + }); + + console.log('PushAPI_chat_getGroupByName | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Chat - PushAPI.chat.getGroup +async function PushAPI_chat_getGroup( + chatId: string, + silent = !showAPIResponse +) { + const response = await PushAPI.chat.getGroup({ + chatId: chatId, + env: env as ENV, + }); + + console.log('PushAPI_chat_getGroup | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Chat - PushAPI.chat.decryptConversation +async function PushAPI_chat_decryptConversation(silent = !showAPIResponse) { + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${signerAddress}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: signer, + }); + + // Fetch conversation hash + // conversation hash are also called link inside chat messages + const conversationHash = await PushAPI.chat.conversationHash({ + account: `eip155:${signerAddress}`, + conversationId: `eip155:${secondSignerAddress}`, // 2nd address + env: env as ENV, + }); + + // Chat History + const encryptedChats = await PushAPI.chat.history({ + threadhash: conversationHash.threadHash, // get conversation hash from conversationHash function and send the response threadhash here + account: `eip155:${signerAddress}`, + limit: 5, + toDecrypt: false, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + + // Decrypted Chat + const decryptedChat = await PushAPI.chat.decryptConversation({ + messages: encryptedChats, // array of message object fetched from chat.history method + connectedUser: user, // user meta data object fetched from chat.get method + pgpPrivateKey: pgpDecrpyptedPvtKey, //decrypted private key + env: env as ENV, + }); + + console.log('PushAPI_chat_decryptConversation | Response - 200 OK'); + if (!silent) { + console.log(decryptedChat); + } +} + +// Push Chat - Socket Connection +async function PushChatSDKSocket(silent = !showAPIResponse) { + const pushSDKSocket = createSocketConnection({ + user: `eip155:${signerAddress}`, + socketType: 'chat', + socketOptions: { autoConnect: true, reconnectionAttempts: 3 }, + env: env as ENV, + }); + + if (!pushSDKSocket) { + throw new Error('Socket not connected'); + } + + pushSDKSocket.on(EVENTS.CONNECT, async () => { + console.log('Socket Connected - will disconnect after 4 seconds'); + + // send a chat from other wallet to this one to see the result + // Fetch user + const user = await PushAPI.user.get({ + account: `eip155:${secondSignerAddress}`, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + + signer: secondSigner, + }); + + // Actual api + const response = await PushAPI.chat.send({ + messageContent: "Gm gm! It's me... Mario", + messageType: 'Text', + receiverAddress: `eip155:${signerAddress}`, + + signer: secondSigner, + pgpPrivateKey: pgpDecrpyptedPvtKey, + env: env as ENV, + }); + console.log('PushAPI_chat_send | Response - 200 OK'); + }); + + pushSDKSocket.on(EVENTS.DISCONNECT, () => { + console.log('Socket Disconnected'); + }); + + pushSDKSocket.on(EVENTS.CHAT_RECEIVED_MESSAGE, (message) => { + // feedItem is the notification data when that notification was received + console.log('Incoming Push Chat message from Socket'); + if (!silent) { + console.log(message); + } + + // disconnect socket after this, not to be done in real implementations + pushSDKSocket.disconnect(); + }); + + const delay = (ms: number) => + new Promise((resolve) => setTimeout(resolve, ms)); + await delay(4000); +} + +async function PushAPI_chat_video_call_notification( + chatId: string, + silent = !showAPIResponse +) { + // Fetch user + const user = await PushAPI.user.get({ + account: signerAddress, + env: env as ENV, + }); + + // Decrypt PGP Key + const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: user.encryptedPrivateKey, + signer: signer, + }); + // get PGP KEy + const apiResponse = await PushAPI.payloads.sendNotification({ + senderType: 1, + signer: signer, + pgpPrivateKey: pgpDecrpyptedPvtKey, + chatId: chatId, + type: 3, // target + identityType: 2, // direct payload + notification: { + title: `VC TITLE:`, + body: `VC BODY`, + }, + payload: { + title: `payload title`, + body: `sample msg body`, + cta: '', + img: '', + additionalMeta: { + type: '1+1', + data: 'Random DATA', + domain: 'push.org', + }, + }, + recipients: secondSignerAddress, // recipient address + channel: signerAddress, // your channel address + env: env as ENV, + }); + + console.log('PushAPI.payloads.sendNotification | Response - 204 OK'); + if (!silent) { + console.log(apiResponse); + } +} diff --git a/packages/examples/sdk-backend-node/chat/chat.ts b/packages/examples/sdk-backend-node/chat/chat.ts index 3b594ec1c..fba19a0be 100644 --- a/packages/examples/sdk-backend-node/chat/chat.ts +++ b/packages/examples/sdk-backend-node/chat/chat.ts @@ -1,25 +1,21 @@ -import * as PushAPI from '@pushprotocol/restapi'; -import { createSocketConnection, EVENTS } from '@pushprotocol/socket'; -import { ethers } from 'ethers'; +import { PushAPI } from '@pushprotocol/restapi'; import { adjectives, animals, colors, uniqueNamesGenerator, } from 'unique-names-generator'; -import { ENV } from '../types'; import { config } from '../config'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; import { createWalletClient, http } from 'viem'; import { goerli } from 'viem/chains'; +import { STREAM } from '@pushprotocol/restapi/src/lib/pushstream/pushStreamTypes'; // CONFIGS const { env, showAPIResponse } = config; /***************** SAMPLE SIGNER GENERATION *********************/ -/** - * USING VIEM - */ +// Uing VIEM // Random Wallet Signers const signer = createWalletClient({ account: privateKeyToAccount(generatePrivateKey()), @@ -33,27 +29,20 @@ const secondSigner = createWalletClient({ transport: http(), }); const secondSignerAddress = secondSigner.account.address; +const thirdSigner = createWalletClient({ + account: privateKeyToAccount(generatePrivateKey()), + chain: goerli, + transport: http(), +}); +const thirdSignerAddress = thirdSigner.account.address; + // Dummy Wallet Addresses const randomWallet1 = privateKeyToAccount(generatePrivateKey()).address; const randomWallet2 = privateKeyToAccount(generatePrivateKey()).address; const randomWallet3 = privateKeyToAccount(generatePrivateKey()).address; +/****************************************************************/ -/** - * USING ETHERS - */ -// // Random Wallet Signers -// const signer = ethers.Wallet.createRandom(); -// const signerAddress = signer.address; -// const secondSigner = ethers.Wallet.createRandom(); -// const secondSignerAddress = secondSigner.address; -// // Dummy Wallet Addresses -// const randomWallet1 = ethers.Wallet.createRandom().address; -// const randomWallet2 = ethers.Wallet.createRandom().address; -// const randomWallet3 = ethers.Wallet.createRandom().address; - -/************************************************************* */ - -// Group Chat Data +/***************** SAMPLE GROUP DATA ****************************/ const groupName = uniqueNamesGenerator({ dictionaries: [adjectives, colors, animals], }); @@ -62,613 +51,211 @@ const groupDescription = uniqueNamesGenerator({ }); const groupImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; - -// Push Chat - Run Chat Use cases -export const runChatUseCases = async (): Promise => { - console.log(` - ██████ ██ ██ █████ ████████ - ██ ██ ██ ██ ██ ██ - ██ ███████ ███████ ██ - ██ ██ ██ ██ ██ ██ - ██████ ██ ██ ██ ██ ██ - `); - console.log('PushAPI.user.create'); - await PushAPI_user_create(); - - console.log('PushAPI.user.get'); - await PushAPI_user_get(); - - console.log('PushAPI_chat_decryptPGPKey'); - await PushAPI_chat_decryptPGPKey(); - - console.log('PushAPI.chat.chats'); - await PushAPI_chat_chats(); - - console.log('PushAPI.chat.requests'); - await PushAPI_chat_requests(); - - console.log('PushAPI.chat.send'); - const TargetChatId = await PushAPI_chat_send(); - - console.log('PushAPI.chat.approve'); - await PushAPI_chat_approve(); - - console.log('PushAPI chat Video call Notification'); - await PushAPI_chat_video_call_notification(TargetChatId); - - console.log('PushAPI.chat.createGroup'); - const { chatId, name } = await PushAPI_chat_createGroup(); - - console.log('PushAPI.chat.conversationHash'); - await PushAPI_chat_conversationHash(); - - console.log('PushAPI_chat_history'); - await PushAPI_chat_history(); - - console.log('PushAPI.chat.latest'); - await PushAPI_chat_latest(); - - console.log('PushAPI.chat.updateGroup'); - await PushAPI_chat_updateGroup(chatId); - - console.log('PushAPI.chat.getGroupByName'); - await PushAPI_chat_getGroupByName(name); - - console.log('PushAPI.chat.getGroup'); - await PushAPI_chat_getGroup(chatId); - - console.log('PushAPI.chat.decryptConversation'); - await PushAPI_chat_decryptConversation(); - - console.log('Push Chat - PushSDKSocket()'); - await PushChatSDKSocket(); -}; - -// Push Chat - PushAPI.user.create -async function PushAPI_user_create(silent = !showAPIResponse) { - const user = await PushAPI.user.create({ - signer: signer, - env: env as ENV, - }); - - const user_2 = await PushAPI.user.create({ - signer: secondSigner, - env: env as ENV, - }); - - console.log('PushAPI_user_create | Response - 200 OK'); - if (!silent) { - console.log(user); - console.log(user_2); - } - - return user; -} - -// Push Chat - PushAPI.user.get -async function PushAPI_user_get(silent = !showAPIResponse) { - const user = await PushAPI.user.get({ - account: `eip155:${signerAddress}`, - env: env as ENV, +/***************** SAMPLE GROUP DATA ****************************/ + +const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +const eventlistener = async ( + pushAPI: PushAPI, + eventName: string +): Promise => { + pushAPI.stream.on(eventName, (data: any) => { + if (showAPIResponse) { + console.log('Stream Event Received'); + console.log(data); + console.log('\n'); + } }); +}; - console.log('PushAPI_user_get | Response - 200 OK'); - - if (!silent) { - console.log(user); +export const runChatClassUseCases = async (): Promise => { + const userAlice = await PushAPI.initialize(signer, { env }); + const userBob = await PushAPI.initialize(secondSigner, { env }); + const userKate = await PushAPI.initialize(thirdSigner, { env }); + + // Listen stream events to receive websocket events + console.log(`Listening ${STREAM.CHAT} Events`); + eventlistener(userAlice, STREAM.CHAT); + console.log(`Listening ${STREAM.CHAT_OPS} Events`); + eventlistener(userAlice, STREAM.CHAT_OPS); + console.log('\n\n'); + + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.chat.list'); + const aliceChats = await userAlice.chat.list('CHATS'); + const aliceRequests = await userAlice.chat.list('REQUESTS'); + if (showAPIResponse) { + console.log(aliceChats); + console.log(aliceRequests); } -} - -// Push Chat - PushAPI.chat.decryptPGPKey -async function PushAPI_chat_decryptPGPKey(silent = !showAPIResponse) { - // get user and derive encrypted PGP key - const user = await PushAPI.user.get({ - account: `eip155:${signerAddress}`, - env: env as ENV, - }); - - // decrypt the PGP Key - const pgpKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - - signer: signer, - }); - - console.log('PushAPI_chat_decryptPGPKey | Response - 200 OK'); - if (!silent) { - console.log(pgpKey); + console.log('PushAPI.chat.list | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.chat.latest'); + const aliceLatestChatWithBob = await userAlice.chat.latest( + secondSignerAddress + ); + if (showAPIResponse) { + console.log(aliceLatestChatWithBob); } -} - -// Push Chat - PushAPI.chat.chats -async function PushAPI_chat_chats(silent = !showAPIResponse) { - // Fetch user - const user = await PushAPI.user.get({ - account: `eip155:${signerAddress}`, - env: env as ENV, - }); - - // Decrypt PGP Key - const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - - signer: signer, - }); - - // Actual api - const response = await PushAPI.chat.chats({ - account: `eip155:${signerAddress}`, - toDecrypt: true, - pgpPrivateKey: pgpDecrpyptedPvtKey, - env: env as ENV, - }); - - console.log('PushAPI_chat_chats | Response - 200 OK'); - if (!silent) { - console.log(response); + console.log('PushAPI.chat.latest | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.chat.history'); + const aliceChatHistoryWithBob = await userAlice.chat.history( + secondSignerAddress + ); + if (showAPIResponse) { + console.log(aliceChatHistoryWithBob); } -} - -// Push Chat - PushAPI.chat.requests -async function PushAPI_chat_requests(silent = !showAPIResponse) { - // Fetch user - const user = await PushAPI.user.get({ - account: `eip155:${signerAddress}`, - env: env as ENV, - }); - - // Decrypt PGP Key - const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - - signer: signer, - }); - - // Actual api - const response = await PushAPI.chat.requests({ - account: `eip155:${signerAddress}`, - toDecrypt: true, - pgpPrivateKey: pgpDecrpyptedPvtKey, - env: env as ENV, + console.log('PushAPI.chat.history | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.chat.send'); + const aliceMessagesBob = await userAlice.chat.send(secondSignerAddress, { + content: 'Hello Bob!', + type: 'Text', }); - - console.log('PushAPI_chat_requests | Response - 200 OK'); - if (!silent) { - console.log(response); + if (showAPIResponse) { + console.log(aliceMessagesBob); } -} - -// Push Chat - PushAPI.chat.conversationHash -async function PushAPI_chat_conversationHash(silent = !showAPIResponse) { - // conversation hash are also called link inside chat messages - const conversationHash = await PushAPI.chat.conversationHash({ - account: `eip155:${signerAddress}`, - conversationId: `eip155:${secondSignerAddress}`, // 2nd address - env: env as ENV, - }); - - console.log('PushAPI_chat_conversationHash | Response - 200 OK'); - if (!silent) { - console.log(conversationHash); + await delay(2000); // Delay added to log the events in order + console.log('PushAPI.chat.send | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.chat.accept'); + const bobAcceptsRequest = await userBob.chat.accept(signerAddress); + if (showAPIResponse) { + console.log(bobAcceptsRequest); } -} - -// Push Chat - PushAPI.chat.latest -async function PushAPI_chat_latest(silent = !showAPIResponse) { - // Fetch user - const user = await PushAPI.user.get({ - account: `eip155:${signerAddress}`, - env: env as ENV, - }); - - // Decrypt PGP Key - const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - - signer: signer, - }); - - // Fetch conversation hash - // conversation hash are also called link inside chat messages - const conversationHash = await PushAPI.chat.conversationHash({ - account: `eip155:${signerAddress}`, - conversationId: `eip155:${secondSignerAddress}`, // 2nd address - env: env as ENV, - }); - - // Actual API - const response = await PushAPI.chat.latest({ - threadhash: conversationHash.threadHash, // get conversation hash from conversationHash function and send the response threadhash here - account: `eip155:${signerAddress}`, - toDecrypt: true, - pgpPrivateKey: pgpDecrpyptedPvtKey, - env: env as ENV, - }); - - console.log('PushAPI_chat_latest | Response - 200 OK'); - if (!silent) { - console.log(response); + await delay(2000); // Delay added to log the events in order + console.log('PushAPI.chat.accept | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.chat.reject'); + await userKate.chat.send(signerAddress, { + content: 'Sending malicious message', + type: 'Text', + }); + const AliceRejectsRequest = await userAlice.chat.reject(thirdSignerAddress); + if (showAPIResponse) { + console.log(AliceRejectsRequest); } -} - -// Push Chat - PushAPI.chat.history -async function PushAPI_chat_history(silent = !showAPIResponse) { - // Fetch user - const user = await PushAPI.user.get({ - account: `eip155:${signerAddress}`, - env: env as ENV, - }); - - // Decrypt PGP Key - const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - - signer: signer, - }); - - // Fetch conversation hash - // conversation hash are also called link inside chat messages - const conversationHash = await PushAPI.chat.conversationHash({ - account: `eip155:${signerAddress}`, - conversationId: `eip155:${secondSignerAddress}`, // 2nd address - env: env as ENV, - }); - - // Actual API - const response = await PushAPI.chat.history({ - threadhash: conversationHash.threadHash, // get conversation hash from conversationHash function and send the response threadhash here - account: `eip155:${signerAddress}`, - limit: 5, - toDecrypt: true, - pgpPrivateKey: pgpDecrpyptedPvtKey, - env: env as ENV, - }); - - console.log('PushAPI_chat_history | Response - 200 OK'); - if (!silent) { - console.log(response); + await delay(2000); // Delay added to log the events in order + console.log('PushAPI.chat.reject | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.chat.block'); + const AliceBlocksBob = await userAlice.chat.block([secondSignerAddress]); + if (showAPIResponse) { + console.log(AliceBlocksBob); } -} - -// Push Chat - PushAPI.chat.send -// // Will send a message to the user or chat request in case user hasn't approved them -async function PushAPI_chat_send(silent = !showAPIResponse) { - // Fetch user - const user = await PushAPI.user.get({ - account: `eip155:${signerAddress}`, - env: env as ENV, - }); - - // Decrypt PGP Key - const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - - signer: signer, - }); - - // Actual api - const response = await PushAPI.chat.send({ - messageObj: { - content: "Gm gm! It's me... Mario", - }, - messageType: 'Text', // can be "Text" | "Image" | "File" | "GIF" - receiverAddress: secondSignerAddress, - - signer: signer, - pgpPrivateKey: pgpDecrpyptedPvtKey, - env: env as ENV, - }); - - console.log('PushAPI_chat_send | Response - 200 OK'); - if (!silent) { - console.log(response); + console.log('PushAPI.chat.block | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.chat.unblock'); + const AliceUnblocksBob = await userAlice.chat.unblock([secondSignerAddress]); + if (showAPIResponse) { + console.log(AliceUnblocksBob); } - return response.chatId; -} - -// Push Chat - Approve -async function PushAPI_chat_approve(silent = !showAPIResponse) { - // Fetch user - const user = await PushAPI.user.get({ - account: `eip155:${secondSignerAddress}`, - env: env as ENV, - }); - - // Decrypt PGP Key - const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - - signer: secondSigner, - }); - - // Actual api - const approve = await PushAPI.chat.approve({ - status: 'Approved', - senderAddress: signerAddress, // receiver's address or chatId of a group - - signer: secondSigner, - pgpPrivateKey: pgpDecrpyptedPvtKey, - env: env as ENV, - }); - - console.log('PushAPI_chat_approve | Response - 200 OK'); - if (!silent) { - console.log(approve); + console.log('PushAPI.chat.unblock | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.group.create'); + const createdGroup = await userAlice.chat.group.create(groupName, { + description: groupDescription, + image: groupImage, + members: [randomWallet1, randomWallet2], + admins: [], + private: false, + }); + const groupChatId = createdGroup.chatId; // to be used in other examples + if (showAPIResponse) { + console.log(createdGroup); } -} - -// Push Chat - PushAPI.chat.createGroup -async function PushAPI_chat_createGroup( - silent = !showAPIResponse -): Promise<{ chatId: string; name: string }> { - // Fetch user - const user = await PushAPI.user.get({ - account: `eip155:${signerAddress}`, - env: env as ENV, - }); - - // Decrypt PGP Key - const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - - signer: signer, - }); - - // Actual API - // Convert image to base 64 and pass - const response = await PushAPI.chat.createGroup({ - groupName, - groupDescription, - members: [`eip155:${randomWallet1}`, `eip155:${randomWallet2}`], - groupImage, - admins: [], // takes signer as admin automatically, add more if you want to - isPublic: true, - - signer: signer, - pgpPrivateKey: pgpDecrpyptedPvtKey, - env: env as ENV, - }); - - console.log('PushAPI_chat_createGroup | Response - 200 OK'); - if (!silent) { - console.log(response); + await delay(2000); // Delay added to log the events in order + console.log('PushAPI.group.create | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.group.permissions'); + const grouppermissions = await userAlice.chat.group.permissions(groupChatId); + if (showAPIResponse) { + console.log(grouppermissions); } - return { chatId: response.chatId, name: response.groupName }; -} - -// Push Chat - PushAPI.chat.updateGroup -async function PushAPI_chat_updateGroup( - chatId: string, - silent = !showAPIResponse -) { - // Fetch user - const user = await PushAPI.user.get({ - account: `eip155:${signerAddress}`, - env: env as ENV, - }); - - // Decrypt PGP Key - const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - - signer: signer, - }); - - // Actual API - // Convert image to base 64 and pass - // This is an idempotent operation, meaning it requires all group info to be passed no matter if only few things change - // Why so? To ensure that verificationProof always is able to replicate the current group info (trustless since signature is stored with the info) - const response = await PushAPI.chat.updateGroup({ - chatId, - groupName, - groupDescription, - members: [ - `eip155:${randomWallet1}`, - `eip155:${randomWallet2}`, - `eip155:${randomWallet3}`, - `eip155:${signerAddress}`, - ], - groupImage, - admins: [`eip155:${signerAddress}`], // takes signer as admin automatically, add more if you want to - - signer: signer, - pgpPrivateKey: pgpDecrpyptedPvtKey, - env: env as ENV, - }); - - console.log('PushAPI_chat_updateGroup | Response - 200 OK'); - if (!silent) { - console.log(response); + console.log('PushAPI.group.permissions | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.group.info'); + const groupInfo = await userAlice.chat.group.info(groupChatId); + if (showAPIResponse) { + console.log(groupInfo); } -} - -// Push Chat - PushAPI.chat.getGroupByName -async function PushAPI_chat_getGroupByName( - name: string, - silent = !showAPIResponse -) { - const response = await PushAPI.chat.getGroupByName({ - groupName: name, - env: env as ENV, - }); - - console.log('PushAPI_chat_getGroupByName | Response - 200 OK'); - if (!silent) { - console.log(response); + console.log('PushAPI.group.info | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.group.update'); + const updatedGroup = await userAlice.chat.group.update(groupChatId, { + description: 'Updated Description', + }); + if (showAPIResponse) { + console.log(updatedGroup); } -} - -// Push Chat - PushAPI.chat.getGroup -async function PushAPI_chat_getGroup( - chatId: string, - silent = !showAPIResponse -) { - const response = await PushAPI.chat.getGroup({ - chatId: chatId, - env: env as ENV, - }); - - console.log('PushAPI_chat_getGroup | Response - 200 OK'); - if (!silent) { - console.log(response); + await delay(2000); // Delay added to log the events in order + console.log('PushAPI.group.update | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.group.add'); + const addMember = await userAlice.chat.group.add(groupChatId, { + role: 'MEMBER', + accounts: [randomWallet3], + }); + if (showAPIResponse) { + console.log(addMember); } -} - -// Push Chat - PushAPI.chat.decryptConversation -async function PushAPI_chat_decryptConversation(silent = !showAPIResponse) { - // Fetch user - const user = await PushAPI.user.get({ - account: `eip155:${signerAddress}`, - env: env as ENV, - }); - - // Decrypt PGP Key - const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - - signer: signer, - }); - - // Fetch conversation hash - // conversation hash are also called link inside chat messages - const conversationHash = await PushAPI.chat.conversationHash({ - account: `eip155:${signerAddress}`, - conversationId: `eip155:${secondSignerAddress}`, // 2nd address - env: env as ENV, - }); - - // Chat History - const encryptedChats = await PushAPI.chat.history({ - threadhash: conversationHash.threadHash, // get conversation hash from conversationHash function and send the response threadhash here - account: `eip155:${signerAddress}`, - limit: 5, - toDecrypt: false, - pgpPrivateKey: pgpDecrpyptedPvtKey, - env: env as ENV, - }); - - // Decrypted Chat - const decryptedChat = await PushAPI.chat.decryptConversation({ - messages: encryptedChats, // array of message object fetched from chat.history method - connectedUser: user, // user meta data object fetched from chat.get method - pgpPrivateKey: pgpDecrpyptedPvtKey, //decrypted private key - env: env as ENV, - }); - - console.log('PushAPI_chat_decryptConversation | Response - 200 OK'); - if (!silent) { - console.log(decryptedChat); + await delay(2000); // Delay added to log the events in order + console.log('PushAPI.group.add | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.group.remove'); + const removeMember = await userAlice.chat.group.remove(groupChatId, { + role: 'MEMBER', + accounts: [randomWallet3], + }); + if (showAPIResponse) { + console.log(removeMember); } -} - -// Push Chat - Socket Connection -async function PushChatSDKSocket(silent = !showAPIResponse) { - const pushSDKSocket = createSocketConnection({ - user: `eip155:${signerAddress}`, - socketType: 'chat', - socketOptions: { autoConnect: true, reconnectionAttempts: 3 }, - env: env as ENV, - }); - - if (!pushSDKSocket) { - throw new Error('Socket not connected'); + await delay(2000); // Delay added to log the events in order + console.log('PushAPI.group.remove | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.group.join'); + const joinGrp = await userBob.chat.group.join(groupChatId); + if (showAPIResponse) { + console.log(joinGrp); } - - pushSDKSocket.on(EVENTS.CONNECT, async () => { - console.log('Socket Connected - will disconnect after 4 seconds'); - - // send a chat from other wallet to this one to see the result - // Fetch user - const user = await PushAPI.user.get({ - account: `eip155:${secondSignerAddress}`, - env: env as ENV, - }); - - // Decrypt PGP Key - const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - - signer: secondSigner, - }); - - // Actual api - const response = await PushAPI.chat.send({ - messageContent: "Gm gm! It's me... Mario", - messageType: 'Text', - receiverAddress: `eip155:${signerAddress}`, - - signer: secondSigner, - pgpPrivateKey: pgpDecrpyptedPvtKey, - env: env as ENV, - }); - console.log('PushAPI_chat_send | Response - 200 OK'); - }); - - pushSDKSocket.on(EVENTS.DISCONNECT, () => { - console.log('Socket Disconnected'); - }); - - pushSDKSocket.on(EVENTS.CHAT_RECEIVED_MESSAGE, (message) => { - // feedItem is the notification data when that notification was received - console.log('Incoming Push Chat message from Socket'); - if (!silent) { - console.log(message); - } - - // disconnect socket after this, not to be done in real implementations - pushSDKSocket.disconnect(); - }); - - const delay = (ms: number) => - new Promise((resolve) => setTimeout(resolve, ms)); - await delay(4000); -} - -async function PushAPI_chat_video_call_notification( - chatId: string, - silent = !showAPIResponse -) { - // Fetch user - const user = await PushAPI.user.get({ - account: signerAddress, - env: env as ENV, - }); - - // Decrypt PGP Key - const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - signer: signer, - }); - // get PGP KEy - const apiResponse = await PushAPI.payloads.sendNotification({ - senderType: 1, - signer: signer, - pgpPrivateKey: pgpDecrpyptedPvtKey, - chatId: chatId, - type: 3, // target - identityType: 2, // direct payload - notification: { - title: `VC TITLE:`, - body: `VC BODY`, - }, - payload: { - title: `payload title`, - body: `sample msg body`, - cta: '', - img: '', - additionalMeta: { - type: '1+1', - data: 'Random DATA', - domain: 'push.org', - }, - }, - recipients: secondSignerAddress, // recipient address - channel: signerAddress, // your channel address - env: env as ENV, - }); - - console.log('PushAPI.payloads.sendNotification | Response - 204 OK'); - if (!silent) { - console.log(apiResponse); + await delay(2000); // Delay added to log the events in order + console.log('PushAPI.group.join | Response - 200 OK\n\n'); + //------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.group.leave'); + const leaveGrp = await userBob.chat.group.leave(groupChatId); + if (showAPIResponse) { + console.log(leaveGrp); } -} + await delay(2000); // Delay added to log the events in order + console.log('PushAPI.group.leave | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.group.reject'); + const sampleGrp = await userAlice.chat.group.create('Sample Grp', { + description: groupDescription, + image: groupImage, + members: [secondSignerAddress], // invite bob + admins: [], + private: true, + }); + await userBob.chat.group.reject(sampleGrp.chatId); + await delay(2000); // Delay added to log the events in order + console.log('PushAPI.group.reject | Response - 200 OK\n\n'); +}; diff --git a/packages/examples/sdk-backend-node/chat/index.ts b/packages/examples/sdk-backend-node/chat/index.ts index 40bccd361..85621540f 100644 --- a/packages/examples/sdk-backend-node/chat/index.ts +++ b/packages/examples/sdk-backend-node/chat/index.ts @@ -1,2 +1,28 @@ -export { runChatUseCases } from './chat'; -export { runNFTChatUseCases } from './nftChat'; +import { runChatLowlevelUseCases } from './chat.lowlevel'; +import { runNFTChatLowLevelUseCases } from './nftChat.lowlevel'; +import { runChatClassUseCases } from './chat'; + +export const runChatUseCases = async (): Promise => { + console.log(` +░█████╗░██╗░░██╗░█████╗░████████╗ +██╔══██╗██║░░██║██╔══██╗╚══██╔══╝ +██║░░╚═╝███████║███████║░░░██║░░░ +██║░░██╗██╔══██║██╔══██║░░░██║░░░ +╚█████╔╝██║░░██║██║░░██║░░░██║░░░ +░╚════╝░╚═╝░░╚═╝╚═╝░░╚═╝░░░╚═╝░░░ + `); + + await runChatClassUseCases(); + console.log(` +▒█▀▀█ ▒█░▒█ ░█▀▀█ ▀▀█▀▀ ░ ▒█░░░ ▒█▀▀▀█ ▒█░░▒█ ▒█░░░ ▒█▀▀▀ ▒█░░▒█ ▒█▀▀▀ ▒█░░░ +▒█░░░ ▒█▀▀█ ▒█▄▄█ ░▒█░░ ▄ ▒█░░░ ▒█░░▒█ ▒█▒█▒█ ▒█░░░ ▒█▀▀▀ ░▒█▒█░ ▒█▀▀▀ ▒█░░░ +▒█▄▄█ ▒█░▒█ ▒█░▒█ ░▒█░░ █ ▒█▄▄█ ▒█▄▄▄█ ▒█▄▀▄█ ▒█▄▄█ ▒█▄▄▄ ░░▀▄▀░ ▒█▄▄▄ ▒█▄▄█ + `); + await runChatLowlevelUseCases(); + console.log(` +▒█▄░▒█ ▒█▀▀▀ ▀▀█▀▀ ▒█▀▀█ ▒█░▒█ ░█▀▀█ ▀▀█▀▀ ░ ▒█░░░ ▒█▀▀▀█ ▒█░░▒█ ▒█░░░ ▒█▀▀▀ ▒█░░▒█ ▒█▀▀▀ ▒█░░░ +▒█▒█▒█ ▒█▀▀▀ ░▒█░░ ▒█░░░ ▒█▀▀█ ▒█▄▄█ ░▒█░░ ▄ ▒█░░░ ▒█░░▒█ ▒█▒█▒█ ▒█░░░ ▒█▀▀▀ ░▒█▒█░ ▒█▀▀▀ ▒█░░░ +▒█░░▀█ ▒█░░░ ░▒█░░ ▒█▄▄█ ▒█░▒█ ▒█░▒█ ░▒█░░ █ ▒█▄▄█ ▒█▄▄▄█ ▒█▄▀▄█ ▒█▄▄█ ▒█▄▄▄ ░░▀▄▀░ ▒█▄▄▄ ▒█▄▄█ + `); + await runNFTChatLowLevelUseCases(); +}; diff --git a/packages/examples/sdk-backend-node/chat/nftChat.ts b/packages/examples/sdk-backend-node/chat/nftChat.lowlevel.ts similarity index 96% rename from packages/examples/sdk-backend-node/chat/nftChat.ts rename to packages/examples/sdk-backend-node/chat/nftChat.lowlevel.ts index b238022be..2f5142d5c 100644 --- a/packages/examples/sdk-backend-node/chat/nftChat.ts +++ b/packages/examples/sdk-backend-node/chat/nftChat.lowlevel.ts @@ -74,15 +74,7 @@ const skipExample = () => { }; // Push Chat - Run Chat Use cases -export const runNFTChatUseCases = async (): Promise => { - console.log(` - ███ ██ ███████ ████████ ██████ ██ ██ █████ ████████ - ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ - ██ ██ ██ █████ ██ ██ ███████ ███████ ██ - ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ - ██ ████ ██ ██ ██████ ██ ██ ██ ██ ██ - `); - +export const runNFTChatLowLevelUseCases = async (): Promise => { if (skipExample()) { console.log('Skipping examples as required env vars are missing'); return; @@ -526,9 +518,9 @@ async function PushAPI_nft_chat_updateGroup( chatId, groupName: updatedNftGroupName, groupDescription, - members: [nftAccount2, nftAccount3], + members: [nftAccount2, nftAccount3, nftAccount1], groupImage, - admins: [nftAccount2], + admins: [nftAccount1], account: nftAccount1, signer: nftSigner1, pgpPrivateKey: pgpDecrpyptedPvtKey, diff --git a/packages/examples/sdk-backend-node/main.ts b/packages/examples/sdk-backend-node/main.ts index dbb09f210..e8a538268 100644 --- a/packages/examples/sdk-backend-node/main.ts +++ b/packages/examples/sdk-backend-node/main.ts @@ -1,11 +1,12 @@ -import { runNotificaitonsUseCases } from './notification'; -import { runChatUseCases, runNFTChatUseCases } from './chat'; +import { runUserCases } from './user'; +import { runNotificationUseCases } from './notification'; +import { runChatUseCases } from './chat'; import { runVideoUseCases } from './video'; -import { runSpacesUseCases } from './spaces'; -import { runPushAPICases } from './pushAPI'; +import { runSpaceUseCases } from './space'; import { config } from './config'; import { ENV } from './types'; +import { exit } from 'process'; // CONFIGS const { env } = config; @@ -15,12 +16,12 @@ const start = async (): Promise => { console.log(`${returnHeadingLog()}`); console.log(`${returnENVLog()}`); - await runPushAPICases(); - await runNotificaitonsUseCases(); + await runUserCases(); + await runNotificationUseCases(); await runChatUseCases(); - await runNFTChatUseCases(); await runVideoUseCases(); - await runSpacesUseCases(); + await runSpaceUseCases(); + exit(0); }; start(); @@ -32,39 +33,54 @@ start(); // ----------- function returnHeadingLog() { const headingLog = ` - ███████ ██████ ██ ██ ███████ ██ ██ ███ ██ ██████ ████████ ██ ██████ ███ ██ █████ ██ ██ ████████ ██ ██ - ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ - ███████ ██ ██ █████ █████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███████ ██ ██ ██ ████ - ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ - ███████ ██████ ██ ██ ██ ██████ ██ ████ ██████ ██ ██ ██████ ██ ████ ██ ██ ███████ ██ ██ ██ + +░██████╗██████╗░██╗░░██╗ ███████╗██╗░░░██╗███╗░░██╗░█████╗░████████╗██╗░█████╗░███╗░░██╗░█████╗░██╗░░░░░██╗████████╗██╗░░░██╗ +██╔════╝██╔══██╗██║░██╔╝ ██╔════╝██║░░░██║████╗░██║██╔══██╗╚══██╔══╝██║██╔══██╗████╗░██║██╔══██╗██║░░░░░██║╚══██╔══╝╚██╗░██╔╝ +╚█████╗░██║░░██║█████═╝░ █████╗░░██║░░░██║██╔██╗██║██║░░╚═╝░░░██║░░░██║██║░░██║██╔██╗██║███████║██║░░░░░██║░░░██║░░░░╚████╔╝░ +░╚═══██╗██║░░██║██╔═██╗░ ██╔══╝░░██║░░░██║██║╚████║██║░░██╗░░░██║░░░██║██║░░██║██║╚████║██╔══██║██║░░░░░██║░░░██║░░░░░╚██╔╝░░ +██████╔╝██████╔╝██║░╚██╗ ██║░░░░░╚██████╔╝██║░╚███║╚█████╔╝░░░██║░░░██║╚█████╔╝██║░╚███║██║░░██║███████╗██║░░░██║░░░░░░██║░░░ +╚═════╝░╚═════╝░╚═╝░░╚═╝ ╚═╝░░░░░░╚═════╝░╚═╝░░╚══╝░╚════╝░░░░╚═╝░░░╚═╝░╚════╝░╚═╝░░╚══╝╚═╝░░╚═╝╚══════╝╚═╝░░░╚═╝░░░░░░╚═╝░░░ `; return headingLog; } function returnENVLog() { let environmentLog = ` - ███████ ████████ █████ ██████ ██ ███ ██ ██████ - ██ ██ ██ ██ ██ ██ ████ ██ ██ - ███████ ██ ███████ ██ ███ ██ ██ ██ ██ ██ ███ - ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ - ███████ ██ ██ ██ ██████ ██ ██ ████ ██████ + +███████╗███╗░░██╗██╗░░░██╗ ░░░░░░ ░██████╗████████╗░█████╗░░██████╗░██╗███╗░░██╗░██████╗░ +██╔════╝████╗░██║██║░░░██║ ░░░░░░ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝░██║████╗░██║██╔════╝░ +█████╗░░██╔██╗██║╚██╗░██╔╝ █████╗ ╚█████╗░░░░██║░░░███████║██║░░██╗░██║██╔██╗██║██║░░██╗░ +██╔══╝░░██║╚████║░╚████╔╝░ ╚════╝ ░╚═══██╗░░░██║░░░██╔══██║██║░░╚██╗██║██║╚████║██║░░╚██╗ +███████╗██║░╚███║░░╚██╔╝░░ ░░░░░░ ██████╔╝░░░██║░░░██║░░██║╚██████╔╝██║██║░╚███║╚██████╔╝ +╚══════╝╚═╝░░╚══╝░░░╚═╝░░░ ░░░░░░ ╚═════╝░░░░╚═╝░░░╚═╝░░╚═╝░╚═════╝░╚═╝╚═╝░░╚══╝░╚═════╝░ `; if (env === ENV.PROD) { environmentLog = ` - ██████ ██████ ██████ ██████ ██ ██ ██████ ████████ ██ ██████ ███ ██ - ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ - ██████ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ - ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ - ██ ██ ██ ██████ ██████ ██████ ██████ ██ ██ ██████ ██ ████ +███████╗███╗░░██╗██╗░░░██╗ ░░░░░░ ██████╗░██████╗░░█████╗░██████╗░ +██╔════╝████╗░██║██║░░░██║ ░░░░░░ ██╔══██╗██╔══██╗██╔══██╗██╔══██╗ +█████╗░░██╔██╗██║╚██╗░██╔╝ █████╗ ██████╔╝██████╔╝██║░░██║██║░░██║ +██╔══╝░░██║╚████║░╚████╔╝░ ╚════╝ ██╔═══╝░██╔══██╗██║░░██║██║░░██║ +███████╗██║░╚███║░░╚██╔╝░░ ░░░░░░ ██║░░░░░██║░░██║╚█████╔╝██████╔╝ +╚══════╝╚═╝░░╚══╝░░░╚═╝░░░ ░░░░░░ ╚═╝░░░░░╚═╝░░╚═╝░╚════╝░╚═════╝░ `; } else if (env === ENV.DEV) { environmentLog = ` - ██████ ███████ ██ ██ - ██ ██ ██ ██ ██ - ██ ██ █████ ██ ██ - ██ ██ ██ ██ ██ - ██████ ███████ ████ +███████╗███╗░░██╗██╗░░░██╗ ░░░░░░ ██████╗░███████╗██╗░░░██╗ +██╔════╝████╗░██║██║░░░██║ ░░░░░░ ██╔══██╗██╔════╝██║░░░██║ +█████╗░░██╔██╗██║╚██╗░██╔╝ █████╗ ██║░░██║█████╗░░╚██╗░██╔╝ +██╔══╝░░██║╚████║░╚████╔╝░ ╚════╝ ██║░░██║██╔══╝░░░╚████╔╝░ +███████╗██║░╚███║░░╚██╔╝░░ ░░░░░░ ██████╔╝███████╗░░╚██╔╝░░ +╚══════╝╚═╝░░╚══╝░░░╚═╝░░░ ░░░░░░ ╚═════╝░╚══════╝░░░╚═╝░░░ + `; + } else if (env === ENV.LOCAL) { + environmentLog = ` +███████╗███╗░░██╗██╗░░░██╗ ░░░░░░ ██╗░░░░░░█████╗░░█████╗░░█████╗░██╗░░░░░ +██╔════╝████╗░██║██║░░░██║ ░░░░░░ ██║░░░░░██╔══██╗██╔══██╗██╔══██╗██║░░░░░ +█████╗░░██╔██╗██║╚██╗░██╔╝ █████╗ ██║░░░░░██║░░██║██║░░╚═╝███████║██║░░░░░ +██╔══╝░░██║╚████║░╚████╔╝░ ╚════╝ ██║░░░░░██║░░██║██║░░██╗██╔══██║██║░░░░░ +███████╗██║░╚███║░░╚██╔╝░░ ░░░░░░ ███████╗╚█████╔╝╚█████╔╝██║░░██║███████╗ +╚══════╝╚═╝░░╚══╝░░░╚═╝░░░ ░░░░░░ ╚══════╝░╚════╝░░╚════╝░╚═╝░░╚═╝╚══════╝ `; } diff --git a/packages/examples/sdk-backend-node/notification/index.ts b/packages/examples/sdk-backend-node/notification/index.ts index 605a60a23..f2251c1c7 100644 --- a/packages/examples/sdk-backend-node/notification/index.ts +++ b/packages/examples/sdk-backend-node/notification/index.ts @@ -1,384 +1,20 @@ -import * as PushAPI from '@pushprotocol/restapi'; -import { createSocketConnection, EVENTS } from '@pushprotocol/socket'; -import { ethers } from 'ethers'; -import { config } from '../config'; +import { runNotificaitonsLowLevelUseCases } from './notification.lowlevel'; +import { runNotificationClassUseCases } from './notification'; -import { createWalletClient, http } from 'viem'; -import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; -import { goerli } from 'viem/chains'; - -enum ENV { - PROD = 'prod', - STAGING = 'staging', - DEV = 'dev', - /** - * **This is for local development only** - */ - LOCAL = 'local', -} - -// CONFIGS -const { env, showAPIResponse } = config; - -// If you own a channel, you can use your channel address as well -const channelPrivateKey = process.env.WALLET_PRIVATE_KEY; - -/***************** SAMPLE SIGNER GENERATION *********************/ -/** - * USING VIEM - */ -const signerChannel = channelPrivateKey - ? createWalletClient({ - account: privateKeyToAccount(`0x${channelPrivateKey}`), - chain: goerli, - transport: http(), - }) - : undefined; -const channelAddress = signerChannel - ? signerChannel.account.address - : undefined; -// Random Wallet Signers -const signer = createWalletClient({ - account: privateKeyToAccount(generatePrivateKey()), - chain: goerli, - transport: http(), -}); -const signerAddress = signer.account.address; -// Dummy Wallet Addresses -const randomWallet1 = privateKeyToAccount(generatePrivateKey()).address; - -/** - * USING ETHERS - */ -// const signerChannel = new ethers.Wallet(`0x${channelPrivateKey}`); -// const channelAddress = signerChannel.address; -// // Random Wallet Signers -// const signer = ethers.Wallet.createRandom(); -// const signerAddress = signer.address; -// // Dummy Wallet Addresses -// const randomWallet1 = ethers.Wallet.createRandom().address; -/************************************************************* */ - -const skipExample = () => { - const requiredEnvVars = ['WALLET_PRIVATE_KEY']; - - for (const envVar of requiredEnvVars) { - if (!process.env[envVar]) { - return true; // Skip the example if any of the required env vars is missing - } - } - - return false; // All required env vars are present, don't skip the example -}; - -// Push Notification - Run Notifications Use cases -export const runNotificaitonsUseCases = async (): Promise => { +export const runNotificationUseCases = async (): Promise => { + console.log(` +███╗░░██╗░█████╗░████████╗██╗███████╗██╗░█████╗░░█████╗░████████╗██╗░█████╗░███╗░░██╗ +████╗░██║██╔══██╗╚══██╔══╝██║██╔════╝██║██╔══██╗██╔══██╗╚══██╔══╝██║██╔══██╗████╗░██║ +██╔██╗██║██║░░██║░░░██║░░░██║█████╗░░██║██║░░╚═╝███████║░░░██║░░░██║██║░░██║██╔██╗██║ +██║╚████║██║░░██║░░░██║░░░██║██╔══╝░░██║██║░░██╗██╔══██║░░░██║░░░██║██║░░██║██║╚████║ +██║░╚███║╚█████╔╝░░░██║░░░██║██║░░░░░██║╚█████╔╝██║░░██║░░░██║░░░██║╚█████╔╝██║░╚███║ +╚═╝░░╚══╝░╚════╝░░░░╚═╝░░░╚═╝╚═╝░░░░░╚═╝░╚════╝░╚═╝░░╚═╝░░░╚═╝░░░╚═╝░╚════╝░╚═╝░░╚══╝ + `); + await runNotificationClassUseCases(); console.log(` - ███ ██ ██████ ████████ ██ ███████ ██ ██████ █████ ████████ ██ ██████ ███ ██ ███████ - ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ - ██ ██ ██ ██ ██ ██ ██ █████ ██ ██ ███████ ██ ██ ██ ██ ██ ██ ██ ███████ - ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ - ██ ████ ██████ ██ ██ ██ ██ ██████ ██ ██ ██ ██ ██████ ██ ████ ███████ +▒█▄░▒█ ▒█▀▀▀█ ▀▀█▀▀ ▀█▀ ▒█▀▀▀ ▀█▀ ▒█▀▀█ ░█▀▀█ ▀▀█▀▀ ▀█▀ ▒█▀▀▀█ ▒█▄░▒█ ░ ▒█░░░ ▒█▀▀▀█ ▒█░░▒█ ▒█░░░ ▒█▀▀▀ ▒█░░▒█ ▒█▀▀▀ ▒█░░░ +▒█▒█▒█ ▒█░░▒█ ░▒█░░ ▒█░ ▒█▀▀▀ ▒█░ ▒█░░░ ▒█▄▄█ ░▒█░░ ▒█░ ▒█░░▒█ ▒█▒█▒█ ▄ ▒█░░░ ▒█░░▒█ ▒█▒█▒█ ▒█░░░ ▒█▀▀▀ ░▒█▒█░ ▒█▀▀▀ ▒█░░░ +▒█░░▀█ ▒█▄▄▄█ ░▒█░░ ▄█▄ ▒█░░░ ▄█▄ ▒█▄▄█ ▒█░▒█ ░▒█░░ ▄█▄ ▒█▄▄▄█ ▒█░░▀█ █ ▒█▄▄█ ▒█▄▄▄█ ▒█▄▀▄█ ▒█▄▄█ ▒█▄▄▄ ░░▀▄▀░ ▒█▄▄▄ ▒█▄▄█ `); - console.log('PushAPI.user.getFeeds'); - await PushAPI_user_getFeeds(); - - console.log('PushAPI.user.getFeeds [Spam]'); - await PushAPI_user_getFeeds__spam(); - - console.log('PushAPI.user.getSubscriptions'); - await PushAPI_user_getSubscriptions(); - - if (!skipExample()) { - console.log('PushAPI.channels.getChannel()'); - await PushAPI_channels_getChannel(); - - console.log('PushAPI.channels.search()'); - await PushAPI_channels_search(); - - console.log('PushAPI.channels.subscribe()'); - await PushAPI_channels_subscribe(); - - console.log('PushAPI.channels.unsubscribe()'); - await PushAPI_channels_unsubscribe(); - - // IMPORTANT: VARIOUS OTHER NOTIFICATIONS FORMAT SUPPORTED - // EXAMPLES HERE: https://github.com/ethereum-push-notification-service/push-sdk/blob/main/packages/restapi/README.md - console.log( - 'PushAPI.payloads.sendNotification() [Direct Payload, Single Recipient]' - ); - await PushAPI_payloads_sendNotification__direct_payload_single_recipient(); - - console.log( - 'PushAPI.payloads.sendNotification() [Direct Payload, Batch of Recipients (Subset)]' - ); - await PushAPI_payloads_sendNotification__direct_payload_group_of_recipient_subset(); - - console.log( - 'PushAPI.payloads.sendNotification() [Direct Payload, All Recipients (Broadcast)]' - ); - await PushAPI_payloads_sendNotification__direct_payload_all_recipients_brodcast(); - - console.log('PushAPI.channels._getSubscribers()'); - await PushAPI_channels_getSubscribers(); - - console.log('Push Notification - PushSDKSocket()'); - await PushSDKSocket(); - } + await runNotificaitonsLowLevelUseCases(); }; - -// Push Notification - PushAPI.user.getFeeds -async function PushAPI_user_getFeeds(silent = !showAPIResponse) { - const notifications = await PushAPI.user.getFeeds({ - user: `eip155:5:${signerAddress}`, // user address in CAIP - env: env as ENV, - }); - - console.log('PushAPI.user.getFeeds | Response - 200 OK'); - if (!silent) { - console.log(notifications); - } -} - -// Push Notification - PushAPI.user.getFeeds - Spam -async function PushAPI_user_getFeeds__spam(silent = !showAPIResponse) { - const notifications = await PushAPI.user.getFeeds({ - user: `eip155:5:${signerAddress}`, // user address in CAIP - spam: true, - env: env as ENV, - }); - - console.log('PushAPI.user.getFeeds [Spam] | Response - 200 OK'); - if (!silent) { - console.log(notifications); - } -} - -// Push Notification - PushAPI.user.getSubscriptions -async function PushAPI_user_getSubscriptions(silent = !showAPIResponse) { - const subscriptions = await PushAPI.user.getSubscriptions({ - user: `eip155:5:${signerAddress}`, // user address in CAIP - env: env as ENV, - }); - - console.log('PushAPI.user.getSubscriptions | Response - 200 OK'); - if (!silent) { - console.log(subscriptions); - } -} - -// Push Notification - PushAPI.channels.getChannel -async function PushAPI_channels_getChannel(silent = !showAPIResponse) { - const channelData = await PushAPI.channels.getChannel({ - channel: channelAddress as string, - env: env as ENV, - }); - - console.log('PushAPI.channels.getChannel | Response - 200 OK'); - if (!silent) { - console.log(channelData); - } -} - -// Push Notification - PushAPI.channels.search -async function PushAPI_channels_search(silent = !showAPIResponse) { - const channelsData = await PushAPI.channels.search({ - query: 'push', // a search query - page: 1, // page index - limit: 20, // no of items per page - env: env as ENV, - }); - - console.log('PushAPI.channels.search | Response - 200 OK'); - if (!silent) { - console.log(channelsData); - } -} - -// Push Notification - PushAPI.channels.subscribe -async function PushAPI_channels_subscribe(silent = !showAPIResponse) { - const response = await PushAPI.channels.subscribe({ - signer: signer, - channelAddress: `eip155:5:${channelAddress}`, // channel address in CAIP - userAddress: `eip155:5:${signerAddress}`, // user address in CAIP - onSuccess: () => { - console.log('opt in success'); - }, - onError: () => { - console.error('opt in error'); - }, - env: env as ENV, - }); - - console.log('PushAPI.channels.subscribe | Response - 200 OK'); - if (!silent) { - console.log(response); - } -} - -// Push Notification - PushAPI.channels.unsubscribe -async function PushAPI_channels_unsubscribe(silent = !showAPIResponse) { - const response = await PushAPI.channels.unsubscribe({ - signer: signer, - channelAddress: `eip155:5:${channelAddress}`, // channel address in CAIP - userAddress: `eip155:5:${signerAddress}`, // user address in CAIP - onSuccess: () => { - console.log('opt out success'); - }, - onError: () => { - console.error('opt out error'); - }, - env: env as ENV, - }); - - console.log('PushAPI.channels.unsubscribe | Response - 200 OK'); - if (!silent) { - console.log(response); - } -} - -// Push Notification - Send Notifications -// Direct payload for single recipient(target) -// PushAPI.payloads.sendNotification -async function PushAPI_payloads_sendNotification__direct_payload_single_recipient( - silent = !showAPIResponse -) { - const apiResponse = await PushAPI.payloads.sendNotification({ - signer: signerChannel, // Need to resolve to channel address - type: 3, // target - identityType: 2, // direct payload - notification: { - title: `notification TITLE:`, - body: `notification BODY`, - }, - payload: { - title: `payload title`, - body: `sample msg body`, - cta: '', - img: '', - }, - recipients: `eip155:5:${signerAddress}`, // recipient address - channel: `eip155:5:${channelAddress}`, // your channel address - env: env as ENV, - }); - - console.log('PushAPI.payloads.sendNotification | Response - 204 OK'); - if (!silent) { - console.log(apiResponse); - } -} - -// Push Notification - Direct payload for group of recipients(subset) -// PushAPI.payloads.sendNotification -async function PushAPI_payloads_sendNotification__direct_payload_group_of_recipient_subset( - silent = !showAPIResponse -) { - const apiResponse = await PushAPI.payloads.sendNotification({ - signer: signerChannel, // Need to resolve to channel address - type: 4, // subset - identityType: 2, // direct payload - notification: { - title: `notification TITLE:`, - body: `notification BODY`, - }, - payload: { - title: `payload title`, - body: `sample msg body`, - cta: '', - img: '', - }, - recipients: [`eip155:5:${signerAddress}`, `eip155:5:${randomWallet1}`], // recipient addresses - channel: `eip155:5:${channelAddress}`, // your channel address - env: env as ENV, - }); - - console.log('PushAPI.payloads.sendNotification | Response - 204 OK'); - if (!silent) { - console.log(apiResponse); - } -} - -// Push Notification - Direct payload for all recipients(broadcast) -// PushAPI.payloads.sendNotification -async function PushAPI_payloads_sendNotification__direct_payload_all_recipients_brodcast( - silent = !showAPIResponse -) { - const apiResponse = await PushAPI.payloads.sendNotification({ - signer: signerChannel, // Needs to resolve to channel address - type: 1, // broadcast - identityType: 2, // direct payload - notification: { - title: `notification TITLE:`, - body: `notification BODY`, - }, - payload: { - title: `payload title`, - body: `sample msg body`, - cta: '', - img: '', - }, - channel: `eip155:5:${channelAddress}`, // your channel address - env: env as ENV, - }); - - console.log('PushAPI.payloads.sendNotification | Response - 204 OK'); - if (!silent) { - console.log(apiResponse); - } -} - -// Push Notification - Get Subscribers list from channels (DEPRECATED) -async function PushAPI_channels_getSubscribers(silent = !showAPIResponse) { - const subscribers = await PushAPI.channels._getSubscribers({ - channel: `eip155:5:${channelAddress}`, // channel address in CAIP - env: env as ENV, - }); - - console.log('PushAPI.channels._getSubscribers | Response - 200 OK'); - if (!silent) { - console.log(subscribers); - } -} - -// Push Notification - Socket Connection -async function PushSDKSocket(silent = !showAPIResponse) { - const pushSDKSocket = createSocketConnection({ - user: `eip155:5:${signerAddress}`, // CAIP, see below - socketOptions: { autoConnect: false }, - env: env as ENV, - }); - - if (!pushSDKSocket) { - throw new Error('PushSDKSocket | Socket Connection Failed'); - } - - pushSDKSocket.connect(); - - pushSDKSocket.on(EVENTS.CONNECT, async () => { - console.log('Socket Connected - will disconnect after 4 seconds'); - - // send a notification to see the result - await PushAPI_payloads_sendNotification__direct_payload_single_recipient( - true - ); - }); - - pushSDKSocket.on(EVENTS.DISCONNECT, () => { - console.log('Socket Disconnected'); - }); - - pushSDKSocket.on(EVENTS.USER_FEEDS, (feedItem) => { - // feedItem is the notification data when that notification was received - console.log('Incoming Feed from Socket'); - if (!silent) { - console.log(feedItem); - } - - // disconnect socket after this, not to be done in real implementations - pushSDKSocket.disconnect(); - }); - - const delay = (ms: number) => - new Promise((resolve) => setTimeout(resolve, ms)); - await delay(4000); -} diff --git a/packages/examples/sdk-backend-node/notification/notification.lowlevel.ts b/packages/examples/sdk-backend-node/notification/notification.lowlevel.ts new file mode 100644 index 000000000..e2f04f99a --- /dev/null +++ b/packages/examples/sdk-backend-node/notification/notification.lowlevel.ts @@ -0,0 +1,377 @@ +import * as PushAPI from '@pushprotocol/restapi'; +import { createSocketConnection, EVENTS } from '@pushprotocol/socket'; +import { ethers } from 'ethers'; +import { config } from '../config'; + +import { createWalletClient, http } from 'viem'; +import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; +import { goerli } from 'viem/chains'; + +enum ENV { + PROD = 'prod', + STAGING = 'staging', + DEV = 'dev', + /** + * **This is for local development only** + */ + LOCAL = 'local', +} + +// CONFIGS +const { env, showAPIResponse } = config; + +// If you own a channel, you can use your channel address as well +const channelPrivateKey = process.env.WALLET_PRIVATE_KEY; + +/***************** SAMPLE SIGNER GENERATION *********************/ +/** + * USING VIEM + */ +const signerChannel = channelPrivateKey + ? createWalletClient({ + account: privateKeyToAccount(`0x${channelPrivateKey}`), + chain: goerli, + transport: http(), + }) + : undefined; +const channelAddress = signerChannel + ? signerChannel.account.address + : undefined; +// Random Wallet Signers +const signer = createWalletClient({ + account: privateKeyToAccount(generatePrivateKey()), + chain: goerli, + transport: http(), +}); +const signerAddress = signer.account.address; +// Dummy Wallet Addresses +const randomWallet1 = privateKeyToAccount(generatePrivateKey()).address; + +/** + * USING ETHERS + */ +// const signerChannel = new ethers.Wallet(`0x${channelPrivateKey}`); +// const channelAddress = signerChannel.address; +// // Random Wallet Signers +// const signer = ethers.Wallet.createRandom(); +// const signerAddress = signer.address; +// // Dummy Wallet Addresses +// const randomWallet1 = ethers.Wallet.createRandom().address; +/************************************************************* */ + +const skipExample = () => { + const requiredEnvVars = ['WALLET_PRIVATE_KEY']; + + for (const envVar of requiredEnvVars) { + if (!process.env[envVar]) { + return true; // Skip the example if any of the required env vars is missing + } + } + + return false; // All required env vars are present, don't skip the example +}; + +// Push Notification - Run Notifications Use cases +export const runNotificaitonsLowLevelUseCases = async (): Promise => { + console.log('PushAPI.user.getFeeds'); + await PushAPI_user_getFeeds(); + + console.log('PushAPI.user.getFeeds [Spam]'); + await PushAPI_user_getFeeds__spam(); + + console.log('PushAPI.user.getSubscriptions'); + await PushAPI_user_getSubscriptions(); + + if (!skipExample()) { + console.log('PushAPI.channels.getChannel()'); + await PushAPI_channels_getChannel(); + + console.log('PushAPI.channels.search()'); + await PushAPI_channels_search(); + + console.log('PushAPI.channels.subscribe()'); + await PushAPI_channels_subscribe(); + + console.log('PushAPI.channels.unsubscribe()'); + await PushAPI_channels_unsubscribe(); + + // IMPORTANT: VARIOUS OTHER NOTIFICATIONS FORMAT SUPPORTED + // EXAMPLES HERE: https://github.com/ethereum-push-notification-service/push-sdk/blob/main/packages/restapi/README.md + console.log( + 'PushAPI.payloads.sendNotification() [Direct Payload, Single Recipient]' + ); + await PushAPI_payloads_sendNotification__direct_payload_single_recipient(); + + console.log( + 'PushAPI.payloads.sendNotification() [Direct Payload, Batch of Recipients (Subset)]' + ); + await PushAPI_payloads_sendNotification__direct_payload_group_of_recipient_subset(); + + console.log( + 'PushAPI.payloads.sendNotification() [Direct Payload, All Recipients (Broadcast)]' + ); + await PushAPI_payloads_sendNotification__direct_payload_all_recipients_brodcast(); + + console.log('PushAPI.channels._getSubscribers()'); + await PushAPI_channels_getSubscribers(); + + console.log('Push Notification - PushSDKSocket()'); + await PushSDKSocket(); + } +}; + +// Push Notification - PushAPI.user.getFeeds +async function PushAPI_user_getFeeds(silent = !showAPIResponse) { + const notifications = await PushAPI.user.getFeeds({ + user: `eip155:5:${signerAddress}`, // user address in CAIP + env: env as ENV, + }); + + console.log('PushAPI.user.getFeeds | Response - 200 OK'); + if (!silent) { + console.log(notifications); + } +} + +// Push Notification - PushAPI.user.getFeeds - Spam +async function PushAPI_user_getFeeds__spam(silent = !showAPIResponse) { + const notifications = await PushAPI.user.getFeeds({ + user: `eip155:5:${signerAddress}`, // user address in CAIP + spam: true, + env: env as ENV, + }); + + console.log('PushAPI.user.getFeeds [Spam] | Response - 200 OK'); + if (!silent) { + console.log(notifications); + } +} + +// Push Notification - PushAPI.user.getSubscriptions +async function PushAPI_user_getSubscriptions(silent = !showAPIResponse) { + const subscriptions = await PushAPI.user.getSubscriptions({ + user: `eip155:5:${signerAddress}`, // user address in CAIP + env: env as ENV, + }); + + console.log('PushAPI.user.getSubscriptions | Response - 200 OK'); + if (!silent) { + console.log(subscriptions); + } +} + +// Push Notification - PushAPI.channels.getChannel +async function PushAPI_channels_getChannel(silent = !showAPIResponse) { + const channelData = await PushAPI.channels.getChannel({ + channel: channelAddress as string, + env: env as ENV, + }); + + console.log('PushAPI.channels.getChannel | Response - 200 OK'); + if (!silent) { + console.log(channelData); + } +} + +// Push Notification - PushAPI.channels.search +async function PushAPI_channels_search(silent = !showAPIResponse) { + const channelsData = await PushAPI.channels.search({ + query: 'push', // a search query + page: 1, // page index + limit: 20, // no of items per page + env: env as ENV, + }); + + console.log('PushAPI.channels.search | Response - 200 OK'); + if (!silent) { + console.log(channelsData); + } +} + +// Push Notification - PushAPI.channels.subscribe +async function PushAPI_channels_subscribe(silent = !showAPIResponse) { + const response = await PushAPI.channels.subscribe({ + signer: signer, + channelAddress: `eip155:5:${channelAddress}`, // channel address in CAIP + userAddress: `eip155:5:${signerAddress}`, // user address in CAIP + onSuccess: () => { + console.log('opt in success'); + }, + onError: () => { + console.error('opt in error'); + }, + env: env as ENV, + }); + + console.log('PushAPI.channels.subscribe | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Notification - PushAPI.channels.unsubscribe +async function PushAPI_channels_unsubscribe(silent = !showAPIResponse) { + const response = await PushAPI.channels.unsubscribe({ + signer: signer, + channelAddress: `eip155:5:${channelAddress}`, // channel address in CAIP + userAddress: `eip155:5:${signerAddress}`, // user address in CAIP + onSuccess: () => { + console.log('opt out success'); + }, + onError: () => { + console.error('opt out error'); + }, + env: env as ENV, + }); + + console.log('PushAPI.channels.unsubscribe | Response - 200 OK'); + if (!silent) { + console.log(response); + } +} + +// Push Notification - Send Notifications +// Direct payload for single recipient(target) +// PushAPI.payloads.sendNotification +async function PushAPI_payloads_sendNotification__direct_payload_single_recipient( + silent = !showAPIResponse +) { + const apiResponse = await PushAPI.payloads.sendNotification({ + signer: signerChannel, // Need to resolve to channel address + type: 3, // target + identityType: 2, // direct payload + notification: { + title: `notification TITLE:`, + body: `notification BODY`, + }, + payload: { + title: `payload title`, + body: `sample msg body`, + cta: '', + img: '', + }, + recipients: `eip155:5:${signerAddress}`, // recipient address + channel: `eip155:5:${channelAddress}`, // your channel address + env: env as ENV, + }); + + console.log('PushAPI.payloads.sendNotification | Response - 204 OK'); + if (!silent) { + console.log(apiResponse); + } +} + +// Push Notification - Direct payload for group of recipients(subset) +// PushAPI.payloads.sendNotification +async function PushAPI_payloads_sendNotification__direct_payload_group_of_recipient_subset( + silent = !showAPIResponse +) { + const apiResponse = await PushAPI.payloads.sendNotification({ + signer: signerChannel, // Need to resolve to channel address + type: 4, // subset + identityType: 2, // direct payload + notification: { + title: `notification TITLE:`, + body: `notification BODY`, + }, + payload: { + title: `payload title`, + body: `sample msg body`, + cta: '', + img: '', + }, + recipients: [`eip155:5:${signerAddress}`, `eip155:5:${randomWallet1}`], // recipient addresses + channel: `eip155:5:${channelAddress}`, // your channel address + env: env as ENV, + }); + + console.log('PushAPI.payloads.sendNotification | Response - 204 OK'); + if (!silent) { + console.log(apiResponse); + } +} + +// Push Notification - Direct payload for all recipients(broadcast) +// PushAPI.payloads.sendNotification +async function PushAPI_payloads_sendNotification__direct_payload_all_recipients_brodcast( + silent = !showAPIResponse +) { + const apiResponse = await PushAPI.payloads.sendNotification({ + signer: signerChannel, // Needs to resolve to channel address + type: 1, // broadcast + identityType: 2, // direct payload + notification: { + title: `notification TITLE:`, + body: `notification BODY`, + }, + payload: { + title: `payload title`, + body: `sample msg body`, + cta: '', + img: '', + }, + channel: `eip155:5:${channelAddress}`, // your channel address + env: env as ENV, + }); + + console.log('PushAPI.payloads.sendNotification | Response - 204 OK'); + if (!silent) { + console.log(apiResponse); + } +} + +// Push Notification - Get Subscribers list from channels (DEPRECATED) +async function PushAPI_channels_getSubscribers(silent = !showAPIResponse) { + const subscribers = await PushAPI.channels._getSubscribers({ + channel: `eip155:5:${channelAddress}`, // channel address in CAIP + env: env as ENV, + }); + + console.log('PushAPI.channels._getSubscribers | Response - 200 OK'); + if (!silent) { + console.log(subscribers); + } +} + +// Push Notification - Socket Connection +async function PushSDKSocket(silent = !showAPIResponse) { + const pushSDKSocket = createSocketConnection({ + user: `eip155:5:${signerAddress}`, // CAIP, see below + socketOptions: { autoConnect: false }, + env: env as ENV, + }); + + if (!pushSDKSocket) { + throw new Error('PushSDKSocket | Socket Connection Failed'); + } + + pushSDKSocket.connect(); + + pushSDKSocket.on(EVENTS.CONNECT, async () => { + console.log('Socket Connected - will disconnect after 4 seconds'); + + // send a notification to see the result + await PushAPI_payloads_sendNotification__direct_payload_single_recipient( + true + ); + }); + + pushSDKSocket.on(EVENTS.DISCONNECT, () => { + console.log('Socket Disconnected'); + }); + + pushSDKSocket.on(EVENTS.USER_FEEDS, (feedItem) => { + // feedItem is the notification data when that notification was received + console.log('Incoming Feed from Socket'); + if (!silent) { + console.log(feedItem); + } + + // disconnect socket after this, not to be done in real implementations + pushSDKSocket.disconnect(); + }); + + const delay = (ms: number) => + new Promise((resolve) => setTimeout(resolve, ms)); + await delay(4000); +} diff --git a/packages/examples/sdk-backend-node/notification/notification.ts b/packages/examples/sdk-backend-node/notification/notification.ts new file mode 100644 index 000000000..2865fee94 --- /dev/null +++ b/packages/examples/sdk-backend-node/notification/notification.ts @@ -0,0 +1,257 @@ +import { PushAPI } from '@pushprotocol/restapi'; +import { config } from '../config'; +import { ethers } from 'ethers'; +import { STREAM } from '@pushprotocol/restapi/src/lib/pushstream/pushStreamTypes'; + +// CONFIGS +const { env, showAPIResponse } = config; + +const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + +const eventlistener = async ( + pushAPI: PushAPI, + eventName: string +): Promise => { + pushAPI.stream.on(eventName, (data: any) => { + if (showAPIResponse) { + console.log('Stream Event Received'); + console.log(data); + console.log('\n'); + } + }); +}; + +export const runNotificationClassUseCases = async (): Promise => { + if (!process.env.WALLET_PRIVATE_KEY) { + console.log( + 'skipping PushAPI.channel examples, no private key passed in .env' + ); + return; + } + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + // Signer Generation + const provider = new ethers.providers.JsonRpcProvider( + 'https://goerli.blockpi.network/v1/rpc/public' // Goerli Provider + ); + const signer = new ethers.Wallet( + `0x${process.env.WALLET_PRIVATE_KEY}`, + provider + ); + const randomWallet1 = ethers.Wallet.createRandom().address; + const randomWallet2 = ethers.Wallet.createRandom().address; + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + const userAlice = await PushAPI.initialize(signer, { env }); + + // Listen Stream Events for getting websocket events + console.log(`Listening ${STREAM.NOTIF} Events`); + eventlistener(userAlice, STREAM.NOTIF); + console.log(`Listening ${STREAM.NOTIF_OPS} Events`); + eventlistener(userAlice, STREAM.NOTIF_OPS); + console.log('\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.info'); + const channelInfo = await userAlice.channel.info(); + if (showAPIResponse) { + console.log(channelInfo); + } + console.log('PushAPI.channel.info | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.search'); + const searchedChannels = await userAlice.channel.search( + 'push' // search by name or address + ); + if (showAPIResponse) { + console.log(searchedChannels); + } + console.log('PushAPI.channel.search | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.subscribers'); + const channelSubscribers = await userAlice.channel.subscribers(); + if (showAPIResponse) { + console.log(channelSubscribers); + } + console.log('PushAPI.channel.subscribers | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.send'); + if (channelInfo) { + const broadcastNotif = await userAlice.channel.send(['*'], { + notification: { + title: 'test', + body: 'test', + }, + }); + await delay(3000); // Delay added to log the events in order + const targetedNotif = await userAlice.channel.send([signer.address], { + notification: { + title: 'test', + body: 'test', + }, + }); + await delay(3000); // Delay added to log the events in order + const subsetNotif = await userAlice.channel.send( + [randomWallet1, randomWallet2, signer.address], + { + notification: { + title: 'test', + body: 'test', + }, + } + ); + await delay(3000); // Delay added to log the events in order + if (showAPIResponse) { + console.log(broadcastNotif, targetedNotif, subsetNotif); + } + console.log('PushAPI.channel.send | Response - 200 OK\n\n'); + } else { + console.log( + 'skipping PushAPI.channel.send as no channel exists with the signer\n\n' + ); + } + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + // These Examples requires wallet to hold some ETH & PUSH + const balance = await provider.getBalance(signer.address); + if (parseFloat(ethers.utils.formatEther(balance)) < 0.001) { + console.log( + 'skipping PushAPI.channel examples, wallet does not have enough balance to pay fee' + ); + } + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.create'); + if (channelInfo) { + console.log('skipping PushAPI.channel.create as it already exists\n\n'); + } else { + const createdChannel = await userAlice.channel.create({ + name: 'Test Channel', + description: 'Test Description', + icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAz0lEQVR4AcXBsU0EQQyG0e+saWJ7oACiKYDMEZVs6GgSpC2BIhzRwAS0sgk9HKn3gpFOAv3v3V4/3+4U4Z1q5KTy42Ql940qvFONnFSGmCFmiN2+fj7uCBlihpgh1ngwcvKfwjuVIWaIGWKNB+GdauSk8uNkJfeNKryzYogZYoZY40m5b/wlQ8wQM8TayMlKeKcaOVkJ71QjJyuGmCFmiDUe+HFy4VyEd57hx0mV+0ZliBlihlgL71w4FyMnVXhnZeSkiu93qheuDDFDzBD7BcCyMAOfy204AAAAAElFTkSuQmCC', + url: 'https://push.org', + }); + if (showAPIResponse) { + console.log(createdChannel); + } + console.log('PushAPI.channel.create | Response - 200 OK\n\n'); + } + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.update'); + const updatedChannel = await userAlice.channel.update({ + name: 'Updated Name', + description: 'Testing new description', + url: 'https://google.com', + icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAz0lEQVR4AcXBsU0EQQyG0e+saWJ7oACiKYDMEZVs6GgSpC2BIhzRwAS0sgk9HKn3gpFOAv3v3V4/3+4U4Z1q5KTy42Ql940qvFONnFSGmCFmiN2+fj7uCBlihpgh1ngwcvKfwjuVIWaIGWKNB+GdauSk8uNkJfeNKryzYogZYoZY40m5b/wlQ8wQM8TayMlKeKcaOVkJ71QjJyuGmCFmiDUe+HFy4VyEd57hx0mV+0ZliBlihlgL71w4FyMnVXhnZeSkiu93qheuDDFDzBD7BcCyMAOfy204AAAAAElFTkSuQmCC', + }); + if (showAPIResponse) { + console.log(updatedChannel); + } + console.log('PushAPI.channel.update | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.verify'); + // only verified channels can verify other channels (otherwise this action is skipped by sdk) + if (channelInfo.verified_status) { + const verifiedTrx = await userAlice.channel.verify( + '0x35B84d6848D16415177c64D64504663b998A6ab4' + ); + if (showAPIResponse) { + console.log(verifiedTrx); + } + } + console.log('PushAPI.channel.verify | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.setting'); + const channelSettingTrx = await userAlice.channel.setting([ + { type: 0, default: 1, description: 'My Notif Settings' }, + ]); + if (showAPIResponse) { + console.log(channelSettingTrx); + } + console.log('PushAPI.channel.setting | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.delegate.add'); + const addedDelegate = await userAlice.channel.delegate.add( + `eip155:5:${randomWallet1}` + ); + + if (showAPIResponse) { + console.log(addedDelegate); + } + console.log('PushAPI.channel.delegate.add | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.delegate.get'); + const delegates = await userAlice.channel.delegate.get(); + if (showAPIResponse) { + console.log(delegates); + } + console.log('PushAPI.channel.delegate.get | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.delegate.remove'); + const removedDelegate = await userAlice.channel.delegate.remove( + `eip155:5:${randomWallet1}` + ); + if (showAPIResponse) { + console.log(removedDelegate); + } + console.log('PushAPI.channel.delegate.remove | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.channel.alias.info'); + const aliasInfo = await userAlice.channel.alias.info({ + alias: '0x35B84d6848D16415177c64D64504663b998A6ab4', + aliasChain: 'POLYGON', + }); + if (showAPIResponse) { + console.log(aliasInfo); + } + console.log('PushAPI.channel.alias.info | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.notification.list'); + const inboxNotifications = await userAlice.notification.list('INBOX'); + const spamNotifications = await userAlice.notification.list('SPAM'); + if (showAPIResponse) { + console.log(inboxNotifications, spamNotifications); + } + console.log('PushAPI.notification.list | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.notification.subscribe'); + const subscribeResponse = await userAlice.notification.subscribe( + 'eip155:5:0xD8634C39BBFd4033c0d3289C4515275102423681' // channel to subscribe + ); + if (showAPIResponse) { + console.log(subscribeResponse); + } + console.log('PushAPI.notification.subscribe | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.notification.subscriptions'); + const aliceSubscriptions = await userAlice.notification.subscriptions(); + if (showAPIResponse) { + console.log(aliceSubscriptions); + } + console.log('PushAPI.notification.subscriptions | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.notification.unsubscribe'); + const unsubscribeResponse = await userAlice.notification.unsubscribe( + 'eip155:5:0xD8634C39BBFd4033c0d3289C4515275102423681' // channel to unsubscribe + ); + if (showAPIResponse) { + console.log(unsubscribeResponse); + } + console.log('PushAPI.notification.unsubscribe | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- +}; diff --git a/packages/examples/sdk-backend-node/package.json b/packages/examples/sdk-backend-node/package.json index 64da4f88a..a75fdb60c 100644 --- a/packages/examples/sdk-backend-node/package.json +++ b/packages/examples/sdk-backend-node/package.json @@ -11,7 +11,7 @@ "author": "", "license": "ISC", "dependencies": { - "@pushprotocol/restapi": "0.0.1-alpha.39", + "@pushprotocol/restapi": "0.0.1-alpha.44", "@pushprotocol/socket": "^0.5.2" } } diff --git a/packages/examples/sdk-backend-node/pushAPI/index.ts b/packages/examples/sdk-backend-node/pushAPI/index.ts deleted file mode 100644 index 2b02dca10..000000000 --- a/packages/examples/sdk-backend-node/pushAPI/index.ts +++ /dev/null @@ -1,305 +0,0 @@ -import { PushAPI } from '@pushprotocol/restapi'; -import { - adjectives, - animals, - colors, - uniqueNamesGenerator, -} from 'unique-names-generator'; -import { config } from '../config'; -import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; -import { createWalletClient, http } from 'viem'; -import { goerli } from 'viem/chains'; -import { createSocketConnection, EVENTS } from '@pushprotocol/socket'; - -// CONFIGS -const { env, showAPIResponse } = config; - -/***************** SAMPLE SIGNER GENERATION *********************/ -// Uing VIEM -// Random Wallet Signers -const signer = createWalletClient({ - account: privateKeyToAccount(generatePrivateKey()), - chain: goerli, - transport: http(), -}); -const signerAddress = signer.account.address; -const secondSigner = createWalletClient({ - account: privateKeyToAccount(generatePrivateKey()), - chain: goerli, - transport: http(), -}); -const secondSignerAddress = secondSigner.account.address; -const thirdSigner = createWalletClient({ - account: privateKeyToAccount(generatePrivateKey()), - chain: goerli, - transport: http(), -}); -const thirdSignerAddress = thirdSigner.account.address; -// Dummy Wallet Addresses -const randomWallet1 = privateKeyToAccount(generatePrivateKey()).address; -const randomWallet2 = privateKeyToAccount(generatePrivateKey()).address; -const randomWallet3 = privateKeyToAccount(generatePrivateKey()).address; -/****************************************************************/ - -/***************** SAMPLE GROUP DATA ****************************/ -const groupName = uniqueNamesGenerator({ - dictionaries: [adjectives, colors, animals], -}); -const groupDescription = uniqueNamesGenerator({ - dictionaries: [adjectives, colors, animals], -}); -const groupImage = - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; -/***************** SAMPLE GROUP DATA ****************************/ - -export const runPushAPICases = async (): Promise => { - console.log(` - -██████╗░██╗░░░██╗░██████╗██╗░░██╗░█████╗░██████╗░██╗ ░█████╗░██╗░░░░░░█████╗░░██████╗░██████╗ -██╔══██╗██║░░░██║██╔════╝██║░░██║██╔══██╗██╔══██╗██║ ██╔══██╗██║░░░░░██╔══██╗██╔════╝██╔════╝ -██████╔╝██║░░░██║╚█████╗░███████║███████║██████╔╝██║ ██║░░╚═╝██║░░░░░███████║╚█████╗░╚█████╗░ -██╔═══╝░██║░░░██║░╚═══██╗██╔══██║██╔══██║██╔═══╝░██║ ██║░░██╗██║░░░░░██╔══██║░╚═══██╗░╚═══██╗ -██║░░░░░╚██████╔╝██████╔╝██║░░██║██║░░██║██║░░░░░██║ ╚█████╔╝███████╗██║░░██║██████╔╝██████╔╝ -╚═╝░░░░░░╚═════╝░╚═════╝░╚═╝░░╚═╝╚═╝░░╚═╝╚═╝░░░░░╚═╝ ░╚════╝░╚══════╝╚═╝░░╚═╝╚═════╝░╚═════╝░ - `); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.initialize'); - const userAlice = await PushAPI.initialize(signer, { env }); - const userBob = await PushAPI.initialize(secondSigner, { env }); - console.log('PushAPI.initialize | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.info'); - const userAliceInfo = await userAlice.user.info(); - if (showAPIResponse) { - console.log(userAliceInfo); - } - console.log('PushAPI.info | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.profile.info'); - const userAliceProfileInfo = await userAlice.profile.info(); - if (showAPIResponse) { - console.log(userAliceProfileInfo); - } - console.log('PushAPI.profile.info | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.profile.update'); - const updatedName = 'Bob The Builder'; - const response = await userAlice.profile.update({ name: updatedName }); - if (showAPIResponse) { - console.log(response); - } - console.log('PushAPI.profile.update | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.chat.list'); - const aliceChats = await userAlice.chat.list('CHATS'); - const aliceRequests = await userAlice.chat.list('REQUESTS'); - if (showAPIResponse) { - console.log(aliceChats); - console.log(aliceRequests); - } - console.log('PushAPI.chat.list | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.chat.latest'); - const aliceLatestChatWithBob = await userAlice.chat.latest( - secondSignerAddress - ); - if (showAPIResponse) { - console.log(aliceLatestChatWithBob); - } - console.log('PushAPI.chat.latest | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.chat.history'); - const aliceChatHistoryWithBob = await userAlice.chat.history( - secondSignerAddress - ); - if (showAPIResponse) { - console.log(aliceChatHistoryWithBob); - } - console.log('PushAPI.chat.history | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.chat.send'); - const aliceMessagesBob = await userAlice.chat.send(secondSignerAddress, { - content: 'Hello Bob!', - type: 'Text', - }); - if (showAPIResponse) { - console.log(aliceMessagesBob); - } - console.log('PushAPI.chat.send | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.chat.decrypt'); - const pushSDKSocket = createSocketConnection({ - user: signerAddress, - socketType: 'chat', - socketOptions: { autoConnect: true, reconnectionAttempts: 3 }, - env: env, - }); - if (pushSDKSocket) { - await userAlice.chat.send(secondSignerAddress, { - content: 'Hello Bob!', - type: 'Text', - }); - pushSDKSocket.on(EVENTS.CHAT_RECEIVED_MESSAGE, async (message) => { - // uncomment after latest sdk deployment - // await userAlice.chat.decrypt([message]); - // pushSDKSocket.disconnect(); - }); - } - console.log('PushAPI.chat.decrypt | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.chat.accept'); - const bobAcceptsRequest = await userBob.chat.accept(signerAddress); - if (showAPIResponse) { - console.log(bobAcceptsRequest); - } - console.log('PushAPI.chat.accept | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.chat.reject'); - const tempUser = await PushAPI.initialize(thirdSigner, { env }); - await tempUser.chat.send(secondSignerAddress, { - content: 'Sending Malicious message to bob', - }); - const bobRejectsRequest = await userBob.chat.reject(thirdSignerAddress); - if (showAPIResponse) { - console.log(bobRejectsRequest); - } - console.log('PushAPI.chat.reject | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.chat.block'); - const AliceBlocksBob = await userAlice.chat.block([secondSignerAddress]); - if (showAPIResponse) { - console.log(AliceBlocksBob); - } - console.log('PushAPI.chat.block | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.chat.unblock'); - const AliceUnblocksBob = await userAlice.chat.unblock([secondSignerAddress]); - if (showAPIResponse) { - console.log(AliceUnblocksBob); - } - console.log('PushAPI.chat.unblock | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.group.create'); - const createdGroup = await userAlice.chat.group.create(groupName, { - description: groupDescription, - image: groupImage, - members: [randomWallet1, randomWallet2], - admins: [], - private: false, - }); - const groupChatId = createdGroup.chatId; // to be used in other examples - if (showAPIResponse) { - console.log(createdGroup); - } - console.log('PushAPI.group.create | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.group.permissions'); - const grouppermissions = await userAlice.chat.group.permissions(groupChatId); - if (showAPIResponse) { - console.log(grouppermissions); - } - console.log('PushAPI.group.permissions | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.group.info'); - const groupInfo = await userAlice.chat.group.info(groupChatId); - if (showAPIResponse) { - console.log(groupInfo); - } - console.log('PushAPI.group.info | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.group.update'); - const updatedGroup = await userAlice.chat.group.update(groupChatId, { - description: 'Updated Description', - }); - if (showAPIResponse) { - console.log(updatedGroup); - } - console.log('PushAPI.group.update | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.group.add'); - const addMember = await userAlice.chat.group.add(groupChatId, { - role: 'MEMBER', - accounts: [randomWallet3], - }); - if (showAPIResponse) { - console.log(addMember); - } - console.log('PushAPI.group.add | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.group.remove'); - const removeMember = await userAlice.chat.group.remove(groupChatId, { - role: 'MEMBER', - accounts: [randomWallet3], - }); - if (showAPIResponse) { - console.log(removeMember); - } - console.log('PushAPI.group.remove | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.group.join'); - const joinGrp = await userBob.chat.group.join(groupChatId); - if (showAPIResponse) { - console.log(joinGrp); - } - console.log('PushAPI.group.join | Response - 200 OK\n\n'); - //------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.group.leave'); - const leaveGrp = await userBob.chat.group.leave(groupChatId); - if (showAPIResponse) { - console.log(leaveGrp); - } - console.log('PushAPI.group.leave | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.group.reject'); - const sampleGrp = await userAlice.chat.group.create('Sample Grp', { - description: groupDescription, - image: groupImage, - members: [secondSignerAddress], // invite bob - admins: [], - private: true, - }); - const rejectGrpJoiningReq = await userBob.chat.group.reject(sampleGrp.chatId); - if (showAPIResponse) { - console.log(rejectGrpJoiningReq); - } - console.log('PushAPI.group.reject | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.encryption.info'); - const encryptionInfo = await userAlice.encryption.info(); - if (showAPIResponse) { - console.log(encryptionInfo); - } - console.log('PushAPI.encryption.info | Response - 200 OK\n\n'); - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - console.log('PushAPI.encryption.update'); - const PGP_V3 = 'eip191-aes256-gcm-hkdf-sha256'; - const encryptionUpdate = await userAlice.encryption.update(PGP_V3 as any); - if (showAPIResponse) { - console.log(encryptionUpdate); - } - console.log('PushAPI.encryption.update | Response - 200 OK\n\n'); -}; diff --git a/packages/examples/sdk-backend-node/spaces/index.ts b/packages/examples/sdk-backend-node/space/index.ts similarity index 94% rename from packages/examples/sdk-backend-node/spaces/index.ts rename to packages/examples/sdk-backend-node/space/index.ts index 64e04891d..43c7afb32 100644 --- a/packages/examples/sdk-backend-node/spaces/index.ts +++ b/packages/examples/sdk-backend-node/space/index.ts @@ -43,15 +43,14 @@ const spaceDescription = uniqueNamesGenerator({ const spaceImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; -export const runSpacesUseCases = async (): Promise => { +export const runSpaceUseCases = async (): Promise => { console.log(` - ███████╗██████╗ █████╗ ██████╗███████╗███████╗ - ██╔════╝██╔══██╗██╔══██╗██╔════╝██╔════╝██╔════╝ - ███████╗██████╔╝███████║██║ █████╗ ███████╗ - ╚════██║██╔═══╝ ██╔══██║██║ ██╔══╝ ╚════██║ - ███████║██║ ██║ ██║╚██████╗███████╗███████║ - ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝╚══════╝ - +░██████╗██████╗░░█████╗░░█████╗░███████╗ +██╔════╝██╔══██╗██╔══██╗██╔══██╗██╔════╝ +╚█████╗░██████╔╝███████║██║░░╚═╝█████╗░░ +░╚═══██╗██╔═══╝░██╔══██║██║░░██╗██╔══╝░░ +██████╔╝██║░░░░░██║░░██║╚█████╔╝███████╗ +╚═════╝░╚═╝░░░░░╚═╝░░╚═╝░╚════╝░╚══════╝ `); console.log('PushAPI.user.create'); diff --git a/packages/examples/sdk-backend-node/user/index.ts b/packages/examples/sdk-backend-node/user/index.ts new file mode 100644 index 000000000..6a9dd6d30 --- /dev/null +++ b/packages/examples/sdk-backend-node/user/index.ts @@ -0,0 +1,75 @@ +import { PushAPI } from '@pushprotocol/restapi'; +import { config } from '../config'; +import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; +import { createWalletClient, http } from 'viem'; +import { goerli } from 'viem/chains'; + +// CONFIGS +const { env, showAPIResponse } = config; + +/***************** SAMPLE SIGNER GENERATION *********************/ +// Uing VIEM +// Random Wallet Signers +const signer = createWalletClient({ + account: privateKeyToAccount(generatePrivateKey()), + chain: goerli, + transport: http(), +}); + +export const runUserCases = async (): Promise => { + console.log(` +██╗░░░██╗░██████╗███████╗██████╗░ +██║░░░██║██╔════╝██╔════╝██╔══██╗ +██║░░░██║╚█████╗░█████╗░░██████╔╝ +██║░░░██║░╚═══██╗██╔══╝░░██╔══██╗ +╚██████╔╝██████╔╝███████╗██║░░██║ +░╚═════╝░╚═════╝░╚══════╝╚═╝░░╚═╝ +`); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.initialize'); + const userAlice = await PushAPI.initialize(signer, { env }); + console.log('PushAPI.initialize | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.info'); + const userAliceInfo = await userAlice.info(); + if (showAPIResponse) { + console.log(userAliceInfo); + } + console.log('PushAPI.info | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.profile.info'); + const userAliceProfileInfo = await userAlice.profile.info(); + if (showAPIResponse) { + console.log(userAliceProfileInfo); + } + console.log('PushAPI.profile.info | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.profile.update'); + const updatedName = 'Bob The Builder'; + const response = await userAlice.profile.update({ name: updatedName }); + if (showAPIResponse) { + console.log(response); + } + console.log('PushAPI.profile.update | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.encryption.info'); + const encryptionInfo = await userAlice.encryption.info(); + if (showAPIResponse) { + console.log(encryptionInfo); + } + console.log('PushAPI.encryption.info | Response - 200 OK\n\n'); + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + console.log('PushAPI.encryption.update'); + const PGP_V3 = 'eip191-aes256-gcm-hkdf-sha256'; + const encryptionUpdate = await userAlice.encryption.update(PGP_V3 as any); + if (showAPIResponse) { + console.log(encryptionUpdate); + } + console.log('PushAPI.encryption.update | Response - 200 OK\n\n'); +}; diff --git a/packages/examples/sdk-backend-node/video/index.ts b/packages/examples/sdk-backend-node/video/index.ts index 209522514..afc8e636e 100644 --- a/packages/examples/sdk-backend-node/video/index.ts +++ b/packages/examples/sdk-backend-node/video/index.ts @@ -21,14 +21,14 @@ const videoSetData: ( let videoObject: any = null; const videoLocalStream = null; // get the local stream const videoSenderAddress = process.env.VIDEO_SENDER_ADDRESS; -const videoRecipientAddress = process.env.VIDEO_RECIPEINT_ADDRESS; +const videoRecipientAddress = process.env.VIDEO_RECIPIENT_ADDRESS; const videoChatId = process.env.VIDEO_CHAT_ID; let videoSignalData_1: any = null; const skipExample = () => { const requiredEnvVars = [ 'VIDEO_SENDER_ADDRESS', - 'VIDEO_RECIPEINT_ADDRESS', + 'VIDEO_RECIPIENT_ADDRESS', 'VIDEO_CHAT_ID', 'VIDEO_CHAIN_ID', ]; @@ -45,12 +45,12 @@ const skipExample = () => { // Push Video - Run Video Use cases export const runVideoUseCases = async (): Promise => { console.log(` - ██╗ ██╗██╗██████╗ ███████╗ ██████╗ - ██║ ██║██║██╔══██╗██╔════╝██╔═══██╗ - ██║ ██║██║██║ ██║█████╗ ██║ ██║ - ╚██╗ ██╔╝██║██║ ██║██╔══╝ ██║ ██║ - ╚████╔╝ ██║██████╔╝███████╗╚██████╔╝ - ╚═══╝ ╚═╝╚═════╝ ╚══════╝ ╚═════╝ +██╗░░░██╗██╗██████╗░███████╗░█████╗░ +██║░░░██║██║██╔══██╗██╔════╝██╔══██╗ +╚██╗░██╔╝██║██║░░██║█████╗░░██║░░██║ +░╚████╔╝░██║██║░░██║██╔══╝░░██║░░██║ +░░╚██╔╝░░██║██████╔╝███████╗╚█████╔╝ +░░░╚═╝░░░╚═╝╚═════╝░╚══════╝░╚════╝░ `); if (videoLocalStream === null) { diff --git a/packages/examples/sdk-frontend-react/src/app/components/Connect.tsx b/packages/examples/sdk-frontend-react/src/app/components/Connect.tsx index 1041ea25b..cc5b89378 100644 --- a/packages/examples/sdk-frontend-react/src/app/components/Connect.tsx +++ b/packages/examples/sdk-frontend-react/src/app/components/Connect.tsx @@ -19,10 +19,12 @@ const NETWORK_MAPPING: NwMappingType = { 10: 'OPTIMISM_MAINNET', 1442: 'POLYGON_ZK_EVM_TESTNET', 1101: 'POLYGON_ZK_EVM_MAINNET', + 421613: "ARBITRUM_TESTNET", + 42161: "ARBITRUMONE_MAINNET" }; const injected = new InjectedConnector({ - supportedChainIds: [1, 3, 4, 5, 42, 137, 80001, 56, 97, 10, 420, 1442, 1101], + supportedChainIds: [1, 3, 4, 5, 42, 137, 80001, 56, 97, 10, 420, 1442, 1101, 421613, 42161], }); const ConnectWrapper = styled.div` diff --git a/packages/examples/sdk-frontend-react/src/app/helpers.ts b/packages/examples/sdk-frontend-react/src/app/helpers.ts index d5af6bc15..bad12f49d 100644 --- a/packages/examples/sdk-frontend-react/src/app/helpers.ts +++ b/packages/examples/sdk-frontend-react/src/app/helpers.ts @@ -18,7 +18,7 @@ const Constants = { }, DEFAULT_CHAIN_ID: 5, DEV_CHAIN_ID: 99999, - NON_ETH_CHAINS: [137, 80001, 56, 97, 10, 420, 1442, 1101], + NON_ETH_CHAINS: [137, 80001, 56, 97, 10, 420, 1442, 1101, 421613, 42161], ETH_CHAINS: [1, 5], }; diff --git a/packages/reactnative/README.md b/packages/reactnative/README.md index 4eae3bfa0..d3e665c64 100644 --- a/packages/reactnative/README.md +++ b/packages/reactnative/README.md @@ -208,5 +208,5 @@ where | cta | string | Call To Action Link (given during notification creation) | | image | string | Any media link (given during notification creation) | | appbot | string | is the notification is from EPNS bot the value is "1" else "0" | -| chainName | string | Can be anyone of the following blockchain networks on which the notification was sent - "ETH_MAINNET", "ETH_TEST_GOERLI", "POLYGON_MAINNET", "POLYGON_TEST_MUMBAI", "BSC_MAINNET, "BSC_TESTNET", "OPTIMISM_MAINNET", "OPTIMISM_TESTNET", "POLYGON_ZK_EVM_TESTNET", "POLYGON_ZK_EVM_MAINNET", "THE_GRAPH" | +| chainName | string | Can be anyone of the following blockchain networks on which the notification was sent - "ETH_MAINNET", "ETH_TEST_GOERLI", "POLYGON_MAINNET", "POLYGON_TEST_MUMBAI", "BSC_MAINNET, "BSC_TESTNET", "OPTIMISM_MAINNET", "OPTIMISM_TESTNET", "POLYGON_ZK_EVM_TESTNET", "POLYGON_ZK_EVM_MAINNET", "ARBITRUM_TESTNET", "ARBITRUMONE_MAINNET", "THE_GRAPH" | | youTubeAPIKey | string | Your generated Youtube API key | \ No newline at end of file diff --git a/packages/reactnative/src/lib/components/chainDetails/arbitrumSVG.tsx b/packages/reactnative/src/lib/components/chainDetails/arbitrumSVG.tsx new file mode 100644 index 000000000..7106c3552 --- /dev/null +++ b/packages/reactnative/src/lib/components/chainDetails/arbitrumSVG.tsx @@ -0,0 +1,29 @@ +import * as React from 'react'; +import { SVGProps } from 'react'; + +const ArbitrumSvgComponent = (props: SVGProps) => ( + + + + + + + +); + +export default ArbitrumSvgComponent; diff --git a/packages/reactnative/src/lib/components/chainDetails/index.tsx b/packages/reactnative/src/lib/components/chainDetails/index.tsx index 08c8cb55b..dbd6c8e19 100644 --- a/packages/reactnative/src/lib/components/chainDetails/index.tsx +++ b/packages/reactnative/src/lib/components/chainDetails/index.tsx @@ -3,9 +3,15 @@ import PolygonSvg from "./polygonSVG"; import GraphSvg from "./thegraphSVG"; import BscSvg from "./bscSVG"; import OptimismSvg from "./optimismSVG" -import PolygonZKEVMSvg from "./polygonZKEVMSVG"; +import PolygonZKEVMSvg from "./polygonZkEVMSVG"; +import ArbitrumSvgComponent from "./arbitrumSVG"; -export default { +type Network = { + label: string; + Icon: any; +}; + +const networks: Record = { ETH_TEST_GOERLI: { label: "ETHEREUM GOERLI", Icon: EthereumSvg }, ETH_MAINNET: { label: "ETHEREUM MAINNET", Icon: EthereumSvg }, POLYGON_TEST_MUMBAI: { label: "POLYGON MUMBAI", Icon: PolygonSvg }, @@ -16,5 +22,9 @@ export default { OPTIMISM_MAINNET: { label: "OPTIMISM MAINNET", Icon: OptimismSvg }, POLYGON_ZK_EVM_TESTNET: {label:"POLYGON_ZK_EVM_TESTNET",Icon: PolygonZKEVMSvg}, POLYGON_ZK_EVM_MAINNET: {label:"POLYGON_ZK_EVM_MAINNET",Icon: PolygonZKEVMSvg}, + ARBITRUM_TESTNET: {label:"ARBITRUM_TESTNET",Icon: ArbitrumSvgComponent}, + ARBITRUMONE_MAINNET: {label: "ARBITRUMONE_MAINNET", Icon: ArbitrumSvgComponent}, THE_GRAPH: { label: "THE GRAPH", Icon: GraphSvg }, -}; \ No newline at end of file +}; + +export default networks \ No newline at end of file diff --git a/packages/reactnative/src/lib/components/notifications/notification.tsx b/packages/reactnative/src/lib/components/notifications/notification.tsx index 30869655e..bbc064056 100644 --- a/packages/reactnative/src/lib/components/notifications/notification.tsx +++ b/packages/reactnative/src/lib/components/notifications/notification.tsx @@ -18,7 +18,7 @@ import { ImageDownloadWithIndicator, VideoDownloadWithIndicator } from '../load // ================= Define types -export type chainNameType = "ETH_TEST_GOERLI" | "POLYGON_TEST_MUMBAI" | "ETH_MAINNET" | "POLYGON_MAINNET" | "BSC_MAINNET" | "BSC_TESTNET" | "OPTIMISM_MAINNET" | "OPTIMISM_TESTNET" | "POLYGON_ZK_EVM_TESTNET" | "POLYGON_ZK_EVM_MAINNET" | "THE_GRAPH" | undefined; +export type chainNameType = "ETH_TEST_GOERLI" | "POLYGON_TEST_MUMBAI" | "ETH_MAINNET" | "POLYGON_MAINNET" | "BSC_MAINNET" | "BSC_TESTNET" | "OPTIMISM_MAINNET" | "OPTIMISM_TESTNET" | "POLYGON_ZK_EVM_TESTNET" | "POLYGON_ZK_EVM_MAINNET" | "ARBITRUMONE_MAINNET" | "ARBITRUM_TESTNET" | "THE_GRAPH" | undefined; const botImageLocalPath = '../../assets/epnsbot.png'; diff --git a/packages/restapi/README.md b/packages/restapi/README.md index 1aa9dffde..1c51666e1 100644 --- a/packages/restapi/README.md +++ b/packages/restapi/README.md @@ -181,6 +181,8 @@ Binance Mainnet - 0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa Binance Testnet - 0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa Optimism Mainnet - 0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa Optimism Testnet - 0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa +Arbitrum Mainnet - 0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa +Arbitrum One Testnet - 0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa ``` # SDK Features @@ -4567,15 +4569,14 @@ const aliceMessagesBob = await userAlice.chat.send(bobAddress, { }); ``` -| Param | Type | Default | Remarks | -| ---------------------- | ---------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------- | -| `recipient` | `string` | - | Recipient ( For Group Chats target is chatId, for 1 To 1 chat target is Push DID ) | -| `options` | `object` | - | Configuration for message to be sent | -| `options.type` \* | `Text` or `Image` or `File` or `MediaEmbed` or `GIF` or `Meta` or `Reaction` | - | Type of message Content | -| `options.content` | `string` | - | Message Content | -| `options.action` \* | `string` | - | Message action ( Only available for Meta & Reaction Messages ) | -| `options.reference` \* | `string` or `null` | - | Message reference hash ( Only available for Reaction Messages ) | -| `options.info` \* | `{ affected : string[]: arbitrary?: { [key: string]: any } }` | - | Message reference hash ( Only available for Meta Messages ) | +| Param | Type | Default | Remarks | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------- | +| `recipient` | `string` | - | Recipient ( For Group Chats target is chatId, for 1 To 1 chat target is Push DID ) | +| `options` | `object` | - | Configuration for message to be sent | +| `options.type` \* | `Text` or `Image` or `Audio` or `Video` or `File` or `MediaEmbed` or `GIF` or `Meta` or `Reaction` or `Receipt` or `Intent` or `Reply` or `Composite` | - | Type of message Content | +| `options.content` | `string` or `{type: `Text`or`Image`or`Audio`or`Video`or`File`or`MediaEmbed`or`GIF` ; content: string}` [For Reply] or `{type: `Text`or`Image`or`Audio`or`Video`or`File`or`MediaEmbed`or`GIF` ; content: string}[]` [For Composite] | - | Message Content | +| `options.reference` \* | `string` | - | Message reference hash ( Only available for Reaction & Reply Messages ) | +| `options.info` \* | `{ affected : string[]: arbitrary?: { [key: string]: any } }` | - | Message reference hash ( Only available for Meta & UserActivity Messages ) | \* - Optional diff --git a/packages/restapi/src/lib/chat/send.ts b/packages/restapi/src/lib/chat/send.ts index 30a396495..095f0fa73 100644 --- a/packages/restapi/src/lib/chat/send.ts +++ b/packages/restapi/src/lib/chat/send.ts @@ -11,16 +11,8 @@ import { import { conversationHash } from './conversationHash'; import { ISendMessagePayload, sendMessagePayload } from './helpers'; import { getGroup } from './getGroup'; -import { - MessageObj, - REACTION_SYMBOL, - ReactionMessage, -} from '../types/messageTypes'; -import { - messageObjSchema, - metaMessageObjSchema, - reationMessageObjSchema, -} from '../validations/messageObject'; +import { MessageObj } from '../types/messageTypes'; +import { validateMessageObj } from '../validations/messageObject'; /** * SENDS A PUSH CHAT MESSAGE @@ -54,14 +46,18 @@ export const send = async ( }) : null; - // OVERRIDE CONTENT FOR REACTION MESSAGE - if (messageType === MessageType.REACTION) { - messageObj.content = - REACTION_SYMBOL[(messageObj as Omit).action]; + // Not supported by legacy sdk versions, need to override messageContent to avoid parsing errors on legacy sdk versions + let messageContent: string; + if ( + messageType === MessageType.REPLY || + messageType === MessageType.COMPOSITE + ) { + messageContent = + 'MessageType Not Supported by this sdk version. Plz upgrade !!!'; + } else { + messageContent = messageObj.content as string; } - const messageContent = messageObj.content; // provide backward compatibility & override deprecated field - const conversationResponse = await conversationHash({ conversationId: receiver, account: sender.did, @@ -138,36 +134,7 @@ const validateOptions = async (options: ComputedOptionsType) => { } } - if ( - messageType === MessageType.TEXT || - messageType === MessageType.IMAGE || - messageType === MessageType.FILE || - messageType === MessageType.MEDIA_EMBED || - messageType === MessageType.GIF - ) { - const { error } = messageObjSchema.validate(messageObj); - if (error) { - throw new Error( - `Unable to parse this messageType. Please ensure 'messageObj' is properly defined.` - ); - } - } - - if (messageType === MessageType.META) { - const { error } = metaMessageObjSchema.validate(messageObj); - if (error) { - throw new Error( - `Unable to parse this messageType. Please ensure 'messageObj' is properly defined.` - ); - } - } else if (messageType === MessageType.REACTION) { - const { error } = reationMessageObjSchema.validate(messageObj); - if (error) { - throw new Error( - `Unable to parse this messageType. Please ensure 'messageObj' is properly defined.` - ); - } - } + validateMessageObj(messageObj, messageType); }; const computeOptions = (options: ChatSendOptionsType): ComputedOptionsType => { @@ -203,6 +170,36 @@ const computeOptions = (options: ChatSendOptionsType): ComputedOptionsType => { messageObj = rest; } + // Parse Reply Message + if (messageType === MessageType.REPLY) { + if (typeof messageObj.content === 'object') { + const { type, ...rest } = messageObj.content; + messageObj.content = { + messageType: type, + messageObj: rest, + }; + } else { + throw new Error('Options.message is not properly defined for Reply'); + } + } + + // Parse Composite Message + if (messageType === MessageType.COMPOSITE) { + if (messageObj.content instanceof Array) { + messageObj.content = messageObj.content.map( + (obj: { type: string; content: string }) => { + const { type, ...rest } = obj; + return { + messageType: type, + messageObj: rest, + }; + } + ); + } else { + throw new Error('Options.message is not properly defined for Composite'); + } + } + const account = options.account !== undefined ? options.account : null; const to = options.to !== undefined ? options.to : options.receiverAddress; diff --git a/packages/restapi/src/lib/config.ts b/packages/restapi/src/lib/config.ts index e597c22bc..36f9e6ddc 100644 --- a/packages/restapi/src/lib/config.ts +++ b/packages/restapi/src/lib/config.ts @@ -39,9 +39,11 @@ const BLOCKCHAIN_NETWORK = { OPTIMISM_MAINNET: 'eip155:10', POLYGON_ZK_EVM_TESTNET: 'eip155:1442', POLYGON_ZK_EVM_MAINNET: 'eip155:1101', + ARBITRUM_TESTNET: 'eip155:421613', + ARBITRUMONE_MAINNET: "eip155:42161" }; -export type ALIAS_CHAIN = 'POLYGON' | 'BSC' | 'OPTIMISM' | 'POLYGONZKEVM'; +export type ALIAS_CHAIN = 'POLYGON' | 'BSC' | 'OPTIMISM' | 'POLYGONZKEVM' | "ARBITRUMONE"; export const ETH_CHAIN_ID = { [ENV.PROD]: 1, @@ -74,6 +76,12 @@ export const ALIAS_CHAIN_ID = { [ENV.DEV]: 1442, [ENV.LOCAL]: 1442, }, + ARBITRUMONE: { + [ENV.PROD]: 42161, + [ENV.STAGING]: 421613, + [ENV.DEV]: 421613, + [ENV.LOCAL]: 421613, + } }; export const CHAIN_ID = { @@ -168,6 +176,10 @@ const CONFIG = { API_BASE_URL: API_BASE_URL[ENV.PROD], EPNS_COMMUNICATOR_CONTRACT: '0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa', }, + [BLOCKCHAIN_NETWORK.ARBITRUMONE_MAINNET]: { + API_BASE_URL: API_BASE_URL[ENV.PROD], + EPNS_COMMUNICATOR_CONTRACT: '0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa', + }, }, [ENV.STAGING]: { [BLOCKCHAIN_NETWORK.ETH_GOERLI]: { @@ -190,6 +202,10 @@ const CONFIG = { API_BASE_URL: API_BASE_URL[ENV.STAGING], EPNS_COMMUNICATOR_CONTRACT: '0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa', }, + [BLOCKCHAIN_NETWORK.ARBITRUM_TESTNET]: { + API_BASE_URL: API_BASE_URL[ENV.STAGING], + EPNS_COMMUNICATOR_CONTRACT: '0xb3971BCef2D791bc4027BbfedFb47319A4AAaaAa', + }, }, [ENV.DEV]: { [BLOCKCHAIN_NETWORK.ETH_GOERLI]: { @@ -212,6 +228,10 @@ const CONFIG = { API_BASE_URL: API_BASE_URL[ENV.DEV], EPNS_COMMUNICATOR_CONTRACT: '0x630b152e4185c63D7177c656b56b26f878C61572', }, + [BLOCKCHAIN_NETWORK.ARBITRUM_TESTNET]: { + API_BASE_URL: API_BASE_URL[ENV.STAGING], + EPNS_COMMUNICATOR_CONTRACT: '0x2f6aE0907116A2c50D712e78b48D874fadeB6850', + }, }, [ENV.LOCAL]: { [BLOCKCHAIN_NETWORK.ETH_GOERLI]: { @@ -234,6 +254,10 @@ const CONFIG = { API_BASE_URL: API_BASE_URL[ENV.DEV], EPNS_COMMUNICATOR_CONTRACT: '0x630b152e4185c63D7177c656b56b26f878C61572', }, + [BLOCKCHAIN_NETWORK.ARBITRUM_TESTNET]: { + API_BASE_URL: API_BASE_URL[ENV.STAGING], + EPNS_COMMUNICATOR_CONTRACT: '0x2f6aE0907116A2c50D712e78b48D874fadeB6850', + }, }, }; diff --git a/packages/restapi/src/lib/constants.ts b/packages/restapi/src/lib/constants.ts index 4735b547a..94d46f3d4 100644 --- a/packages/restapi/src/lib/constants.ts +++ b/packages/restapi/src/lib/constants.ts @@ -27,21 +27,20 @@ export enum ENCRYPTION_TYPE { export enum MessageType { TEXT = 'Text', IMAGE = 'Image', + VIDEO = 'Video', + AUDIO = 'Audio', FILE = 'File', + /** @deprecated - Use `MediaEmbed` Instead */ + GIF = 'GIF', MEDIA_EMBED = 'MediaEmbed', META = 'Meta', REACTION = 'Reaction', - /** - * @deprecated - Use MediaEmbed Instead - */ - GIF = 'GIF', - - // TODO - // AUDIO = 'Audio', - // VIDEO = 'Video', - // PAYMENT = 'Payment', - // REPLY = 'Reply', - // COMPOSITE = 'Composite', + RECEIPT = 'Receipt', + USER_ACTIVITY = 'UserActivity', + INTENT = 'Intent', + REPLY = 'Reply', + COMPOSITE = 'Composite', + PAYMENT = 'Payment', } const Constants = { @@ -55,7 +54,7 @@ const Constants = { }, DEFAULT_CHAIN_ID: 5, DEV_CHAIN_ID: 99999, - NON_ETH_CHAINS: [137, 80001, 56, 97, 10, 420, 1442, 1101], + NON_ETH_CHAINS: [137, 80001, 56, 97, 10, 420, 1442, 1101, 421613, 42161], ETH_CHAINS: [1, 5], ENC_TYPE_V1: 'x25519-xsalsa20-poly1305', ENC_TYPE_V2: 'aes256GcmHkdfSha256', diff --git a/packages/restapi/src/lib/payloads/constants.ts b/packages/restapi/src/lib/payloads/constants.ts index a3c5d9a41..da01fafc7 100644 --- a/packages/restapi/src/lib/payloads/constants.ts +++ b/packages/restapi/src/lib/payloads/constants.ts @@ -13,6 +13,8 @@ export const CHAIN_ID_TO_SOURCE: ChainIdToSourceType = { 420: 'OPTIMISM_TESTNET', 1442: 'POLYGON_ZK_EVM_TESTNET', 1101: 'POLYGON_ZK_EVM_MAINNET', + 421613: "ARBITRUM_TESTNET", + 42161: "ARBITRUMONE_MAINNET" }; export const SOURCE_TYPES = { @@ -26,6 +28,8 @@ export const SOURCE_TYPES = { OPTIMISM_TESTNET: 'OPTIMISM_TESTNET', POLYGON_ZK_EVM_TESTNET: 'POLYGON_ZK_EVM_TESTNET', POLYGON_ZK_EVM_MAINNET: 'POLYGON_ZK_EVM_MAINNET', + ARBITRUM_TESTNET: "ARBITRUM_TESTNET", + ARBITRUMONE_MAINNET: "ARBITRUMONE_MAINNET", THE_GRAPH: 'THE_GRAPH', PUSH_VIDEO: 'PUSH_VIDEO', }; diff --git a/packages/restapi/src/lib/payloads/helpers.ts b/packages/restapi/src/lib/payloads/helpers.ts index 6b7016feb..1863ed1ca 100644 --- a/packages/restapi/src/lib/payloads/helpers.ts +++ b/packages/restapi/src/lib/payloads/helpers.ts @@ -321,7 +321,7 @@ export function getSource( export function getCAIPFormat(chainId: number, address: string) { // EVM based chains - if ([1, 5, 42, 137, 80001, 56, 97, 10, 420, 1442, 1101].includes(chainId)) { + if ([1, 5, 42, 137, 80001, 56, 97, 10, 420, 1442, 1101, 421613, 42161].includes(chainId)) { return `eip155:${chainId}:${address}`; } diff --git a/packages/restapi/src/lib/space/Space.ts b/packages/restapi/src/lib/space/Space.ts index 7ddd78b27..a466da5fb 100644 --- a/packages/restapi/src/lib/space/Space.ts +++ b/packages/restapi/src/lib/space/Space.ts @@ -29,7 +29,7 @@ import { } from '../types'; import { VIDEO_CALL_TYPE } from '../payloads/constants'; import sendLiveSpaceData from './helpers/sendLiveSpaceData'; -import { META_ACTION } from '../types/messageTypes'; +import { CHAT } from '../types/messageTypes'; import { broadcastRaisedHand } from './broadcastRaisedHand'; import { onReceiveMetaMessage } from './onReceiveMetaMessage'; import { onJoinListener } from './onJoinListener'; @@ -157,7 +157,7 @@ export class Space extends Video { env: this.env, spaceId: this.spaceSpecificData.spaceId, signer: this.signer, - action: META_ACTION.PROMOTE_TO_ADMIN, // TODO: Add a meta action for SPEAKER_JOINED + action: CHAT.META.GROUP.ADMIN.PRVILEGE, // TODO: Add a meta action for SPEAKER_JOINED }); } }, diff --git a/packages/restapi/src/lib/space/broadcastRaisedHand.ts b/packages/restapi/src/lib/space/broadcastRaisedHand.ts index db2c0b1c9..d90b706e8 100644 --- a/packages/restapi/src/lib/space/broadcastRaisedHand.ts +++ b/packages/restapi/src/lib/space/broadcastRaisedHand.ts @@ -1,6 +1,6 @@ import { produce } from 'immer'; import sendLiveSpaceData from './helpers/sendLiveSpaceData'; -import { META_ACTION } from '../types/messageTypes'; +import { CHAT } from '../types/messageTypes'; import { pCAIP10ToWallet } from '../helpers'; import type Space from './Space'; @@ -41,6 +41,6 @@ export async function broadcastRaisedHand( env: this.env, spaceId: this.spaceSpecificData.spaceId, signer: this.signer, - action: META_ACTION.USER_INTERACTION, + action: CHAT.META.GROUP.USER.INTERACTION, }); } diff --git a/packages/restapi/src/lib/space/helpers/getLiveSpaceData.ts b/packages/restapi/src/lib/space/helpers/getLiveSpaceData.ts index 4d3f952a4..7f8896b00 100644 --- a/packages/restapi/src/lib/space/helpers/getLiveSpaceData.ts +++ b/packages/restapi/src/lib/space/helpers/getLiveSpaceData.ts @@ -1,7 +1,7 @@ import { conversationHash, history } from '../../chat'; import { MessageType } from '../../constants'; import { EnvOptionsType, LiveSpaceData } from '../../types'; -import { MetaMessage } from '../../types/messageTypes'; +import { InfoMessage } from '../../types/messageTypes'; import { initLiveSpaceData } from '../Space'; interface GetLatestMessageType extends EnvOptionsType { @@ -54,7 +54,7 @@ const getLiveSpaceData = async ({ latestMetaMessage.messageObj !== null ) { // found the latest meta message - liveSpaceData = (latestMetaMessage.messageObj as Omit) + liveSpaceData = (latestMetaMessage.messageObj as Omit) ?.info?.arbitrary as LiveSpaceData; } diff --git a/packages/restapi/src/lib/space/helpers/sendLiveSpaceData.ts b/packages/restapi/src/lib/space/helpers/sendLiveSpaceData.ts index 78cb59fb1..099eed844 100644 --- a/packages/restapi/src/lib/space/helpers/sendLiveSpaceData.ts +++ b/packages/restapi/src/lib/space/helpers/sendLiveSpaceData.ts @@ -1,11 +1,10 @@ import { send } from '../../chat'; import { MessageType } from '../../constants'; import { EnvOptionsType, LiveSpaceData, SignerType } from '../../types'; -import { META_ACTION } from '../../types/messageTypes'; interface SendLiveSpaceData extends EnvOptionsType { liveSpaceData?: LiveSpaceData; - action: META_ACTION; + action: string; spaceId: string; pgpPrivateKey: string; signer: SignerType; @@ -26,8 +25,7 @@ const sendLiveSpaceData = async ({ signer, messageType: MessageType.META, messageObj: { - content: 'PUSH SPACE META MESSAGE', - action, + content: action, info: { affected: [], arbitrary: liveSpaceData, diff --git a/packages/restapi/src/lib/space/onJoinListener.ts b/packages/restapi/src/lib/space/onJoinListener.ts index 30db1c4dd..72aa30c68 100644 --- a/packages/restapi/src/lib/space/onJoinListener.ts +++ b/packages/restapi/src/lib/space/onJoinListener.ts @@ -3,7 +3,7 @@ import { get } from './get'; import { pCAIP10ToWallet } from '../helpers'; import { produce } from 'immer'; -import { META_ACTION } from '../types/messageTypes'; +import { CHAT } from '../types/messageTypes'; import type Space from './Space'; export interface OnJoinListenerType { @@ -43,11 +43,12 @@ export async function onJoinListener(this: Space, options: OnJoinListenerType) { const modifiedLiveSpaceData = produce( this.spaceSpecificData.liveSpaceData, (draft) => { - const isListenerAlreadyAdded = this.spaceSpecificData.liveSpaceData.listeners.find( - (currentListener) => - pCAIP10ToWallet(currentListener.address) === - pCAIP10ToWallet(receivedAddress) - ); + const isListenerAlreadyAdded = + this.spaceSpecificData.liveSpaceData.listeners.find( + (currentListener) => + pCAIP10ToWallet(currentListener.address) === + pCAIP10ToWallet(receivedAddress) + ); if (isListenerAlreadyAdded) { // listener is already added in the meta message @@ -75,6 +76,6 @@ export async function onJoinListener(this: Space, options: OnJoinListenerType) { env: this.env, signer: this.signer, liveSpaceData: modifiedLiveSpaceData, - action: META_ACTION.ADD_LISTENER, + action: CHAT.META.SPACE.LISTENER.ADD, }); } diff --git a/packages/restapi/src/lib/space/onReceiveMetaMessage.ts b/packages/restapi/src/lib/space/onReceiveMetaMessage.ts index f6b6ae24c..800511e31 100644 --- a/packages/restapi/src/lib/space/onReceiveMetaMessage.ts +++ b/packages/restapi/src/lib/space/onReceiveMetaMessage.ts @@ -1,6 +1,6 @@ import { MessageType } from '../constants'; import { IMessageIPFS, LiveSpaceData } from '../types'; -import { MetaMessage } from '../types/messageTypes'; +import { InfoMessage } from '../types/messageTypes'; import type Space from './Space'; export interface OnReceiveMetaMessageType { @@ -18,14 +18,14 @@ export function onReceiveMetaMessage( if ( receivedMetaMessage.messageType !== MessageType.META || typeof receivedMetaMessage.messageObj !== 'object' || - !(receivedMetaMessage?.messageObj as Omit)?.info + !(receivedMetaMessage?.messageObj as Omit)?.info ?.arbitrary ) { return; } const receivedLiveSpaceData = ( - receivedMetaMessage.messageObj as Omit + receivedMetaMessage.messageObj as Omit ).info.arbitrary as LiveSpaceData; console.log('RECEIVED LIVE SPACE DATA', receivedLiveSpaceData); diff --git a/packages/restapi/src/lib/space/rejectPromotionRequest.ts b/packages/restapi/src/lib/space/rejectPromotionRequest.ts index 3fb45154b..f2be499e9 100644 --- a/packages/restapi/src/lib/space/rejectPromotionRequest.ts +++ b/packages/restapi/src/lib/space/rejectPromotionRequest.ts @@ -1,6 +1,6 @@ import { produce } from 'immer'; import sendLiveSpaceData from './helpers/sendLiveSpaceData'; -import { META_ACTION } from '../types/messageTypes'; +import { CHAT } from '../types/messageTypes'; import { pCAIP10ToWallet } from '../helpers'; import type Space from './Space'; @@ -41,6 +41,6 @@ export async function rejectPromotionRequest( env: this.env, spaceId: this.spaceSpecificData.spaceId, signer: this.signer, - action: META_ACTION.USER_INTERACTION, // TODO: Add a reject request type + action: CHAT.META.GROUP.USER.INTERACTION, // TODO: Add a reject request type }); } diff --git a/packages/restapi/src/lib/space/start.ts b/packages/restapi/src/lib/space/start.ts index 23ac20bc9..5fd42f966 100644 --- a/packages/restapi/src/lib/space/start.ts +++ b/packages/restapi/src/lib/space/start.ts @@ -24,7 +24,7 @@ export interface StartSpaceType extends EnvOptionsType { import type Space from './Space'; import { produce } from 'immer'; import { pCAIP10ToWallet } from '../helpers'; -import { META_ACTION } from '../types/messageTypes'; +import { CHAT } from '../types/messageTypes'; import sendLiveSpaceData from './helpers/sendLiveSpaceData'; type StartType = { @@ -94,7 +94,7 @@ export async function start(this: Space): Promise { await sendLiveSpaceData({ liveSpaceData, - action: META_ACTION.CREATE_SPACE, + action: CHAT.META.SPACE.CREATE, spaceId: this.spaceSpecificData.spaceId, signer: this.signer, pgpPrivateKey: this.pgpPrivateKey, diff --git a/packages/restapi/src/lib/types/messageTypes.ts b/packages/restapi/src/lib/types/messageTypes.ts index 49f4d986a..634121784 100644 --- a/packages/restapi/src/lib/types/messageTypes.ts +++ b/packages/restapi/src/lib/types/messageTypes.ts @@ -3,67 +3,92 @@ */ import { MessageType } from '../constants'; -export enum META_ACTION { - /** - * DEFAULT GROUP ACTIONS - */ - CREATE_GROUP = 1, - ADD_MEMBER = 2, - REMOVE_MEMBER = 3, - PROMOTE_TO_ADMIN = 4, - DEMOTE_FROM_ADMIN = 5, - /** - * SHARED ACTIONS - */ - CHANGE_IMAGE_OR_DESC = 6, - CHANGE_META = 7, - /** - * SPACES ACTIONS - */ - CREATE_SPACE = 8, - ADD_LISTENER = 9, - REMOVE_LISTENER = 10, - PROMOTE_TO_SPEAKER = 11, - DEMOTE_FROM_SPEARKER = 12, - PROMOTE_TO_COHOST = 13, - DEMOTE_FROM_COHOST = 14, - USER_INTERACTION = 15, // For MIC_ON | MIC_OFF | RAISE_HAND | EMOJI REACTION | or any other user activity -} +export const CHAT = { + META: { + GROUP: { + CREATE: 'CREATE_GROUP', + MEMBER: { + ADD: 'ADD_MEMBER', + REMOVE: 'REMOVE_MEMBER', + PRIVILEGE: 'ASSIGN_MEMBER_PRIVILEGE', + }, + ADMIN: { + PRVILEGE: 'ASSIGN_ADMIN_PRIVILEGE', + }, + // todo: Why do we need update group when we already have profile and meta update + UPDATE: 'UPDATE_GROUP', + PROFILE: { + UPDATE: 'UPDATE_GROUP_PROFILE', + }, + // todo : this seems to be a wierd name CHAT.META.GROUP.META.UPDATE + META: { + UPDATE: 'UPDATE_GROUP_META', + }, + // todo : Remove this as it comes under UserActivity now ( remove after space changes ) + USER: { + INTERACTION: 'USER_INTERACTION', + }, + }, + SPACE: { + CREATE: 'CREATE_SPACE', + LISTENER: { + ADD: 'ADD_LISTENER', + REMOVE: 'REMOVE_LISTENER', + PRVILEGE: 'ASSIGN_LISTENER_PRIVILEGE', + }, + SPEAKER: { + PRVILEGE: 'ASSIGN_SPEAKER_PRIVILEGE', + }, + COHOST: { + PRVILEGE: 'ASSIGN_COHOST_PRIVILEGE', + }, + }, + }, -export enum REACTION_TYPE { - THUMBS_UP, - THUMBS_DOWN, - HEART, - CLAP, - LAUGHING_FACE, - SAD_FACE, - ANGRY_FACE, - SURPRISED_FACE, - CLAPPING_HANDS, - FIRE, -} + REACTION: { + THUMBSUP: '\u{1F44D}', + THUMBSDOWN: '\u{1F44E}', + HEART: '\u{2764}\u{FE0F}', + CLAP: '\u{1F44F}', + LAUGH: '\u{1F602}', + SAD: '\u{1F622}', + ANGRY: '\u{1F621}', + SUPRISE: '\u{1F632}', + FIRE: '\u{1F525}', + }, + + RECEIPT: { + READ: 'READ_RECEIPT', + }, -// Create a mapping object that associates reaction types with their Unicode escape sequences -export const REACTION_SYMBOL: Record = { - [REACTION_TYPE.THUMBS_UP]: '\u{1F44D}', - [REACTION_TYPE.THUMBS_DOWN]: '\u{1F44E}', - [REACTION_TYPE.HEART]: '\u{2764}\u{FE0F}', - [REACTION_TYPE.CLAP]: '\u{1F44F}', - [REACTION_TYPE.LAUGHING_FACE]: '\u{1F602}', - [REACTION_TYPE.SAD_FACE]: '\u{1F622}', - [REACTION_TYPE.ANGRY_FACE]: '\u{1F621}', - [REACTION_TYPE.SURPRISED_FACE]: '\u{1F632}', - [REACTION_TYPE.CLAPPING_HANDS]: '\u{1F44F}\u{1F44F}', - [REACTION_TYPE.FIRE]: '\u{1F525}', + UA: { + LISTENER: { + JOIN: 'LISTENER_JOIN', + LEAVE: 'LISTENER_LEAVE', + MICREQUEST: 'LISTENER_REQUEST_MIC', + }, + SPEAKER: { + MIC_ON: 'SPEAKER_MIC_ON', + MIC_OFF: 'SPEAKER_MIC_OFF', + }, + }, + + INTENT: { + ACCEPT: 'ACCEPT_INTENT', + REJECT: 'REJECT_INTENT', + JOIN: 'JOIN_GROUP', + LEAVE: 'LEAVE_GROUP', + }, }; -export interface BaseMessage { +interface BaseMessage { type?: T; content: string; } -export interface MetaMessage extends BaseMessage<`${MessageType.META}`> { - action: META_ACTION; +// Used by MessageType.Meta & MessageType.USER_ACTIVITY +export interface InfoMessage + extends BaseMessage<`${MessageType.META}` | `${MessageType.USER_ACTIVITY}`> { info: { affected: string[]; arbitrary?: { @@ -72,28 +97,53 @@ export interface MetaMessage extends BaseMessage<`${MessageType.META}`> { }; } -export interface ReactionMessage - extends BaseMessage<`${MessageType.REACTION}`> { - action: REACTION_TYPE; - reference?: string | null; +interface ReferenceMessage + extends BaseMessage<`${MessageType.REACTION}` | `${MessageType.RECEIPT}`> { + reference: string; +} + +interface ReplyMessage { + type: `${MessageType.REPLY}`; + /** Only Few BaseMessageTypes are allowed, this can be changed in the future */ + content: { + type: string; + content: string; + }; + reference: string; +} + +interface CompositeMessage { + type: `${MessageType.COMPOSITE}`; + /** Only Few BaseMessageTypes are allowed, this can be changed in the future */ + content: { + type: string; + content: string; + }[]; } -export type BaseMessageTypes = +type BaseMessageTypes = | `${MessageType.TEXT}` | `${MessageType.IMAGE}` + | `${MessageType.VIDEO}` + | `${MessageType.AUDIO}` | `${MessageType.FILE}` + | `${MessageType.GIF}` | `${MessageType.MEDIA_EMBED}` - | `${MessageType.GIF}`; + | `${MessageType.INTENT}`; export type Message = | BaseMessage - | MetaMessage - | ReactionMessage; + | InfoMessage + | ReferenceMessage + | ReplyMessage + | CompositeMessage; /** * @deprecated */ export type MessageObj = | Omit, 'type'> - | Omit - | Omit; + | Omit + | Omit + | Omit + | Omit; diff --git a/packages/restapi/src/lib/validations/messageObject.ts b/packages/restapi/src/lib/validations/messageObject.ts index 6057d12d5..d40382126 100644 --- a/packages/restapi/src/lib/validations/messageObject.ts +++ b/packages/restapi/src/lib/validations/messageObject.ts @@ -1,14 +1,26 @@ import * as Joi from 'joi'; -import { META_ACTION, REACTION_TYPE } from '../types/messageTypes'; +import { CHAT, MessageObj } from '../types/messageTypes'; +import { MessageType } from '../constants'; -export const messageObjSchema = Joi.object({ +const extractValidValues = (obj: any): string[] => { + const validValues: string[] = []; + for (const key in obj) { + if (typeof obj[key] === 'string') { + validValues.push(obj[key]); + } else if (typeof obj[key] === 'object') { + validValues.push(...extractValidValues(obj[key])); + } + } + return validValues; +}; + +const messageObjSchema = Joi.object({ content: Joi.string().required().allow(''), }); -export const metaMessageObjSchema = Joi.object({ - content: Joi.string().required().allow(''), - action: Joi.number() - .valid(...Object.values(META_ACTION)) +const metaMessageObjSchema = Joi.object({ + content: Joi.string() + .valid(...Object.values(extractValidValues(CHAT.META))) .required(), info: Joi.object({ affected: Joi.array().items(Joi.string()).required(), @@ -16,10 +28,133 @@ export const metaMessageObjSchema = Joi.object({ }).required(), }); -export const reationMessageObjSchema = Joi.object({ - content: Joi.string().required().allow(''), - action: Joi.number() - .valid(...Object.values(REACTION_TYPE)) +const reationMessageObjSchema = Joi.object({ + content: Joi.string() + .valid(...Object.values(extractValidValues(CHAT.REACTION))) + .required(), + reference: Joi.string().required(), +}); + +const receiptMessageObjSchema = Joi.object({ + content: Joi.string() + .valid(...Object.values(extractValidValues(CHAT.RECEIPT))) .required(), - reference: Joi.string().allow(null), + reference: Joi.string().required(), }); + +const userActivityMessageObjSchema = Joi.object({ + content: Joi.string() + .valid(...Object.values(extractValidValues(CHAT.UA))) + .required(), + info: Joi.object({ + affected: Joi.array().items(Joi.string()).required(), + arbitrary: Joi.object().pattern(Joi.string(), Joi.any()), + }).required(), +}); + +const intentMessageObjSchema = Joi.object({ + content: Joi.string().valid( + ...Object.values(extractValidValues(CHAT.INTENT)) + ), +}); + +const replyMessageObjSchema = Joi.object({ + content: Joi.object({ + messageType: Joi.string() + .valid( + ...Object.values([ + MessageType.TEXT, + MessageType.IMAGE, + MessageType.AUDIO, + MessageType.VIDEO, + MessageType.FILE, + MessageType.MEDIA_EMBED, + ]) + ) + .required(), + messageObj: Joi.object({ + content: Joi.string().required(), // Change the validation as needed + }).required(), + }).required(), + reference: Joi.string().required(), +}); + +const compositeMessageObjSchema = Joi.object({ + content: Joi.array() + .items( + Joi.object({ + messageType: Joi.string() + .valid( + ...Object.values([ + MessageType.TEXT, + MessageType.IMAGE, + MessageType.AUDIO, + MessageType.VIDEO, + MessageType.FILE, + MessageType.MEDIA_EMBED, + ]) + ) + .required(), + messageObj: Joi.object({ + content: Joi.string().required(), + }).required(), + }) + ) + .required(), +}); + +export const validateMessageObj = ( + messageObj: MessageObj, + messageType: MessageType +) => { + let error: Joi.ValidationError | undefined = undefined; + switch (messageType) { + case MessageType.TEXT: + case MessageType.IMAGE: + case MessageType.VIDEO: + case MessageType.AUDIO: + case MessageType.FILE: + case MessageType.MEDIA_EMBED: + case MessageType.GIF: { + error = messageObjSchema.validate(messageObj).error; + break; + } + case MessageType.META: { + error = metaMessageObjSchema.validate(messageObj).error; + break; + } + case MessageType.REACTION: { + error = reationMessageObjSchema.validate(messageObj).error; + break; + } + case MessageType.RECEIPT: { + error = receiptMessageObjSchema.validate(messageObj).error; + break; + } + case MessageType.USER_ACTIVITY: { + error = userActivityMessageObjSchema.validate(messageObj).error; + break; + } + case MessageType.INTENT: { + error = intentMessageObjSchema.validate(messageObj).error; + break; + } + case MessageType.REPLY: { + error = replyMessageObjSchema.validate(messageObj).error; + break; + } + case MessageType.COMPOSITE: { + error = compositeMessageObjSchema.validate(messageObj).error; + break; + } + default: { + throw new Error('Invalid MessageType'); + } + } + + if (error) { + throw new Error( + `Unable to parse this messageType. Please ensure 'messageObj' is properly defined.` + ); + } +}; diff --git a/packages/restapi/tests/lib/chat/createGroup.test.ts b/packages/restapi/tests/lib/chat/createGroup.test.ts index 5c8db3987..d9ea55a2e 100644 --- a/packages/restapi/tests/lib/chat/createGroup.test.ts +++ b/packages/restapi/tests/lib/chat/createGroup.test.ts @@ -127,8 +127,8 @@ const expectGroup = async ( expect(group.members[0].image).to.be.a('string'); expect(group.pendingMembers).to.be.an('array'); expect(group.pendingMembers.length).to.equal(pendingMembers.length); - expect(group.pendingMembers[0].wallet).to.equal(pendingMembers[0]); - expect(group.pendingMembers[1].wallet).to.equal(pendingMembers[1]); + expect(pendingMembers.includes(group.pendingMembers[0].wallet)).to.be.true; + expect(pendingMembers.includes(group.pendingMembers[1].wallet)).to.be.true; expect(group.groupImage).to.equal(groupImage); expect(group.groupName).to.equal(groupName); expect(group.groupDescription).to.equal(groupDescription); diff --git a/packages/restapi/tests/lib/chat/send.test.ts b/packages/restapi/tests/lib/chat/send.test.ts index fc3e8d0dd..5aeb21512 100644 --- a/packages/restapi/tests/lib/chat/send.test.ts +++ b/packages/restapi/tests/lib/chat/send.test.ts @@ -6,7 +6,7 @@ import { ethers } from 'ethers'; import Constants, { MessageType } from '../../../src/lib/constants'; import { upgrade } from '../../../src/lib/user/upgradeUser'; import { decryptPGPKey } from '../../../src/lib/helpers'; -import { createGroup, send } from '../../../src/lib/chat'; +import { approve, createGroup, send } from '../../../src/lib/chat'; import { MessageWithCID, SignerType } from '../../../src/lib/types'; import { decryptAndVerifyMessage } from '../../../src/lib/chat/helpers'; import { @@ -15,14 +15,11 @@ import { colors, uniqueNamesGenerator, } from 'unique-names-generator'; -import { - REACTION_SYMBOL, - REACTION_TYPE, -} from '../../../src/lib/types/messageTypes'; +import { CHAT } from '../../../src/lib/types/messageTypes'; chai.use(chaiAsPromised); const _env = Constants.ENV.DEV; -describe('PushAPI.chat.send', () => { +describe.only('PushAPI.chat.send', () => { const provider = ethers.getDefaultProvider(5); let _signer1: any; let walletAddress1: string; @@ -630,6 +627,232 @@ describe('PushAPI.chat.send', () => { ); }); }); + describe('Video Message', () => { + const MESSAGE_TYPE = MessageType.VIDEO; + const MESSAGE = '{"content":"data:application/mp4;base64,JVBERi0xLjQKJ}'; + it('should throw error using wrong messageObj', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + action: 1, + info: { affected: [] }, + }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + // Video message was not supported in v1 & v2 + it('should throw error for deprecated V1', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageContent: MESSAGE, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('Deprecated V2 | EncType - Plaintext', async () => { + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + MESSAGE, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('Deprecated V2 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + version: Constants.ENC_TYPE_V1, + }); + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + MESSAGE, + account1, + _signer1, + account2, + 'pgp' + ); + }); + it('V3 | EncType - Plaintext', async () => { + const msg = await send({ + message: { type: MESSAGE_TYPE, content: MESSAGE }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { content: MESSAGE }, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('V3 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + version: Constants.ENC_TYPE_V1, + }); + const msg = await send({ + message: { type: MESSAGE_TYPE, content: MESSAGE }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { content: MESSAGE }, + account1, + _signer1, + account2, + 'pgp' + ); + }); + }); + describe('Audio Message', () => { + const MESSAGE_TYPE = MessageType.AUDIO; + const MESSAGE = '{"content":"data:application/mp3;base64,JVBERi0xLjQKJ}'; + it('should throw error using wrong messageObj', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + action: 1, + info: { affected: [] }, + }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + // Audio message was not supported in v1 & v2 + it('should throw error for deprecated V1', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageContent: MESSAGE, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('Deprecated V2 | EncType - Plaintext', async () => { + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + MESSAGE, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('Deprecated V2 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + version: Constants.ENC_TYPE_V1, + }); + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + MESSAGE, + account1, + _signer1, + account2, + 'pgp' + ); + }); + it('V3 | EncType - Plaintext', async () => { + const msg = await send({ + message: { type: MESSAGE_TYPE, content: MESSAGE }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { content: MESSAGE }, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('V3 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + version: Constants.ENC_TYPE_V1, + }); + const msg = await send({ + message: { type: MESSAGE_TYPE, content: MESSAGE }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { content: MESSAGE }, + account1, + _signer1, + account2, + 'pgp' + ); + }); + }); describe('File Message', () => { const MESSAGE_TYPE = MessageType.FILE; const MESSAGE = '{"content":"data:application/pdf;base64,JVBERi0xLjQKJ}'; @@ -773,8 +996,8 @@ describe('PushAPI.chat.send', () => { ); }); }); - describe('MediaEmbed Message', () => { - const MESSAGE_TYPE = MessageType.MEDIA_EMBED; + describe('GIF Message', () => { + const MESSAGE_TYPE = MessageType.GIF; const MESSAGE = 'ttps://media1.giphy.com/media/FtlUfrq3pVZXVNjoxf/giphy360p.mp4?cid=ecf05e47jk317254v9hbdjrknemduocie4pf54wtsir98xsx&ep=v1_videos_search&rid=giphy360p.mp4&ct=v'; it('should throw error using wrong messageObj', async () => { @@ -917,8 +1140,8 @@ describe('PushAPI.chat.send', () => { ); }); }); - describe('GIF Message', () => { - const MESSAGE_TYPE = MessageType.GIF; + describe('MediaEmbed Message', () => { + const MESSAGE_TYPE = MessageType.MEDIA_EMBED; const MESSAGE = 'ttps://media1.giphy.com/media/FtlUfrq3pVZXVNjoxf/giphy360p.mp4?cid=ecf05e47jk317254v9hbdjrknemduocie4pf54wtsir98xsx&ep=v1_videos_search&rid=giphy360p.mp4&ct=v'; it('should throw error using wrong messageObj', async () => { @@ -1063,7 +1286,7 @@ describe('PushAPI.chat.send', () => { }); describe('Meta Message', () => { const MESSAGE_TYPE = MessageType.META; - const MESSAGE = 'xyz created group PUSH'; + const MESSAGE = CHAT.META.GROUP.CREATE; it('should throw error using messageContent or wrong MessageObject', async () => { await expect( send({ @@ -1087,7 +1310,7 @@ describe('PushAPI.chat.send', () => { await expect( send({ messageType: MESSAGE_TYPE, - messageObj: { content: MESSAGE, reference: '' }, + messageObj: { content: MESSAGE }, messageContent: MESSAGE, receiverAddress: account2, signer: _signer1, @@ -1097,30 +1320,25 @@ describe('PushAPI.chat.send', () => { await expect( send({ messageType: MESSAGE_TYPE, - messageObj: { content: MESSAGE, action: 1 }, // no info provided + messageObj: { content: MESSAGE, action: 1 }, // no info messageContent: MESSAGE, receiverAddress: account2, signer: _signer1, env: _env, }) ).to.be.rejected; - }); - it('should throw error for non-group', async () => { await expect( send({ messageType: MESSAGE_TYPE, - messageObj: { - content: MESSAGE, - action: 1, - info: { affected: [] }, - }, + messageObj: { content: MESSAGE, action: 1, info: { affected: [] } }, // action is not allowed + messageContent: MESSAGE, receiverAddress: account2, signer: _signer1, env: _env, }) ).to.be.rejected; }); - it('should throw error for non member of group', async () => { + it('should throw error for invalid content', async () => { const groupName = uniqueNamesGenerator({ dictionaries: [adjectives, colors, animals], }); @@ -1133,28 +1351,76 @@ describe('PushAPI.chat.send', () => { const group = await createGroup({ groupName, groupDescription, - members: [_nftAccount1, _nftAccount2], + members: [_nftAccount1, _nftAccount2, account2], groupImage, admins: [], // takes signer as admin automatically, add more if you want to isPublic: true, signer: _signer1, env: _env, }); + + await expect( + send({ + messageType: MESSAGE_TYPE, + message: { + type: MESSAGE_TYPE, + content: 'INVALID CONTENT', + info: { affected: [] }, + }, + receiverAddress: group.chatId, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('should throw error for non-group', async () => { await expect( send({ messageType: MESSAGE_TYPE, messageObj: { content: MESSAGE, - action: 1, info: { affected: [] }, }, - receiverAddress: group.chatId, - signer: _signer2, + receiverAddress: account2, + signer: _signer1, env: _env, }) ).to.be.rejected; }); - it('should throw error for Non-Admin member of group', async () => { + it('should throw error for non member of group', async () => { + const groupName = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupDescription = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupImage = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; + + const group = await createGroup({ + groupName, + groupDescription, + members: [_nftAccount1, _nftAccount2], + groupImage, + admins: [], // takes signer as admin automatically, add more if you want to + isPublic: true, + signer: _signer1, + env: _env, + }); + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + info: { affected: [] }, + }, + receiverAddress: group.chatId, + signer: _signer2, + env: _env, + }) + ).to.be.rejected; + }); + it('should throw error for Non-Admin member of group', async () => { const groupName = uniqueNamesGenerator({ dictionaries: [adjectives, colors, animals], }); @@ -1179,7 +1445,6 @@ describe('PushAPI.chat.send', () => { messageType: MESSAGE_TYPE, messageObj: { content: MESSAGE, - action: 1, info: { affected: [] }, }, receiverAddress: group.chatId, @@ -1212,7 +1477,6 @@ describe('PushAPI.chat.send', () => { messageType: MESSAGE_TYPE, messageObj: { content: MESSAGE, - action: 1, info: { affected: [] }, }, receiverAddress: group.chatId, @@ -1222,7 +1486,7 @@ describe('PushAPI.chat.send', () => { await expectMsg( msg, MESSAGE_TYPE, - { content: MESSAGE, action: 1, info: { affected: [] } }, + { content: MESSAGE, info: { affected: [] } }, account1, _signer1, group.chatId, @@ -1253,7 +1517,6 @@ describe('PushAPI.chat.send', () => { messageType: MESSAGE_TYPE, messageObj: { content: MESSAGE, - action: 1, info: { affected: [] }, }, receiverAddress: group.chatId, @@ -1263,7 +1526,7 @@ describe('PushAPI.chat.send', () => { await expectMsg( msg, MESSAGE_TYPE, - { content: MESSAGE, action: 1, info: { affected: [] } }, + { content: MESSAGE, info: { affected: [] } }, account1, _signer1, group.chatId, @@ -1294,7 +1557,6 @@ describe('PushAPI.chat.send', () => { message: { type: MESSAGE_TYPE, content: MESSAGE, - action: 1, info: { affected: [] }, }, to: group.chatId, @@ -1304,7 +1566,7 @@ describe('PushAPI.chat.send', () => { await expectMsg( msg, MESSAGE_TYPE, - { content: MESSAGE, action: 1, info: { affected: [] } }, + { content: MESSAGE, info: { affected: [] } }, account1, _signer1, group.chatId, @@ -1335,7 +1597,6 @@ describe('PushAPI.chat.send', () => { message: { type: MESSAGE_TYPE, content: MESSAGE, - action: 1, info: { affected: [] }, }, to: group.chatId, @@ -1345,7 +1606,7 @@ describe('PushAPI.chat.send', () => { await expectMsg( msg, MESSAGE_TYPE, - { content: MESSAGE, action: 1, info: { affected: [] } }, + { content: MESSAGE, info: { affected: [] } }, account1, _signer1, group.chatId, @@ -1355,8 +1616,8 @@ describe('PushAPI.chat.send', () => { }); describe('Reaction Message', () => { const MESSAGE_TYPE = MessageType.REACTION; - const MESSAGE = ''; - it('should throw error using messageContent or wrong MessageObject', async () => { + const MESSAGE = CHAT.REACTION.CLAP; + it('should throw error using messageContent on wrong MessageObject', async () => { await expect( send({ messageType: MESSAGE_TYPE, @@ -1370,12 +1631,175 @@ describe('PushAPI.chat.send', () => { send({ messageType: MESSAGE_TYPE, messageObj: { content: MESSAGE }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE, info: { affected: [] } }, + messageContent: MESSAGE, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('should throw error on wrong content', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: 'Invalid Symbol', + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + messageContent: MESSAGE, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('Deprecated V1 | EncType - PlainText', async () => { + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: MESSAGE, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('Deprecated V1 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + }); + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: MESSAGE, // REACTION OVERRIDES THE MESSAGE CONTENT TO THE SYMBOL + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + account1, + _signer1, + account2, + 'pgp' + ); + }); + it('V2 | EncType - PlainText', async () => { + const msg = await send({ + message: { + type: MESSAGE_TYPE, + content: MESSAGE, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: MESSAGE, // REACTION OVERRIDES THE MESSAGE CONTENT TO THE SYMBOL, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('V2 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + }); + const msg = await send({ + message: { + type: MESSAGE_TYPE, + content: MESSAGE, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: MESSAGE, // REACTION OVERRIDES THE MESSAGE CONTENT TO THE SYMBOL + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + account1, + _signer1, + account2, + 'pgp' + ); + }); + }); + describe('Receipt Message', () => { + const MESSAGE_TYPE = MessageType.RECEIPT; + const MESSAGE = CHAT.RECEIPT.READ; + it('should throw error using messageContent on wrong MessageObject', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, messageContent: MESSAGE, receiverAddress: account2, signer: _signer1, env: _env, }) ).to.be.rejected; + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; await expect( send({ messageType: MESSAGE_TYPE, @@ -1387,12 +1811,29 @@ describe('PushAPI.chat.send', () => { }) ).to.be.rejected; }); + it('should throw error on wrong content', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: 'Invalid Message Content', + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + messageContent: MESSAGE, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); it('Deprecated V1 | EncType - PlainText', async () => { const msg = await send({ messageType: MESSAGE_TYPE, messageObj: { content: MESSAGE, - action: REACTION_TYPE.THUMBS_UP, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', }, receiverAddress: walletAddress2, signer: _signer1, @@ -1402,8 +1843,9 @@ describe('PushAPI.chat.send', () => { msg, MESSAGE_TYPE, { - content: REACTION_SYMBOL[REACTION_TYPE.THUMBS_UP], // REACTION OVERRIDES THE MESSAGE CONTENT TO THE SYMBOL, - action: REACTION_TYPE.THUMBS_UP, + content: MESSAGE, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', }, account1, _signer1, @@ -1421,7 +1863,8 @@ describe('PushAPI.chat.send', () => { messageType: MESSAGE_TYPE, messageObj: { content: MESSAGE, - action: REACTION_TYPE.THUMBS_UP, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', }, receiverAddress: walletAddress2, signer: _signer1, @@ -1431,8 +1874,9 @@ describe('PushAPI.chat.send', () => { msg, MESSAGE_TYPE, { - content: REACTION_SYMBOL[REACTION_TYPE.THUMBS_UP], // REACTION OVERRIDES THE MESSAGE CONTENT TO THE SYMBOL - action: REACTION_TYPE.THUMBS_UP, + content: MESSAGE, // REACTION OVERRIDES THE MESSAGE CONTENT TO THE SYMBOL + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', }, account1, _signer1, @@ -1445,7 +1889,8 @@ describe('PushAPI.chat.send', () => { message: { type: MESSAGE_TYPE, content: MESSAGE, - action: REACTION_TYPE.THUMBS_UP, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', }, to: walletAddress2, signer: _signer1, @@ -1455,8 +1900,9 @@ describe('PushAPI.chat.send', () => { msg, MESSAGE_TYPE, { - content: REACTION_SYMBOL[REACTION_TYPE.THUMBS_UP], // REACTION OVERRIDES THE MESSAGE CONTENT TO THE SYMBOL, - action: REACTION_TYPE.THUMBS_UP, + content: MESSAGE, // REACTION OVERRIDES THE MESSAGE CONTENT TO THE SYMBOL, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', }, account1, _signer1, @@ -1474,7 +1920,8 @@ describe('PushAPI.chat.send', () => { message: { type: MESSAGE_TYPE, content: MESSAGE, - action: REACTION_TYPE.THUMBS_UP, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', }, to: walletAddress2, signer: _signer1, @@ -1484,8 +1931,9 @@ describe('PushAPI.chat.send', () => { msg, MESSAGE_TYPE, { - content: REACTION_SYMBOL[REACTION_TYPE.THUMBS_UP], // REACTION OVERRIDES THE MESSAGE CONTENT TO THE SYMBOL - action: REACTION_TYPE.THUMBS_UP, + content: MESSAGE, // REACTION OVERRIDES THE MESSAGE CONTENT TO THE SYMBOL + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', }, account1, _signer1, @@ -1494,21 +1942,817 @@ describe('PushAPI.chat.send', () => { ); }); }); -}); + describe('User Activity Message', () => { + const MESSAGE_TYPE = MessageType.USER_ACTIVITY; + const MESSAGE = CHAT.UA.LISTENER.JOIN; + it('should throw error using messageContent or wrong MessageObject', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageContent: MESSAGE, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE }, + messageContent: MESSAGE, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE }, + messageContent: MESSAGE, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE, action: 1 }, // no info + messageContent: MESSAGE, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE, action: 1, info: { affected: [] } }, // action is not allowed + messageContent: MESSAGE, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('should throw error for invalid content', async () => { + const groupName = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupDescription = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupImage = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; -/** - * HELPER FUNCTION - */ -const expectMsg = async ( - msg: MessageWithCID, - messageType: string, - content: string | { [key: string]: any }, - sender: string, - senderSigner: SignerType, // or receiverSigner - receiver: string, - encType?: 'PlainText' | 'pgp' -): Promise => { - expect(msg.fromDID).to.include(sender); + const group = await createGroup({ + groupName, + groupDescription, + members: [_nftAccount1, _nftAccount2, account2], + groupImage, + admins: [], // takes signer as admin automatically, add more if you want to + isPublic: true, + signer: _signer1, + env: _env, + }); + + await expect( + send({ + messageType: MESSAGE_TYPE, + message: { + type: MESSAGE_TYPE, + content: 'INVALID CONTENT', + info: { affected: [] }, + }, + receiverAddress: group.chatId, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('should throw error for non-group', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + info: { affected: [] }, + }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('should throw error for non member of group', async () => { + const groupName = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupDescription = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupImage = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; + + const group = await createGroup({ + groupName, + groupDescription, + members: [_nftAccount1, _nftAccount2], + groupImage, + admins: [], // takes signer as admin automatically, add more if you want to + isPublic: true, + signer: _signer1, + env: _env, + }); + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + info: { affected: [] }, + }, + receiverAddress: group.chatId, + signer: _signer2, + env: _env, + }) + ).to.be.rejected; + }); + it('Deprecated V1 | EncType - PlainText ( Public Grp )', async () => { + const groupName = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupDescription = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupImage = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; + + const group = await createGroup({ + groupName, + groupDescription, + members: [account2], + groupImage, + admins: [], // takes signer as admin automatically, add more if you want to + isPublic: true, + signer: _signer1, + env: _env, + }); + // approve intent + await approve({ + senderAddress: group.chatId, + status: 'Approved', + account: account2, + signer: _signer2, + env: _env, + }); + // send message + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + info: { affected: [] }, + }, + receiverAddress: group.chatId, + signer: _signer2, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { content: MESSAGE, info: { affected: [] } }, + account2, + _signer2, + group.chatId, + 'PlainText' + ); + }); + it('Deprecated V1 | EncType - pgp ( Private Grp )', async () => { + const groupName = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupDescription = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupImage = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; + + const group = await createGroup({ + groupName, + groupDescription, + members: [_nftAccount1, _nftAccount2, account2], + groupImage, + admins: [], // takes signer as admin automatically, add more if you want to + isPublic: false, + signer: _signer1, + env: _env, + }); + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + info: { affected: [] }, + }, + receiverAddress: group.chatId, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { content: MESSAGE, info: { affected: [] } }, + account1, + _signer1, + group.chatId, + 'pgp' + ); + }); + it('V2 | EncType - PlainText ( Public Grp )', async () => { + const groupName = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupDescription = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupImage = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; + + const group = await createGroup({ + groupName, + groupDescription, + members: [_nftAccount1, _nftAccount2, account2], + groupImage, + admins: [], // takes signer as admin automatically, add more if you want to + isPublic: true, + signer: _signer1, + env: _env, + }); + const msg = await send({ + message: { + type: MESSAGE_TYPE, + content: MESSAGE, + info: { affected: [] }, + }, + to: group.chatId, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { content: MESSAGE, info: { affected: [] } }, + account1, + _signer1, + group.chatId, + 'PlainText' + ); + }); + it('V2 | EncType - pgp ( Private Grp )', async () => { + const groupName = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupDescription = uniqueNamesGenerator({ + dictionaries: [adjectives, colors, animals], + }); + const groupImage = + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg=='; + + const group = await createGroup({ + groupName, + groupDescription, + members: [_nftAccount1, _nftAccount2, account2], + groupImage, + admins: [], // takes signer as admin automatically, add more if you want to + isPublic: false, + signer: _signer1, + env: _env, + }); + const msg = await send({ + message: { + type: MESSAGE_TYPE, + content: MESSAGE, + info: { affected: [] }, + }, + to: group.chatId, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { content: MESSAGE, info: { affected: [] } }, + account1, + _signer1, + group.chatId, + 'pgp' + ); + }); + }); + describe('Intent Message', () => { + const MESSAGE_TYPE = MessageType.INTENT; + const MESSAGE = CHAT.INTENT.ACCEPT; + it('should throw error using wrong messageObj', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + info: { affected: [] }, // not supported for intent + }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('should throw error using wrong content', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: 'Invalid Message', + }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('Deprecated V1 | EncType - Plaintext', async () => { + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + MESSAGE, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('Deprecated V1 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + version: Constants.ENC_TYPE_V1, + }); + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { content: MESSAGE }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + MESSAGE, + account1, + _signer1, + account2, + 'pgp' + ); + }); + it('V2 | EncType - Plaintext', async () => { + const msg = await send({ + message: { type: MESSAGE_TYPE, content: MESSAGE }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { content: MESSAGE }, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('V2 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + version: Constants.ENC_TYPE_V1, + }); + const msg = await send({ + message: { type: MESSAGE_TYPE, content: MESSAGE }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { content: MESSAGE }, + account1, + _signer1, + account2, + 'pgp' + ); + }); + }); + describe('Reply Message', () => { + const MESSAGE_TYPE = MessageType.REPLY; + const MESSAGE = { + type: MessageType.TEXT, + content: 'Replying to prev message', + }; + it('should throw error using wrong messageObj', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + // Adding content is legacy format is not allowed for reply + content: { + messageType: MessageType.TEXT, + messageObj: { + content: 'Hey', + }, + }, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('should throw error using wrong content', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: 'Invalid Message', + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('should throw error for unsupported messageType reply', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: { + type: MessageType.RECEIPT, + content: CHAT.RECEIPT.READ, + }, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('Deprecated V1 | EncType - Plaintext', async () => { + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: { + messageType: MESSAGE.type, + messageObj: { content: MESSAGE.content }, + }, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('Deprecated V1 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + version: Constants.ENC_TYPE_V1, + }); + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: { + messageType: MESSAGE.type, + messageObj: { content: MESSAGE.content }, + }, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + account1, + _signer1, + account2, + 'pgp' + ); + }); + it('V2 | EncType - Plaintext', async () => { + const msg = await send({ + message: { + type: MESSAGE_TYPE, + content: MESSAGE, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: { + messageType: MESSAGE.type, + messageObj: { content: MESSAGE.content }, + }, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('V2 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + version: Constants.ENC_TYPE_V1, + }); + const msg = await send({ + message: { + type: MESSAGE_TYPE, + content: MESSAGE, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: { + messageType: MESSAGE.type, + messageObj: { content: MESSAGE.content }, + }, + reference: + 'bafyreia22girudospfbs3q7t6eelb453rmwsi7shkejwxtwpp57xww6vae', + }, + account1, + _signer1, + account2, + 'pgp' + ); + }); + }); + describe('Composite Message', () => { + const MESSAGE_TYPE = MessageType.COMPOSITE; + const MESSAGE = [ + { + type: MessageType.TEXT as string, + content: 'Replying to prev message', + }, + ]; + it('should throw error using wrong messageObj', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + info: { affected: [] }, // not supported for composite + }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('should throw error using wrong content', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: 'Invalid Message', + }, + receiverAddress: account2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('should throw error for unsupported messageType composite', async () => { + await expect( + send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: [ + { + type: MessageType.READ_RECEIPT, + content: CHAT.READ_RECEIPT, + }, + ], + }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }) + ).to.be.rejected; + }); + it('Deprecated V1 | EncType - Plaintext', async () => { + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: [ + { + messageType: MESSAGE[0].type, + messageObj: { content: MESSAGE[0].content }, + }, + ], + }, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('Deprecated V1 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + version: Constants.ENC_TYPE_V1, + }); + const msg = await send({ + messageType: MESSAGE_TYPE, + messageObj: { + content: MESSAGE, + }, + receiverAddress: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: [ + { + messageType: MESSAGE[0].type, + messageObj: { content: MESSAGE[0].content }, + }, + ], + }, + account1, + _signer1, + account2, + 'pgp' + ); + }); + it('V2 | EncType - Plaintext', async () => { + const msg = await send({ + message: { + type: MESSAGE_TYPE, + content: MESSAGE, + }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: [ + { + messageType: MESSAGE[0].type, + messageObj: { content: MESSAGE[0].content }, + }, + ], + }, + account1, + _signer1, + account2, + 'PlainText' + ); + }); + it('V2 | EncType - pgp', async () => { + await create({ + account: account2, + env: _env, + signer: _signer2, + version: Constants.ENC_TYPE_V1, + }); + const msg = await send({ + message: { + type: MESSAGE_TYPE, + content: MESSAGE, + }, + to: walletAddress2, + signer: _signer1, + env: _env, + }); + await expectMsg( + msg, + MESSAGE_TYPE, + { + content: [ + { + messageType: MESSAGE[0].type, + messageObj: { content: MESSAGE[0].content }, + }, + ], + }, + account1, + _signer1, + account2, + 'pgp' + ); + }); + }); +}); + +/** + * HELPER FUNCTION + */ +const expectMsg = async ( + msg: MessageWithCID, + messageType: string, + content: string | { [key: string]: any }, + sender: string, + senderSigner: SignerType, // or receiverSigner + receiver: string, + encType?: 'PlainText' | 'pgp' +): Promise => { + expect(msg.fromDID).to.include(sender); expect(msg.fromCAIP10).to.include(sender); expect(msg.toDID).to.include(receiver); expect(msg.toCAIP10).to.include(receiver); @@ -1518,6 +2762,9 @@ const expectMsg = async ( expect(msg.sigType).to.equal(msg.verificationProof?.split(':')[0]); //Backward Compatibility check ( signature signs messageContent and will be diff from vProof ) expect(msg.signature).not.to.equal(msg.verificationProof?.split(':')[1]); + + const unsupportedContent = + 'MessageType Not Supported by this sdk version. Plz upgrade !!!'; try { if (encType && encType === 'pgp') { throw new Error('Should be encrypted'); @@ -1527,11 +2774,14 @@ const expectMsg = async ( if (typeof content === 'string') { expect((msg.messageObj as { content: string }).content).to.equal(content); //Backward Compatibility check - expect(msg.messageContent).to.equal(content); + expect(msg.messageContent).to.be.oneOf([content, unsupportedContent]); } else { expect(msg.messageObj).to.eql(content); //Backward Compatibility check - expect(msg.messageContent).to.equal((content as any).content); + expect(msg.messageContent).to.be.oneOf([ + (content as any).content, + unsupportedContent, + ]); } } catch (err) { if (encType && encType === 'PlainText') { @@ -1557,11 +2807,17 @@ const expectMsg = async ( content ); //Backward Compatibility check - expect(decryptedMsg.messageContent).to.equal(content); + expect(decryptedMsg.messageContent).to.be.oneOf([ + content, + unsupportedContent, + ]); } else { expect(decryptedMsg.messageObj).to.eql(content); //Backward Compatibility check - expect(decryptedMsg.messageContent).to.equal((content as any).content); + expect(decryptedMsg.messageContent).to.be.oneOf([ + (content as any).content, + unsupportedContent, + ]); } } }; diff --git a/packages/restapi/tests/lib/chat/updateGroup.test.ts b/packages/restapi/tests/lib/chat/updateGroup.test.ts index 436c10bd6..5f10b2db5 100644 --- a/packages/restapi/tests/lib/chat/updateGroup.test.ts +++ b/packages/restapi/tests/lib/chat/updateGroup.test.ts @@ -179,7 +179,7 @@ const expectGroup = async ( expect(group.pendingMembers).to.be.an('array'); expect(group.pendingMembers.length).to.equal(pendingMembers.length); for (let i = 0; i < pendingMembers.length; i++) { - expect(group.pendingMembers[i].wallet).to.equal(pendingMembers[i]); + expect(pendingMembers.includes(group.pendingMembers[i].wallet)).to.be.true; } expect(group.groupImage).to.equal(groupImage); expect(group.groupName).to.equal(groupName); diff --git a/packages/restapi/tests/lib/progressHook/progressHook.test.ts b/packages/restapi/tests/lib/progressHook/progressHook.test.ts index 3d177985b..4ea5a4155 100644 --- a/packages/restapi/tests/lib/progressHook/progressHook.test.ts +++ b/packages/restapi/tests/lib/progressHook/progressHook.test.ts @@ -86,14 +86,7 @@ describe('ProgressHook Tests', () => { for (let i = 0; i < progressInfo.length - 1; i++) { expect(progressInfo[i]).to.deep.equal(expectedHooks[i]); } - const expectedErrorHook = { - progressId: 'PUSH-ERROR-00', - progressTitle: 'Non Specific Error', - progressInfo: - '[Push SDK] - API - Error - API create() -: Error: [Push SDK] - API https://backend-dev.epns.io/apis/v2/users/: AxiosError: Request failed with status code 400', - level: 'ERROR', - }; - expect(progressInfo[4]).to.deep.equal(expectedErrorHook); + expect(progressInfo[4].progressId).to.be.equal('PUSH-ERROR-00'); } }); it('Decrypt Push Profile Success ProgressHooks', async () => { diff --git a/packages/uiweb/README.md b/packages/uiweb/README.md index fe84d77d5..d5f2e96f0 100644 --- a/packages/uiweb/README.md +++ b/packages/uiweb/README.md @@ -149,7 +149,7 @@ where | cta | string | Call To Action Link (given during notification creation) | | image | string | Any media link (given during notification creation) | | url | string | Channel Link (given during channel setup) | -| chainName | string | Can be anyone of the following blockchain networks on which the notification was sent - "ETH_MAINNET", "ETH_TEST_GOERLI", "POLYGON_MAINNET", "POLYGON_TEST_MUMBAI", "BSC_MAINNET, "BSC_TESTNET", "OPTIMISM_MAINNET", "OPTIMISM_TESTNET", "POLYGON_ZK_EVM_TESTNET", "POLYGON_ZK_EVM_MAINNET", "THE_GRAPH" | +| chainName | string | Can be anyone of the following blockchain networks on which the notification was sent - "ETH_MAINNET", "ETH_TEST_GOERLI", "POLYGON_MAINNET", "POLYGON_TEST_MUMBAI", "BSC_MAINNET, "BSC_TESTNET", "OPTIMISM_MAINNET", "OPTIMISM_TESTNET", "POLYGON_ZK_EVM_TESTNET", "POLYGON_ZK_EVM_MAINNET", "ARBITRUM_TESTNET", "ARBITRUMONE_MAINNET", "THE_GRAPH" | | theme | string | 'light' or 'dark' (customization to be given by the dApp) | | customTheme | INotificationItemTheme | custom theme object for the component | | isSpam | boolean | whether a spam notification or not | diff --git a/packages/uiweb/src/lib/components/notification/chainDetails.tsx b/packages/uiweb/src/lib/components/notification/chainDetails.tsx index ad783c516..403f12c39 100644 --- a/packages/uiweb/src/lib/components/notification/chainDetails.tsx +++ b/packages/uiweb/src/lib/components/notification/chainDetails.tsx @@ -7,7 +7,7 @@ import { BSCSvg } from "../../icons/BSCSvg"; import { OptimismSvg } from "../../icons/OptimismSvg"; import { PolygonzkevmSvg } from "../../icons/PolygonzkevmSvg"; import { TheGraphSvg } from "../../icons/TheGraphSvg"; -import { ReactElement } from "react"; +import { ArbitrumSvg } from "../../icons/ArbitrumSvg" const createSVGIcon = (element:any, chainName: string) => { return ( @@ -58,5 +58,14 @@ export default { label: 'POLYGON ZK EVM MAINNET', icon: createSVGIcon(, 'Polygon ZK EVM Mainnet'), }, + + ARBITRUMONE_MAINNET: { + label: 'ARBITRUMONE MAINNET', + icon: createSVGIcon(, 'Arbitrum Mainnet'), + }, + ARBITRUM_TESTNET: { + label: 'ARBITRUM TESTNET', + icon: createSVGIcon(, 'Arbitrum Testnet'), + }, THE_GRAPH: { label: 'THE GRAPH', icon: createSVGIcon(, 'The Graph') }, }; diff --git a/packages/uiweb/src/lib/components/notification/index.tsx b/packages/uiweb/src/lib/components/notification/index.tsx index bcec3907b..8ce4dd911 100644 --- a/packages/uiweb/src/lib/components/notification/index.tsx +++ b/packages/uiweb/src/lib/components/notification/index.tsx @@ -34,6 +34,8 @@ export type chainNameType = | 'OPTIMISM_TESTNET' | 'POLYGON_ZK_EVM_TESTNET' | 'POLYGON_ZK_EVM_MAINNET' + | 'ARBITRUMONE_MAINNET' + | 'ARBITRUM_TESTNET' | 'THE_GRAPH' | undefined; diff --git a/packages/uiweb/src/lib/config/constants.ts b/packages/uiweb/src/lib/config/constants.ts index b91a48dad..edd9b7cf7 100644 --- a/packages/uiweb/src/lib/config/constants.ts +++ b/packages/uiweb/src/lib/config/constants.ts @@ -51,25 +51,30 @@ export const allowedNetworks = { 1, //for ethereum mainnet 137, //for polygon mainnet 56, // for bnb mainnet - // 10 // for optimism mainnet + 10, // for optimism mainnet + 42161 // for arbitrum mainnet ], 'dev' : [ 5, // for eth goerli 80001, //for mumbai polygon 97, // bnb testnet - 420 // optimism goerli testnet + 420, // optimism goerli testnet + 421613 // for arbitrum testnet ], 'staging' : [ // 42, //for kovan 5, // for goerli 80001, //for mumbai polygon - 97 // bnb testnet + 97, // bnb testnet + 420, // optimism goerli testnet + 421613 // for arbitrum testnet ], 'local' :[ 5, // for eth goerli 80001, //for mumbai polygon 97, // bnb testnet - 420 // optimism goerli testnet + 420, // optimism goerli testnet + 421613 // for arbitrum testnet ] } diff --git a/packages/uiweb/src/lib/icons/ArbitrumSvg.tsx b/packages/uiweb/src/lib/icons/ArbitrumSvg.tsx new file mode 100644 index 000000000..5703e7717 --- /dev/null +++ b/packages/uiweb/src/lib/icons/ArbitrumSvg.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; + +export const ArbitrumSvg = () => ( + + + + + +); +