From bbf5cc6b0038bb52a1c5077b2cf9f11b9ed4bf1d Mon Sep 17 00:00:00 2001 From: Franck Royer Date: Thu, 23 Sep 2021 14:33:09 +1000 Subject: [PATCH] Wrap chat message in ApplicationMetadataMessage --- ...p256k1-npm-4.0.3-945d1c398e-1bd10b9afa.zip | Bin 0 -> 3719 bytes packages/status-communities/package.json | 4 +- .../v1/application_metadata_message.proto | 50 +++ .../src/application_metadata_message.ts | 61 +++ packages/status-communities/src/chat.ts | 6 +- packages/status-communities/src/identity.ts | 29 ++ .../status-communities/src/messenger.spec.ts | 50 ++- packages/status-communities/src/messenger.ts | 68 ++- .../status/v1/application_metadata_message.ts | 409 ++++++++++++++++++ yarn.lock | 11 + 10 files changed, 644 insertions(+), 44 deletions(-) create mode 100644 .yarn/cache/@types-secp256k1-npm-4.0.3-945d1c398e-1bd10b9afa.zip create mode 100644 packages/status-communities/proto/status/v1/application_metadata_message.proto create mode 100644 packages/status-communities/src/application_metadata_message.ts create mode 100644 packages/status-communities/src/identity.ts create mode 100644 packages/status-communities/src/proto/status/v1/application_metadata_message.ts diff --git a/.yarn/cache/@types-secp256k1-npm-4.0.3-945d1c398e-1bd10b9afa.zip b/.yarn/cache/@types-secp256k1-npm-4.0.3-945d1c398e-1bd10b9afa.zip new file mode 100644 index 0000000000000000000000000000000000000000..2507eab4b2869ccd176c04a5b8445c3fc8aac925 GIT binary patch literal 3719 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 AasU7T literal 0 HcmV?d00001 diff --git a/packages/status-communities/package.json b/packages/status-communities/package.json index 41a1fb10..cf5a4389 100644 --- a/packages/status-communities/package.json +++ b/packages/status-communities/package.json @@ -25,6 +25,7 @@ "devDependencies": { "@types/chai": "^4.2.22", "@types/mocha": "^9.0.0", + "@types/secp256k1": "^4.0.3", "@typescript-eslint/eslint-plugin": "^4.31.1", "@typescript-eslint/parser": "^4.31.1", "chai": "^4.3.4", @@ -45,6 +46,7 @@ "buffer": "^6.0.3", "js-sha3": "^0.8.0", "js-waku": "^0.12.0", - "protobufjs": "^6.11.2" + "protobufjs": "^6.11.2", + "secp256k1": "^4.0.2" } } diff --git a/packages/status-communities/proto/status/v1/application_metadata_message.proto b/packages/status-communities/proto/status/v1/application_metadata_message.proto new file mode 100644 index 00000000..53997cb0 --- /dev/null +++ b/packages/status-communities/proto/status/v1/application_metadata_message.proto @@ -0,0 +1,50 @@ +syntax = "proto3"; + +package status.v1; + +message ApplicationMetadataMessage { + // Signature of the payload field + bytes signature = 1; + // This is the encoded protobuf of the application level message, i.e ChatMessage + bytes payload = 2; + + // The type of protobuf message sent + Type type = 3; + + enum Type { + TYPE_UNKNOWN_UNSPECIFIED = 0; + TYPE_CHAT_MESSAGE = 1; + TYPE_CONTACT_UPDATE = 2; + TYPE_MEMBERSHIP_UPDATE_MESSAGE = 3; + TYPE_PAIR_INSTALLATION = 4; + TYPE_SYNC_INSTALLATION = 5; + TYPE_REQUEST_ADDRESS_FOR_TRANSACTION = 6; + TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION = 7; + TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION = 8; + TYPE_REQUEST_TRANSACTION = 9; + TYPE_SEND_TRANSACTION = 10; + TYPE_DECLINE_REQUEST_TRANSACTION = 11; + TYPE_SYNC_INSTALLATION_CONTACT = 12; + TYPE_SYNC_INSTALLATION_ACCOUNT = 13; + TYPE_SYNC_INSTALLATION_PUBLIC_CHAT = 14; + TYPE_CONTACT_CODE_ADVERTISEMENT = 15; + TYPE_PUSH_NOTIFICATION_REGISTRATION = 16; + TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE = 17; + TYPE_PUSH_NOTIFICATION_QUERY = 18; + TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE = 19; + TYPE_PUSH_NOTIFICATION_REQUEST = 20; + TYPE_PUSH_NOTIFICATION_RESPONSE = 21; + TYPE_EMOJI_REACTION = 22; + TYPE_GROUP_CHAT_INVITATION = 23; + TYPE_CHAT_IDENTITY = 24; + TYPE_COMMUNITY_DESCRIPTION = 25; + TYPE_COMMUNITY_INVITATION = 26; + TYPE_COMMUNITY_REQUEST_TO_JOIN = 27; + TYPE_PIN_MESSAGE = 28; + TYPE_EDIT_MESSAGE = 29; + TYPE_STATUS_UPDATE = 30; + TYPE_DELETE_MESSAGE = 31; + TYPE_SYNC_INSTALLATION_COMMUNITY = 32; + TYPE_ANONYMOUS_METRIC_BATCH = 33; + } +} diff --git a/packages/status-communities/src/application_metadata_message.ts b/packages/status-communities/src/application_metadata_message.ts new file mode 100644 index 00000000..63d56587 --- /dev/null +++ b/packages/status-communities/src/application_metadata_message.ts @@ -0,0 +1,61 @@ +import { Reader } from "protobufjs"; + +import { ChatMessage } from "./chat_message"; +import { Identity } from "./identity"; +import * as proto from "./proto/status/v1/application_metadata_message"; +import { ApplicationMetadataMessage_Type } from "./proto/status/v1/application_metadata_message"; + +export class ApplicationMetadataMessage { + private constructor(public proto: proto.ApplicationMetadataMessage) {} + + /** + * Create a chat message to be sent to an Open (permission = no membership) community + */ + public static create( + payload: Uint8Array, + type: ApplicationMetadataMessage_Type, + identity: Identity + ): ApplicationMetadataMessage { + const signature = identity.sign(payload); + + const proto = { + signature, + payload, + type, + }; + + return new ApplicationMetadataMessage(proto); + } + + static decode(bytes: Uint8Array): ApplicationMetadataMessage { + const protoBuf = proto.ApplicationMetadataMessage.decode( + Reader.create(bytes) + ); + + return new ApplicationMetadataMessage(protoBuf); + } + + encode(): Uint8Array { + return proto.ApplicationMetadataMessage.encode(this.proto).finish(); + } + + public get signature(): Uint8Array | undefined { + return this.proto.signature; + } + + public get payload(): Uint8Array | undefined { + return this.proto.payload; + } + public get type(): ApplicationMetadataMessage_Type | undefined { + return this.proto.type; + } + + /** + * Returns a chat message if the type is [TYPE_CHAT_MESSAGE], undefined otherwise. + */ + public get chatMessage(): ChatMessage | undefined { + if (!this.payload) return; + + return ChatMessage.decode(this.payload); + } +} diff --git a/packages/status-communities/src/chat.ts b/packages/status-communities/src/chat.ts index 1e84d8a5..2de593a1 100644 --- a/packages/status-communities/src/chat.ts +++ b/packages/status-communities/src/chat.ts @@ -19,13 +19,13 @@ export class Chat { const message = ChatMessage.createMessage(clock, timestamp, text, this.id); - this._updateFromMessage(message); + this._updateClockFromMessage(message); return message; } public handleNewMessage(message: ChatMessage) { - this._updateFromMessage(message); + this._updateClockFromMessage(message); } private _nextClockAndTimestamp(): { clock: number; timestamp: number } { @@ -41,7 +41,7 @@ export class Chat { return { clock, timestamp }; } - private _updateFromMessage(message: ChatMessage): void { + private _updateClockFromMessage(message: ChatMessage): void { if (!this.lastMessage || this.lastMessage.clock <= message.clock) { this.lastMessage = message; } diff --git a/packages/status-communities/src/identity.ts b/packages/status-communities/src/identity.ts new file mode 100644 index 00000000..fd66568e --- /dev/null +++ b/packages/status-communities/src/identity.ts @@ -0,0 +1,29 @@ +import { Buffer } from "buffer"; + +import { keccak256 } from "js-sha3"; +import { generatePrivateKey } from "js-waku"; +import { utils } from "js-waku"; +import * as secp256k1 from "secp256k1"; + +export class Identity { + public constructor(private privateKey: Uint8Array) {} + + public static generate(): Identity { + const privateKey = generatePrivateKey(); + return new Identity(privateKey); + } + + /** + * Hashes the payload with SHA3-256 and signs the result using the internal private key. + */ + public sign(payload: Uint8Array): Uint8Array { + const hash = keccak256(payload); + + const { signature, recid } = secp256k1.ecdsaSign( + utils.hexToBuf(hash), + this.privateKey + ); + + return Buffer.concat([signature, Buffer.from([recid])]); + } +} diff --git a/packages/status-communities/src/messenger.spec.ts b/packages/status-communities/src/messenger.spec.ts index 486c120b..e6441f7f 100644 --- a/packages/status-communities/src/messenger.spec.ts +++ b/packages/status-communities/src/messenger.spec.ts @@ -1,38 +1,43 @@ import { expect } from "chai"; -import { ChatMessage } from "./chat_message"; +import { ApplicationMetadataMessage } from "./application_metadata_message"; +import { Identity } from "./identity"; import { Messenger } from "./messenger"; const testChatId = "test-chat-id"; describe("Messenger", () => { - let messenger1: Messenger; - let messenger2: Messenger; + let messengerAlice: Messenger; + let messengerBob: Messenger; beforeEach(async function () { this.timeout(10_000); - [messenger1, messenger2] = await Promise.all([ - Messenger.create(), - Messenger.create({ + const identityAlice = Identity.generate(); + const identityBob = Identity.generate(); + + [messengerAlice, messengerBob] = await Promise.all([ + Messenger.create(identityAlice), + Messenger.create(identityBob, { libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } }, }), ]); // Connect both messengers together for test purposes - messenger1.waku.addPeerToAddressBook( - messenger2.waku.libp2p.peerId, - messenger2.waku.libp2p.multiaddrs + messengerAlice.waku.addPeerToAddressBook( + messengerBob.waku.libp2p.peerId, + messengerBob.waku.libp2p.multiaddrs ); await Promise.all([ new Promise((resolve) => - messenger1.waku.libp2p.pubsub.once("pubsub:subscription-change", () => - resolve(null) + messengerAlice.waku.libp2p.pubsub.once( + "pubsub:subscription-change", + () => resolve(null) ) ), new Promise((resolve) => - messenger2.waku.libp2p.pubsub.once("pubsub:subscription-change", () => + messengerBob.waku.libp2p.pubsub.once("pubsub:subscription-change", () => resolve(null) ) ), @@ -42,29 +47,28 @@ describe("Messenger", () => { it("Sends & Receive message in public chat", async function () { this.timeout(10_000); - messenger1.joinChat(testChatId); - messenger2.joinChat(testChatId); + messengerAlice.joinChat(testChatId); + messengerBob.joinChat(testChatId); const text = "This is a message."; - const receivedMessagePromise: Promise = new Promise( - (resolve) => { - messenger2.addObserver((message) => { + const receivedMessagePromise: Promise = + new Promise((resolve) => { + messengerBob.addObserver((message) => { resolve(message); }, testChatId); - } - ); + }); - await messenger1.sendMessage(text, testChatId); + await messengerAlice.sendMessage(text, testChatId); const receivedMessage = await receivedMessagePromise; - expect(receivedMessage?.text).to.eq(text); + expect(receivedMessage.chatMessage?.text).to.eq(text); }); afterEach(async function () { this.timeout(5000); - await messenger1.stop(); - await messenger2.stop(); + await messengerAlice.stop(); + await messengerBob.stop(); }); }); diff --git a/packages/status-communities/src/messenger.ts b/packages/status-communities/src/messenger.ts index 8376f43e..0436a96d 100644 --- a/packages/status-communities/src/messenger.ts +++ b/packages/status-communities/src/messenger.ts @@ -1,26 +1,37 @@ +import debug from "debug"; import { Waku, WakuMessage } from "js-waku"; import { CreateOptions as WakuCreateOptions } from "js-waku/build/main/lib/waku"; +import { ApplicationMetadataMessage } from "./application_metadata_message"; import { Chat } from "./chat"; import { ChatMessage } from "./chat_message"; +import { Identity } from "./identity"; +import { ApplicationMetadataMessage_Type } from "./proto/status/v1/application_metadata_message"; + +const dbg = debug("communities:messenger"); export class Messenger { waku: Waku; chatsById: Map; observers: { - [chatId: string]: Set<(chatMessage: ChatMessage) => void>; + [chatId: string]: Set<(message: ApplicationMetadataMessage) => void>; }; + identity: Identity; - private constructor(waku: Waku) { + private constructor(identity: Identity, waku: Waku) { + this.identity = identity; this.waku = waku; this.chatsById = new Map(); this.observers = {}; } - public static async create(wakuOptions?: WakuCreateOptions) { + public static async create( + identity: Identity, + wakuOptions?: WakuCreateOptions + ) { const _wakuOptions = Object.assign({ bootstrap: true }, wakuOptions); const waku = await Waku.create(_wakuOptions); - return new Messenger(waku); + return new Messenger(identity, waku); } /** @@ -37,14 +48,14 @@ export class Messenger { (wakuMessage: WakuMessage) => { if (!wakuMessage.payload) return; - const chatMessage = ChatMessage.decode(wakuMessage.payload); + const message = ApplicationMetadataMessage.decode(wakuMessage.payload); - chat.handleNewMessage(chatMessage); - - if (this.observers[chatId]) { - this.observers[chatId].forEach((observer) => { - observer(chatMessage); - }); + switch (message.type) { + case ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE: + this._handleNewChatMessage(chat, message); + break; + default: + dbg("Received unsupported message type", message.type); } }, [chat.contentTopic] @@ -63,10 +74,17 @@ export class Messenger { const chat = this.chatsById.get(chatId); if (!chat) throw `Chat not joined: ${chatId}`; - const message = chat.createMessage(text); + const chatMessage = chat.createMessage(text); + const appMetadataMessage = ApplicationMetadataMessage.create( + chatMessage.encode(), + ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE, + this.identity + ); + + // TODO: Use version 1 with signature const wakuMessage = await WakuMessage.fromBytes( - message.encode(), + appMetadataMessage.encode(), chat.contentTopic ); @@ -74,12 +92,12 @@ export class Messenger { } /** - * Add an observer of new messages received on the chat. + * Add an observer of new messages received on the given chat id. * * @throws string If the chat has not been joined first using [joinChat]. */ public addObserver( - observer: (chatMessage: ChatMessage) => void, + observer: (message: ApplicationMetadataMessage) => void, chatId: string ) { // Not sure this is the best design here. Maybe `addObserver` and `joinChat` should be merged. @@ -94,13 +112,13 @@ export class Messenger { } /** - * Add an observer of new messages received on the chat. + * Delete an observer of new messages received on the given chat id. * * @throws string If the chat has not been joined first using [joinChat]. */ deleteObserver( - observer: (chatMessage: ChatMessage) => void, + observer: (message: ApplicationMetadataMessage) => void, chatId: string ): void { if (this.observers[chatId]) { @@ -114,4 +132,20 @@ export class Messenger { public async stop(): Promise { await this.waku.stop(); } + + private _handleNewChatMessage( + chat: Chat, + message: ApplicationMetadataMessage + ) { + if (!message.payload || !message.type || !message.signature) return; + + const chatMessage = ChatMessage.decode(message.payload); + chat.handleNewMessage(chatMessage); + + if (this.observers[chat.id]) { + this.observers[chat.id].forEach((observer) => { + observer(message); + }); + } + } } diff --git a/packages/status-communities/src/proto/status/v1/application_metadata_message.ts b/packages/status-communities/src/proto/status/v1/application_metadata_message.ts new file mode 100644 index 00000000..25a169f9 --- /dev/null +++ b/packages/status-communities/src/proto/status/v1/application_metadata_message.ts @@ -0,0 +1,409 @@ +/* eslint-disable */ +import Long from "long"; +import _m0 from "protobufjs/minimal"; + +export const protobufPackage = "status.v1"; + +export interface ApplicationMetadataMessage { + /** Signature of the payload field */ + signature: Uint8Array; + /** This is the encoded protobuf of the application level message, i.e ChatMessage */ + payload: Uint8Array; + /** The type of protobuf message sent */ + type: ApplicationMetadataMessage_Type; +} + +export enum ApplicationMetadataMessage_Type { + TYPE_UNKNOWN_UNSPECIFIED = 0, + TYPE_CHAT_MESSAGE = 1, + TYPE_CONTACT_UPDATE = 2, + TYPE_MEMBERSHIP_UPDATE_MESSAGE = 3, + TYPE_PAIR_INSTALLATION = 4, + TYPE_SYNC_INSTALLATION = 5, + TYPE_REQUEST_ADDRESS_FOR_TRANSACTION = 6, + TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION = 7, + TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION = 8, + TYPE_REQUEST_TRANSACTION = 9, + TYPE_SEND_TRANSACTION = 10, + TYPE_DECLINE_REQUEST_TRANSACTION = 11, + TYPE_SYNC_INSTALLATION_CONTACT = 12, + TYPE_SYNC_INSTALLATION_ACCOUNT = 13, + TYPE_SYNC_INSTALLATION_PUBLIC_CHAT = 14, + TYPE_CONTACT_CODE_ADVERTISEMENT = 15, + TYPE_PUSH_NOTIFICATION_REGISTRATION = 16, + TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE = 17, + TYPE_PUSH_NOTIFICATION_QUERY = 18, + TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE = 19, + TYPE_PUSH_NOTIFICATION_REQUEST = 20, + TYPE_PUSH_NOTIFICATION_RESPONSE = 21, + TYPE_EMOJI_REACTION = 22, + TYPE_GROUP_CHAT_INVITATION = 23, + TYPE_CHAT_IDENTITY = 24, + TYPE_COMMUNITY_DESCRIPTION = 25, + TYPE_COMMUNITY_INVITATION = 26, + TYPE_COMMUNITY_REQUEST_TO_JOIN = 27, + TYPE_PIN_MESSAGE = 28, + TYPE_EDIT_MESSAGE = 29, + TYPE_STATUS_UPDATE = 30, + TYPE_DELETE_MESSAGE = 31, + TYPE_SYNC_INSTALLATION_COMMUNITY = 32, + TYPE_ANONYMOUS_METRIC_BATCH = 33, + UNRECOGNIZED = -1, +} + +export function applicationMetadataMessage_TypeFromJSON( + object: any +): ApplicationMetadataMessage_Type { + switch (object) { + case 0: + case "TYPE_UNKNOWN_UNSPECIFIED": + return ApplicationMetadataMessage_Type.TYPE_UNKNOWN_UNSPECIFIED; + case 1: + case "TYPE_CHAT_MESSAGE": + return ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE; + case 2: + case "TYPE_CONTACT_UPDATE": + return ApplicationMetadataMessage_Type.TYPE_CONTACT_UPDATE; + case 3: + case "TYPE_MEMBERSHIP_UPDATE_MESSAGE": + return ApplicationMetadataMessage_Type.TYPE_MEMBERSHIP_UPDATE_MESSAGE; + case 4: + case "TYPE_PAIR_INSTALLATION": + return ApplicationMetadataMessage_Type.TYPE_PAIR_INSTALLATION; + case 5: + case "TYPE_SYNC_INSTALLATION": + return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION; + case 6: + case "TYPE_REQUEST_ADDRESS_FOR_TRANSACTION": + return ApplicationMetadataMessage_Type.TYPE_REQUEST_ADDRESS_FOR_TRANSACTION; + case 7: + case "TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION": + return ApplicationMetadataMessage_Type.TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION; + case 8: + case "TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION": + return ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION; + case 9: + case "TYPE_REQUEST_TRANSACTION": + return ApplicationMetadataMessage_Type.TYPE_REQUEST_TRANSACTION; + case 10: + case "TYPE_SEND_TRANSACTION": + return ApplicationMetadataMessage_Type.TYPE_SEND_TRANSACTION; + case 11: + case "TYPE_DECLINE_REQUEST_TRANSACTION": + return ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_TRANSACTION; + case 12: + case "TYPE_SYNC_INSTALLATION_CONTACT": + return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_CONTACT; + case 13: + case "TYPE_SYNC_INSTALLATION_ACCOUNT": + return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_ACCOUNT; + case 14: + case "TYPE_SYNC_INSTALLATION_PUBLIC_CHAT": + return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_PUBLIC_CHAT; + case 15: + case "TYPE_CONTACT_CODE_ADVERTISEMENT": + return ApplicationMetadataMessage_Type.TYPE_CONTACT_CODE_ADVERTISEMENT; + case 16: + case "TYPE_PUSH_NOTIFICATION_REGISTRATION": + return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION; + case 17: + case "TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE": + return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE; + case 18: + case "TYPE_PUSH_NOTIFICATION_QUERY": + return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY; + case 19: + case "TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE": + return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE; + case 20: + case "TYPE_PUSH_NOTIFICATION_REQUEST": + return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REQUEST; + case 21: + case "TYPE_PUSH_NOTIFICATION_RESPONSE": + return ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_RESPONSE; + case 22: + case "TYPE_EMOJI_REACTION": + return ApplicationMetadataMessage_Type.TYPE_EMOJI_REACTION; + case 23: + case "TYPE_GROUP_CHAT_INVITATION": + return ApplicationMetadataMessage_Type.TYPE_GROUP_CHAT_INVITATION; + case 24: + case "TYPE_CHAT_IDENTITY": + return ApplicationMetadataMessage_Type.TYPE_CHAT_IDENTITY; + case 25: + case "TYPE_COMMUNITY_DESCRIPTION": + return ApplicationMetadataMessage_Type.TYPE_COMMUNITY_DESCRIPTION; + case 26: + case "TYPE_COMMUNITY_INVITATION": + return ApplicationMetadataMessage_Type.TYPE_COMMUNITY_INVITATION; + case 27: + case "TYPE_COMMUNITY_REQUEST_TO_JOIN": + return ApplicationMetadataMessage_Type.TYPE_COMMUNITY_REQUEST_TO_JOIN; + case 28: + case "TYPE_PIN_MESSAGE": + return ApplicationMetadataMessage_Type.TYPE_PIN_MESSAGE; + case 29: + case "TYPE_EDIT_MESSAGE": + return ApplicationMetadataMessage_Type.TYPE_EDIT_MESSAGE; + case 30: + case "TYPE_STATUS_UPDATE": + return ApplicationMetadataMessage_Type.TYPE_STATUS_UPDATE; + case 31: + case "TYPE_DELETE_MESSAGE": + return ApplicationMetadataMessage_Type.TYPE_DELETE_MESSAGE; + case 32: + case "TYPE_SYNC_INSTALLATION_COMMUNITY": + return ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_COMMUNITY; + case 33: + case "TYPE_ANONYMOUS_METRIC_BATCH": + return ApplicationMetadataMessage_Type.TYPE_ANONYMOUS_METRIC_BATCH; + case -1: + case "UNRECOGNIZED": + default: + return ApplicationMetadataMessage_Type.UNRECOGNIZED; + } +} + +export function applicationMetadataMessage_TypeToJSON( + object: ApplicationMetadataMessage_Type +): string { + switch (object) { + case ApplicationMetadataMessage_Type.TYPE_UNKNOWN_UNSPECIFIED: + return "TYPE_UNKNOWN_UNSPECIFIED"; + case ApplicationMetadataMessage_Type.TYPE_CHAT_MESSAGE: + return "TYPE_CHAT_MESSAGE"; + case ApplicationMetadataMessage_Type.TYPE_CONTACT_UPDATE: + return "TYPE_CONTACT_UPDATE"; + case ApplicationMetadataMessage_Type.TYPE_MEMBERSHIP_UPDATE_MESSAGE: + return "TYPE_MEMBERSHIP_UPDATE_MESSAGE"; + case ApplicationMetadataMessage_Type.TYPE_PAIR_INSTALLATION: + return "TYPE_PAIR_INSTALLATION"; + case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION: + return "TYPE_SYNC_INSTALLATION"; + case ApplicationMetadataMessage_Type.TYPE_REQUEST_ADDRESS_FOR_TRANSACTION: + return "TYPE_REQUEST_ADDRESS_FOR_TRANSACTION"; + case ApplicationMetadataMessage_Type.TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION: + return "TYPE_ACCEPT_REQUEST_ADDRESS_FOR_TRANSACTION"; + case ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION: + return "TYPE_DECLINE_REQUEST_ADDRESS_FOR_TRANSACTION"; + case ApplicationMetadataMessage_Type.TYPE_REQUEST_TRANSACTION: + return "TYPE_REQUEST_TRANSACTION"; + case ApplicationMetadataMessage_Type.TYPE_SEND_TRANSACTION: + return "TYPE_SEND_TRANSACTION"; + case ApplicationMetadataMessage_Type.TYPE_DECLINE_REQUEST_TRANSACTION: + return "TYPE_DECLINE_REQUEST_TRANSACTION"; + case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_CONTACT: + return "TYPE_SYNC_INSTALLATION_CONTACT"; + case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_ACCOUNT: + return "TYPE_SYNC_INSTALLATION_ACCOUNT"; + case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_PUBLIC_CHAT: + return "TYPE_SYNC_INSTALLATION_PUBLIC_CHAT"; + case ApplicationMetadataMessage_Type.TYPE_CONTACT_CODE_ADVERTISEMENT: + return "TYPE_CONTACT_CODE_ADVERTISEMENT"; + case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION: + return "TYPE_PUSH_NOTIFICATION_REGISTRATION"; + case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE: + return "TYPE_PUSH_NOTIFICATION_REGISTRATION_RESPONSE"; + case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY: + return "TYPE_PUSH_NOTIFICATION_QUERY"; + case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE: + return "TYPE_PUSH_NOTIFICATION_QUERY_RESPONSE"; + case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_REQUEST: + return "TYPE_PUSH_NOTIFICATION_REQUEST"; + case ApplicationMetadataMessage_Type.TYPE_PUSH_NOTIFICATION_RESPONSE: + return "TYPE_PUSH_NOTIFICATION_RESPONSE"; + case ApplicationMetadataMessage_Type.TYPE_EMOJI_REACTION: + return "TYPE_EMOJI_REACTION"; + case ApplicationMetadataMessage_Type.TYPE_GROUP_CHAT_INVITATION: + return "TYPE_GROUP_CHAT_INVITATION"; + case ApplicationMetadataMessage_Type.TYPE_CHAT_IDENTITY: + return "TYPE_CHAT_IDENTITY"; + case ApplicationMetadataMessage_Type.TYPE_COMMUNITY_DESCRIPTION: + return "TYPE_COMMUNITY_DESCRIPTION"; + case ApplicationMetadataMessage_Type.TYPE_COMMUNITY_INVITATION: + return "TYPE_COMMUNITY_INVITATION"; + case ApplicationMetadataMessage_Type.TYPE_COMMUNITY_REQUEST_TO_JOIN: + return "TYPE_COMMUNITY_REQUEST_TO_JOIN"; + case ApplicationMetadataMessage_Type.TYPE_PIN_MESSAGE: + return "TYPE_PIN_MESSAGE"; + case ApplicationMetadataMessage_Type.TYPE_EDIT_MESSAGE: + return "TYPE_EDIT_MESSAGE"; + case ApplicationMetadataMessage_Type.TYPE_STATUS_UPDATE: + return "TYPE_STATUS_UPDATE"; + case ApplicationMetadataMessage_Type.TYPE_DELETE_MESSAGE: + return "TYPE_DELETE_MESSAGE"; + case ApplicationMetadataMessage_Type.TYPE_SYNC_INSTALLATION_COMMUNITY: + return "TYPE_SYNC_INSTALLATION_COMMUNITY"; + case ApplicationMetadataMessage_Type.TYPE_ANONYMOUS_METRIC_BATCH: + return "TYPE_ANONYMOUS_METRIC_BATCH"; + default: + return "UNKNOWN"; + } +} + +const baseApplicationMetadataMessage: object = { type: 0 }; + +export const ApplicationMetadataMessage = { + encode( + message: ApplicationMetadataMessage, + writer: _m0.Writer = _m0.Writer.create() + ): _m0.Writer { + if (message.signature.length !== 0) { + writer.uint32(10).bytes(message.signature); + } + if (message.payload.length !== 0) { + writer.uint32(18).bytes(message.payload); + } + if (message.type !== 0) { + writer.uint32(24).int32(message.type); + } + return writer; + }, + + decode( + input: _m0.Reader | Uint8Array, + length?: number + ): ApplicationMetadataMessage { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = { + ...baseApplicationMetadataMessage, + } as ApplicationMetadataMessage; + message.signature = new Uint8Array(); + message.payload = new Uint8Array(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.signature = reader.bytes(); + break; + case 2: + message.payload = reader.bytes(); + break; + case 3: + message.type = reader.int32() as any; + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): ApplicationMetadataMessage { + const message = { + ...baseApplicationMetadataMessage, + } as ApplicationMetadataMessage; + message.signature = new Uint8Array(); + message.payload = new Uint8Array(); + if (object.signature !== undefined && object.signature !== null) { + message.signature = bytesFromBase64(object.signature); + } + if (object.payload !== undefined && object.payload !== null) { + message.payload = bytesFromBase64(object.payload); + } + if (object.type !== undefined && object.type !== null) { + message.type = applicationMetadataMessage_TypeFromJSON(object.type); + } else { + message.type = 0; + } + return message; + }, + + toJSON(message: ApplicationMetadataMessage): unknown { + const obj: any = {}; + message.signature !== undefined && + (obj.signature = base64FromBytes( + message.signature !== undefined ? message.signature : new Uint8Array() + )); + message.payload !== undefined && + (obj.payload = base64FromBytes( + message.payload !== undefined ? message.payload : new Uint8Array() + )); + message.type !== undefined && + (obj.type = applicationMetadataMessage_TypeToJSON(message.type)); + return obj; + }, + + fromPartial( + object: DeepPartial + ): ApplicationMetadataMessage { + const message = { + ...baseApplicationMetadataMessage, + } as ApplicationMetadataMessage; + if (object.signature !== undefined && object.signature !== null) { + message.signature = object.signature; + } else { + message.signature = new Uint8Array(); + } + if (object.payload !== undefined && object.payload !== null) { + message.payload = object.payload; + } else { + message.payload = new Uint8Array(); + } + if (object.type !== undefined && object.type !== null) { + message.type = object.type; + } else { + message.type = 0; + } + return message; + }, +}; + +declare var self: any | undefined; +declare var window: any | undefined; +declare var global: any | undefined; +var globalThis: any = (() => { + if (typeof globalThis !== "undefined") return globalThis; + if (typeof self !== "undefined") return self; + if (typeof window !== "undefined") return window; + if (typeof global !== "undefined") return global; + throw "Unable to locate global object"; +})(); + +const atob: (b64: string) => string = + globalThis.atob || + ((b64) => globalThis.Buffer.from(b64, "base64").toString("binary")); +function bytesFromBase64(b64: string): Uint8Array { + const bin = atob(b64); + const arr = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; ++i) { + arr[i] = bin.charCodeAt(i); + } + return arr; +} + +const btoa: (bin: string) => string = + globalThis.btoa || + ((bin) => globalThis.Buffer.from(bin, "binary").toString("base64")); +function base64FromBytes(arr: Uint8Array): string { + const bin: string[] = []; + for (const byte of arr) { + bin.push(String.fromCharCode(byte)); + } + return btoa(bin.join("")); +} + +type Builtin = + | Date + | Function + | Uint8Array + | string + | number + | boolean + | undefined; +export type DeepPartial = T extends Builtin + ? T + : T extends Array + ? Array> + : T extends ReadonlyArray + ? ReadonlyArray> + : T extends {} + ? { [K in keyof T]?: DeepPartial } + : Partial; + +if (_m0.util.Long !== Long) { + _m0.util.Long = Long as any; + _m0.configure(); +} diff --git a/yarn.lock b/yarn.lock index 99fb038c..c5160f68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -604,6 +604,15 @@ __metadata: languageName: node linkType: hard +"@types/secp256k1@npm:^4.0.3": + version: 4.0.3 + resolution: "@types/secp256k1@npm:4.0.3" + dependencies: + "@types/node": "*" + checksum: 1bd10b9afa724084b655dc81b7b315def3d2d0e272014ef16009fa76e17537411c07c0695fdea412bc7b36d2a02687f5fea33522d55b8ef29eda42992f812913 + languageName: node + linkType: hard + "@types/yargs-parser@npm:*": version: 20.2.1 resolution: "@types/yargs-parser@npm:20.2.1" @@ -5621,6 +5630,7 @@ fsevents@~2.3.2: dependencies: "@types/chai": ^4.2.22 "@types/mocha": ^9.0.0 + "@types/secp256k1": ^4.0.3 "@typescript-eslint/eslint-plugin": ^4.31.1 "@typescript-eslint/parser": ^4.31.1 buffer: ^6.0.3 @@ -5637,6 +5647,7 @@ fsevents@~2.3.2: npm-run-all: ^4.1.5 prettier: ^2.4.0 protobufjs: ^6.11.2 + secp256k1: ^4.0.2 ts-node: ^10.2.1 ts-proto: ^1.83.0 typescript: ^4.4.3