diff --git a/packages/restapi/src/lib/channels/subscribeV2.ts b/packages/restapi/src/lib/channels/subscribeV2.ts index c38fdc456..b460fc4cc 100644 --- a/packages/restapi/src/lib/channels/subscribeV2.ts +++ b/packages/restapi/src/lib/channels/subscribeV2.ts @@ -7,6 +7,8 @@ import { import Constants, { ENV } from '../constants'; import { SignerType } from '../types'; import { axiosPost } from '../utils/axiosUtil'; +import { sign } from '../chat/helpers'; +import * as CryptoJS from 'crypto-js'; export type SubscribeOptionsV2Type = { signer: SignerType; @@ -18,6 +20,7 @@ export type SubscribeOptionsV2Type = { origin?: string; onSuccess?: () => void; onError?: (err: Error) => void; + pgpPrivateKey?: string; }; export const subscribeV2 = async (options: SubscribeOptionsV2Type) => { @@ -31,6 +34,7 @@ export const subscribeV2 = async (options: SubscribeOptionsV2Type) => { origin, onSuccess, onError, + pgpPrivateKey, } = options || {}; try { const _channelAddress = await getCAIPAddress( @@ -47,6 +51,7 @@ export const subscribeV2 = async (options: SubscribeOptionsV2Type) => { const _userAddress = await getCAIPAddress(env, userAddress, 'User'); const userCAIPDetails = getCAIPDetails(_userAddress); + if (!userCAIPDetails) throw Error('Invalid User CAIP!'); const { API_BASE_URL, EPNS_COMMUNICATOR_CONTRACT } = getConfig( @@ -55,39 +60,60 @@ export const subscribeV2 = async (options: SubscribeOptionsV2Type) => { ); const requestUrl = `${API_BASE_URL}/v1/channels/${_channelAddress}/subscribe`; - // get domain information - const domainInformation = getDomainInformation( - chainId, - verifyingContractAddress || EPNS_COMMUNICATOR_CONTRACT - ); - // get type information - const typeInformation = getTypeInformationV2(); - - // get message - const messageInformation = { - data: getSubscriptionMessageV2( + let verificationProof: string; + let messageInformation: { data: any } = { data: {} }; + if (pgpPrivateKey) { + const data = getSubscriptionMessageV2( channelCAIPDetails.address, - userCAIPDetails.address, + _userAddress, 'Subscribe', settings - ), - }; - // sign a message using EIP712 - const pushSigner = new Signer(signer); - const signature = await pushSigner.signTypedData( - domainInformation, - typeInformation, - messageInformation, - 'Data' - ); - - const verificationProof = signature; // might change + ); + messageInformation = { + data: data, + }; + const hash = CryptoJS.SHA256( + JSON.stringify(messageInformation) + ).toString(); + console.log(' hash ', hash); + const signature = await sign({ + message: hash, + signingKey: pgpPrivateKey!, + }); + verificationProof = `pgpv4:${signature}`; + } else { + const domainInformation = getDomainInformation( + chainId, + verifyingContractAddress || EPNS_COMMUNICATOR_CONTRACT + ); + + // get type information + const typeInformation = getTypeInformationV2(); + + messageInformation = { + data: getSubscriptionMessageV2( + channelCAIPDetails.address, + userCAIPDetails.address, + 'Subscribe', + settings + ), + }; + // Existing EIP712 flow + const pushSigner = new Signer(signer); + const signature = await pushSigner.signTypedData( + domainInformation, + typeInformation, + messageInformation, + 'Data' + ); + verificationProof = `eip712v2:${signature}`; + } const body = { - verificationProof: `eip712v2:${verificationProof}`, + verificationProof: verificationProof, message: messageInformation.data, - origin: origin + origin: origin, }; const res = await axiosPost(requestUrl, body); @@ -103,4 +129,4 @@ export const subscribeV2 = async (options: SubscribeOptionsV2Type) => { message: err instanceof Error ? err.message : JSON.stringify(err), }; } -}; +}; \ No newline at end of file diff --git a/packages/restapi/src/lib/channels/unsubscribeV2.ts b/packages/restapi/src/lib/channels/unsubscribeV2.ts index 545273ca2..2fc940e3c 100644 --- a/packages/restapi/src/lib/channels/unsubscribeV2.ts +++ b/packages/restapi/src/lib/channels/unsubscribeV2.ts @@ -7,6 +7,8 @@ import { import Constants, { ENV } from '../constants'; import { SignerType } from '../types'; import { axiosPost } from '../utils/axiosUtil'; +import { sign } from '../chat/helpers'; +import * as CryptoJS from 'crypto-js'; export type UnSubscribeOptionsV2Type = { signer: SignerType; @@ -16,6 +18,7 @@ export type UnSubscribeOptionsV2Type = { env?: ENV; onSuccess?: () => void; onError?: (err: Error) => void; + pgpPrivateKey?: string; }; export const unsubscribeV2 = async (options: UnSubscribeOptionsV2Type) => { @@ -27,6 +30,7 @@ export const unsubscribeV2 = async (options: UnSubscribeOptionsV2Type) => { env = Constants.ENV.PROD, onSuccess, onError, + pgpPrivateKey, } = options || {}; try { @@ -63,27 +67,49 @@ export const unsubscribeV2 = async (options: UnSubscribeOptionsV2Type) => { const typeInformation = getTypeInformationV2(); // get message - const messageInformation = { - data: getSubscriptionMessageV2( + let messageInformation: { data: any } = { data: {} }; + + let verificationProof: string; + if (pgpPrivateKey) { + // TODO: Entire payload: domainInformation typeInformation messageInformation + // TODO: Add chainid + const data = getSubscriptionMessageV2( channelCAIPDetails.address, - userCAIPDetails.address, + _userAddress, 'Unsubscribe' - ), - }; - - // sign a message using EIP712 - const pushSigner = new Signer(signer); - const signature = await pushSigner.signTypedData( - domainInformation, - typeInformation, - messageInformation, - 'Data' - ); - - const verificationProof = signature; // might change + ); + messageInformation = { + data: data, + }; + const hash = CryptoJS.SHA256( + JSON.stringify(messageInformation) + ).toString(); + const signature = await sign({ + message: hash, + signingKey: pgpPrivateKey, + }); + verificationProof = `pgpv4:${signature}`; + } else { + messageInformation = { + data: getSubscriptionMessageV2( + channelCAIPDetails.address, + userCAIPDetails.address, + 'Unsubscribe' + ), + }; + // Existing EIP712 flow + const pushSigner = new Signer(signer); + const signature = await pushSigner.signTypedData( + domainInformation, + typeInformation, + messageInformation, + 'Data' + ); + verificationProof = `eip712v2:${signature}`; + } const body = { - verificationProof: `eip712v2:${verificationProof}`, + verificationProof: verificationProof, message: messageInformation.data, }; diff --git a/packages/restapi/src/lib/payloads/helpers.ts b/packages/restapi/src/lib/payloads/helpers.ts index 6b58987bd..429adc7a2 100644 --- a/packages/restapi/src/lib/payloads/helpers.ts +++ b/packages/restapi/src/lib/payloads/helpers.ts @@ -251,22 +251,31 @@ export async function getVerificationProof({ switch (senderType) { case 0: { - const type = { - Data: [{ name: 'data', type: 'string' }], - }; - const domain = { - name: 'EPNS COMM V1', - chainId: chainId, - verifyingContract: verifyingContract, - }; - const pushSigner = new Signer(signer); - const signature = await pushSigner.signTypedData( - domain, - type, - message, - 'Data' - ); - verificationProof = `eip712v2:${signature}::uid::${uuid}`; + if (pgpPrivateKey) { + const hash = CryptoJS.SHA256(JSON.stringify(message)).toString(); + const signature = await sign({ + message: hash, + signingKey: pgpPrivateKey!, + }); + verificationProof = `pgpv4:${signature}`; + } else { + const type = { + Data: [{ name: 'data', type: 'string' }], + }; + const domain = { + name: 'EPNS COMM V1', + chainId: chainId, + verifyingContract: verifyingContract, + }; + const pushSigner = new Signer(signer); + const signature = await pushSigner.signTypedData( + domain, + type, + message, + 'Data' + ); + verificationProof = `eip712v2:${signature}::uid::${uuid}`; + } break; } case 1: { diff --git a/packages/restapi/src/lib/pushNotification/channel.ts b/packages/restapi/src/lib/pushNotification/channel.ts index 0b93273bf..428dc597e 100644 --- a/packages/restapi/src/lib/pushNotification/channel.ts +++ b/packages/restapi/src/lib/pushNotification/channel.ts @@ -38,8 +38,13 @@ export class Channel extends PushNotificationBaseClass { public alias!: Alias; public tags!: Tags; - constructor(signer?: SignerType, env?: ENV, account?: string) { - super(signer, env, account); + constructor( + signer?: SignerType, + env?: ENV, + account?: string, + pgpPrivateKey?: string + ) { + super(signer, env, account, pgpPrivateKey); this.delegate = new Delegate(signer, env, account); this.alias = new Alias(signer, env, account); this.tags = new Tags(this, signer, env, account); @@ -79,7 +84,7 @@ export class Channel extends PushNotificationBaseClass { limit = Constants.PAGINATION.LIMIT, filter, tag, - oldFormat = true + oldFormat = true, } = options || {}; return await PUSH_CHANNEL.search({ query: query, @@ -88,7 +93,7 @@ export class Channel extends PushNotificationBaseClass { filter: filter, tag: tag, env: this.env, - oldFormat + oldFormat, }); } catch (error) { throw new Error(`Push SDK Error: API : channel::search : ${error}`); @@ -145,6 +150,10 @@ export class Channel extends PushNotificationBaseClass { options.channel! ?? this.account ); + options.advanced = options.advanced || {}; + options.advanced.pgpPrivateKey = + options.advanced.pgpPrivateKey ?? this.pgpPrivateKey; + const lowLevelPayload = this.generateNotificationLowLevelPayload({ signer: this.signer!, env: this.env!, @@ -219,7 +228,7 @@ export class Channel extends PushNotificationBaseClass { url: url, icon: icon, aliasDetails: aliasInfo ?? {}, - tags + tags, }; const cid = await this.uploadToIPFSViaPushNode(JSON.stringify(input)); const allowanceAmount = await this.fetchAllownace( @@ -325,7 +334,7 @@ export class Channel extends PushNotificationBaseClass { url: url, icon: icon, aliasDetails: aliasInfo ?? {}, - tags + tags, }; const cid = await this.uploadToIPFSViaPushNode(JSON.stringify(input)); // approve the tokens to core contract @@ -489,7 +498,7 @@ export class Channel extends PushNotificationBaseClass { sort, order, filter, - tag + tag, }); } catch (error) { throw new Error(`Push SDK Error: Contract : channel::list : ${error}`); diff --git a/packages/restapi/src/lib/pushNotification/notification.ts b/packages/restapi/src/lib/pushNotification/notification.ts index 896ba3ee7..280b92511 100644 --- a/packages/restapi/src/lib/pushNotification/notification.ts +++ b/packages/restapi/src/lib/pushNotification/notification.ts @@ -27,8 +27,13 @@ export const FEED_MAP = { SPAM: true, }; export class Notification extends PushNotificationBaseClass { - constructor(signer?: SignerType, env?: ENV, account?: string) { - super(signer, env, account); + constructor( + signer?: SignerType, + env?: ENV, + account?: string, + pgpPrivateKey?: string + ) { + super(signer, env, account, pgpPrivateKey); } /** @@ -175,6 +180,7 @@ export class Notification extends PushNotificationBaseClass { settings: minimalSetting ?? '', onSuccess: onSuccess, onError: onError, + pgpPrivateKey: this.pgpPrivateKey, }); } catch (error) { throw new Error( @@ -225,6 +231,7 @@ export class Notification extends PushNotificationBaseClass { env: this.env, onSuccess: onSuccess, onError: onError, + pgpPrivateKey: this.pgpPrivateKey, }); } catch (error) { throw new Error( diff --git a/packages/restapi/src/lib/pushNotification/pushNotificationBase.ts b/packages/restapi/src/lib/pushNotification/pushNotificationBase.ts index 1e8f1bbde..2659a6e97 100644 --- a/packages/restapi/src/lib/pushNotification/pushNotificationBase.ts +++ b/packages/restapi/src/lib/pushNotification/pushNotificationBase.ts @@ -35,7 +35,6 @@ import { PushAPI } from '../pushapi/PushAPI'; import { channel } from 'diagnostics_channel'; import * as viem from 'viem'; - // ERROR CONSTANTS const ERROR_ACCOUNT_NEEDED = 'Account is required'; const ERROR_SIGNER_NEEDED = 'Signer object is required'; @@ -61,12 +60,19 @@ export class PushNotificationBaseClass { protected env: ENV | undefined; protected guestMode: boolean; protected coreContract: any; + protected pgpPrivateKey?: string; - constructor(signer?: SignerType, env?: ENV, account?: string) { + constructor( + signer?: SignerType, + env?: ENV, + account?: string, + pgpPrivateKey?: string + ) { this.signer = signer; this.env = env; this.guestMode = !!(account && signer); this.account = account; + this.pgpPrivateKey = pgpPrivateKey; this.initializeCoreContract({ signer: this.signer, env: this.env }); } diff --git a/packages/restapi/src/lib/pushapi/PushAPI.ts b/packages/restapi/src/lib/pushapi/PushAPI.ts index a071234f1..639d3acea 100644 --- a/packages/restapi/src/lib/pushapi/PushAPI.ts +++ b/packages/restapi/src/lib/pushapi/PushAPI.ts @@ -71,8 +71,18 @@ export class PushAPI { this.pgpPublicKey = pgpPublicKey; this.progressHook = progressHook; // Instantiate the notification classes - this.channel = new Channel(this.signer, this.env, this.account); - this.notification = new Notification(this.signer, this.env, this.account); + this.channel = new Channel( + this.signer, + this.env, + this.account, + this.decryptedPgpPvtKey + ); + this.notification = new Notification( + this.signer, + this.env, + this.account, + this.decryptedPgpPvtKey + ); this.uid = uuidv4(); this.cache = cache; @@ -341,6 +351,19 @@ export class PushAPI { this.signer, this.progressHook ); + + this.channel = new Channel( + this.signer, + this.env, + this.account, + this.decryptedPgpPvtKey + ); + this.notification = new Notification( + this.signer, + this.env, + this.account, + this.decryptedPgpPvtKey + ); } async initStream(