Add metamask support (#173)
This commit is contained in:
parent
f8d24eb264
commit
8a0ac14413
|
@ -2,8 +2,10 @@ import React, { useEffect } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { ChatState, useChatState } from "../../contexts/chatStateProvider";
|
import { ChatState, useChatState } from "../../contexts/chatStateProvider";
|
||||||
|
import { useIdentity } from "../../contexts/identityProvider";
|
||||||
import { useMessengerContext } from "../../contexts/messengerProvider";
|
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||||
import { CreateIcon } from "../Icons/CreateIcon";
|
import { CreateIcon } from "../Icons/CreateIcon";
|
||||||
|
import { UserCreation } from "../UserCreation/UserCreation";
|
||||||
|
|
||||||
import { Channel } from "./Channel";
|
import { Channel } from "./Channel";
|
||||||
|
|
||||||
|
@ -55,24 +57,34 @@ export function Channels({ onCommunityClick }: ChannelsProps) {
|
||||||
}
|
}
|
||||||
}, [notifications, activeChannel]);
|
}, [notifications, activeChannel]);
|
||||||
const setChatState = useChatState()[1];
|
const setChatState = useChatState()[1];
|
||||||
|
const identity = useIdentity();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChannelList>
|
<ChannelList>
|
||||||
<GenerateChannels type={"channel"} onCommunityClick={onCommunityClick} />
|
<GenerateChannels type={"channel"} onCommunityClick={onCommunityClick} />
|
||||||
|
|
||||||
<Chats>
|
<Chats>
|
||||||
<ChatsBar>
|
{identity ? (
|
||||||
<Heading>Chat</Heading>
|
<>
|
||||||
<EditBtn onClick={() => setChatState(ChatState.ChatCreation)}>
|
<ChatsBar>
|
||||||
<CreateIcon />
|
<Heading>Chat</Heading>
|
||||||
</EditBtn>
|
<EditBtn onClick={() => setChatState(ChatState.ChatCreation)}>
|
||||||
</ChatsBar>
|
<CreateIcon />
|
||||||
<ChatsList>
|
</EditBtn>
|
||||||
<GenerateChannels
|
</ChatsBar>
|
||||||
type={"group"}
|
<ChatsList>
|
||||||
onCommunityClick={onCommunityClick}
|
<GenerateChannels
|
||||||
/>
|
type={"group"}
|
||||||
<GenerateChannels type={"dm"} onCommunityClick={onCommunityClick} />
|
onCommunityClick={onCommunityClick}
|
||||||
</ChatsList>
|
/>
|
||||||
|
<GenerateChannels
|
||||||
|
type={"dm"}
|
||||||
|
onCommunityClick={onCommunityClick}
|
||||||
|
/>
|
||||||
|
</ChatsList>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<UserCreation permission={true} />
|
||||||
|
)}
|
||||||
</Chats>
|
</Chats>
|
||||||
</ChannelList>
|
</ChannelList>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,7 +2,6 @@ import React, { useState } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
import { ChatState, useChatState } from "../contexts/chatStateProvider";
|
import { ChatState, useChatState } from "../contexts/chatStateProvider";
|
||||||
import { useIdentity } from "../contexts/identityProvider";
|
|
||||||
import { useNarrow } from "../contexts/narrowProvider";
|
import { useNarrow } from "../contexts/narrowProvider";
|
||||||
|
|
||||||
import { Channels } from "./Channels/Channels";
|
import { Channels } from "./Channels/Channels";
|
||||||
|
@ -20,7 +19,6 @@ import { UserCreationModal } from "./Modals/UserCreationModal";
|
||||||
import { WalletConnectModal } from "./Modals/WalletConnectModal";
|
import { WalletConnectModal } from "./Modals/WalletConnectModal";
|
||||||
import { WalletModal } from "./Modals/WalletModal";
|
import { WalletModal } from "./Modals/WalletModal";
|
||||||
import { ToastMessageList } from "./ToastMessages/ToastMessageList";
|
import { ToastMessageList } from "./ToastMessages/ToastMessageList";
|
||||||
import { UserCreation } from "./UserCreation/UserCreation";
|
|
||||||
|
|
||||||
function Modals() {
|
function Modals() {
|
||||||
return (
|
return (
|
||||||
|
@ -42,13 +40,12 @@ export function Chat() {
|
||||||
const [state] = useChatState();
|
const [state] = useChatState();
|
||||||
const [showMembers, setShowMembers] = useState(false);
|
const [showMembers, setShowMembers] = useState(false);
|
||||||
const narrow = useNarrow();
|
const narrow = useNarrow();
|
||||||
const identity = useIdentity();
|
|
||||||
return (
|
return (
|
||||||
<ChatWrapper>
|
<ChatWrapper>
|
||||||
{!narrow && (
|
{!narrow && (
|
||||||
<ChannelsWrapper>
|
<ChannelsWrapper>
|
||||||
<StyledCommunity />
|
<StyledCommunity />
|
||||||
{identity ? <Channels /> : <UserCreation permission={true} />}
|
<Channels />
|
||||||
</ChannelsWrapper>
|
</ChannelsWrapper>
|
||||||
)}
|
)}
|
||||||
{state === ChatState.ChatBody && (
|
{state === ChatState.ChatBody && (
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
useIdentity,
|
useIdentity,
|
||||||
useNickname,
|
useNickname,
|
||||||
useSetIdentity,
|
useSetIdentity,
|
||||||
|
useSetNikcname,
|
||||||
} from "../../contexts/identityProvider";
|
} from "../../contexts/identityProvider";
|
||||||
import { useModal } from "../../contexts/modalProvider";
|
import { useModal } from "../../contexts/modalProvider";
|
||||||
import { ButtonNo, ButtonYes } from "../Buttons/buttonStyle";
|
import { ButtonNo, ButtonYes } from "../Buttons/buttonStyle";
|
||||||
|
@ -26,6 +27,7 @@ export const LogoutModalName = "LogoutModal";
|
||||||
export const LogoutModal = () => {
|
export const LogoutModal = () => {
|
||||||
const { setModal } = useModal(LogoutModalName);
|
const { setModal } = useModal(LogoutModalName);
|
||||||
const logout = useSetIdentity();
|
const logout = useSetIdentity();
|
||||||
|
const setNickname = useSetNikcname();
|
||||||
const identity = useIdentity();
|
const identity = useIdentity();
|
||||||
const nickname = useNickname();
|
const nickname = useNickname();
|
||||||
|
|
||||||
|
@ -71,6 +73,7 @@ export const LogoutModal = () => {
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setModal(false);
|
setModal(false);
|
||||||
logout(undefined);
|
logout(undefined);
|
||||||
|
setNickname(undefined);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Disconnect
|
Disconnect
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
useIdentity,
|
useIdentity,
|
||||||
useSetIdentity,
|
useSetIdentity,
|
||||||
useSetNikcname,
|
useSetNikcname,
|
||||||
|
useWalletIdentity,
|
||||||
} from "../../contexts/identityProvider";
|
} from "../../contexts/identityProvider";
|
||||||
import { useModal } from "../../contexts/modalProvider";
|
import { useModal } from "../../contexts/modalProvider";
|
||||||
import { Contact } from "../../models/Contact";
|
import { Contact } from "../../models/Contact";
|
||||||
|
@ -36,6 +37,7 @@ import { EmojiKey, UserAddress } from "./ProfileModal";
|
||||||
export const UserCreationModalName = "UserCreationModal";
|
export const UserCreationModalName = "UserCreationModal";
|
||||||
|
|
||||||
export function UserCreationModal() {
|
export function UserCreationModal() {
|
||||||
|
const walletIdentity = useWalletIdentity();
|
||||||
const identity = useIdentity();
|
const identity = useIdentity();
|
||||||
const setIdentity = useSetIdentity();
|
const setIdentity = useSetIdentity();
|
||||||
const setNickname = useSetNikcname();
|
const setNickname = useSetNikcname();
|
||||||
|
@ -93,7 +95,7 @@ export function UserCreationModal() {
|
||||||
onChange={(e) => setCustomNameInput(e.currentTarget.value)}
|
onChange={(e) => setCustomNameInput(e.currentTarget.value)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!nextStep && encryptedIdentity && (
|
{!nextStep && encryptedIdentity && !walletIdentity && (
|
||||||
<button
|
<button
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const identity = await decryptIdentity(
|
const identity = await decryptIdentity(
|
||||||
|
@ -141,10 +143,10 @@ export function UserCreationModal() {
|
||||||
if (nextStep) {
|
if (nextStep) {
|
||||||
setModal(false);
|
setModal(false);
|
||||||
} else {
|
} else {
|
||||||
const identity = Identity.generate();
|
const identity = walletIdentity || Identity.generate();
|
||||||
setIdentity(identity);
|
|
||||||
saveIdentity(identity, "noPassword");
|
|
||||||
setNickname(customNameInput);
|
setNickname(customNameInput);
|
||||||
|
setIdentity(identity);
|
||||||
|
!walletIdentity && saveIdentity(identity, "noPassword");
|
||||||
setNextStep(true);
|
setNextStep(true);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
import React from "react";
|
import React, { useCallback } from "react";
|
||||||
|
import { Identity } from "status-communities/dist/cjs";
|
||||||
|
import { genPrivateKeyWithEntropy } from "status-communities/dist/cjs/utils";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
import {
|
||||||
|
useSetIdentity,
|
||||||
|
useSetWalletIdentity,
|
||||||
|
} from "../../contexts/identityProvider";
|
||||||
|
import { useMessengerContext } from "../../contexts/messengerProvider";
|
||||||
import { useModal } from "../../contexts/modalProvider";
|
import { useModal } from "../../contexts/modalProvider";
|
||||||
import { CoinbaseLogo } from "../Icons/CoinbaseLogo";
|
import { CoinbaseLogo } from "../Icons/CoinbaseLogo";
|
||||||
import { MetamaskLogo } from "../Icons/MetamaskLogo";
|
import { MetamaskLogo } from "../Icons/MetamaskLogo";
|
||||||
|
@ -9,14 +16,87 @@ import { WalletConnectLogo } from "../Icons/WalletConnectLogo";
|
||||||
import { CoinbaseModalName } from "./CoinbaseModal";
|
import { CoinbaseModalName } from "./CoinbaseModal";
|
||||||
import { Modal } from "./Modal";
|
import { Modal } from "./Modal";
|
||||||
import { Heading, MiddleSection, Section, Text } from "./ModalStyle";
|
import { Heading, MiddleSection, Section, Text } from "./ModalStyle";
|
||||||
|
import { UserCreationModalName } from "./UserCreationModal";
|
||||||
import { WalletConnectModalName } from "./WalletConnectModal";
|
import { WalletConnectModalName } from "./WalletConnectModal";
|
||||||
|
|
||||||
export const WalletModalName = "WalletModal";
|
export const WalletModalName = "WalletModal";
|
||||||
|
|
||||||
export function WalletModal() {
|
export function WalletModal() {
|
||||||
const { setModal } = useModal(WalletModalName);
|
const { setModal } = useModal(WalletModalName);
|
||||||
|
const setIdentity = useSetIdentity();
|
||||||
|
const setWalletIdentity = useSetWalletIdentity();
|
||||||
|
const userCreationModal = useModal(UserCreationModalName);
|
||||||
const { setModal: setWalleConnectModal } = useModal(WalletConnectModalName);
|
const { setModal: setWalleConnectModal } = useModal(WalletConnectModalName);
|
||||||
const { setModal: setCoinbaseModal } = useModal(CoinbaseModalName);
|
const { setModal: setCoinbaseModal } = useModal(CoinbaseModalName);
|
||||||
|
const { messenger } = useMessengerContext();
|
||||||
|
|
||||||
|
const handleMetamaskClick = useCallback(async () => {
|
||||||
|
const ethereum = (window as any)?.ethereum as any | undefined;
|
||||||
|
if (ethereum && messenger) {
|
||||||
|
try {
|
||||||
|
if (ethereum?.isMetaMask) {
|
||||||
|
const [account] = await ethereum.request({
|
||||||
|
method: "eth_requestAccounts",
|
||||||
|
});
|
||||||
|
|
||||||
|
const msgParams = JSON.stringify({
|
||||||
|
domain: {
|
||||||
|
chainId: 1,
|
||||||
|
name: window.location.origin,
|
||||||
|
version: "1",
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
action: "Status Chat Key",
|
||||||
|
onlySignOn: "https://auth.status.im/",
|
||||||
|
message:
|
||||||
|
"I'm aware that i am signing message that creates a private chat key for status communicator. And I have double checked everything is fine.",
|
||||||
|
},
|
||||||
|
primaryType: "Mail",
|
||||||
|
types: {
|
||||||
|
EIP712Domain: [
|
||||||
|
{ name: "name", type: "string" },
|
||||||
|
{ name: "version", type: "string" },
|
||||||
|
{ name: "chainId", type: "uint256" },
|
||||||
|
],
|
||||||
|
Mail: [
|
||||||
|
{ name: "action", type: "string" },
|
||||||
|
{ name: "onlySignOn", type: "string" },
|
||||||
|
{ name: "message", type: "string" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const params = [account, msgParams];
|
||||||
|
const method = "eth_signTypedData_v4";
|
||||||
|
|
||||||
|
const signature = await ethereum.request({
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
from: account,
|
||||||
|
});
|
||||||
|
const privateKey = genPrivateKeyWithEntropy(signature);
|
||||||
|
|
||||||
|
const loadedIdentity = new Identity(privateKey);
|
||||||
|
|
||||||
|
const userInNetwork = await messenger.checkIfUserInWakuNetwork(
|
||||||
|
loadedIdentity.publicKey
|
||||||
|
);
|
||||||
|
|
||||||
|
if (userInNetwork) {
|
||||||
|
setIdentity(loadedIdentity);
|
||||||
|
} else {
|
||||||
|
setWalletIdentity(loadedIdentity);
|
||||||
|
userCreationModal.setModal(true);
|
||||||
|
}
|
||||||
|
setModal(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
alert("Error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alert("Metamask not found");
|
||||||
|
}, [messenger]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal name={WalletModalName}>
|
<Modal name={WalletModalName}>
|
||||||
|
@ -34,7 +114,7 @@ export function WalletModal() {
|
||||||
<Heading>Coinbase Wallet</Heading>
|
<Heading>Coinbase Wallet</Heading>
|
||||||
<CoinbaseLogo />
|
<CoinbaseLogo />
|
||||||
</Wallet>
|
</Wallet>
|
||||||
<Wallet>
|
<Wallet onClick={handleMetamaskClick}>
|
||||||
<Heading>MetaMask</Heading>
|
<Heading>MetaMask</Heading>
|
||||||
<MetamaskLogo />
|
<MetamaskLogo />
|
||||||
</Wallet>
|
</Wallet>
|
||||||
|
|
|
@ -4,11 +4,15 @@ import { Identity } from "status-communities/dist/cjs";
|
||||||
const IdentityContext = createContext<{
|
const IdentityContext = createContext<{
|
||||||
identity: Identity | undefined;
|
identity: Identity | undefined;
|
||||||
setIdentity: React.Dispatch<React.SetStateAction<Identity | undefined>>;
|
setIdentity: React.Dispatch<React.SetStateAction<Identity | undefined>>;
|
||||||
|
walletIdentity: Identity | undefined;
|
||||||
|
setWalletIdentity: React.Dispatch<React.SetStateAction<Identity | undefined>>;
|
||||||
nickname: string | undefined;
|
nickname: string | undefined;
|
||||||
setNickname: React.Dispatch<React.SetStateAction<string | undefined>>;
|
setNickname: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||||
}>({
|
}>({
|
||||||
identity: undefined,
|
identity: undefined,
|
||||||
setIdentity: () => undefined,
|
setIdentity: () => undefined,
|
||||||
|
walletIdentity: undefined,
|
||||||
|
setWalletIdentity: () => undefined,
|
||||||
nickname: undefined,
|
nickname: undefined,
|
||||||
setNickname: () => undefined,
|
setNickname: () => undefined,
|
||||||
});
|
});
|
||||||
|
@ -21,6 +25,14 @@ export function useSetIdentity() {
|
||||||
return useContext(IdentityContext).setIdentity;
|
return useContext(IdentityContext).setIdentity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useWalletIdentity() {
|
||||||
|
return useContext(IdentityContext).walletIdentity;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useSetWalletIdentity() {
|
||||||
|
return useContext(IdentityContext).setWalletIdentity;
|
||||||
|
}
|
||||||
|
|
||||||
export function useNickname() {
|
export function useNickname() {
|
||||||
return useContext(IdentityContext).nickname;
|
return useContext(IdentityContext).nickname;
|
||||||
}
|
}
|
||||||
|
@ -35,11 +47,21 @@ interface IdentityProviderProps {
|
||||||
|
|
||||||
export function IdentityProvider({ children }: IdentityProviderProps) {
|
export function IdentityProvider({ children }: IdentityProviderProps) {
|
||||||
const [identity, setIdentity] = useState<Identity | undefined>(undefined);
|
const [identity, setIdentity] = useState<Identity | undefined>(undefined);
|
||||||
|
const [walletIdentity, setWalletIdentity] = useState<Identity | undefined>(
|
||||||
|
undefined
|
||||||
|
);
|
||||||
const [nickname, setNickname] = useState<string | undefined>(undefined);
|
const [nickname, setNickname] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IdentityContext.Provider
|
<IdentityContext.Provider
|
||||||
value={{ identity, setIdentity, nickname, setNickname }}
|
value={{
|
||||||
|
identity,
|
||||||
|
setIdentity,
|
||||||
|
nickname,
|
||||||
|
setNickname,
|
||||||
|
walletIdentity,
|
||||||
|
setWalletIdentity,
|
||||||
|
}}
|
||||||
children={children}
|
children={children}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { PageDirection, Waku, WakuMessage } from "js-waku";
|
||||||
import { idToContactCodeTopic } from "./contentTopic";
|
import { idToContactCodeTopic } from "./contentTopic";
|
||||||
import { Identity } from "./identity";
|
import { Identity } from "./identity";
|
||||||
import { StatusUpdate_StatusType } from "./proto/communities/v1/status_update";
|
import { StatusUpdate_StatusType } from "./proto/communities/v1/status_update";
|
||||||
import { bufToHex } from "./utils";
|
import { bufToHex, getLatestUserNickname } from "./utils";
|
||||||
import { ChatIdentity } from "./wire/chat_identity";
|
import { ChatIdentity } from "./wire/chat_identity";
|
||||||
import { StatusUpdate } from "./wire/status_update";
|
import { StatusUpdate } from "./wire/status_update";
|
||||||
|
|
||||||
|
@ -115,30 +115,11 @@ export class Contacts {
|
||||||
|
|
||||||
const handleNickname = async (): Promise<void> => {
|
const handleNickname = async (): Promise<void> => {
|
||||||
if (this.identity) {
|
if (this.identity) {
|
||||||
const publicKey = bufToHex(this.identity.publicKey);
|
|
||||||
const now = new Date().getTime();
|
const now = new Date().getTime();
|
||||||
let newNickname = "";
|
const { clock, nickname: newNickname } = await getLatestUserNickname(
|
||||||
let clock = 0;
|
this.identity.publicKey,
|
||||||
await this.waku.store.queryHistory([idToContactCodeTopic(publicKey)], {
|
this.waku
|
||||||
callback: (msgs) =>
|
);
|
||||||
msgs.some((e) => {
|
|
||||||
try {
|
|
||||||
if (e.payload) {
|
|
||||||
const chatIdentity = ChatIdentity.decode(e?.payload);
|
|
||||||
if (chatIdentity) {
|
|
||||||
if (chatIdentity?.displayName) {
|
|
||||||
clock = chatIdentity?.clock ?? 0;
|
|
||||||
newNickname = chatIdentity?.displayName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
pageDirection: PageDirection.BACKWARD,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.nickname) {
|
if (this.nickname) {
|
||||||
if (this.nickname !== newNickname) {
|
if (this.nickname !== newNickname) {
|
||||||
|
@ -150,7 +131,7 @@ export class Contacts {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.nickname = newNickname;
|
this.nickname = newNickname;
|
||||||
this.callbackNickname(publicKey, newNickname);
|
this.callbackNickname(bufToHex(this.identity.publicKey), newNickname);
|
||||||
if (clock < now - NICKNAME_BROADCAST_INTERVAL) {
|
if (clock < now - NICKNAME_BROADCAST_INTERVAL) {
|
||||||
await sendNickname();
|
await sendNickname();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,10 @@ import * as secp256k1 from "secp256k1";
|
||||||
import { hexToBuf } from "./utils";
|
import { hexToBuf } from "./utils";
|
||||||
|
|
||||||
export class Identity {
|
export class Identity {
|
||||||
public constructor(public privateKey: Uint8Array) {}
|
private pubKey: Uint8Array;
|
||||||
|
public constructor(public privateKey: Uint8Array) {
|
||||||
|
this.pubKey = secp256k1.publicKeyCreate(this.privateKey, true);
|
||||||
|
}
|
||||||
|
|
||||||
public static generate(): Identity {
|
public static generate(): Identity {
|
||||||
const privateKey = generatePrivateKey();
|
const privateKey = generatePrivateKey();
|
||||||
|
@ -31,6 +34,6 @@ export class Identity {
|
||||||
* Returns the compressed public key.
|
* Returns the compressed public key.
|
||||||
*/
|
*/
|
||||||
public get publicKey(): Uint8Array {
|
public get publicKey(): Uint8Array {
|
||||||
return secp256k1.publicKeyCreate(this.privateKey, true);
|
return this.pubKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { CreateOptions as WakuCreateOptions } from "js-waku/build/main/lib/waku"
|
||||||
import { Chat } from "./chat";
|
import { Chat } from "./chat";
|
||||||
import { Identity } from "./identity";
|
import { Identity } from "./identity";
|
||||||
import { ApplicationMetadataMessage_Type } from "./proto/status/v1/application_metadata_message";
|
import { ApplicationMetadataMessage_Type } from "./proto/status/v1/application_metadata_message";
|
||||||
|
import { getLatestUserNickname } from "./utils";
|
||||||
import { ApplicationMetadataMessage } from "./wire/application_metadata_message";
|
import { ApplicationMetadataMessage } from "./wire/application_metadata_message";
|
||||||
import { ChatMessage, Content } from "./wire/chat_message";
|
import { ChatMessage, Content } from "./wire/chat_message";
|
||||||
|
|
||||||
|
@ -249,4 +250,12 @@ export class Messenger {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async checkIfUserInWakuNetwork(publicKey: Uint8Array): Promise<boolean> {
|
||||||
|
const { clock, nickname } = await getLatestUserNickname(
|
||||||
|
publicKey,
|
||||||
|
this.waku
|
||||||
|
);
|
||||||
|
return clock > 0 && nickname !== "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import { ec } from "elliptic";
|
import { ec } from "elliptic";
|
||||||
import { utils } from "js-waku";
|
import { PageDirection, utils, Waku } from "js-waku";
|
||||||
|
|
||||||
|
import { idToContactCodeTopic } from "./contentTopic";
|
||||||
|
import { ChatIdentity } from "./proto/communities/v1/chat_identity";
|
||||||
|
|
||||||
const EC = new ec("secp256k1");
|
const EC = new ec("secp256k1");
|
||||||
|
|
||||||
|
@ -17,3 +20,38 @@ export function compressPublicKey(key: Uint8Array): string {
|
||||||
const PubKey = EC.keyFromPublic(key);
|
const PubKey = EC.keyFromPublic(key);
|
||||||
return "0x" + PubKey.getPublic(true, "hex");
|
return "0x" + PubKey.getPublic(true, "hex");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function genPrivateKeyWithEntropy(key: string): Uint8Array {
|
||||||
|
const pair = EC.genKeyPair({ entropy: key });
|
||||||
|
return hexToBuf("0x" + pair.getPrivate("hex"));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getLatestUserNickname(
|
||||||
|
key: Uint8Array,
|
||||||
|
waku: Waku
|
||||||
|
): Promise<{ clock: number; nickname: string }> {
|
||||||
|
const publicKey = bufToHex(key);
|
||||||
|
let nickname = "";
|
||||||
|
let clock = 0;
|
||||||
|
await waku.store.queryHistory([idToContactCodeTopic(publicKey)], {
|
||||||
|
callback: (msgs) =>
|
||||||
|
msgs.some((e) => {
|
||||||
|
try {
|
||||||
|
if (e.payload) {
|
||||||
|
const chatIdentity = ChatIdentity.decode(e?.payload);
|
||||||
|
if (chatIdentity) {
|
||||||
|
if (chatIdentity?.displayName) {
|
||||||
|
clock = chatIdentity?.clock ?? 0;
|
||||||
|
nickname = chatIdentity?.displayName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
pageDirection: PageDirection.BACKWARD,
|
||||||
|
});
|
||||||
|
return { clock, nickname };
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue