diff --git a/package.json b/package.json index 3b2dda4ec..49514fb87 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,8 @@ "tslib": "^2.3.0", "unique-names-generator": "^4.7.1", "uuid": "^9.0.0", - "video-stream-merger": "^4.0.1" + "video-stream-merger": "^4.0.1", + "viem": "^1.3.0" }, "devDependencies": { "@commitlint/cli": "^17.0.0", diff --git a/packages/examples/sdk-backend-node/src/chat/chat.ts b/packages/examples/sdk-backend-node/src/chat/chat.ts index 91cc898e1..31b4bb6d8 100644 --- a/packages/examples/sdk-backend-node/src/chat/chat.ts +++ b/packages/examples/sdk-backend-node/src/chat/chat.ts @@ -9,18 +9,49 @@ import { } 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 = ethers.Wallet.createRandom(); -const signerSecondAccount = ethers.Wallet.createRandom(); - +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 = ethers.Wallet.createRandom().address; -const randomWallet2 = ethers.Wallet.createRandom().address; -const randomWallet3 = ethers.Wallet.createRandom().address; +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({ @@ -101,7 +132,7 @@ async function PushAPI_user_create(silent = !showAPIResponse) { }); const user_2 = await PushAPI.user.create({ - signer: signerSecondAccount, + signer: secondSigner, env: env as ENV, }); @@ -117,7 +148,7 @@ async function PushAPI_user_create(silent = !showAPIResponse) { // Push Chat - PushAPI.user.get async function PushAPI_user_get(silent = !showAPIResponse) { const user = await PushAPI.user.get({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, env: env as ENV, }); @@ -132,7 +163,7 @@ async function PushAPI_user_get(silent = !showAPIResponse) { async function PushAPI_chat_decryptPGPKey(silent = !showAPIResponse) { // get user and derive encrypted PGP key const user = await PushAPI.user.get({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, env: env as ENV, }); @@ -153,7 +184,7 @@ async function PushAPI_chat_decryptPGPKey(silent = !showAPIResponse) { async function PushAPI_chat_chats(silent = !showAPIResponse) { // Fetch user const user = await PushAPI.user.get({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, env: env as ENV, }); @@ -166,7 +197,7 @@ async function PushAPI_chat_chats(silent = !showAPIResponse) { // Actual api const response = await PushAPI.chat.chats({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, toDecrypt: true, pgpPrivateKey: pgpDecrpyptedPvtKey, env: env as ENV, @@ -182,7 +213,7 @@ async function PushAPI_chat_chats(silent = !showAPIResponse) { async function PushAPI_chat_requests(silent = !showAPIResponse) { // Fetch user const user = await PushAPI.user.get({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, env: env as ENV, }); @@ -195,7 +226,7 @@ async function PushAPI_chat_requests(silent = !showAPIResponse) { // Actual api const response = await PushAPI.chat.requests({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, toDecrypt: true, pgpPrivateKey: pgpDecrpyptedPvtKey, env: env as ENV, @@ -211,8 +242,8 @@ async function PushAPI_chat_requests(silent = !showAPIResponse) { async function PushAPI_chat_conversationHash(silent = !showAPIResponse) { // conversation hash are also called link inside chat messages const conversationHash = await PushAPI.chat.conversationHash({ - account: `eip155:${signer.address}`, - conversationId: `eip155:${signerSecondAccount.address}`, // 2nd address + account: `eip155:${signerAddress}`, + conversationId: `eip155:${secondSignerAddress}`, // 2nd address env: env as ENV, }); @@ -226,7 +257,7 @@ async function PushAPI_chat_conversationHash(silent = !showAPIResponse) { async function PushAPI_chat_latest(silent = !showAPIResponse) { // Fetch user const user = await PushAPI.user.get({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, env: env as ENV, }); @@ -240,15 +271,15 @@ async function PushAPI_chat_latest(silent = !showAPIResponse) { // Fetch conversation hash // conversation hash are also called link inside chat messages const conversationHash = await PushAPI.chat.conversationHash({ - account: `eip155:${signer.address}`, - conversationId: `eip155:${signerSecondAccount.address}`, // 2nd address + 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:${signer.address}`, + account: `eip155:${signerAddress}`, toDecrypt: true, pgpPrivateKey: pgpDecrpyptedPvtKey, env: env as ENV, @@ -264,7 +295,7 @@ async function PushAPI_chat_latest(silent = !showAPIResponse) { async function PushAPI_chat_history(silent = !showAPIResponse) { // Fetch user const user = await PushAPI.user.get({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, env: env as ENV, }); @@ -278,15 +309,15 @@ async function PushAPI_chat_history(silent = !showAPIResponse) { // Fetch conversation hash // conversation hash are also called link inside chat messages const conversationHash = await PushAPI.chat.conversationHash({ - account: `eip155:${signer.address}`, - conversationId: `eip155:${signerSecondAccount.address}`, // 2nd address + 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:${signer.address}`, + account: `eip155:${signerAddress}`, limit: 5, toDecrypt: true, pgpPrivateKey: pgpDecrpyptedPvtKey, @@ -304,7 +335,7 @@ async function PushAPI_chat_history(silent = !showAPIResponse) { async function PushAPI_chat_send(silent = !showAPIResponse) { // Fetch user const user = await PushAPI.user.get({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, env: env as ENV, }); @@ -321,7 +352,7 @@ async function PushAPI_chat_send(silent = !showAPIResponse) { content: "Gm gm! It's me... Mario", }, messageType: 'Text', // can be "Text" | "Image" | "File" | "GIF" - receiverAddress: signerSecondAccount.address, + receiverAddress: secondSignerAddress, signer: signer, pgpPrivateKey: pgpDecrpyptedPvtKey, @@ -339,7 +370,7 @@ async function PushAPI_chat_send(silent = !showAPIResponse) { async function PushAPI_chat_approve(silent = !showAPIResponse) { // Fetch user const user = await PushAPI.user.get({ - account: `eip155:${signerSecondAccount.address}`, + account: `eip155:${secondSignerAddress}`, env: env as ENV, }); @@ -347,15 +378,15 @@ async function PushAPI_chat_approve(silent = !showAPIResponse) { const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ encryptedPGPPrivateKey: user.encryptedPrivateKey, - signer: signerSecondAccount, + signer: secondSigner, }); // Actual api const approve = await PushAPI.chat.approve({ status: 'Approved', - senderAddress: signer.address, // receiver's address or chatId of a group + senderAddress: signerAddress, // receiver's address or chatId of a group - signer: signerSecondAccount, + signer: secondSigner, pgpPrivateKey: pgpDecrpyptedPvtKey, env: env as ENV, }); @@ -372,7 +403,7 @@ async function PushAPI_chat_createGroup( ): Promise { // Fetch user const user = await PushAPI.user.get({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, env: env as ENV, }); @@ -412,7 +443,7 @@ async function PushAPI_chat_updateGroup( ) { // Fetch user const user = await PushAPI.user.get({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, env: env as ENV, }); @@ -435,10 +466,10 @@ async function PushAPI_chat_updateGroup( `eip155:${randomWallet1}`, `eip155:${randomWallet2}`, `eip155:${randomWallet3}`, - `eip155:${signer.address}`, + `eip155:${signerAddress}`, ], groupImage, - admins: [`eip155:${signer.address}`], // takes signer as admin automatically, add more if you want to + admins: [`eip155:${signerAddress}`], // takes signer as admin automatically, add more if you want to signer: signer, pgpPrivateKey: pgpDecrpyptedPvtKey, @@ -484,7 +515,7 @@ async function PushAPI_chat_getGroup( async function PushAPI_chat_decryptConversation(silent = !showAPIResponse) { // Fetch user const user = await PushAPI.user.get({ - account: `eip155:${signer.address}`, + account: `eip155:${signerAddress}`, env: env as ENV, }); @@ -498,15 +529,15 @@ async function PushAPI_chat_decryptConversation(silent = !showAPIResponse) { // Fetch conversation hash // conversation hash are also called link inside chat messages const conversationHash = await PushAPI.chat.conversationHash({ - account: `eip155:${signer.address}`, - conversationId: `eip155:${signerSecondAccount.address}`, // 2nd address + 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:${signer.address}`, + account: `eip155:${signerAddress}`, limit: 5, toDecrypt: false, pgpPrivateKey: pgpDecrpyptedPvtKey, @@ -530,7 +561,7 @@ async function PushAPI_chat_decryptConversation(silent = !showAPIResponse) { // Push Chat - Socket Connection async function PushChatSDKSocket(silent = !showAPIResponse) { const pushSDKSocket = createSocketConnection({ - user: `eip155:${signer.address}`, + user: `eip155:${signerAddress}`, socketType: 'chat', socketOptions: { autoConnect: true, reconnectionAttempts: 3 }, env: env as ENV, @@ -546,7 +577,7 @@ async function PushChatSDKSocket(silent = !showAPIResponse) { // send a chat from other wallet to this one to see the result // Fetch user const user = await PushAPI.user.get({ - account: `eip155:${signerSecondAccount.address}`, + account: `eip155:${secondSignerAddress}`, env: env as ENV, }); @@ -554,16 +585,16 @@ async function PushChatSDKSocket(silent = !showAPIResponse) { const pgpDecrpyptedPvtKey = await PushAPI.chat.decryptPGPKey({ encryptedPGPPrivateKey: user.encryptedPrivateKey, - signer: signerSecondAccount, + signer: secondSigner, }); // Actual api const response = await PushAPI.chat.send({ messageContent: "Gm gm! It's me... Mario", messageType: 'Text', - receiverAddress: `eip155:${signer.address}`, + receiverAddress: `eip155:${signerAddress}`, - signer: signerSecondAccount, + signer: secondSigner, pgpPrivateKey: pgpDecrpyptedPvtKey, env: env as ENV, }); @@ -596,7 +627,7 @@ async function PushAPI_chat_video_call_notification( ) { // Fetch user const user = await PushAPI.user.get({ - account: signer.address, + account: signerAddress, env: env as ENV, }); @@ -628,8 +659,8 @@ async function PushAPI_chat_video_call_notification( domain: 'push.org', }, }, - recipients: signerSecondAccount.address, // recipient address - channel: signer.address, // your channel address + recipients: secondSignerAddress, // recipient address + channel: signerAddress, // your channel address env: env as ENV, }); diff --git a/packages/examples/sdk-backend-node/src/notification/index.ts b/packages/examples/sdk-backend-node/src/notification/index.ts index 1df6f2a79..259ec1dd9 100644 --- a/packages/examples/sdk-backend-node/src/notification/index.ts +++ b/packages/examples/sdk-backend-node/src/notification/index.ts @@ -3,6 +3,10 @@ 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', @@ -18,12 +22,38 @@ const { env, showAPIResponse } = config; // If you own a channel, you can use your channel address as well const channelPrivateKey: string = process.env.WALLET_PRIVATE_KEY!; -const signerChannel = new ethers.Wallet(`0x${channelPrivateKey}`); -const channelAddress = signerChannel.address; -// Some Random Accounts -const signer = ethers.Wallet.createRandom(); -const signerSecondAccount = ethers.Wallet.createRandom(); +/***************** SAMPLE SIGNER GENERATION *********************/ +/** + * USING VIEM + */ +const signerChannel = createWalletClient({ + account: privateKeyToAccount(`0x${channelPrivateKey}`), + chain: goerli, + transport: http(), +}); +const channelAddress = signerChannel.account.address; +// 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; +/************************************************************* */ // Push Notification - Run Notifications Use cases export const runNotificaitonsUseCases = async (): Promise => { @@ -82,7 +112,7 @@ export const runNotificaitonsUseCases = async (): Promise => { // Push Notification - PushAPI.user.getFeeds async function PushAPI_user_getFeeds(silent = !showAPIResponse) { const notifications = await PushAPI.user.getFeeds({ - user: `eip155:5:${signer.address}`, // user address in CAIP + user: `eip155:5:${signerAddress}`, // user address in CAIP env: env as ENV, }); @@ -95,7 +125,7 @@ async function PushAPI_user_getFeeds(silent = !showAPIResponse) { // Push Notification - PushAPI.user.getFeeds - Spam async function PushAPI_user_getFeeds__spam(silent = !showAPIResponse) { const notifications = await PushAPI.user.getFeeds({ - user: `eip155:5:${signer.address}`, // user address in CAIP + user: `eip155:5:${signerAddress}`, // user address in CAIP spam: true, env: env as ENV, }); @@ -109,7 +139,7 @@ async function PushAPI_user_getFeeds__spam(silent = !showAPIResponse) { // Push Notification - PushAPI.user.getSubscriptions async function PushAPI_user_getSubscriptions(silent = !showAPIResponse) { const subscriptions = await PushAPI.user.getSubscriptions({ - user: `eip155:5:${signer.address}`, // user address in CAIP + user: `eip155:5:${signerAddress}`, // user address in CAIP env: env as ENV, }); @@ -152,7 +182,7 @@ 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:${signer.address}`, // user address in CAIP + userAddress: `eip155:5:${signerAddress}`, // user address in CAIP onSuccess: () => { console.log('opt in success'); }, @@ -173,7 +203,7 @@ 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:${signer.address}`, // user address in CAIP + userAddress: `eip155:5:${signerAddress}`, // user address in CAIP onSuccess: () => { console.log('opt out success'); }, @@ -209,8 +239,8 @@ async function PushAPI_payloads_sendNotification__direct_payload_single_recipien cta: '', img: '', }, - recipients: `eip155:5:${signer.address}`, // recipient address - channel: `eip155:5:${signerChannel.address}`, // your channel address + recipients: `eip155:5:${signerAddress}`, // recipient address + channel: `eip155:5:${channelAddress}`, // your channel address env: env as ENV, }); @@ -239,11 +269,8 @@ async function PushAPI_payloads_sendNotification__direct_payload_group_of_recipi cta: '', img: '', }, - recipients: [ - `eip155:5:${signer.address}`, - `eip155:5:${signerSecondAccount.address}`, - ], // recipient addresses - channel: `eip155:5:${signerChannel.address}`, // your channel address + recipients: [`eip155:5:${signerAddress}`, `eip155:5:${randomWallet1}`], // recipient addresses + channel: `eip155:5:${channelAddress}`, // your channel address env: env as ENV, }); @@ -272,7 +299,7 @@ async function PushAPI_payloads_sendNotification__direct_payload_all_recipients_ cta: '', img: '', }, - channel: `eip155:5:${signerChannel.address}`, // your channel address + channel: `eip155:5:${channelAddress}`, // your channel address env: env as ENV, }); @@ -298,7 +325,7 @@ async function PushAPI_channels_getSubscribers(silent = !showAPIResponse) { // Push Notification - Socket Connection async function PushSDKSocket(silent = !showAPIResponse) { const pushSDKSocket = createSocketConnection({ - user: `eip155:5:${signer.address}`, // CAIP, see below + user: `eip155:5:${signerAddress}`, // CAIP, see below socketOptions: { autoConnect: false }, env: env as ENV, }); diff --git a/packages/examples/sdk-backend-node/src/spaces/index.ts b/packages/examples/sdk-backend-node/src/spaces/index.ts index f320f7659..6b2034b85 100644 --- a/packages/examples/sdk-backend-node/src/spaces/index.ts +++ b/packages/examples/sdk-backend-node/src/spaces/index.ts @@ -55,7 +55,7 @@ export const runSpacesUseCases = async (): Promise < void > => { ╚════██║██╔═══╝ ██╔══██║██║ ██╔══╝ ╚════██║ ███████║██║ ██║ ██║╚██████╗███████╗███████║ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝╚══════╝ - + `) console.log('PushAPI.user.create'); @@ -143,9 +143,9 @@ async function PushAPI_space_create( const response = await PushAPI.space.create({ spaceName, spaceDescription, - members: [`eip155:${randomWallet1}`, `eip155:${randomWallet2}`], + listeners: [`eip155:${randomWallet1}`, `eip155:${randomWallet2}`], spaceImage, - admins: [], + speakers: [], isPublic: true, signer: signer, pgpPrivateKey: pgpDecrpyptedPvtKey, @@ -191,14 +191,14 @@ async function PushAPI_space_update( spaceId, spaceName, spaceDescription, - members: [ + listeners: [ `eip155:${randomWallet1}`, `eip155:${randomWallet2}`, `eip155:${randomWallet3}`, `eip155:${signer.address}`, ], spaceImage, - admins: [`eip155:${signer.address}`], // takes signer as admin automatically, add more if you want to + speakers: [`eip155:${signer.address}`], // takes signer as admin automatically, add more if you want to scheduleAt: start, scheduleEnd: end, status: PushAPI.ChatStatus.PENDING, @@ -255,9 +255,9 @@ async function PushAPI_space_start_and_stop( dictionaries: [adjectives, colors, animals], }), spaceDescription, - members: [`eip155:${randomWallet1}`, `eip155:${randomWallet2}`], + listeners: [`eip155:${randomWallet1}`, `eip155:${randomWallet2}`], spaceImage, - admins: [], + speakers: [], isPublic: true, signer: signer, pgpPrivateKey: pgpDecrpyptedPvtKey, @@ -323,9 +323,9 @@ async function PushAPI_space_approve( dictionaries: [adjectives, colors, animals], }), spaceDescription, - members: [`eip155:${randomWallet1}`, `eip155:${randomWallet2}`], + listeners: [`eip155:${randomWallet1}`, `eip155:${randomWallet2}`], spaceImage, - admins: [], + speakers: [], isPublic: true, signer: signer, pgpPrivateKey: pgpDecrpyptedPvtKey, diff --git a/packages/restapi/src/lib/channels/subscribe.ts b/packages/restapi/src/lib/channels/subscribe.ts index 4db84c914..9bfc4dde9 100644 --- a/packages/restapi/src/lib/channels/subscribe.ts +++ b/packages/restapi/src/lib/channels/subscribe.ts @@ -3,6 +3,7 @@ import { getCAIPAddress, getConfig, getCAIPDetails, + signTypedData } from '../helpers'; import { getTypeInformation, @@ -10,15 +11,7 @@ import { getSubscriptionMessage } from './signature.helpers'; import Constants, {ENV} from '../constants'; - -type SignerType = { - _signTypedData: ( - domain: any, - types: any, - value: any - ) => Promise -} - +import { SignerType } from "../types"; export type SubscribeOptionsType = { signer: SignerType; channelAddress: string; @@ -76,11 +69,7 @@ export const subscribe = async ( ); // sign a message using EIP712 - const signature = await signer._signTypedData( - domainInformation, - typeInformation, - messageInformation - ); + const signature = await signTypedData(signer, domainInformation, typeInformation, messageInformation); const verificationProof = signature; // might change diff --git a/packages/restapi/src/lib/channels/unsubscribe.ts b/packages/restapi/src/lib/channels/unsubscribe.ts index 19ec57b36..839dd83b7 100644 --- a/packages/restapi/src/lib/channels/unsubscribe.ts +++ b/packages/restapi/src/lib/channels/unsubscribe.ts @@ -3,6 +3,7 @@ import { getCAIPAddress, getConfig, getCAIPDetails, + signTypedData } from '../helpers'; import { getTypeInformation, @@ -10,14 +11,7 @@ import { getSubscriptionMessage } from './signature.helpers'; import Constants, {ENV} from '../constants'; - -type SignerType = { - _signTypedData: ( - domain: any, - types: any, - value: any - ) => Promise -} +import { SignerType } from "../types"; export type UnSubscribeOptionsType = { signer: SignerType; @@ -76,11 +70,7 @@ export const unsubscribe = async ( ); // sign a message using EIP712 - const signature = await signer._signTypedData( - domainInformation, - typeInformation, - messageInformation - ); + const signature = await signTypedData(signer, domainInformation, typeInformation, messageInformation); const verificationProof = signature; // might change diff --git a/packages/restapi/src/lib/chat/helpers/crypto.ts b/packages/restapi/src/lib/chat/helpers/crypto.ts index 86e64b590..46e8dcba3 100644 --- a/packages/restapi/src/lib/chat/helpers/crypto.ts +++ b/packages/restapi/src/lib/chat/helpers/crypto.ts @@ -16,6 +16,8 @@ import { decryptWithWalletRPCMethod, isValidETHAddress, walletToPCAIP10, + signTypedData, + signMessage, } from '../../helpers'; import { get as getUser } from '../../user'; import { createUserService } from './service'; @@ -289,7 +291,8 @@ export const getEip191Signature = async ( } const _signer = wallet?.signer; // EIP191 signature - const signature = await _signer?.signMessage(message); + + const signature = await signMessage(_signer, message); const sigType = version === 'v1' ? 'eip191' : 'eip191v2'; return { verificationProof: `${sigType}:${signature}` }; }; @@ -316,7 +319,8 @@ export const getEip712Signature = async ( const domain = getDomainInformation(chainId); // sign a message using EIP712 - const signedMessage = await _signer?._signTypedData!( + const signedMessage = await signTypedData( + _signer, isDomainEmpty ? {} : domain, typeInformation, { data: hash } diff --git a/packages/restapi/src/lib/chat/helpers/wallet.ts b/packages/restapi/src/lib/chat/helpers/wallet.ts index 0633efdd3..1481e62bf 100644 --- a/packages/restapi/src/lib/chat/helpers/wallet.ts +++ b/packages/restapi/src/lib/chat/helpers/wallet.ts @@ -1,4 +1,4 @@ -import { pCAIP10ToWallet } from "../../helpers"; +import { pCAIP10ToWallet, getAddress } from "../../helpers"; import { SignerType, walletType } from "../../types"; export const getWallet = (options: walletType): { @@ -22,5 +22,5 @@ export const getAccountAddress = async (options: walletType): Promise => signer } = options || {}; - return account || (await signer?.getAddress()) || '' + return account || (await getAddress(signer as SignerType)) || '' } \ No newline at end of file diff --git a/packages/restapi/src/lib/helpers/crypto.ts b/packages/restapi/src/lib/helpers/crypto.ts index b03e10ac6..d3af27c08 100644 --- a/packages/restapi/src/lib/helpers/crypto.ts +++ b/packages/restapi/src/lib/helpers/crypto.ts @@ -32,6 +32,7 @@ import { import { verifyProfileSignature } from '../chat/helpers/signature'; import { upgrade } from '../user/upgradeUser'; import PROGRESSHOOK from '../progressHook'; +import { getAddress } from './signer'; const KDFSaltSize = 32; // bytes const AESGCMNonceSize = 12; // property iv @@ -51,7 +52,8 @@ if (typeof window !== 'undefined' && window.crypto) { /** DEPRECATED */ export const getPublicKey = async (options: walletType): Promise => { const { account, signer } = options || {}; - const address: string = account || (await signer?.getAddress()) || ''; + const address: string = + account || (await getAddress(signer as SignerType)) || ''; const metamaskProvider = new ethers.providers.Web3Provider( (window as any).ethereum ); diff --git a/packages/restapi/src/lib/helpers/index.ts b/packages/restapi/src/lib/helpers/index.ts index 718ba6cd2..182450d34 100644 --- a/packages/restapi/src/lib/helpers/index.ts +++ b/packages/restapi/src/lib/helpers/index.ts @@ -2,3 +2,4 @@ export * from './config'; export * from './address'; export * from './api'; export * from './crypto'; +export * from './signer'; diff --git a/packages/restapi/src/lib/helpers/signer.ts b/packages/restapi/src/lib/helpers/signer.ts new file mode 100644 index 000000000..89cbe4fbf --- /dev/null +++ b/packages/restapi/src/lib/helpers/signer.ts @@ -0,0 +1,59 @@ +import { SignerType } from '../types'; + +export const signMessage = async ( + signer: SignerType, + message: string +): Promise => { + // Check the signer type using type guards + if ('signMessage' in signer) { + // If the signer has a signMessage function with the ethersV5SignerType signature + if ('_signTypedData' in signer) { + // It's ethersV5SignerType, use its signMessage function + const signature = await signer.signMessage(message); + return signature; + } else { + // It's viemSignerType, use its signMessage function + const signature = await signer.signMessage({ + message, + account: signer.account, + }); + return signature; + } + } else { + throw new Error('Invalid signer type provided.'); + } +}; + +export const signTypedData = async ( + signer: SignerType, + domain: any, + types: any, + value: any +): Promise => { + // Check the signer type using type guards + if ('_signTypedData' in signer) { + // It's ethersV5SignerType, use its functions + const signature = await signer._signTypedData(domain, types, value); + return signature; + } else if ('signTypedData' in signer) { + // It's viemSignerType, use its functions + const signature = await signer.signTypedData({ + account: signer.account, + domain, + types, + primaryType: 'Data', + message: value, + }); + return signature; + } else { + throw new Error('Invalid signer type provided.'); + } +}; + +export const getAddress = async (signer: SignerType): Promise => { + if ('getAddress' in signer) { + return await signer.getAddress(); + } else { + return signer.account['address'] ?? ''; + } +}; diff --git a/packages/restapi/src/lib/payloads/helpers.ts b/packages/restapi/src/lib/payloads/helpers.ts index 500a53cd2..6022c9996 100644 --- a/packages/restapi/src/lib/payloads/helpers.ts +++ b/packages/restapi/src/lib/payloads/helpers.ts @@ -1,6 +1,6 @@ import { v4 as uuidv4 } from 'uuid'; import { ENV } from '../constants'; -import { getCAIPAddress } from '../helpers'; +import { getCAIPAddress, signTypedData } from '../helpers'; import * as CryptoJS from 'crypto-js'; import { @@ -252,7 +252,7 @@ export async function getVerificationProof({ chainId: chainId, verifyingContract: verifyingContract, }; - const signature = await signer._signTypedData(domain, type, message); + const signature = await signTypedData(signer, domain, type, message); verificationProof = `eip712v2:${signature}::uid::${uuid}`; break; } diff --git a/packages/restapi/src/lib/types/index.ts b/packages/restapi/src/lib/types/index.ts index a3b440803..d479b28a0 100644 --- a/packages/restapi/src/lib/types/index.ts +++ b/packages/restapi/src/lib/types/index.ts @@ -1,4 +1,4 @@ -import { ethers } from 'ethers'; +import { Bytes, TypedDataDomain, TypedDataField, providers } from 'ethers'; import { ADDITIONAL_META_TYPE, IDENTITY_TYPE, @@ -306,7 +306,7 @@ export interface Member { export enum ChatStatus { ACTIVE = 'ACTIVE', PENDING = 'PENDING', - ENDED = 'ENDED' + ENDED = 'ENDED', } export interface GroupDTO { members: { @@ -442,10 +442,38 @@ export interface UserInfo { isAdmin: boolean; } -export type SignerType = ethers.Signer & { - _signTypedData?: (domain: any, types: any, value: any) => Promise; +type ethersV5SignerType = { + _signTypedData: ( + domain: TypedDataDomain, + types: Record>, + value: Record + ) => Promise; + getChainId: () => Promise; + getAddress: () => Promise; + signMessage: (message: Bytes | string) => Promise; privateKey?: string; + provider?: providers.Provider; }; +type viemSignerType = { + signTypedData: (args: { + account: any; + domain: any; + types: any; + primaryType: any; + message: any; + }) => Promise<`0x${string}`>; + getChainId: () => Promise; + signMessage: (args: { + message: any; + account: any; + [key: string]: any; + }) => Promise<`0x${string}`>; + account: { [key: string]: any }; + privateKey?: string; + provider?: providers.Provider; +}; + +export type SignerType = ethersV5SignerType | viemSignerType; export type EnvOptionsType = { env?: ENV; diff --git a/packages/uiweb/src/lib/components/chatAndNotification/ChatAndNotificationWidget.tsx b/packages/uiweb/src/lib/components/chatAndNotification/ChatAndNotificationWidget.tsx index 37e3dc39d..4d7ace1be 100644 --- a/packages/uiweb/src/lib/components/chatAndNotification/ChatAndNotificationWidget.tsx +++ b/packages/uiweb/src/lib/components/chatAndNotification/ChatAndNotificationWidget.tsx @@ -17,7 +17,7 @@ export type ChatAndNotificationProps = { activeTab?: PushTabs, activeChat?: string, onClose?: () => void, - signer?: WithRequiredProperty + signer?: SignerType env?: Env; }; diff --git a/packages/uiweb/src/lib/types/index.ts b/packages/uiweb/src/lib/types/index.ts index 6f2fd1781..5a48d32f5 100644 --- a/packages/uiweb/src/lib/types/index.ts +++ b/packages/uiweb/src/lib/types/index.ts @@ -1,8 +1,7 @@ import type { ReactElement } from 'react'; -import React from 'react'; import type { ENV } from '../config'; -import type { ethers } from 'ethers'; import type { ParsedResponseType, IFeeds, } from '@pushprotocol/restapi'; +import { Bytes, TypedDataDomain, TypedDataField, providers } from 'ethers'; export interface IMessageIPFS { fromCAIP10: string; @@ -38,10 +37,38 @@ export interface ITheme { moduleColor?: string; } -export type SignerType = ethers.Signer & { - _signTypedData?: (domain: any, types: any, value: any) => Promise; +type ethersV5SignerType = { + _signTypedData: ( + domain: TypedDataDomain, + types: Record>, + value: Record + ) => Promise; + getChainId: () => Promise; + getAddress: () => Promise; + signMessage: (message: Bytes | string) => Promise; privateKey?: string; + provider?: providers.Provider; }; +type viemSignerType = { + signTypedData: (args: { + account: any; + domain: any; + types: any; + primaryType: any; + message: any; + }) => Promise<`0x${string}`>; + getChainId: () => Promise; + signMessage: (args: { + message: any; + account: any; + [key: string]: any; + }) => Promise<`0x${string}`>; + account: { [key: string]: any }; + privateKey?: string; + provider?: providers.Provider; +}; + +export type SignerType = ethersV5SignerType | viemSignerType; export type ParsedNotificationType = ParsedResponseType & { channel:string; diff --git a/yarn.lock b/yarn.lock index 3be1ac607..bc45eb097 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adraffy/ens-normalize@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.9.0.tgz#223572538f6bea336750039bb43a4016dcc8182d" + integrity sha512-iowxq3U30sghZotgl4s/oJRci6WPBfNO5YYgk2cIOMCHr3LeGPcsZjCEr+33Q4N+oV3OABDAtA+pyvWjbvBifQ== + "@ampproject/remapping@^2.1.0": version "2.2.0" resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" @@ -2319,6 +2324,23 @@ dependencies: events "3.3.0" +"@noble/curves@1.0.0", "@noble/curves@~1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.0.0.tgz#e40be8c7daf088aaf291887cbc73f43464a92932" + integrity sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw== + dependencies: + "@noble/hashes" "1.3.0" + +"@noble/hashes@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" + integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== + +"@noble/hashes@~1.3.0": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" + integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -3017,6 +3039,28 @@ estree-walker "^2.0.1" picomatch "^2.2.2" +"@scure/base@~1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" + integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== + +"@scure/bip32@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.0.tgz#6c8d980ef3f290987736acd0ee2e0f0d50068d87" + integrity sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q== + dependencies: + "@noble/curves" "~1.0.0" + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.0.tgz#a207e2ef96de354de7d0002292ba1503538fc77b" + integrity sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + "@segment/loosely-validate-event@^2.0.0": version "2.0.0" resolved "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz" @@ -3922,6 +3966,11 @@ "@urql/core" ">=2.3.1" wonka "^4.0.14" +"@wagmi/chains@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@wagmi/chains/-/chains-1.6.0.tgz#eb992ad28dbaaab729b5bcab3e5b461e8a035656" + integrity sha512-5FRlVxse5P4ZaHG3GTvxwVANSmYJas1eQrTBHhjxVtqXoorm0aLmCHbhmN8Xo1yu09PaWKlleEvfE98yH4AgIw== + "@web3-react/abstract-connector@^6.0.7": version "6.0.7" resolved "https://registry.npmjs.org/@web3-react/abstract-connector/-/abstract-connector-6.0.7.tgz" @@ -4117,6 +4166,11 @@ abab@^2.0.3, abab@^2.0.5: resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== +abitype@0.8.11: + version "0.8.11" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.8.11.tgz#66e1cf2cbf46f48d0e57132d7c1c392447536cc1" + integrity sha512-bM4v2dKvX08sZ9IU38IN5BKmN+ZkOSd2oI4a9f0ejHYZQYV6cDr7j+d95ga0z2XHG36Y4jzoG5Z7qDqxp7fi/A== + abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" @@ -9255,6 +9309,11 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +isomorphic-ws@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.0" resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz" @@ -15200,6 +15259,21 @@ video-stream-merger@^4.0.1: resolved "https://registry.yarnpkg.com/video-stream-merger/-/video-stream-merger-4.0.1.tgz#b0061251bd211121d1256ccf9e2be9477e59d5cb" integrity sha512-VazYSr8tk6S/zkOq5jpR/ryy1HnGxm5XCw+d2Ejpqy1m6d71oZpyFG82dUkgAo7dg/lk3k4TqvJPtuRUtR8URA== +viem@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/viem/-/viem-1.3.0.tgz#99c941e9bcfc62b53ffc5bd7470d7900a00d876c" + integrity sha512-gCtachbNPG9G9D7UNuiqLaLf8IFV15FypBrSpXEFeeEczXxI+Jgi9FTwDS+NJLreVrjBeZXQVj1ITTqKpItw4w== + dependencies: + "@adraffy/ens-normalize" "1.9.0" + "@noble/curves" "1.0.0" + "@noble/hashes" "1.3.0" + "@scure/bip32" "1.3.0" + "@scure/bip39" "1.2.0" + "@wagmi/chains" "1.6.0" + abitype "0.8.11" + isomorphic-ws "5.0.0" + ws "8.12.0" + vlq@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz" @@ -15558,6 +15632,11 @@ ws@7.4.6: resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8" + integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig== + ws@^6.1.4: version "6.2.2" resolved "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz"