diff --git a/api/geth_backend.go b/api/geth_backend.go index b8ba74366..d1ca17152 100644 --- a/api/geth_backend.go +++ b/api/geth_backend.go @@ -876,6 +876,11 @@ func (b *GethStatusBackend) loadNodeConfig(inputNodeCfg *params.NodeConfig) erro } if inputNodeCfg != nil { + // If an installationID is provided, we override it + if conf != nil && conf.ShhextConfig.InstallationID != "" { + inputNodeCfg.ShhextConfig.InstallationID = conf.ShhextConfig.InstallationID + } + conf, err = b.OverwriteNodeConfigValues(conf, inputNodeCfg) if err != nil { return err diff --git a/api/multiformat/utils.go b/api/multiformat/utils.go index d33d2f79b..e607db950 100644 --- a/api/multiformat/utils.go +++ b/api/multiformat/utils.go @@ -78,6 +78,20 @@ func SerializeLegacyKey(key string) (string, error) { return SerializePublicKey(keyWithPrefix, "z") } +// DeserializeCompressedKey converts a base58 compressed key to +// a secp251k1 uncompressed key +func DeserializeCompressedKey(key string) (string, error) { + if len(key) == 0 { + return "", errors.New("invalid key length") + } + deserialisedKey, err := DeserializePublicKey(key, "f") + if err != nil { + return "", err + } + + return "0x" + deserialisedKey[5:], nil +} + // getPublicKeyType wrapper for the `varint.FromUvarint()` func func getPublicKeyType(key []byte) (uint64, int, error) { return varint.FromUvarint(key) diff --git a/cmd/populate-db/main.go b/cmd/populate-db/main.go index c973c3655..2c69459d5 100644 --- a/cmd/populate-db/main.go +++ b/cmd/populate-db/main.go @@ -165,7 +165,7 @@ func main() { } keyString := common.PubkeyToHex(&key.PublicKey) - _, err = wakuext.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(keyString)}) + _, err = wakuext.AddContact(context.Background(), &requests.AddContact{ID: keyString}) if err != nil { logger.Error("failed Add contact", "err", err) return @@ -185,7 +185,7 @@ func main() { return } - _, err = wakuext.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contact.ID)}) + _, err = wakuext.AddContact(context.Background(), &requests.AddContact{ID: contact.ID}) if err != nil { return } diff --git a/cmd/spiff-workflow/.gitignore b/cmd/spiff-workflow/.gitignore new file mode 100644 index 000000000..9760d04db --- /dev/null +++ b/cmd/spiff-workflow/.gitignore @@ -0,0 +1,3 @@ +spiff-workflow +run.sh +tmp/ diff --git a/cmd/spiff-workflow/README.md b/cmd/spiff-workflow/README.md new file mode 100644 index 000000000..5cef76cac --- /dev/null +++ b/cmd/spiff-workflow/README.md @@ -0,0 +1,86 @@ +### How to build + +You must have go installed. +Then you can run, from `cmd/spiff-workflow` + +``` +go build --mod=vendor +``` + +which should create a `spiff-workflow` executable + +### How to run +``` +./spiff-workflow --seed-phrase "your seed phrase" +``` + + +The parameters are: + +`seed-phrase`: the seed phrase of the account to be created + +The db will be created in the `./tmp` directory, and it will erase any previous data +The server will be listening on `localhost:8545` and it will respond to RPC calls. + + +### Sending a message + +First add the user as a contact (if you have a message): + +``` + curl -XPOST http://localhost:8545 -H 'Content-type: application/json' -d '{"jsonrpc":"2.0","method":"wakuext_sendContactRequest","params":[{"id": "0x04d3c86dfc77b195b705e1831935066076018aa0d7c40044829801ebbfe9b06480ce4662072bf16a3ca7cb8f6289207614deceaf7d33e099dfc9281610375fec08", "message": "hello"}],"id":1}' +``` + +If you don't want to send a message: + +``` + curl -XPOST http://localhost:8545 -H 'Content-type: application/json' -d '{"jsonrpc":"2.0","method":"wakuext_addContact","params":[{"id": "0x04d3c86dfc77b195b705e1831935066076018aa0d7c40044829801ebbfe9b06480ce4662072bf16a3ca7cb8f6289207614deceaf7d33e099dfc9281610375fec08"}],"id":1}' +``` + + +Accept the contact request in the receiving device (you should see a notification in the activity center) + + +``` +curl -XPOST http://localhost:8545 -H 'Content-type: application/json' -d '{"jsonrpc":"2.0","method":"wakuext_sendOneToOneMessage","params":[{"id": "0x04e431a0baaac2602052f259d4304371d0e0d86cb024497899cf3e82211ff17a9723d8ca67b6575a700086b2aa6ab0df4dab1f8e94114912f269fc6b1ee6764a58", "message": "hello"}],"id":1}' +``` + +Just replace `id` with the public key you want to use, and `message` with the text you want to send. + + +### Creating a private group chat + +To create a private group chat, you need interactions on both devices. + +First add the user as a contact: + +``` + curl -XPOST http://localhost:8545 -H 'Content-type: application/json' -d '{"jsonrpc":"2.0","method":"wakuext_sendContactRequest","params":[{"id": "0x04d3c86dfc77b195b705e1831935066076018aa0d7c40044829801ebbfe9b06480ce4662072bf16a3ca7cb8f6289207614deceaf7d33e099dfc9281610375fec08", "message": "hello"}],"id":1}' +``` + +Accept the contact request in the receiving device (you should see a notification in the activity center) + +Then create a group chat with the member(s): + +``` +curl -XPOST http://localhost:8545 -H 'Content-type: application/json' -d '{"jsonrpc":"2.0","method":"wakuext_createGroupChatWithMembers","params":[null, "group-chat-name", ["0x04d3c86dfc77b195b705e1831935066076018aa0d7c40044829801ebbfe9b06480ce4662072bf16a3ca7cb8f6289207614deceaf7d33e099dfc9281610375fec08"]],"id":1}' +``` + +You will need to note the ID returned by the response, for example, in the response: + +``` +{"jsonrpc":"2.0","id":1,"result":{"chats":[{"id":"8291eae1-338c-4481-9997-04edd2d2bbed-0x0490cbce029eaf094c7f2dcf1feb2d60e91ab1498847eb29fa98cc5ea5a36666b3f9ada142f3080f5074abd942c863438f6af9475f30781790c7e36f9acd2ac93e","name":"group-chat-name", +``` +The ID is: + +``` +"8291eae1-338c-4481-9997-04edd2d2bbed-0x0490cbce029eaf094c7f2dcf1feb2d60e91ab1498847eb29fa98cc5ea5a36666b3f9ada142f3080f5074abd942c863438f6af9475f30781790c7e36f9acd2ac93e" +``` + +You can then send messages to this group chat similarly as you send messages for 1-to-1 chats, using the id of the newly created chat: + +``` +curl -XPOST http://localhost:8545 -H 'Content-type: application/json' -d '{"jsonrpc":"2.0","method":"wakuext_sendGroupChatMessage","params":[{"id": "8291eae1-338c-4481-9997-04edd2d2bbed-0x0490cbce029eaf094c7f2dcf1feb2d60e91ab1498847eb29fa98cc5ea5a36666b3f9ada142f3080f5074abd942c863438f6af9475f30781790c7e36f9acd2ac93e", "message": "hello"}],"id":1}' +``` + +Mind that if you restart the node, you will need to create a new group chat, since we are currently not keeping storage on restart. diff --git a/cmd/spiff-workflow/flags.go b/cmd/spiff-workflow/flags.go new file mode 100644 index 000000000..be519d51c --- /dev/null +++ b/cmd/spiff-workflow/flags.go @@ -0,0 +1,37 @@ +package main + +import ( + "fmt" + "os" + "path" + "strings" +) + +// configFlags represents an array of JSON configuration files passed to a command line utility +type configFlags []string + +func (f *configFlags) String() string { + return strings.Join(*f, ", ") +} + +func (f *configFlags) Set(value string) error { + if !path.IsAbs(value) { + // Convert to absolute path + cwd, err := os.Getwd() + if err != nil { + return err + } + value = path.Join(cwd, value) + } + + // Check that the file exists + stat, err := os.Stat(value) + if err != nil { + return err + } + if stat.IsDir() { + return fmt.Errorf("path does not represent a file: %s", value) + } + *f = append(*f, value) + return nil +} diff --git a/cmd/spiff-workflow/main.go b/cmd/spiff-workflow/main.go new file mode 100644 index 000000000..2fe262252 --- /dev/null +++ b/cmd/spiff-workflow/main.go @@ -0,0 +1,407 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + stdlog "log" + "os" + "path/filepath" + "runtime" + "strings" + "time" + + "github.com/google/uuid" + "golang.org/x/crypto/ssh/terminal" + + "github.com/ethereum/go-ethereum/log" + + "github.com/status-im/status-go/account/generator" + "github.com/status-im/status-go/api" + "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/logutils" + "github.com/status-im/status-go/multiaccounts" + "github.com/status-im/status-go/multiaccounts/accounts" + "github.com/status-im/status-go/multiaccounts/settings" + "github.com/status-im/status-go/params" + "github.com/status-im/status-go/protocol" + "github.com/status-im/status-go/protocol/identity/alias" + waku2extn "github.com/status-im/status-go/services/wakuv2ext" + "github.com/status-im/status-go/sqlite" +) + +const ( + serverClientName = "Statusd" +) + +var ( + configFiles configFlags + logLevel = flag.String("log", "INFO", `Log level, one of: "ERROR", "WARN", "INFO", "DEBUG", and "TRACE"`) + logWithoutColors = flag.Bool("log-without-color", false, "Disables log colors") + seedPhrase = flag.String("seed-phrase", "", "Seed phrase") + version = flag.Bool("version", false, "Print version and dump configuration") + + dataDir = flag.String("dir", getDefaultDataDir(), "Directory used by node to store data") + networkID = flag.Int( + "network-id", + params.GoerliNetworkID, + fmt.Sprintf( + "A network ID: %d (Mainnet), %d (Goerli)", + params.MainNetworkID, params.GoerliNetworkID, + ), + ) + listenAddr = flag.String("addr", "", "address to bind listener to") +) + +// All general log messages in this package should be routed through this logger. +var logger = log.New("package", "status-go/cmd/statusd") + +func init() { + flag.Var(&configFiles, "c", "JSON configuration file(s). Multiple configuration files can be specified, and will be merged in occurrence order") +} + +// nolint:gocyclo +func main() { + colors := terminal.IsTerminal(int(os.Stdin.Fd())) + if err := logutils.OverrideRootLog(true, "ERROR", logutils.FileOptions{}, colors); err != nil { + stdlog.Fatalf("Error initializing logger: %v", err) + } + + flag.Usage = printUsage + flag.Parse() + if flag.NArg() > 0 { + printUsage() + logger.Error("Extra args in command line: %v", flag.Args()) + os.Exit(1) + } + + opts := []params.Option{} + + config, err := params.NewNodeConfigWithDefaultsAndFiles( + *dataDir, + uint64(*networkID), + opts, + configFiles, + ) + if err != nil { + printUsage() + logger.Error(err.Error()) + os.Exit(1) + } + + // Use listenAddr if and only if explicitly provided in the arguments. + // The default value is set in params.NewNodeConfigWithDefaultsAndFiles(). + if *listenAddr != "" { + config.ListenAddr = *listenAddr + } + + if *logLevel != "" { + config.LogLevel = *logLevel + } + + // set up logging options + setupLogging(config) + + // We want statusd to be distinct from StatusIM client. + config.Name = serverClientName + + if *version { + printVersion(config) + return + } + + backend := api.NewGethStatusBackend() + err = ImportAccount(*seedPhrase, backend) + if err != nil { + logger.Error("failed import account", "err", err) + return + } + + wakuextservice := backend.StatusNode().WakuV2ExtService() + if wakuextservice == nil { + logger.Error("wakuext not available") + return + } + + wakuext := waku2extn.NewPublicAPI(wakuextservice) + + // This will start the push notification server as well as + // the config is set to Enabled + _, err = wakuext.StartMessenger() + if err != nil { + logger.Error("failed to start messenger", "error", err) + return + } + + retrieveMessagesLoop(wakuext.Messenger(), 300*time.Millisecond) + +} + +func getDefaultDataDir() string { + if home := os.Getenv("HOME"); home != "" { + return filepath.Join(home, ".statusd") + } + return "./statusd-data" +} + +func setupLogging(config *params.NodeConfig) { + logSettings := logutils.LogSettings{ + Enabled: config.LogEnabled, + MobileSystem: config.LogMobileSystem, + Level: config.LogLevel, + File: config.LogFile, + MaxSize: config.LogMaxSize, + MaxBackups: config.LogMaxBackups, + CompressRotated: config.LogCompressRotated, + } + colors := !(*logWithoutColors) && terminal.IsTerminal(int(os.Stdin.Fd())) + if err := logutils.OverrideRootLogWithConfig(logSettings, colors); err != nil { + stdlog.Fatalf("Error initializing logger: %v", err) + } +} + +// printVersion prints verbose output about version and config. +func printVersion(config *params.NodeConfig) { + fmt.Println(strings.Title(config.Name)) + fmt.Println("Version:", config.Version) + fmt.Println("Network ID:", config.NetworkID) + fmt.Println("Go Version:", runtime.Version()) + fmt.Println("OS:", runtime.GOOS) + fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH")) + fmt.Printf("GOROOT=%s\n", runtime.GOROOT()) + + fmt.Println("Loaded Config: ", config) +} + +func printUsage() { + usage := ` +Usage: statusd [options] +Examples: + statusd # run regular Whisper node that joins Status network + statusd -c ./default.json # run node with configuration specified in ./default.json file + statusd -c ./default.json -c ./standalone.json # run node with configuration specified in ./default.json file, after merging ./standalone.json file + statusd -c ./default.json -metrics # run node with configuration specified in ./default.json file, and expose ethereum metrics with debug_metrics jsonrpc call + +Options: +` + fmt.Fprint(os.Stderr, usage) + flag.PrintDefaults() +} + +const pathWalletRoot = "m/44'/60'/0'/0" +const pathEIP1581 = "m/43'/60'/1581'" +const pathDefaultChat = pathEIP1581 + "/0'/0" +const pathDefaultWallet = pathWalletRoot + "/0" + +var paths = []string{pathWalletRoot, pathEIP1581, pathDefaultChat, pathDefaultWallet} + +func defaultSettings(generatedAccountInfo generator.GeneratedAccountInfo, derivedAddresses map[string]generator.AccountInfo, mnemonic *string) (*settings.Settings, error) { + chatKeyString := derivedAddresses[pathDefaultChat].PublicKey + + settings := &settings.Settings{} + settings.KeyUID = generatedAccountInfo.KeyUID + settings.Address = types.HexToAddress(generatedAccountInfo.Address) + settings.WalletRootAddress = types.HexToAddress(derivedAddresses[pathWalletRoot].Address) + + // Set chat key & name + name, err := alias.GenerateFromPublicKeyString(chatKeyString) + if err != nil { + return nil, err + } + settings.Name = name + settings.PublicKey = chatKeyString + + settings.DappsAddress = types.HexToAddress(derivedAddresses[pathDefaultWallet].Address) + settings.EIP1581Address = types.HexToAddress(derivedAddresses[pathEIP1581].Address) + settings.Mnemonic = mnemonic + + signingPhrase, err := buildSigningPhrase() + if err != nil { + return nil, err + } + settings.SigningPhrase = signingPhrase + + settings.SendPushNotifications = true + settings.InstallationID = uuid.New().String() + settings.UseMailservers = true + + settings.PreviewPrivacy = true + settings.Currency = "usd" + settings.ProfilePicturesVisibility = 1 + settings.LinkPreviewRequestEnabled = true + + visibleTokens := make(map[string][]string) + visibleTokens["mainnet"] = []string{"SNT"} + visibleTokensJSON, err := json.Marshal(visibleTokens) + if err != nil { + return nil, err + } + visibleTokenJSONRaw := json.RawMessage(visibleTokensJSON) + settings.WalletVisibleTokens = &visibleTokenJSONRaw + + // TODO: fix this + networks := make([]map[string]string, 0) + networksJSON, err := json.Marshal(networks) + if err != nil { + return nil, err + } + networkRawMessage := json.RawMessage(networksJSON) + settings.Networks = &networkRawMessage + settings.CurrentNetwork = "mainnet_rpc" + + return settings, nil +} + +func defaultNodeConfig(installationID string) (*params.NodeConfig, error) { + // Set mainnet + nodeConfig := ¶ms.NodeConfig{} + nodeConfig.NetworkID = 1 + nodeConfig.LogLevel = "DEBUG" + nodeConfig.DataDir = "/ethereum/mainnet_rpc" + nodeConfig.HTTPEnabled = true + nodeConfig.HTTPPort = 8545 + // FIXME: This should be taken from CLI flags. + nodeConfig.HTTPHost = "0.0.0.0" + // FIXME: This should be taken from CLI flags. + nodeConfig.HTTPVirtualHosts = []string{"localhost", "wakunode"} + nodeConfig.APIModules = "wakuext,ext,waku" + + nodeConfig.UpstreamConfig = params.UpstreamRPCConfig{ + Enabled: true, + URL: "https://mainnet.infura.io/v3/800c641949d64d768a5070a1b0511938", + } + + nodeConfig.Name = "StatusIM" + nodeConfig.Rendezvous = false + clusterConfig, err := params.LoadClusterConfigFromFleet("eth.prod") + if err != nil { + return nil, err + } + nodeConfig.ClusterConfig = *clusterConfig + + nodeConfig.WalletConfig = params.WalletConfig{Enabled: true} + nodeConfig.LocalNotificationsConfig = params.LocalNotificationsConfig{Enabled: true} + nodeConfig.BrowsersConfig = params.BrowsersConfig{Enabled: true} + nodeConfig.PermissionsConfig = params.PermissionsConfig{Enabled: true} + nodeConfig.MailserversConfig = params.MailserversConfig{Enabled: true} + nodes := []string{"enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@prod.nodes.status.im"} + nodeConfig.ClusterConfig.WakuNodes = nodes + nodeConfig.ClusterConfig.DiscV5BootstrapNodes = nodes + + nodeConfig.EnableNTPSync = true + nodeConfig.WakuV2Config = params.WakuV2Config{ + Enabled: true, + EnableDiscV5: true, + DiscoveryLimit: 20, + UDPPort: 9002, + } + + nodeConfig.ShhextConfig = params.ShhextConfig{ + BackupDisabledDataDir: "", + InstallationID: installationID, + MaxMessageDeliveryAttempts: 6, + MailServerConfirmations: true, + VerifyTransactionURL: "", + VerifyENSURL: "", + VerifyENSContractAddress: "", + VerifyTransactionChainID: 1, + DataSyncEnabled: true, + PFSEnabled: true, + } + + // TODO: check topics + + return nodeConfig, nil +} + +func ImportAccount(seedPhrase string, backend *api.GethStatusBackend) error { + backend.UpdateRootDataDir("./tmp") + manager := backend.AccountManager() + if err := manager.InitKeystore("./tmp"); err != nil { + return err + } + err := backend.OpenAccounts() + if err != nil { + logger.Error("failed open accounts", err) + return err + } + generator := manager.AccountsGenerator() + generatedAccountInfo, err := generator.ImportMnemonic(seedPhrase, "") + if err != nil { + logger.Error("failed import mnemonic", err) + return err + } + + derivedAddresses, err := generator.DeriveAddresses(generatedAccountInfo.ID, paths) + if err != nil { + logger.Error("failed derive", err) + return err + } + + var exist bool + _, err = generator.StoreDerivedAccounts(generatedAccountInfo.ID, "", paths) + if err != nil && err.Error() == "account already exists" { + exist = true + } else if err != nil { + logger.Error("failed store derive", err) + return err + } + + account := multiaccounts.Account{ + KeyUID: generatedAccountInfo.KeyUID, + KDFIterations: sqlite.ReducedKDFIterationsNumber, + } + settings, err := defaultSettings(generatedAccountInfo, derivedAddresses, &seedPhrase) + if err != nil { + return err + } + + nodeConfig, err := defaultNodeConfig(settings.InstallationID) + if err != nil { + return err + } + + walletDerivedAccount := derivedAddresses[pathDefaultWallet] + walletAccount := &accounts.Account{ + PublicKey: types.Hex2Bytes(walletDerivedAccount.PublicKey), + KeyUID: generatedAccountInfo.KeyUID, + Address: types.HexToAddress(walletDerivedAccount.Address), + Color: "", + Wallet: true, + Path: pathDefaultWallet, + Name: "Ethereum account", + } + + chatDerivedAccount := derivedAddresses[pathDefaultChat] + chatAccount := &accounts.Account{ + PublicKey: types.Hex2Bytes(chatDerivedAccount.PublicKey), + KeyUID: generatedAccountInfo.KeyUID, + Address: types.HexToAddress(chatDerivedAccount.Address), + Name: settings.Name, + Chat: true, + Path: pathDefaultChat, + } + + fmt.Println(nodeConfig) + accounts := []*accounts.Account{walletAccount, chatAccount} + if !exist { + return backend.StartNodeWithAccountAndInitialConfig(account, "", *settings, nodeConfig, accounts) + } + return backend.StartNodeWithAccount(account, "", nodeConfig) +} + +func retrieveMessagesLoop(messenger *protocol.Messenger, tick time.Duration) { + ticker := time.NewTicker(tick) + defer ticker.Stop() + + for { //nolint: gosimple + select { + case <-ticker.C: + _, err := messenger.RetrieveAll() + if err != nil { + logger.Error("failed to retrieve raw messages", "err", err) + continue + } + } + } +} diff --git a/cmd/spiff-workflow/signing_phrase.go b/cmd/spiff-workflow/signing_phrase.go new file mode 100644 index 000000000..42f45c745 --- /dev/null +++ b/cmd/spiff-workflow/signing_phrase.go @@ -0,0 +1,650 @@ +package main + +import ( + "crypto/rand" + "math/big" +) + +func buildSigningPhrase() (string, error) { + length := big.NewInt(int64(len(dictionary))) + a, err := rand.Int(rand.Reader, length) + if err != nil { + return "", err + } + b, err := rand.Int(rand.Reader, length) + if err != nil { + return "", err + } + c, err := rand.Int(rand.Reader, length) + if err != nil { + return "", err + } + + return dictionary[a.Int64()] + " " + dictionary[b.Int64()] + " " + dictionary[c.Int64()], nil + +} + +var dictionary = []string{ + "acid", + "alto", + "apse", + "arch", + "area", + "army", + "atom", + "aunt", + "babe", + "baby", + "back", + "bail", + "bait", + "bake", + "ball", + "band", + "bank", + "barn", + "base", + "bass", + "bath", + "bead", + "beak", + "beam", + "bean", + "bear", + "beat", + "beef", + "beer", + "beet", + "bell", + "belt", + "bend", + "bike", + "bill", + "bird", + "bite", + "blow", + "blue", + "boar", + "boat", + "body", + "bolt", + "bomb", + "bone", + "book", + "boot", + "bore", + "boss", + "bowl", + "brow", + "bulb", + "bull", + "burn", + "bush", + "bust", + "cafe", + "cake", + "calf", + "call", + "calm", + "camp", + "cane", + "cape", + "card", + "care", + "carp", + "cart", + "case", + "cash", + "cast", + "cave", + "cell", + "cent", + "chap", + "chef", + "chin", + "chip", + "chop", + "chub", + "chug", + "city", + "clam", + "clef", + "clip", + "club", + "clue", + "coal", + "coat", + "code", + "coil", + "coin", + "coke", + "cold", + "colt", + "comb", + "cone", + "cook", + "cope", + "copy", + "cord", + "cork", + "corn", + "cost", + "crab", + "craw", + "crew", + "crib", + "crop", + "crow", + "curl", + "cyst", + "dame", + "dare", + "dark", + "dart", + "dash", + "data", + "date", + "dead", + "deal", + "dear", + "debt", + "deck", + "deep", + "deer", + "desk", + "dhow", + "diet", + "dill", + "dime", + "dirt", + "dish", + "disk", + "dock", + "doll", + "door", + "dory", + "drag", + "draw", + "drop", + "drug", + "drum", + "duck", + "dump", + "dust", + "duty", + "ease", + "east", + "eave", + "eddy", + "edge", + "envy", + "epee", + "exam", + "exit", + "face", + "fact", + "fail", + "fall", + "fame", + "fang", + "farm", + "fawn", + "fear", + "feed", + "feel", + "feet", + "file", + "fill", + "film", + "find", + "fine", + "fire", + "fish", + "flag", + "flat", + "flax", + "flow", + "foam", + "fold", + "font", + "food", + "foot", + "fork", + "form", + "fort", + "fowl", + "frog", + "fuel", + "full", + "gain", + "gale", + "galn", + "game", + "garb", + "gate", + "gear", + "gene", + "gift", + "girl", + "give", + "glad", + "glen", + "glue", + "glut", + "goal", + "goat", + "gold", + "golf", + "gong", + "good", + "gown", + "grab", + "gram", + "gray", + "grey", + "grip", + "grit", + "gyro", + "hail", + "hair", + "half", + "hall", + "hand", + "hang", + "harm", + "harp", + "hate", + "hawk", + "head", + "heat", + "heel", + "hell", + "helo", + "help", + "hemp", + "herb", + "hide", + "high", + "hill", + "hire", + "hive", + "hold", + "hole", + "home", + "hood", + "hoof", + "hook", + "hope", + "hops", + "horn", + "hose", + "host", + "hour", + "hunt", + "hurt", + "icon", + "idea", + "inch", + "iris", + "iron", + "item", + "jail", + "jeep", + "jeff", + "joey", + "join", + "joke", + "judo", + "jump", + "junk", + "jury", + "jute", + "kale", + "keep", + "kick", + "kill", + "kilt", + "kind", + "king", + "kiss", + "kite", + "knee", + "knot", + "lace", + "lack", + "lady", + "lake", + "lamb", + "lamp", + "land", + "lark", + "lava", + "lawn", + "lead", + "leaf", + "leek", + "lier", + "life", + "lift", + "lily", + "limo", + "line", + "link", + "lion", + "lisa", + "list", + "load", + "loaf", + "loan", + "lock", + "loft", + "long", + "look", + "loss", + "lout", + "love", + "luck", + "lung", + "lute", + "lynx", + "lyre", + "maid", + "mail", + "main", + "make", + "male", + "mall", + "manx", + "many", + "mare", + "mark", + "mask", + "mass", + "mate", + "math", + "meal", + "meat", + "meet", + "menu", + "mess", + "mice", + "midi", + "mile", + "milk", + "mime", + "mind", + "mine", + "mini", + "mint", + "miss", + "mist", + "moat", + "mode", + "mole", + "mood", + "moon", + "most", + "moth", + "move", + "mule", + "mutt", + "nail", + "name", + "neat", + "neck", + "need", + "neon", + "nest", + "news", + "node", + "nose", + "note", + "oboe", + "okra", + "open", + "oval", + "oven", + "oxen", + "pace", + "pack", + "page", + "pail", + "pain", + "pair", + "palm", + "pard", + "park", + "part", + "pass", + "past", + "path", + "peak", + "pear", + "peen", + "peer", + "pelt", + "perp", + "pest", + "pick", + "pier", + "pike", + "pile", + "pimp", + "pine", + "ping", + "pink", + "pint", + "pipe", + "piss", + "pith", + "plan", + "play", + "plot", + "plow", + "poem", + "poet", + "pole", + "polo", + "pond", + "pony", + "poof", + "pool", + "port", + "post", + "prow", + "pull", + "puma", + "pump", + "pupa", + "push", + "quit", + "race", + "rack", + "raft", + "rage", + "rail", + "rain", + "rake", + "rank", + "rate", + "read", + "rear", + "reef", + "rent", + "rest", + "rice", + "rich", + "ride", + "ring", + "rise", + "risk", + "road", + "robe", + "rock", + "role", + "roll", + "roof", + "room", + "root", + "rope", + "rose", + "ruin", + "rule", + "rush", + "ruth", + "sack", + "safe", + "sage", + "sail", + "sale", + "salt", + "sand", + "sari", + "sash", + "save", + "scow", + "seal", + "seat", + "seed", + "self", + "sell", + "shed", + "shin", + "ship", + "shoe", + "shop", + "shot", + "show", + "sick", + "side", + "sign", + "silk", + "sill", + "silo", + "sing", + "sink", + "site", + "size", + "skin", + "sled", + "slip", + "smog", + "snob", + "snow", + "soap", + "sock", + "soda", + "sofa", + "soft", + "soil", + "song", + "soot", + "sort", + "soup", + "spot", + "spur", + "stag", + "star", + "stay", + "stem", + "step", + "stew", + "stop", + "stud", + "suck", + "suit", + "swan", + "swim", + "tail", + "tale", + "talk", + "tank", + "tard", + "task", + "taxi", + "team", + "tear", + "teen", + "tell", + "temp", + "tent", + "term", + "test", + "text", + "thaw", + "tile", + "till", + "time", + "tire", + "toad", + "toga", + "togs", + "tone", + "tool", + "toot", + "tote", + "tour", + "town", + "tram", + "tray", + "tree", + "trim", + "trip", + "tuba", + "tube", + "tuna", + "tune", + "turn", + "tutu", + "twig", + "type", + "unit", + "user", + "vane", + "vase", + "vast", + "veal", + "veil", + "vein", + "vest", + "vibe", + "view", + "vise", + "wait", + "wake", + "walk", + "wall", + "wash", + "wasp", + "wave", + "wear", + "weed", + "week", + "well", + "west", + "whip", + "wife", + "will", + "wind", + "wine", + "wing", + "wire", + "wish", + "wolf", + "wood", + "wool", + "word", + "work", + "worm", + "wrap", + "wren", + "yard", + "yarn", + "yawl", + "year", + "yoga", + "yoke", + "yurt", + "zinc", + "zone", +} diff --git a/protocol/communities_messenger_test.go b/protocol/communities_messenger_test.go index cb3bb742f..4a2a20ab5 100644 --- a/protocol/communities_messenger_test.go +++ b/protocol/communities_messenger_test.go @@ -1828,7 +1828,7 @@ func (s *MessengerCommunitiesSuite) TestShareCommunity() { // Add bob to contacts so it does not go on activity center bobPk := common.PubkeyToHex(&s.alice.identity.PublicKey) - request := &requests.AddContact{ID: types.Hex2Bytes(bobPk)} + request := &requests.AddContact{ID: bobPk} _, err = s.alice.AddContact(context.Background(), request) s.Require().NoError(err) diff --git a/protocol/messenger_activity_center_test.go b/protocol/messenger_activity_center_test.go index 00ec3bdeb..4f21b6320 100644 --- a/protocol/messenger_activity_center_test.go +++ b/protocol/messenger_activity_center_test.go @@ -70,7 +70,7 @@ func (s *MessengerActivityCenterMessageSuite) TestDeleteOneToOneChat() { s.Require().NoError(err) r := &requests.SendContactRequest{ - ID: types.Hex2Bytes(s.m.myHexIdentity()), + ID: s.m.myHexIdentity(), Message: "hello", } sendResponse, err := theirMessenger.SendContactRequest(context.Background(), r) diff --git a/protocol/messenger_backup_test.go b/protocol/messenger_backup_test.go index 2c63da158..5a65cbb88 100644 --- a/protocol/messenger_backup_test.go +++ b/protocol/messenger_backup_test.go @@ -77,14 +77,14 @@ func (s *MessengerBackupSuite) TestBackupContacts() { s.Require().NoError(err) contactID1 := types.EncodeHex(crypto.FromECDSAPub(&contact1Key.PublicKey)) - _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contactID1)}) + _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID1}) s.Require().NoError(err) contact2Key, err := crypto.GenerateKey() s.Require().NoError(err) contactID2 := types.EncodeHex(crypto.FromECDSAPub(&contact2Key.PublicKey)) - _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contactID2)}) + _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID2}) s.Require().NoError(err) s.Require().Len(bob1.Contacts(), 2) @@ -325,7 +325,7 @@ func (s *MessengerBackupSuite) TestBackupContactsGreaterThanBatch() { s.Require().NoError(err) contactID := types.EncodeHex(crypto.FromECDSAPub(&contactKey.PublicKey)) - _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contactID)}) + _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID}) s.Require().NoError(err) } @@ -365,14 +365,14 @@ func (s *MessengerBackupSuite) TestBackupRemovedContact() { s.Require().NoError(err) contactID1 := types.EncodeHex(crypto.FromECDSAPub(&contact1Key.PublicKey)) - _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contactID1)}) + _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID1}) s.Require().NoError(err) contact2Key, err := crypto.GenerateKey() s.Require().NoError(err) contactID2 := types.EncodeHex(crypto.FromECDSAPub(&contact2Key.PublicKey)) - _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contactID2)}) + _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID2}) s.Require().NoError(err) s.Require().Len(bob1.Contacts(), 2) @@ -388,7 +388,7 @@ func (s *MessengerBackupSuite) TestBackupRemovedContact() { // Bob 2 add one of the same contacts - _, err = bob2.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contactID2)}) + _, err = bob2.AddContact(context.Background(), &requests.AddContact{ID: contactID2}) s.Require().NoError(err) // Bob 1 now removes one of the contact that was also on bob 2 @@ -488,7 +488,7 @@ func (s *MessengerBackupSuite) TestBackupBlockedContacts() { s.Require().NoError(err) contactID1 := types.EncodeHex(crypto.FromECDSAPub(&contact1Key.PublicKey)) - _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contactID1)}) + _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: contactID1}) s.Require().NoError(err) // Backup diff --git a/protocol/messenger_contact_requests_test.go b/protocol/messenger_contact_requests_test.go index 660772357..6c872bb5e 100644 --- a/protocol/messenger_contact_requests_test.go +++ b/protocol/messenger_contact_requests_test.go @@ -71,7 +71,7 @@ func (s *MessengerContactRequestSuite) TestReceiveAndAcceptContactRequest() { // contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) request := &requests.SendContactRequest{ - ID: types.Hex2Bytes(contactID), + ID: contactID, Message: messageText, } @@ -219,7 +219,7 @@ func (s *MessengerContactRequestSuite) TestReceiveAndDismissContactRequest() { contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) request := &requests.SendContactRequest{ - ID: types.Hex2Bytes(contactID), + ID: contactID, Message: messageText, } @@ -314,7 +314,7 @@ func (s *MessengerContactRequestSuite) TestReceiveAcceptAndRetractContactRequest contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) request := &requests.SendContactRequest{ - ID: types.Hex2Bytes(contactID), + ID: contactID, Message: messageText, } @@ -525,7 +525,7 @@ func (s *MessengerContactRequestSuite) TestReceiveAndAcceptContactRequestTwice() contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) request := &requests.SendContactRequest{ - ID: types.Hex2Bytes(contactID), + ID: contactID, Message: messageText, } @@ -675,7 +675,7 @@ func (s *MessengerContactRequestSuite) TestAcceptLatestContactRequestForContact( myID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey)) request := &requests.SendContactRequest{ - ID: types.Hex2Bytes(contactID), + ID: contactID, Message: messageText, } @@ -805,7 +805,7 @@ func (s *MessengerContactRequestSuite) TestDismissLatestContactRequestForContact myID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey)) request := &requests.SendContactRequest{ - ID: types.Hex2Bytes(contactID), + ID: contactID, Message: messageText, } @@ -880,7 +880,7 @@ func (s *MessengerContactRequestSuite) TestReceiveAndAcceptLegacyContactRequest( contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) request := &requests.AddContact{ - ID: types.Hex2Bytes(contactID), + ID: contactID, } // Send contact request @@ -952,7 +952,7 @@ func (s *MessengerContactRequestSuite) TestLegacyContactRequestNotifications() { contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) request := &requests.AddContact{ - ID: types.Hex2Bytes(contactID), + ID: contactID, } // Send legacy contact request @@ -1003,7 +1003,7 @@ func (s *MessengerContactRequestSuite) TestReceiveMultipleLegacy() { contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) request := &requests.AddContact{ - ID: types.Hex2Bytes(contactID), + ID: contactID, } // Send legacy contact request @@ -1103,7 +1103,7 @@ func (s *MessengerContactRequestSuite) TestAcceptLatestLegacyContactRequestForCo myID := types.EncodeHex(crypto.FromECDSAPub(&s.m.identity.PublicKey)) request := &requests.AddContact{ - ID: types.Hex2Bytes(contactID), + ID: contactID, } // Send contact request @@ -1188,7 +1188,7 @@ func (s *MessengerContactRequestSuite) TestPairedDevicesRemoveContact() { myID := types.EncodeHex(crypto.FromECDSAPub(&alice1.identity.PublicKey)) request := &requests.AddContact{ - ID: types.Hex2Bytes(contactID), + ID: contactID, } // Send contact request @@ -1347,7 +1347,7 @@ func (s *MessengerContactRequestSuite) TestAliceRecoverStateSendContactRequest() myID := types.EncodeHex(crypto.FromECDSAPub(&alice1.identity.PublicKey)) request := &requests.AddContact{ - ID: types.Hex2Bytes(bobID), + ID: bobID, } _, err = alice1.AddContact(context.Background(), request) @@ -1400,7 +1400,7 @@ func (s *MessengerContactRequestSuite) TestAliceRecoverStateSendContactRequest() // adds bob again to her device request = &requests.AddContact{ - ID: types.Hex2Bytes(bobID), + ID: bobID, } _, err = alice2.AddContact(context.Background(), request) @@ -1454,7 +1454,7 @@ func (s *MessengerContactRequestSuite) TestAliceRecoverStateReceiveContactReques myID := types.EncodeHex(crypto.FromECDSAPub(&alice1.identity.PublicKey)) request := &requests.AddContact{ - ID: types.Hex2Bytes(bobID), + ID: bobID, } _, err = alice1.AddContact(context.Background(), request) @@ -1565,7 +1565,7 @@ func (s *MessengerContactRequestSuite) TestAliceOfflineRetractsAndAddsCorrectOrd myID := types.EncodeHex(crypto.FromECDSAPub(&alice1.identity.PublicKey)) request := &requests.AddContact{ - ID: types.Hex2Bytes(bobID), + ID: bobID, } _, err = alice1.AddContact(context.Background(), request) @@ -1614,7 +1614,7 @@ func (s *MessengerContactRequestSuite) TestAliceOfflineRetractsAndAddsCorrectOrd // adds bob again to her device request = &requests.AddContact{ - ID: types.Hex2Bytes(bobID), + ID: bobID, } _, err = alice1.AddContact(context.Background(), request) @@ -1651,7 +1651,7 @@ func (s *MessengerContactRequestSuite) TestAliceOfflineRetractsAndAddsWrongOrder myID := types.EncodeHex(crypto.FromECDSAPub(&alice1.identity.PublicKey)) request := &requests.AddContact{ - ID: types.Hex2Bytes(bobID), + ID: bobID, } _, err = alice1.AddContact(context.Background(), request) @@ -1700,7 +1700,7 @@ func (s *MessengerContactRequestSuite) TestAliceOfflineRetractsAndAddsWrongOrder // adds bob again to her device request = &requests.AddContact{ - ID: types.Hex2Bytes(bobID), + ID: bobID, } _, err = alice1.AddContact(context.Background(), request) diff --git a/protocol/messenger_contact_update_test.go b/protocol/messenger_contact_update_test.go index 100f5a715..9843c5197 100644 --- a/protocol/messenger_contact_update_test.go +++ b/protocol/messenger_contact_update_test.go @@ -74,7 +74,7 @@ func (s *MessengerContactUpdateSuite) TestReceiveContactUpdate() { theirContactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) - response, err := theirMessenger.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contactID)}) + response, err := theirMessenger.AddContact(context.Background(), &requests.AddContact{ID: contactID}) s.Require().NoError(err) s.Require().NotNil(response) @@ -136,7 +136,7 @@ func (s *MessengerContactUpdateSuite) TestAddContact() { _, err := theirMessenger.Start() s.Require().NoError(err) - response, err := theirMessenger.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contactID)}) + response, err := theirMessenger.AddContact(context.Background(), &requests.AddContact{ID: contactID}) s.Require().NoError(err) s.Require().NotNil(response) @@ -171,7 +171,7 @@ func (s *MessengerContactUpdateSuite) TestAddContactWithENS() { s.Require().NoError(theirMessenger.ENSVerified(contactID, ensName)) - response, err := theirMessenger.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contactID)}) + response, err := theirMessenger.AddContact(context.Background(), &requests.AddContact{ID: contactID}) s.Require().NoError(err) s.Require().NotNil(response) s.Require().Len(response.Contacts, 1) diff --git a/protocol/messenger_contact_verification_test.go b/protocol/messenger_contact_verification_test.go index c682b8e2b..98a78733b 100644 --- a/protocol/messenger_contact_verification_test.go +++ b/protocol/messenger_contact_verification_test.go @@ -54,7 +54,7 @@ func (s *MessengerVerificationRequests) mutualContact(theirMessenger *Messenger) contactID := types.EncodeHex(crypto.FromECDSAPub(&theirMessenger.identity.PublicKey)) request := &requests.SendContactRequest{ - ID: types.Hex2Bytes(contactID), + ID: contactID, Message: messageText, } diff --git a/protocol/messenger_contacts.go b/protocol/messenger_contacts.go index 80fd54d67..b3fad6392 100644 --- a/protocol/messenger_contacts.go +++ b/protocol/messenger_contacts.go @@ -187,7 +187,10 @@ func (m *Messenger) SendContactRequest(ctx context.Context, request *requests.Se return nil, err } - chatID := request.ID.String() + chatID, err := request.HexID() + if err != nil { + return nil, err + } response, err := m.addContact( chatID, @@ -530,8 +533,13 @@ func (m *Messenger) AddContact(ctx context.Context, request *requests.AddContact return nil, err } + id, err := request.HexID() + if err != nil { + return nil, err + } + return m.addContact( - request.ID.String(), + id, request.ENSName, request.Nickname, request.DisplayName, diff --git a/protocol/messenger_group_chat.go b/protocol/messenger_group_chat.go index f8aa7031f..7123ef279 100644 --- a/protocol/messenger_group_chat.go +++ b/protocol/messenger_group_chat.go @@ -13,6 +13,7 @@ import ( "github.com/status-im/status-go/images" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/protobuf" + "github.com/status-im/status-go/protocol/requests" v1protocol "github.com/status-im/status-go/protocol/v1" ) @@ -34,13 +35,22 @@ func (m *Messenger) validateAddedGroupMembers(members []string) error { } func (m *Messenger) CreateGroupChatWithMembers(ctx context.Context, name string, members []string) (*MessengerResponse, error) { - if err := m.validateAddedGroupMembers(members); err != nil { + var convertedKeyMembers []string + for _, m := range members { + k, err := requests.ConvertCompressedToLegacyKey(m) + if err != nil { + return nil, err + } + convertedKeyMembers = append(convertedKeyMembers, k) + + } + if err := m.validateAddedGroupMembers(convertedKeyMembers); err != nil { return nil, err } var response MessengerResponse logger := m.logger.With(zap.String("site", "CreateGroupChatWithMembers")) - logger.Info("Creating group chat", zap.String("name", name), zap.Any("members", members)) + logger.Info("Creating group chat", zap.String("name", name), zap.Any("members", convertedKeyMembers)) chat := CreateGroupChat(m.getTimesource()) clock, _ := chat.NextClockAndTimestamp(m.getTimesource()) @@ -57,8 +67,8 @@ func (m *Messenger) CreateGroupChatWithMembers(ctx context.Context, name string, clock, _ = chat.NextClockAndTimestamp(m.getTimesource()) // Add members - if len(members) > 0 { - event := v1protocol.NewMembersAddedEvent(members, clock) + if len(convertedKeyMembers) > 0 { + event := v1protocol.NewMembersAddedEvent(convertedKeyMembers, clock) event.ChatID = chat.ID err = event.Sign(m.identity) if err != nil { diff --git a/protocol/messenger_identity_image_test.go b/protocol/messenger_identity_image_test.go index ce1f5457f..6ea3d59d8 100644 --- a/protocol/messenger_identity_image_test.go +++ b/protocol/messenger_identity_image_test.go @@ -320,7 +320,7 @@ func (s *MessengerProfilePictureHandlerSuite) TestE2eSendingReceivingProfilePict s.logger.Debug("bob add contact before") if bc { s.logger.Debug("bob has contact to add") - _, err = s.bob.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(s.generateKeyUID(&s.alice.identity.PublicKey))}) + _, err = s.bob.AddContact(context.Background(), &requests.AddContact{ID: s.generateKeyUID(&s.alice.identity.PublicKey)}) s.Require().NoError(err) s.logger.Debug("bob add contact after") } @@ -367,7 +367,7 @@ func (s *MessengerProfilePictureHandlerSuite) TestE2eSendingReceivingProfilePict s.logger.Debug("alice add contact before") if ac { s.logger.Debug("alice has contact to add") - _, err = s.alice.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(s.generateKeyUID(&s.bob.identity.PublicKey))}) + _, err = s.alice.AddContact(context.Background(), &requests.AddContact{ID: s.generateKeyUID(&s.bob.identity.PublicKey)}) s.Require().NoError(err) s.logger.Debug("alice add contact after") } diff --git a/protocol/messenger_installations_test.go b/protocol/messenger_installations_test.go index 4c6ec8fb7..f7e5b584c 100644 --- a/protocol/messenger_installations_test.go +++ b/protocol/messenger_installations_test.go @@ -106,7 +106,7 @@ func (s *MessengerInstallationSuite) TestReceiveInstallation() { contact, err := BuildContactFromPublicKey(&contactKey.PublicKey) s.Require().NoError(err) - response, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contact.ID)}) + response, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: contact.ID}) s.Require().NoError(err) s.Require().Len(response.Contacts, 1) @@ -179,7 +179,7 @@ func (s *MessengerInstallationSuite) TestSyncInstallation() { s.m.allContacts.Store(contact.ID, contact) contact.LocalNickname = "Test Nickname" - _, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contact.ID)}) + _, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: contact.ID}) s.Require().NoError(err) _, err = s.m.SetContactLocalNickname(&requests.SetContactLocalNickname{ID: types.Hex2Bytes(contact.ID), Nickname: contact.LocalNickname}) s.Require().NoError(err) diff --git a/protocol/messenger_messages.go b/protocol/messenger_messages.go index bf8e6d33f..d466253a1 100644 --- a/protocol/messenger_messages.go +++ b/protocol/messenger_messages.go @@ -359,3 +359,61 @@ func (m *Messenger) addContactRequestPropagatedState(message *common.Message) er message.ContactRequestPropagatedState = contact.ContactRequestPropagatedState() return nil } + +func (m *Messenger) SendOneToOneMessage(request *requests.SendOneToOneMessage) (*MessengerResponse, error) { + if err := request.Validate(); err != nil { + return nil, err + } + + chatID, err := request.HexID() + if err != nil { + return nil, err + } + + _, ok := m.allChats.Load(chatID) + if !ok { + // Only one to one chan be muted when it's not in the database + publicKey, err := common.HexToPubkey(chatID) + if err != nil { + return nil, err + } + + // Create a one to one chat + chat := CreateOneToOneChat(chatID, publicKey, m.getTimesource()) + err = m.initChatSyncFields(chat) + if err != nil { + return nil, err + } + err = m.saveChat(chat) + if err != nil { + return nil, err + } + } + + message := &common.Message{} + message.Text = request.Message + message.ChatId = chatID + message.ContentType = protobuf.ChatMessage_TEXT_PLAIN + + return m.sendChatMessage(context.Background(), message) +} + +func (m *Messenger) SendGroupChatMessage(request *requests.SendGroupChatMessage) (*MessengerResponse, error) { + if err := request.Validate(); err != nil { + return nil, err + } + + chatID := request.ID + + _, ok := m.allChats.Load(chatID) + if !ok { + return nil, ErrChatNotFound + } + + message := &common.Message{} + message.Text = request.Message + message.ChatId = chatID + message.ContentType = protobuf.ChatMessage_TEXT_PLAIN + + return m.sendChatMessage(context.Background(), message) +} diff --git a/protocol/messenger_test.go b/protocol/messenger_test.go index af12da412..0ea7eb4e7 100644 --- a/protocol/messenger_test.go +++ b/protocol/messenger_test.go @@ -156,7 +156,7 @@ func (s *MessengerSuite) TestInit() { Prep: func() { key, err := crypto.GenerateKey() s.Require().NoError(err) - _, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(types.EncodeHex(crypto.FromECDSAPub(&key.PublicKey)))}) + _, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: types.EncodeHex(crypto.FromECDSAPub(&key.PublicKey))}) s.Require().NoError(err) }, AddedFilters: 2, @@ -1289,7 +1289,7 @@ func (s *MessengerSuite) TestBlockContact() { s.Require().NoError(s.m.SaveChat(chat2)) s.Require().NoError(s.m.SaveChat(chat3)) - _, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contact.ID)}) + _, err = s.m.AddContact(context.Background(), &requests.AddContact{ID: contact.ID}) s.Require().NoError(err) messages := []*common.Message{ @@ -1418,7 +1418,7 @@ func (s *MessengerSuite) TestBlockContact() { } func (s *MessengerSuite) TestContactPersistence() { - _, err := s.m.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(testPK)}) + _, err := s.m.AddContact(context.Background(), &requests.AddContact{ID: testPK}) s.Require().NoError(err) savedContacts := s.m.Contacts() diff --git a/protocol/push_notification_test.go b/protocol/push_notification_test.go index 89019c92f..de45b2e81 100644 --- a/protocol/push_notification_test.go +++ b/protocol/push_notification_test.go @@ -300,7 +300,7 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationFromContactO ContactRequestLocalState: ContactRequestStateSent, } - _, err = bob.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(aliceContact.ID)}) + _, err = bob.AddContact(context.Background(), &requests.AddContact{ID: aliceContact.ID}) s.Require().NoError(err) // Enable from contacts only @@ -446,7 +446,7 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationRetries() { ContactRequestLocalState: ContactRequestStateSent, } - _, err = bob.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(aliceContact.ID)}) + _, err = bob.AddContact(context.Background(), &requests.AddContact{ID: aliceContact.ID}) s.Require().NoError(err) // Add frank has a contact @@ -456,7 +456,7 @@ func (s *MessengerPushNotificationSuite) TestReceivePushNotificationRetries() { ContactRequestLocalState: ContactRequestStateSent, } - _, err = bob.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(frankContact.ID)}) + _, err = bob.AddContact(context.Background(), &requests.AddContact{ID: frankContact.ID}) s.Require().NoError(err) // Enable from contacts only diff --git a/protocol/requests/add_contact.go b/protocol/requests/add_contact.go index 7c794e0e2..66f652ece 100644 --- a/protocol/requests/add_contact.go +++ b/protocol/requests/add_contact.go @@ -2,17 +2,15 @@ package requests import ( "errors" - - "github.com/status-im/status-go/eth-node/types" ) var ErrAddContactInvalidID = errors.New("add-contact: invalid id") type AddContact struct { - ID types.HexBytes `json:"id"` - Nickname string `json:"nickname"` - DisplayName string `json:"displayName"` - ENSName string `json:"ensName"` + ID string `json:"id"` + Nickname string `json:"nickname"` + DisplayName string `json:"displayName"` + ENSName string `json:"ensName"` } func (a *AddContact) Validate() error { @@ -22,3 +20,7 @@ func (a *AddContact) Validate() error { return nil } + +func (a *AddContact) HexID() (string, error) { + return ConvertCompressedToLegacyKey(a.ID) +} diff --git a/protocol/requests/create_account.go b/protocol/requests/create_account.go new file mode 100644 index 000000000..d342fc856 --- /dev/null +++ b/protocol/requests/create_account.go @@ -0,0 +1,39 @@ +package requests + +import ( + "errors" +) + +var ErrCreateAccountInvalidDisplayName = errors.New("create-account: invalid display name") +var ErrCreateAccountInvalidPassword = errors.New("create-account: invalid password") +var ErrCreateAccountInvalidImagePath = errors.New("create-account: invalid image path") +var ErrCreateAccountInvalidColor = errors.New("create-account: invalid color") + +type CreateAccount struct { + DisplayName string `json:"displayName"` + Password string `json:"password"` + ImagePath string `json:"imagePath"` + Color string `json:"color"` +} + +func (c *CreateAccount) Validate() error { + // TODO(cammellos): Add proper validation for password/displayname/etc + if len(c.DisplayName) == 0 { + return ErrCreateAccountInvalidDisplayName + } + + if len(c.Password) == 0 { + return ErrCreateAccountInvalidPassword + } + + if len(c.ImagePath) == 0 { + return ErrCreateAccountInvalidImagePath + } + + if len(c.Color) == 0 { + return ErrCreateAccountInvalidColor + } + + return nil + +} diff --git a/protocol/requests/send_contact_request.go b/protocol/requests/send_contact_request.go index 5427d9497..375fa5006 100644 --- a/protocol/requests/send_contact_request.go +++ b/protocol/requests/send_contact_request.go @@ -3,15 +3,17 @@ package requests import ( "errors" - "github.com/status-im/status-go/eth-node/types" + "github.com/status-im/status-go/api/multiformat" ) var ErrSendContactRequestInvalidID = errors.New("send-contact-request: invalid id") var ErrSendContactRequestInvalidMessage = errors.New("send-contact-request: invalid message") +const legacyKeyLength = 132 + type SendContactRequest struct { - ID types.HexBytes `json:"id"` - Message string `json:"message"` + ID string `json:"id"` + Message string `json:"message"` } func (a *SendContactRequest) Validate() error { @@ -25,3 +27,14 @@ func (a *SendContactRequest) Validate() error { return nil } + +func ConvertCompressedToLegacyKey(k string) (string, error) { + if len(k) == legacyKeyLength { + return k, nil + } + return multiformat.DeserializeCompressedKey(k) +} + +func (a *SendContactRequest) HexID() (string, error) { + return ConvertCompressedToLegacyKey(a.ID) +} diff --git a/protocol/requests/send_group_chat_message.go b/protocol/requests/send_group_chat_message.go new file mode 100644 index 000000000..527e3905d --- /dev/null +++ b/protocol/requests/send_group_chat_message.go @@ -0,0 +1,25 @@ +package requests + +import ( + "errors" +) + +var ErrSendGroupChatMessageInvalidID = errors.New("send-group-chat-message: invalid id") +var ErrSendGroupChatMessageInvalidMessage = errors.New("send-group-chat-message: invalid message") + +type SendGroupChatMessage struct { + ID string `json:"id"` + Message string `json:"message"` +} + +func (a *SendGroupChatMessage) Validate() error { + if len(a.ID) == 0 { + return ErrSendGroupChatMessageInvalidID + } + + if len(a.Message) == 0 { + return ErrSendGroupChatMessageInvalidMessage + } + + return nil +} diff --git a/protocol/requests/send_one_to_one_message.go b/protocol/requests/send_one_to_one_message.go new file mode 100644 index 000000000..5a077ee5a --- /dev/null +++ b/protocol/requests/send_one_to_one_message.go @@ -0,0 +1,29 @@ +package requests + +import ( + "errors" +) + +var ErrSendOneToOneMessageInvalidID = errors.New("send-one-to-one-message: invalid id") +var ErrSendOneToOneMessageInvalidMessage = errors.New("send-one-to-one-message: invalid message") + +type SendOneToOneMessage struct { + ID string `json:"id"` + Message string `json:"message"` +} + +func (a *SendOneToOneMessage) Validate() error { + if len(a.ID) == 0 { + return ErrSendOneToOneMessageInvalidID + } + + if len(a.Message) == 0 { + return ErrSendOneToOneMessageInvalidMessage + } + + return nil +} + +func (a *SendOneToOneMessage) HexID() (string, error) { + return ConvertCompressedToLegacyKey(a.ID) +} diff --git a/services/ext/api.go b/services/ext/api.go index 399806948..e1a7e765f 100644 --- a/services/ext/api.go +++ b/services/ext/api.go @@ -771,6 +771,14 @@ func (api *PublicAPI) SendChatMessages(ctx context.Context, messages []*common.M return api.service.messenger.SendChatMessages(ctx, messages) } +func (api *PublicAPI) SendOneToOneMessage(request *requests.SendOneToOneMessage) (*protocol.MessengerResponse, error) { + return api.service.messenger.SendOneToOneMessage(request) +} + +func (api *PublicAPI) SendGroupChatMessage(request *requests.SendGroupChatMessage) (*protocol.MessengerResponse, error) { + return api.service.messenger.SendGroupChatMessage(request) +} + func (api *PublicAPI) EditMessage(ctx context.Context, request *requests.EditMessage) (*protocol.MessengerResponse, error) { return api.service.messenger.EditMessage(ctx, request) } @@ -1272,6 +1280,10 @@ func (api *PublicAPI) CollapsedCommunityCategories() ([]protocol.CollapsedCommun return api.service.messenger.CollapsedCommunityCategories() } +func (api *PublicAPI) Messenger() *protocol.Messenger { + return api.service.messenger +} + // ----- // HELPER // -----