diff --git a/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp b/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp
index 4e2e22841..cc17a6d20 100644
--- a/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp
+++ b/native/cpp/CommonCpp/NativeModules/CommRustModule.cpp
@@ -1,1012 +1,1038 @@
 #include "CommRustModule.h"
 #include "InternalModules/RustPromiseManager.h"
 #include "JSIRust.h"
 #include "lib.rs.h"
 
 #include <ReactCommon/TurboModuleUtils.h>
 
 namespace comm {
 
 using namespace facebook::react;
 
 CommRustModule::CommRustModule(std::shared_ptr<CallInvoker> jsInvoker)
     : CommRustModuleSchemaCxxSpecJSI(jsInvoker) {
 }
 
 jsi::Value CommRustModule::generateNonce(jsi::Runtime &rt) {
   return createPromiseAsJSIValue(
       rt, [this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityGenerateNonce(currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::registerPasswordUser(
     jsi::Runtime &rt,
     jsi::String username,
     jsi::String password,
     jsi::String keyPayload,
     jsi::String keyPayloadSignature,
     jsi::String contentPrekey,
     jsi::String contentPrekeySignature,
     jsi::String notifPrekey,
     jsi::String notifPrekeySignature,
     jsi::Array contentOneTimeKeys,
     jsi::Array notifOneTimeKeys,
     jsi::String farcasterID,
     jsi::String initialDeviceList) {
   auto usernameRust = jsiStringToRustString(username, rt);
   auto passwordRust = jsiStringToRustString(password, rt);
   auto keyPayloadRust = jsiStringToRustString(keyPayload, rt);
   auto keyPayloadSignatureRust = jsiStringToRustString(keyPayloadSignature, rt);
   auto contentPrekeyRust = jsiStringToRustString(contentPrekey, rt);
   auto contentPrekeySignatureRust =
       jsiStringToRustString(contentPrekeySignature, rt);
   auto notifPrekeyRust = jsiStringToRustString(notifPrekey, rt);
   auto notifPrekeySignatureRust =
       jsiStringToRustString(notifPrekeySignature, rt);
   auto contentOneTimeKeysRust = jsiStringArrayToRustVec(contentOneTimeKeys, rt);
   auto notifOneTimeKeysRust = jsiStringArrayToRustVec(notifOneTimeKeys, rt);
   auto farcasterIDRust = jsiStringToRustString(farcasterID, rt);
   auto initialDeviceListRust = jsiStringToRustString(initialDeviceList, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityRegisterPasswordUser(
               usernameRust,
               passwordRust,
               keyPayloadRust,
               keyPayloadSignatureRust,
               contentPrekeyRust,
               contentPrekeySignatureRust,
               notifPrekeyRust,
               notifPrekeySignatureRust,
               contentOneTimeKeysRust,
               notifOneTimeKeysRust,
               farcasterIDRust,
               initialDeviceListRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::registerReservedPasswordUser(
     jsi::Runtime &rt,
     jsi::String username,
     jsi::String password,
     jsi::String keyPayload,
     jsi::String keyPayloadSignature,
     jsi::String contentPrekey,
     jsi::String contentPrekeySignature,
     jsi::String notifPrekey,
     jsi::String notifPrekeySignature,
     jsi::Array contentOneTimeKeys,
     jsi::Array notifOneTimeKeys,
     jsi::String keyserverMessage,
     jsi::String keyserverSignature,
     jsi::String initialDeviceList) {
   auto usernameRust = jsiStringToRustString(username, rt);
   auto passwordRust = jsiStringToRustString(password, rt);
   auto keyPayloadRust = jsiStringToRustString(keyPayload, rt);
   auto keyPayloadSignatureRust = jsiStringToRustString(keyPayloadSignature, rt);
   auto contentPrekeyRust = jsiStringToRustString(contentPrekey, rt);
   auto contentPrekeySignatureRust =
       jsiStringToRustString(contentPrekeySignature, rt);
   auto notifPrekeyRust = jsiStringToRustString(notifPrekey, rt);
   auto notifPrekeySignatureRust =
       jsiStringToRustString(notifPrekeySignature, rt);
   auto contentOneTimeKeysRust = jsiStringArrayToRustVec(contentOneTimeKeys, rt);
   auto notifOneTimeKeysRust = jsiStringArrayToRustVec(notifOneTimeKeys, rt);
   auto keyserverMessageRust = jsiStringToRustString(keyserverMessage, rt);
   auto keyserverSignatureRust = jsiStringToRustString(keyserverSignature, rt);
   auto initialDeviceListRust = jsiStringToRustString(initialDeviceList, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityRegisterReservedPasswordUser(
               usernameRust,
               passwordRust,
               keyPayloadRust,
               keyPayloadSignatureRust,
               contentPrekeyRust,
               contentPrekeySignatureRust,
               notifPrekeyRust,
               notifPrekeySignatureRust,
               contentOneTimeKeysRust,
               notifOneTimeKeysRust,
               keyserverMessageRust,
               keyserverSignatureRust,
               initialDeviceListRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::logInPasswordUser(
     jsi::Runtime &rt,
     jsi::String username,
     jsi::String password,
     jsi::String keyPayload,
     jsi::String keyPayloadSignature,
     jsi::String contentPrekey,
     jsi::String contentPrekeySignature,
     jsi::String notifPrekey,
     jsi::String notifPrekeySignature) {
   auto usernameRust = jsiStringToRustString(username, rt);
   auto passwordRust = jsiStringToRustString(password, rt);
   auto keyPayloadRust = jsiStringToRustString(keyPayload, rt);
   auto keyPayloadSignatureRust = jsiStringToRustString(keyPayloadSignature, rt);
   auto contentPrekeyRust = jsiStringToRustString(contentPrekey, rt);
   auto contentPrekeySignatureRust =
       jsiStringToRustString(contentPrekeySignature, rt);
   auto notifPrekeyRust = jsiStringToRustString(notifPrekey, rt);
   auto notifPrekeySignatureRust =
       jsiStringToRustString(notifPrekeySignature, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityLogInPasswordUser(
               usernameRust,
               passwordRust,
               keyPayloadRust,
               keyPayloadSignatureRust,
               contentPrekeyRust,
               contentPrekeySignatureRust,
               notifPrekeyRust,
               notifPrekeySignatureRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::registerWalletUser(
     jsi::Runtime &rt,
     jsi::String siweMessage,
     jsi::String siweSignature,
     jsi::String keyPayload,
     jsi::String keyPayloadSignature,
     jsi::String contentPrekey,
     jsi::String contentPrekeySignature,
     jsi::String notifPrekey,
     jsi::String notifPrekeySignature,
     jsi::Array contentOneTimeKeys,
     jsi::Array notifOneTimeKeys,
     jsi::String farcasterID,
     jsi::String initialDeviceList) {
   auto siweMessageRust = jsiStringToRustString(siweMessage, rt);
   auto siweSignatureRust = jsiStringToRustString(siweSignature, rt);
   auto keyPayloadRust = jsiStringToRustString(keyPayload, rt);
   auto keyPayloadSignatureRust = jsiStringToRustString(keyPayloadSignature, rt);
   auto contentPrekeyRust = jsiStringToRustString(contentPrekey, rt);
   auto contentPrekeySignatureRust =
       jsiStringToRustString(contentPrekeySignature, rt);
   auto notifPrekeyRust = jsiStringToRustString(notifPrekey, rt);
   auto notifPrekeySignatureRust =
       jsiStringToRustString(notifPrekeySignature, rt);
   auto contentOneTimeKeysRust = jsiStringArrayToRustVec(contentOneTimeKeys, rt);
   auto notifOneTimeKeysRust = jsiStringArrayToRustVec(notifOneTimeKeys, rt);
   auto farcasterIDRust = jsiStringToRustString(farcasterID, rt);
   auto initialDeviceListRust = jsiStringToRustString(initialDeviceList, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityRegisterWalletUser(
               siweMessageRust,
               siweSignatureRust,
               keyPayloadRust,
               keyPayloadSignatureRust,
               contentPrekeyRust,
               contentPrekeySignatureRust,
               notifPrekeyRust,
               notifPrekeySignatureRust,
               contentOneTimeKeysRust,
               notifOneTimeKeysRust,
               farcasterIDRust,
               initialDeviceListRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::registerReservedWalletUser(
     jsi::Runtime &rt,
     jsi::String siweMessage,
     jsi::String siweSignature,
     jsi::String keyPayload,
     jsi::String keyPayloadSignature,
     jsi::String contentPrekey,
     jsi::String contentPrekeySignature,
     jsi::String notifPrekey,
     jsi::String notifPrekeySignature,
     jsi::Array contentOneTimeKeys,
     jsi::Array notifOneTimeKeys,
     jsi::String keyserverMessage,
     jsi::String keyserverSignature,
     jsi::String initialDeviceList) {
   auto siweMessageRust = jsiStringToRustString(siweMessage, rt);
   auto siweSignatureRust = jsiStringToRustString(siweSignature, rt);
   auto keyPayloadRust = jsiStringToRustString(keyPayload, rt);
   auto keyPayloadSignatureRust = jsiStringToRustString(keyPayloadSignature, rt);
   auto contentPrekeyRust = jsiStringToRustString(contentPrekey, rt);
   auto contentPrekeySignatureRust =
       jsiStringToRustString(contentPrekeySignature, rt);
   auto notifPrekeyRust = jsiStringToRustString(notifPrekey, rt);
   auto notifPrekeySignatureRust =
       jsiStringToRustString(notifPrekeySignature, rt);
   auto contentOneTimeKeysRust = jsiStringArrayToRustVec(contentOneTimeKeys, rt);
   auto notifOneTimeKeysRust = jsiStringArrayToRustVec(notifOneTimeKeys, rt);
   auto keyserverMessageRust = jsiStringToRustString(keyserverMessage, rt);
   auto keyserverSignatureRust = jsiStringToRustString(keyserverSignature, rt);
   auto initialDeviceListRust = jsiStringToRustString(initialDeviceList, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityRegisterReservedWalletUser(
               siweMessageRust,
               siweSignatureRust,
               keyPayloadRust,
               keyPayloadSignatureRust,
               contentPrekeyRust,
               contentPrekeySignatureRust,
               notifPrekeyRust,
               notifPrekeySignatureRust,
               contentOneTimeKeysRust,
               notifOneTimeKeysRust,
               keyserverMessageRust,
               keyserverSignatureRust,
               initialDeviceListRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::logInWalletUser(
     jsi::Runtime &rt,
     jsi::String siweMessage,
     jsi::String siweSignature,
     jsi::String keyPayload,
     jsi::String keyPayloadSignature,
     jsi::String contentPrekey,
     jsi::String contentPrekeySignature,
     jsi::String notifPrekey,
     jsi::String notifPrekeySignature) {
   auto siweMessageRust = jsiStringToRustString(siweMessage, rt);
   auto siweSignatureRust = jsiStringToRustString(siweSignature, rt);
   auto keyPayloadRust = jsiStringToRustString(keyPayload, rt);
   auto keyPayloadSignatureRust = jsiStringToRustString(keyPayloadSignature, rt);
   auto contentPrekeyRust = jsiStringToRustString(contentPrekey, rt);
   auto contentPrekeySignatureRust =
       jsiStringToRustString(contentPrekeySignature, rt);
   auto notifPrekeyRust = jsiStringToRustString(notifPrekey, rt);
   auto notifPrekeySignatureRust =
       jsiStringToRustString(notifPrekeySignature, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityLogInWalletUser(
               siweMessageRust,
               siweSignatureRust,
               keyPayloadRust,
               keyPayloadSignatureRust,
               contentPrekeyRust,
               contentPrekeySignatureRust,
               notifPrekeyRust,
               notifPrekeySignatureRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::updatePassword(
     jsi::Runtime &rt,
     jsi::String userID,
     jsi::String deviceID,
     jsi::String accessToken,
     jsi::String password) {
   auto userIDRust = jsiStringToRustString(userID, rt);
   auto deviceIDRust = jsiStringToRustString(deviceID, rt);
   auto accessTokenRust = jsiStringToRustString(accessToken, rt);
   auto passwordRust = jsiStringToRustString(password, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityUpdateUserPassword(
               userIDRust,
               deviceIDRust,
               accessTokenRust,
               passwordRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::deletePasswordUser(
     jsi::Runtime &rt,
     jsi::String userID,
     jsi::String deviceID,
     jsi::String accessToken,
     jsi::String password) {
   auto userIDRust = jsiStringToRustString(userID, rt);
   auto deviceIDRust = jsiStringToRustString(deviceID, rt);
   auto accessTokenRust = jsiStringToRustString(accessToken, rt);
   auto passwordRust = jsiStringToRustString(password, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityDeletePasswordUser(
               userIDRust,
               deviceIDRust,
               accessTokenRust,
               passwordRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::deleteWalletUser(
     jsi::Runtime &rt,
     jsi::String userID,
     jsi::String deviceID,
     jsi::String accessToken) {
   auto userIDRust = jsiStringToRustString(userID, rt);
   auto deviceIDRust = jsiStringToRustString(deviceID, rt);
   auto accessTokenRust = jsiStringToRustString(accessToken, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityDeleteWalletUser(
               userIDRust, deviceIDRust, accessTokenRust, currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::logOut(
     jsi::Runtime &rt,
     jsi::String userID,
     jsi::String deviceID,
     jsi::String accessToken) {
   auto userIDRust = jsiStringToRustString(userID, rt);
   auto deviceIDRust = jsiStringToRustString(deviceID, rt);
   auto accessTokenRust = jsiStringToRustString(accessToken, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityLogOut(userIDRust, deviceIDRust, accessTokenRust, currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::logOutSecondaryDevice(
     jsi::Runtime &rt,
     jsi::String userID,
     jsi::String deviceID,
     jsi::String accessToken) {
   auto userIDRust = jsiStringToRustString(userID, rt);
   auto deviceIDRust = jsiStringToRustString(deviceID, rt);
   auto accessTokenRust = jsiStringToRustString(accessToken, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityLogOutSecondaryDevice(
               userIDRust, deviceIDRust, accessTokenRust, currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::getOutboundKeysForUser(
     jsi::Runtime &rt,
     jsi::String authUserID,
     jsi::String authDeviceID,
     jsi::String authAccessToken,
     jsi::String userID) {
   auto authUserIDRust = jsiStringToRustString(authUserID, rt);
   auto authDeviceIDRust = jsiStringToRustString(authDeviceID, rt);
   auto authAccessTokenRust = jsiStringToRustString(authAccessToken, rt);
   auto userIDRust = jsiStringToRustString(userID, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityGetOutboundKeysForUser(
               authUserIDRust,
               authDeviceIDRust,
               authAccessTokenRust,
               userIDRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::getInboundKeysForUser(
     jsi::Runtime &rt,
     jsi::String authUserID,
     jsi::String authDeviceID,
     jsi::String authAccessToken,
     jsi::String userID) {
   auto authUserIDRust = jsiStringToRustString(authUserID, rt);
   auto authDeviceIDRust = jsiStringToRustString(authDeviceID, rt);
   auto authAccessTokenRust = jsiStringToRustString(authAccessToken, rt);
   auto userIDRust = jsiStringToRustString(userID, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityGetInboundKeysForUser(
               authUserIDRust,
               authDeviceIDRust,
               authAccessTokenRust,
               userIDRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::versionSupported(jsi::Runtime &rt) {
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityVersionSupported(currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::uploadOneTimeKeys(
     jsi::Runtime &rt,
     jsi::String authUserID,
     jsi::String authDeviceID,
     jsi::String authAccessToken,
     jsi::Array contentOneTimePreKeys,
     jsi::Array notifOneTimePreKeys) {
   auto authUserIDRust = jsiStringToRustString(authUserID, rt);
   auto authDeviceIDRust = jsiStringToRustString(authDeviceID, rt);
   auto authAccessTokenRust = jsiStringToRustString(authAccessToken, rt);
   auto contentOneTimePreKeysRust =
       jsiStringArrayToRustVec(contentOneTimePreKeys, rt);
   auto notifOneTimePreKeysRust =
       jsiStringArrayToRustVec(notifOneTimePreKeys, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityUploadOneTimeKeys(
               authUserIDRust,
               authDeviceIDRust,
               authAccessTokenRust,
               contentOneTimePreKeysRust,
               notifOneTimePreKeysRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::getKeyserverKeys(
     jsi::Runtime &rt,
     jsi::String authUserID,
     jsi::String authDeviceID,
     jsi::String authAccessToken,
     jsi::String keyserverID) {
   auto authUserIDRust = jsiStringToRustString(authUserID, rt);
   auto authDeviceIDRust = jsiStringToRustString(authDeviceID, rt);
   auto authAccessTokenRust = jsiStringToRustString(authAccessToken, rt);
   auto keyserverIDRust = jsiStringToRustString(keyserverID, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityGetKeyserverKeys(
               authUserIDRust,
               authDeviceIDRust,
               authAccessTokenRust,
               keyserverIDRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::getDeviceListForUser(
     jsi::Runtime &rt,
     jsi::String authUserID,
     jsi::String authDeviceID,
     jsi::String authAccessToken,
     jsi::String userID,
     std::optional<double> sinceTimestamp) {
   auto authUserIDRust = jsiStringToRustString(authUserID, rt);
   auto authDeviceIDRust = jsiStringToRustString(authDeviceID, rt);
   auto authAccessTokenRust = jsiStringToRustString(authAccessToken, rt);
   auto userIDRust = jsiStringToRustString(userID, rt);
 
   auto timestampI64 = static_cast<int64_t>(sinceTimestamp.value_or(0));
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityGetDeviceListForUser(
               authUserIDRust,
               authDeviceIDRust,
               authAccessTokenRust,
               userIDRust,
               timestampI64,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::getDeviceListsForUsers(
     jsi::Runtime &rt,
     jsi::String authUserID,
     jsi::String authDeviceID,
     jsi::String authAccessToken,
     jsi::Array userIDs) {
   auto authUserIDRust = jsiStringToRustString(authUserID, rt);
   auto authDeviceIDRust = jsiStringToRustString(authDeviceID, rt);
   auto authAccessTokenRust = jsiStringToRustString(authAccessToken, rt);
   auto userIDsRust = jsiStringArrayToRustVec(userIDs, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityGetDeviceListsForUsers(
               authUserIDRust,
               authDeviceIDRust,
               authAccessTokenRust,
               userIDsRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::updateDeviceList(
     jsi::Runtime &rt,
     jsi::String authUserID,
     jsi::String authDeviceID,
     jsi::String authAccessToken,
     jsi::String updatePayload) {
   auto authUserIDRust = jsiStringToRustString(authUserID, rt);
   auto authDeviceIDRust = jsiStringToRustString(authDeviceID, rt);
   auto authAccessTokenRust = jsiStringToRustString(authAccessToken, rt);
   auto updatePayloadRust = jsiStringToRustString(updatePayload, rt);
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityUpdateDeviceList(
               authUserIDRust,
               authDeviceIDRust,
               authAccessTokenRust,
               updatePayloadRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
+jsi::Value CommRustModule::syncPlatformDetails(
+    jsi::Runtime &rt,
+    jsi::String authUserID,
+    jsi::String authDeviceID,
+    jsi::String authAccessToken) {
+  auto authUserIDRust = jsiStringToRustString(authUserID, rt);
+  auto authDeviceIDRust = jsiStringToRustString(authDeviceID, rt);
+  auto authAccessTokenRust = jsiStringToRustString(authAccessToken, rt);
+  return createPromiseAsJSIValue(
+      rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
+        std::string error;
+        try {
+          auto currentID = RustPromiseManager::instance.addPromise(
+              {promise, this->jsInvoker_, innerRt});
+          identitySyncPlatformDetails(
+              authUserIDRust, authDeviceIDRust, authAccessTokenRust, currentID);
+        } catch (const std::exception &e) {
+          error = e.what();
+        };
+        if (!error.empty()) {
+          this->jsInvoker_->invokeAsync(
+              [error, promise]() { promise->reject(error); });
+        }
+      });
+}
+
 jsi::Value CommRustModule::uploadSecondaryDeviceKeysAndLogIn(
     jsi::Runtime &rt,
     jsi::String userID,
     jsi::String nonce,
     jsi::String nonceSignature,
     jsi::String keyPayload,
     jsi::String keyPayloadSignature,
     jsi::String contentPrekey,
     jsi::String contentPrekeySignature,
     jsi::String notifPrekey,
     jsi::String notifPrekeySignature,
     jsi::Array contentOneTimeKeys,
     jsi::Array notifOneTimeKeys) {
   auto userIDRust = jsiStringToRustString(userID, rt);
   auto nonceRust = jsiStringToRustString(nonce, rt);
   auto nonceSignatureRust = jsiStringToRustString(nonceSignature, rt);
   auto keyPayloadRust = jsiStringToRustString(keyPayload, rt);
   auto keyPayloadSignatureRust = jsiStringToRustString(keyPayloadSignature, rt);
   auto contentPrekeyRust = jsiStringToRustString(contentPrekey, rt);
   auto contentPrekeySignatureRust =
       jsiStringToRustString(contentPrekeySignature, rt);
   auto notifPrekeyRust = jsiStringToRustString(notifPrekey, rt);
   auto notifPrekeySignatureRust =
       jsiStringToRustString(notifPrekeySignature, rt);
   auto contentOneTimeKeysRust = jsiStringArrayToRustVec(contentOneTimeKeys, rt);
   auto notifOneTimeKeysRust = jsiStringArrayToRustVec(notifOneTimeKeys, rt);
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityUploadSecondaryDeviceKeysAndLogIn(
               userIDRust,
               nonceRust,
               nonceSignatureRust,
               keyPayloadRust,
               keyPayloadSignatureRust,
               contentPrekeyRust,
               contentPrekeySignatureRust,
               notifPrekeyRust,
               notifPrekeySignatureRust,
               contentOneTimeKeysRust,
               notifOneTimeKeysRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::logInExistingDevice(
     jsi::Runtime &rt,
     jsi::String userID,
     jsi::String deviceID,
     jsi::String nonce,
     jsi::String nonceSignature) {
   auto userIDRust = jsiStringToRustString(userID, rt);
   auto deviceIDRust = jsiStringToRustString(deviceID, rt);
   auto nonceRust = jsiStringToRustString(nonce, rt);
   auto nonceSignatureRust = jsiStringToRustString(nonceSignature, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityLogInExistingDevice(
               userIDRust,
               deviceIDRust,
               nonceRust,
               nonceSignatureRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::findUserIDForWalletAddress(
     jsi::Runtime &rt,
     jsi::String walletAddress) {
   auto walletAddressRust = jsiStringToRustString(walletAddress, rt);
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityFindUserIDForWalletAddress(walletAddressRust, currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value
 CommRustModule::findUserIDForUsername(jsi::Runtime &rt, jsi::String username) {
   auto usernameRust = jsiStringToRustString(username, rt);
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityFindUserIDForUsername(usernameRust, currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value
 CommRustModule::getFarcasterUsers(jsi::Runtime &rt, jsi::Array farcasterIDs) {
   auto farcasterIDsRust = jsiStringArrayToRustVec(farcasterIDs, rt);
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityGetFarcasterUsers(farcasterIDsRust, currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::linkFarcasterAccount(
     jsi::Runtime &rt,
     jsi::String userID,
     jsi::String deviceID,
     jsi::String accessToken,
     jsi::String farcasterID) {
   auto userIDRust = jsiStringToRustString(userID, rt);
   auto deviceIDRust = jsiStringToRustString(deviceID, rt);
   auto accessTokenRust = jsiStringToRustString(accessToken, rt);
   auto farcasterIDRust = jsiStringToRustString(farcasterID, rt);
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityLinkFarcasterAccount(
               userIDRust,
               deviceIDRust,
               accessTokenRust,
               farcasterIDRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::unlinkFarcasterAccount(
     jsi::Runtime &rt,
     jsi::String userID,
     jsi::String deviceID,
     jsi::String accessToken) {
   auto userIDRust = jsiStringToRustString(userID, rt);
   auto deviceIDRust = jsiStringToRustString(deviceID, rt);
   auto accessTokenRust = jsiStringToRustString(accessToken, rt);
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityUnlinkFarcasterAccount(
               userIDRust, deviceIDRust, accessTokenRust, currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 jsi::Value CommRustModule::findUserIdentities(
     jsi::Runtime &rt,
     jsi::String authUserID,
     jsi::String authDeviceID,
     jsi::String authAccessToken,
     jsi::Array userIDs) {
   auto authUserIDRust = jsiStringToRustString(authUserID, rt);
   auto authDeviceIDRust = jsiStringToRustString(authDeviceID, rt);
   auto authAccessTokenRust = jsiStringToRustString(authAccessToken, rt);
   auto userIDsRust = jsiStringArrayToRustVec(userIDs, rt);
 
   return createPromiseAsJSIValue(
       rt, [=, this](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
         std::string error;
         try {
           auto currentID = RustPromiseManager::instance.addPromise(
               {promise, this->jsInvoker_, innerRt});
           identityFindUserIdentities(
               authUserIDRust,
               authDeviceIDRust,
               authAccessTokenRust,
               userIDsRust,
               currentID);
         } catch (const std::exception &e) {
           error = e.what();
         };
         if (!error.empty()) {
           this->jsInvoker_->invokeAsync(
               [error, promise]() { promise->reject(error); });
         }
       });
 }
 
 } // namespace comm
diff --git a/native/cpp/CommonCpp/NativeModules/CommRustModule.h b/native/cpp/CommonCpp/NativeModules/CommRustModule.h
index a35a151c6..d2d368f4f 100644
--- a/native/cpp/CommonCpp/NativeModules/CommRustModule.h
+++ b/native/cpp/CommonCpp/NativeModules/CommRustModule.h
@@ -1,213 +1,218 @@
 #pragma once
 
 #include "../_generated/rustJSI.h"
 
 #include <ReactCommon/TurboModuleUtils.h>
 #include <jsi/jsi.h>
 #include <memory>
 
 namespace comm {
 
 namespace jsi = facebook::jsi;
 
 class CommRustModule : public facebook::react::CommRustModuleSchemaCxxSpecJSI {
   virtual jsi::Value generateNonce(jsi::Runtime &rt) override;
   virtual jsi::Value registerPasswordUser(
       jsi::Runtime &rt,
       jsi::String username,
       jsi::String password,
       jsi::String keyPayload,
       jsi::String keyPayloadSignature,
       jsi::String contentPrekey,
       jsi::String contentPrekeySignature,
       jsi::String notifPrekey,
       jsi::String notifPrekeySignature,
       jsi::Array contentOneTimeKeys,
       jsi::Array notifOneTimeKeys,
       jsi::String farcasterID,
       jsi::String initialDeviceList) override;
   virtual jsi::Value registerReservedPasswordUser(
       jsi::Runtime &rt,
       jsi::String username,
       jsi::String password,
       jsi::String keyPayload,
       jsi::String keyPayloadSignature,
       jsi::String contentPrekey,
       jsi::String contentPrekeySignature,
       jsi::String notifPrekey,
       jsi::String notifPrekeySignature,
       jsi::Array contentOneTimeKeys,
       jsi::Array notifOneTimeKeys,
       jsi::String keyserverMessage,
       jsi::String keyserverSignature,
       jsi::String initialDeviceList) override;
   virtual jsi::Value logInPasswordUser(
       jsi::Runtime &rt,
       jsi::String username,
       jsi::String password,
       jsi::String keyPayload,
       jsi::String keyPayloadSignature,
       jsi::String contentPrekey,
       jsi::String contentPrekeySignature,
       jsi::String notifPrekey,
       jsi::String notifPrekeySignature) override;
   virtual jsi::Value registerWalletUser(
       jsi::Runtime &rt,
       jsi::String siweMessage,
       jsi::String siweSignature,
       jsi::String keyPayload,
       jsi::String keyPayloadSignature,
       jsi::String contentPrekey,
       jsi::String contentPrekeySignature,
       jsi::String notifPrekey,
       jsi::String notifPrekeySignature,
       jsi::Array contentOneTimeKeys,
       jsi::Array notifOneTimeKeys,
       jsi::String farcasterID,
       jsi::String initialDeviceList) override;
   virtual jsi::Value registerReservedWalletUser(
       jsi::Runtime &rt,
       jsi::String siweMessage,
       jsi::String siweSignature,
       jsi::String keyPayload,
       jsi::String keyPayloadSignature,
       jsi::String contentPrekey,
       jsi::String contentPrekeySignature,
       jsi::String notifPrekey,
       jsi::String notifPrekeySignature,
       jsi::Array contentOneTimeKeys,
       jsi::Array notifOneTimeKeys,
       jsi::String keyserverMessage,
       jsi::String keyserverSignature,
       jsi::String initialDeviceList) override;
   virtual jsi::Value logInWalletUser(
       jsi::Runtime &rt,
       jsi::String siweMessage,
       jsi::String siweSignature,
       jsi::String keyPayload,
       jsi::String keyPayloadSignature,
       jsi::String contentPrekey,
       jsi::String contentPrekeySignature,
       jsi::String notifPrekey,
       jsi::String notifPrekeySignature) override;
   virtual jsi::Value updatePassword(
       jsi::Runtime &rt,
       jsi::String userID,
       jsi::String deviceID,
       jsi::String accessToken,
       jsi::String password) override;
   virtual jsi::Value deletePasswordUser(
       jsi::Runtime &rt,
       jsi::String userID,
       jsi::String deviceID,
       jsi::String accessToken,
       jsi::String password) override;
   virtual jsi::Value deleteWalletUser(
       jsi::Runtime &rt,
       jsi::String userID,
       jsi::String deviceID,
       jsi::String accessToken) override;
   virtual jsi::Value logOut(
       jsi::Runtime &rt,
       jsi::String userID,
       jsi::String deviceID,
       jsi::String accessToken) override;
   virtual jsi::Value logOutSecondaryDevice(
       jsi::Runtime &rt,
       jsi::String userID,
       jsi::String deviceID,
       jsi::String accessToken) override;
   virtual jsi::Value getOutboundKeysForUser(
       jsi::Runtime &rt,
       jsi::String authUserID,
       jsi::String authDeviceID,
       jsi::String authAccessToken,
       jsi::String userID) override;
   virtual jsi::Value getInboundKeysForUser(
       jsi::Runtime &rt,
       jsi::String authUserID,
       jsi::String authDeviceID,
       jsi::String authAccessToken,
       jsi::String userID) override;
   virtual jsi::Value versionSupported(jsi::Runtime &rt) override;
   virtual jsi::Value uploadOneTimeKeys(
       jsi::Runtime &rt,
       jsi::String authUserID,
       jsi::String authDeviceID,
       jsi::String authAccessToken,
       jsi::Array contentOneTimePreKeys,
       jsi::Array notifOneTimePreKeys) override;
   virtual jsi::Value getKeyserverKeys(
       jsi::Runtime &rt,
       jsi::String authUserID,
       jsi::String authDeviceID,
       jsi::String authAccessToken,
       jsi::String keyserverID) override;
   virtual jsi::Value getDeviceListForUser(
       jsi::Runtime &rt,
       jsi::String authUserID,
       jsi::String authDeviceID,
       jsi::String authAccessToken,
       jsi::String userID,
       std::optional<double> sinceTimestamp) override;
   virtual jsi::Value getDeviceListsForUsers(
       jsi::Runtime &rt,
       jsi::String authUserID,
       jsi::String authDeviceID,
       jsi::String authAccessToken,
       jsi::Array userIDs) override;
   virtual jsi::Value updateDeviceList(
       jsi::Runtime &rt,
       jsi::String authUserID,
       jsi::String authDeviceID,
       jsi::String authAccessToken,
       jsi::String updatePayload) override;
+  virtual jsi::Value syncPlatformDetails(
+      jsi::Runtime &rt,
+      jsi::String authUserID,
+      jsi::String authDeviceID,
+      jsi::String authAccessToken) override;
   virtual jsi::Value uploadSecondaryDeviceKeysAndLogIn(
       jsi::Runtime &rt,
       jsi::String userID,
       jsi::String nonce,
       jsi::String nonceSignature,
       jsi::String keyPayload,
       jsi::String keyPayloadSignature,
       jsi::String contentPrekey,
       jsi::String contentPrekeySignature,
       jsi::String notifPrekey,
       jsi::String notifPrekeySignature,
       jsi::Array contentOneTimeKeys,
       jsi::Array notifOneTimeKeys) override;
   virtual jsi::Value logInExistingDevice(
       jsi::Runtime &rt,
       jsi::String userID,
       jsi::String deviceID,
       jsi::String nonce,
       jsi::String nonceSignature) override;
   virtual jsi::Value findUserIDForWalletAddress(
       jsi::Runtime &rt,
       jsi::String walletAddress) override;
   virtual jsi::Value
   findUserIDForUsername(jsi::Runtime &rt, jsi::String username) override;
   virtual jsi::Value
   getFarcasterUsers(jsi::Runtime &rt, jsi::Array farcasterIDs) override;
   virtual jsi::Value linkFarcasterAccount(
       jsi::Runtime &rt,
       jsi::String userID,
       jsi::String deviceID,
       jsi::String accessToken,
       jsi::String farcasterID) override;
   virtual jsi::Value unlinkFarcasterAccount(
       jsi::Runtime &rt,
       jsi::String userID,
       jsi::String deviceID,
       jsi::String accessToken) override;
   virtual jsi::Value findUserIdentities(
       jsi::Runtime &rt,
       jsi::String authUserID,
       jsi::String authDeviceID,
       jsi::String authAccessToken,
       jsi::Array userIDs) override;
 
 public:
   CommRustModule(std::shared_ptr<facebook::react::CallInvoker> jsInvoker);
 };
 
 } // namespace comm
diff --git a/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp b/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp
index 1a7351dd8..96dee072c 100644
--- a/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp
+++ b/native/cpp/CommonCpp/_generated/rustJSI-generated.cpp
@@ -1,134 +1,138 @@
 /**
  * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
  *
  * Do not edit this file as changes may cause incorrect behavior and will be lost
  * once the code is regenerated.
  *
  * @generated by codegen project: GenerateModuleH.js
  */
 
 #include "rustJSI.h"
 
 namespace facebook {
 namespace react {
 
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_generateNonce(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->generateNonce(rt);
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_registerPasswordUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->registerPasswordUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt), args[5].asString(rt), args[6].asString(rt), args[7].asString(rt), args[8].asObject(rt).asArray(rt), args[9].asObject(rt).asArray(rt), args[10].asString(rt), args[11].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_registerReservedPasswordUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->registerReservedPasswordUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt), args[5].asString(rt), args[6].asString(rt), args[7].asString(rt), args[8].asObject(rt).asArray(rt), args[9].asObject(rt).asArray(rt), args[10].asString(rt), args[11].asString(rt), args[12].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_logInPasswordUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->logInPasswordUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt), args[5].asString(rt), args[6].asString(rt), args[7].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_registerWalletUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->registerWalletUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt), args[5].asString(rt), args[6].asString(rt), args[7].asString(rt), args[8].asObject(rt).asArray(rt), args[9].asObject(rt).asArray(rt), args[10].asString(rt), args[11].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_registerReservedWalletUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->registerReservedWalletUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt), args[5].asString(rt), args[6].asString(rt), args[7].asString(rt), args[8].asObject(rt).asArray(rt), args[9].asObject(rt).asArray(rt), args[10].asString(rt), args[11].asString(rt), args[12].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_logInWalletUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->logInWalletUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt), args[5].asString(rt), args[6].asString(rt), args[7].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_updatePassword(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->updatePassword(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_deletePasswordUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->deletePasswordUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_deleteWalletUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->deleteWalletUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_logOut(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->logOut(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_logOutSecondaryDevice(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->logOutSecondaryDevice(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_getOutboundKeysForUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->getOutboundKeysForUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_getInboundKeysForUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->getInboundKeysForUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_versionSupported(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->versionSupported(rt);
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_uploadOneTimeKeys(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->uploadOneTimeKeys(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asObject(rt).asArray(rt), args[4].asObject(rt).asArray(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_getKeyserverKeys(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->getKeyserverKeys(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_getDeviceListForUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->getDeviceListForUser(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].isNull() || args[4].isUndefined() ? std::nullopt : std::make_optional(args[4].asNumber()));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_getDeviceListsForUsers(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->getDeviceListsForUsers(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asObject(rt).asArray(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_updateDeviceList(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->updateDeviceList(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt));
 }
+static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_syncPlatformDetails(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
+  return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->syncPlatformDetails(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt));
+}
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_uploadSecondaryDeviceKeysAndLogIn(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->uploadSecondaryDeviceKeysAndLogIn(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt), args[4].asString(rt), args[5].asString(rt), args[6].asString(rt), args[7].asString(rt), args[8].asString(rt), args[9].asObject(rt).asArray(rt), args[10].asObject(rt).asArray(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_logInExistingDevice(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->logInExistingDevice(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_findUserIDForWalletAddress(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->findUserIDForWalletAddress(rt, args[0].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_findUserIDForUsername(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->findUserIDForUsername(rt, args[0].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_getFarcasterUsers(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->getFarcasterUsers(rt, args[0].asObject(rt).asArray(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_linkFarcasterAccount(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->linkFarcasterAccount(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_unlinkFarcasterAccount(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->unlinkFarcasterAccount(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt));
 }
 static jsi::Value __hostFunction_CommRustModuleSchemaCxxSpecJSI_findUserIdentities(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommRustModuleSchemaCxxSpecJSI *>(&turboModule)->findUserIdentities(rt, args[0].asString(rt), args[1].asString(rt), args[2].asString(rt), args[3].asObject(rt).asArray(rt));
 }
 
 CommRustModuleSchemaCxxSpecJSI::CommRustModuleSchemaCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
   : TurboModule("CommRustTurboModule", jsInvoker) {
   methodMap_["generateNonce"] = MethodMetadata {0, __hostFunction_CommRustModuleSchemaCxxSpecJSI_generateNonce};
   methodMap_["registerPasswordUser"] = MethodMetadata {12, __hostFunction_CommRustModuleSchemaCxxSpecJSI_registerPasswordUser};
   methodMap_["registerReservedPasswordUser"] = MethodMetadata {13, __hostFunction_CommRustModuleSchemaCxxSpecJSI_registerReservedPasswordUser};
   methodMap_["logInPasswordUser"] = MethodMetadata {8, __hostFunction_CommRustModuleSchemaCxxSpecJSI_logInPasswordUser};
   methodMap_["registerWalletUser"] = MethodMetadata {12, __hostFunction_CommRustModuleSchemaCxxSpecJSI_registerWalletUser};
   methodMap_["registerReservedWalletUser"] = MethodMetadata {13, __hostFunction_CommRustModuleSchemaCxxSpecJSI_registerReservedWalletUser};
   methodMap_["logInWalletUser"] = MethodMetadata {8, __hostFunction_CommRustModuleSchemaCxxSpecJSI_logInWalletUser};
   methodMap_["updatePassword"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_updatePassword};
   methodMap_["deletePasswordUser"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_deletePasswordUser};
   methodMap_["deleteWalletUser"] = MethodMetadata {3, __hostFunction_CommRustModuleSchemaCxxSpecJSI_deleteWalletUser};
   methodMap_["logOut"] = MethodMetadata {3, __hostFunction_CommRustModuleSchemaCxxSpecJSI_logOut};
   methodMap_["logOutSecondaryDevice"] = MethodMetadata {3, __hostFunction_CommRustModuleSchemaCxxSpecJSI_logOutSecondaryDevice};
   methodMap_["getOutboundKeysForUser"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_getOutboundKeysForUser};
   methodMap_["getInboundKeysForUser"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_getInboundKeysForUser};
   methodMap_["versionSupported"] = MethodMetadata {0, __hostFunction_CommRustModuleSchemaCxxSpecJSI_versionSupported};
   methodMap_["uploadOneTimeKeys"] = MethodMetadata {5, __hostFunction_CommRustModuleSchemaCxxSpecJSI_uploadOneTimeKeys};
   methodMap_["getKeyserverKeys"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_getKeyserverKeys};
   methodMap_["getDeviceListForUser"] = MethodMetadata {5, __hostFunction_CommRustModuleSchemaCxxSpecJSI_getDeviceListForUser};
   methodMap_["getDeviceListsForUsers"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_getDeviceListsForUsers};
   methodMap_["updateDeviceList"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_updateDeviceList};
+  methodMap_["syncPlatformDetails"] = MethodMetadata {3, __hostFunction_CommRustModuleSchemaCxxSpecJSI_syncPlatformDetails};
   methodMap_["uploadSecondaryDeviceKeysAndLogIn"] = MethodMetadata {11, __hostFunction_CommRustModuleSchemaCxxSpecJSI_uploadSecondaryDeviceKeysAndLogIn};
   methodMap_["logInExistingDevice"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_logInExistingDevice};
   methodMap_["findUserIDForWalletAddress"] = MethodMetadata {1, __hostFunction_CommRustModuleSchemaCxxSpecJSI_findUserIDForWalletAddress};
   methodMap_["findUserIDForUsername"] = MethodMetadata {1, __hostFunction_CommRustModuleSchemaCxxSpecJSI_findUserIDForUsername};
   methodMap_["getFarcasterUsers"] = MethodMetadata {1, __hostFunction_CommRustModuleSchemaCxxSpecJSI_getFarcasterUsers};
   methodMap_["linkFarcasterAccount"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_linkFarcasterAccount};
   methodMap_["unlinkFarcasterAccount"] = MethodMetadata {3, __hostFunction_CommRustModuleSchemaCxxSpecJSI_unlinkFarcasterAccount};
   methodMap_["findUserIdentities"] = MethodMetadata {4, __hostFunction_CommRustModuleSchemaCxxSpecJSI_findUserIdentities};
 }
 
 
 } // namespace react
 } // namespace facebook
diff --git a/native/cpp/CommonCpp/_generated/rustJSI.h b/native/cpp/CommonCpp/_generated/rustJSI.h
index 4b4b51d6e..917fa6f8d 100644
--- a/native/cpp/CommonCpp/_generated/rustJSI.h
+++ b/native/cpp/CommonCpp/_generated/rustJSI.h
@@ -1,305 +1,314 @@
 /**
  * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
  *
  * Do not edit this file as changes may cause incorrect behavior and will be lost
  * once the code is regenerated.
  *
  * @generated by codegen project: GenerateModuleH.js
  */
 
 #pragma once
 
 #include <ReactCommon/TurboModule.h>
 #include <react/bridging/Bridging.h>
 
 namespace facebook {
 namespace react {
 
 class JSI_EXPORT CommRustModuleSchemaCxxSpecJSI : public TurboModule {
 protected:
   CommRustModuleSchemaCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);
 
 public:
   virtual jsi::Value generateNonce(jsi::Runtime &rt) = 0;
   virtual jsi::Value registerPasswordUser(jsi::Runtime &rt, jsi::String username, jsi::String password, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys, jsi::String farcasterID, jsi::String initialDeviceList) = 0;
   virtual jsi::Value registerReservedPasswordUser(jsi::Runtime &rt, jsi::String username, jsi::String password, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys, jsi::String keyserverMessage, jsi::String keyserverSignature, jsi::String initialDeviceList) = 0;
   virtual jsi::Value logInPasswordUser(jsi::Runtime &rt, jsi::String username, jsi::String password, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature) = 0;
   virtual jsi::Value registerWalletUser(jsi::Runtime &rt, jsi::String siweMessage, jsi::String siweSignature, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys, jsi::String farcasterID, jsi::String initialDeviceList) = 0;
   virtual jsi::Value registerReservedWalletUser(jsi::Runtime &rt, jsi::String siweMessage, jsi::String siweSignature, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys, jsi::String keyserverMessage, jsi::String keyserverSignature, jsi::String initialDeviceList) = 0;
   virtual jsi::Value logInWalletUser(jsi::Runtime &rt, jsi::String siweMessage, jsi::String siweSignature, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature) = 0;
   virtual jsi::Value updatePassword(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken, jsi::String password) = 0;
   virtual jsi::Value deletePasswordUser(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken, jsi::String password) = 0;
   virtual jsi::Value deleteWalletUser(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken) = 0;
   virtual jsi::Value logOut(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken) = 0;
   virtual jsi::Value logOutSecondaryDevice(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken) = 0;
   virtual jsi::Value getOutboundKeysForUser(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String userID) = 0;
   virtual jsi::Value getInboundKeysForUser(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String userID) = 0;
   virtual jsi::Value versionSupported(jsi::Runtime &rt) = 0;
   virtual jsi::Value uploadOneTimeKeys(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::Array contentOneTimePreKeys, jsi::Array notifOneTimePreKeys) = 0;
   virtual jsi::Value getKeyserverKeys(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String keyserverID) = 0;
   virtual jsi::Value getDeviceListForUser(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String userID, std::optional<double> sinceTimestamp) = 0;
   virtual jsi::Value getDeviceListsForUsers(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::Array userIDs) = 0;
   virtual jsi::Value updateDeviceList(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String updatePayload) = 0;
+  virtual jsi::Value syncPlatformDetails(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken) = 0;
   virtual jsi::Value uploadSecondaryDeviceKeysAndLogIn(jsi::Runtime &rt, jsi::String userID, jsi::String nonce, jsi::String nonceSignature, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys) = 0;
   virtual jsi::Value logInExistingDevice(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String nonce, jsi::String nonceSignature) = 0;
   virtual jsi::Value findUserIDForWalletAddress(jsi::Runtime &rt, jsi::String walletAddress) = 0;
   virtual jsi::Value findUserIDForUsername(jsi::Runtime &rt, jsi::String username) = 0;
   virtual jsi::Value getFarcasterUsers(jsi::Runtime &rt, jsi::Array farcasterIDs) = 0;
   virtual jsi::Value linkFarcasterAccount(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken, jsi::String farcasterID) = 0;
   virtual jsi::Value unlinkFarcasterAccount(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken) = 0;
   virtual jsi::Value findUserIdentities(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::Array userIDs) = 0;
 
 };
 
 template <typename T>
 class JSI_EXPORT CommRustModuleSchemaCxxSpec : public TurboModule {
 public:
   jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propName) override {
     return delegate_.get(rt, propName);
   }
 
 protected:
   CommRustModuleSchemaCxxSpec(std::shared_ptr<CallInvoker> jsInvoker)
     : TurboModule("CommRustTurboModule", jsInvoker),
       delegate_(static_cast<T*>(this), jsInvoker) {}
 
 private:
   class Delegate : public CommRustModuleSchemaCxxSpecJSI {
   public:
     Delegate(T *instance, std::shared_ptr<CallInvoker> jsInvoker) :
       CommRustModuleSchemaCxxSpecJSI(std::move(jsInvoker)), instance_(instance) {}
 
     jsi::Value generateNonce(jsi::Runtime &rt) override {
       static_assert(
           bridging::getParameterCount(&T::generateNonce) == 1,
           "Expected generateNonce(...) to have 1 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::generateNonce, jsInvoker_, instance_);
     }
     jsi::Value registerPasswordUser(jsi::Runtime &rt, jsi::String username, jsi::String password, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys, jsi::String farcasterID, jsi::String initialDeviceList) override {
       static_assert(
           bridging::getParameterCount(&T::registerPasswordUser) == 13,
           "Expected registerPasswordUser(...) to have 13 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::registerPasswordUser, jsInvoker_, instance_, std::move(username), std::move(password), std::move(keyPayload), std::move(keyPayloadSignature), std::move(contentPrekey), std::move(contentPrekeySignature), std::move(notifPrekey), std::move(notifPrekeySignature), std::move(contentOneTimeKeys), std::move(notifOneTimeKeys), std::move(farcasterID), std::move(initialDeviceList));
     }
     jsi::Value registerReservedPasswordUser(jsi::Runtime &rt, jsi::String username, jsi::String password, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys, jsi::String keyserverMessage, jsi::String keyserverSignature, jsi::String initialDeviceList) override {
       static_assert(
           bridging::getParameterCount(&T::registerReservedPasswordUser) == 14,
           "Expected registerReservedPasswordUser(...) to have 14 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::registerReservedPasswordUser, jsInvoker_, instance_, std::move(username), std::move(password), std::move(keyPayload), std::move(keyPayloadSignature), std::move(contentPrekey), std::move(contentPrekeySignature), std::move(notifPrekey), std::move(notifPrekeySignature), std::move(contentOneTimeKeys), std::move(notifOneTimeKeys), std::move(keyserverMessage), std::move(keyserverSignature), std::move(initialDeviceList));
     }
     jsi::Value logInPasswordUser(jsi::Runtime &rt, jsi::String username, jsi::String password, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature) override {
       static_assert(
           bridging::getParameterCount(&T::logInPasswordUser) == 9,
           "Expected logInPasswordUser(...) to have 9 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::logInPasswordUser, jsInvoker_, instance_, std::move(username), std::move(password), std::move(keyPayload), std::move(keyPayloadSignature), std::move(contentPrekey), std::move(contentPrekeySignature), std::move(notifPrekey), std::move(notifPrekeySignature));
     }
     jsi::Value registerWalletUser(jsi::Runtime &rt, jsi::String siweMessage, jsi::String siweSignature, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys, jsi::String farcasterID, jsi::String initialDeviceList) override {
       static_assert(
           bridging::getParameterCount(&T::registerWalletUser) == 13,
           "Expected registerWalletUser(...) to have 13 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::registerWalletUser, jsInvoker_, instance_, std::move(siweMessage), std::move(siweSignature), std::move(keyPayload), std::move(keyPayloadSignature), std::move(contentPrekey), std::move(contentPrekeySignature), std::move(notifPrekey), std::move(notifPrekeySignature), std::move(contentOneTimeKeys), std::move(notifOneTimeKeys), std::move(farcasterID), std::move(initialDeviceList));
     }
     jsi::Value registerReservedWalletUser(jsi::Runtime &rt, jsi::String siweMessage, jsi::String siweSignature, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys, jsi::String keyserverMessage, jsi::String keyserverSignature, jsi::String initialDeviceList) override {
       static_assert(
           bridging::getParameterCount(&T::registerReservedWalletUser) == 14,
           "Expected registerReservedWalletUser(...) to have 14 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::registerReservedWalletUser, jsInvoker_, instance_, std::move(siweMessage), std::move(siweSignature), std::move(keyPayload), std::move(keyPayloadSignature), std::move(contentPrekey), std::move(contentPrekeySignature), std::move(notifPrekey), std::move(notifPrekeySignature), std::move(contentOneTimeKeys), std::move(notifOneTimeKeys), std::move(keyserverMessage), std::move(keyserverSignature), std::move(initialDeviceList));
     }
     jsi::Value logInWalletUser(jsi::Runtime &rt, jsi::String siweMessage, jsi::String siweSignature, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature) override {
       static_assert(
           bridging::getParameterCount(&T::logInWalletUser) == 9,
           "Expected logInWalletUser(...) to have 9 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::logInWalletUser, jsInvoker_, instance_, std::move(siweMessage), std::move(siweSignature), std::move(keyPayload), std::move(keyPayloadSignature), std::move(contentPrekey), std::move(contentPrekeySignature), std::move(notifPrekey), std::move(notifPrekeySignature));
     }
     jsi::Value updatePassword(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken, jsi::String password) override {
       static_assert(
           bridging::getParameterCount(&T::updatePassword) == 5,
           "Expected updatePassword(...) to have 5 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::updatePassword, jsInvoker_, instance_, std::move(userID), std::move(deviceID), std::move(accessToken), std::move(password));
     }
     jsi::Value deletePasswordUser(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken, jsi::String password) override {
       static_assert(
           bridging::getParameterCount(&T::deletePasswordUser) == 5,
           "Expected deletePasswordUser(...) to have 5 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::deletePasswordUser, jsInvoker_, instance_, std::move(userID), std::move(deviceID), std::move(accessToken), std::move(password));
     }
     jsi::Value deleteWalletUser(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken) override {
       static_assert(
           bridging::getParameterCount(&T::deleteWalletUser) == 4,
           "Expected deleteWalletUser(...) to have 4 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::deleteWalletUser, jsInvoker_, instance_, std::move(userID), std::move(deviceID), std::move(accessToken));
     }
     jsi::Value logOut(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken) override {
       static_assert(
           bridging::getParameterCount(&T::logOut) == 4,
           "Expected logOut(...) to have 4 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::logOut, jsInvoker_, instance_, std::move(userID), std::move(deviceID), std::move(accessToken));
     }
     jsi::Value logOutSecondaryDevice(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken) override {
       static_assert(
           bridging::getParameterCount(&T::logOutSecondaryDevice) == 4,
           "Expected logOutSecondaryDevice(...) to have 4 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::logOutSecondaryDevice, jsInvoker_, instance_, std::move(userID), std::move(deviceID), std::move(accessToken));
     }
     jsi::Value getOutboundKeysForUser(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String userID) override {
       static_assert(
           bridging::getParameterCount(&T::getOutboundKeysForUser) == 5,
           "Expected getOutboundKeysForUser(...) to have 5 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::getOutboundKeysForUser, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken), std::move(userID));
     }
     jsi::Value getInboundKeysForUser(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String userID) override {
       static_assert(
           bridging::getParameterCount(&T::getInboundKeysForUser) == 5,
           "Expected getInboundKeysForUser(...) to have 5 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::getInboundKeysForUser, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken), std::move(userID));
     }
     jsi::Value versionSupported(jsi::Runtime &rt) override {
       static_assert(
           bridging::getParameterCount(&T::versionSupported) == 1,
           "Expected versionSupported(...) to have 1 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::versionSupported, jsInvoker_, instance_);
     }
     jsi::Value uploadOneTimeKeys(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::Array contentOneTimePreKeys, jsi::Array notifOneTimePreKeys) override {
       static_assert(
           bridging::getParameterCount(&T::uploadOneTimeKeys) == 6,
           "Expected uploadOneTimeKeys(...) to have 6 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::uploadOneTimeKeys, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken), std::move(contentOneTimePreKeys), std::move(notifOneTimePreKeys));
     }
     jsi::Value getKeyserverKeys(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String keyserverID) override {
       static_assert(
           bridging::getParameterCount(&T::getKeyserverKeys) == 5,
           "Expected getKeyserverKeys(...) to have 5 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::getKeyserverKeys, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken), std::move(keyserverID));
     }
     jsi::Value getDeviceListForUser(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String userID, std::optional<double> sinceTimestamp) override {
       static_assert(
           bridging::getParameterCount(&T::getDeviceListForUser) == 6,
           "Expected getDeviceListForUser(...) to have 6 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::getDeviceListForUser, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken), std::move(userID), std::move(sinceTimestamp));
     }
     jsi::Value getDeviceListsForUsers(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::Array userIDs) override {
       static_assert(
           bridging::getParameterCount(&T::getDeviceListsForUsers) == 5,
           "Expected getDeviceListsForUsers(...) to have 5 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::getDeviceListsForUsers, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken), std::move(userIDs));
     }
     jsi::Value updateDeviceList(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::String updatePayload) override {
       static_assert(
           bridging::getParameterCount(&T::updateDeviceList) == 5,
           "Expected updateDeviceList(...) to have 5 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::updateDeviceList, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken), std::move(updatePayload));
     }
+    jsi::Value syncPlatformDetails(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken) override {
+      static_assert(
+          bridging::getParameterCount(&T::syncPlatformDetails) == 4,
+          "Expected syncPlatformDetails(...) to have 4 parameters");
+
+      return bridging::callFromJs<jsi::Value>(
+          rt, &T::syncPlatformDetails, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken));
+    }
     jsi::Value uploadSecondaryDeviceKeysAndLogIn(jsi::Runtime &rt, jsi::String userID, jsi::String nonce, jsi::String nonceSignature, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys) override {
       static_assert(
           bridging::getParameterCount(&T::uploadSecondaryDeviceKeysAndLogIn) == 12,
           "Expected uploadSecondaryDeviceKeysAndLogIn(...) to have 12 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::uploadSecondaryDeviceKeysAndLogIn, jsInvoker_, instance_, std::move(userID), std::move(nonce), std::move(nonceSignature), std::move(keyPayload), std::move(keyPayloadSignature), std::move(contentPrekey), std::move(contentPrekeySignature), std::move(notifPrekey), std::move(notifPrekeySignature), std::move(contentOneTimeKeys), std::move(notifOneTimeKeys));
     }
     jsi::Value logInExistingDevice(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String nonce, jsi::String nonceSignature) override {
       static_assert(
           bridging::getParameterCount(&T::logInExistingDevice) == 5,
           "Expected logInExistingDevice(...) to have 5 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::logInExistingDevice, jsInvoker_, instance_, std::move(userID), std::move(deviceID), std::move(nonce), std::move(nonceSignature));
     }
     jsi::Value findUserIDForWalletAddress(jsi::Runtime &rt, jsi::String walletAddress) override {
       static_assert(
           bridging::getParameterCount(&T::findUserIDForWalletAddress) == 2,
           "Expected findUserIDForWalletAddress(...) to have 2 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::findUserIDForWalletAddress, jsInvoker_, instance_, std::move(walletAddress));
     }
     jsi::Value findUserIDForUsername(jsi::Runtime &rt, jsi::String username) override {
       static_assert(
           bridging::getParameterCount(&T::findUserIDForUsername) == 2,
           "Expected findUserIDForUsername(...) to have 2 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::findUserIDForUsername, jsInvoker_, instance_, std::move(username));
     }
     jsi::Value getFarcasterUsers(jsi::Runtime &rt, jsi::Array farcasterIDs) override {
       static_assert(
           bridging::getParameterCount(&T::getFarcasterUsers) == 2,
           "Expected getFarcasterUsers(...) to have 2 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::getFarcasterUsers, jsInvoker_, instance_, std::move(farcasterIDs));
     }
     jsi::Value linkFarcasterAccount(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken, jsi::String farcasterID) override {
       static_assert(
           bridging::getParameterCount(&T::linkFarcasterAccount) == 5,
           "Expected linkFarcasterAccount(...) to have 5 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::linkFarcasterAccount, jsInvoker_, instance_, std::move(userID), std::move(deviceID), std::move(accessToken), std::move(farcasterID));
     }
     jsi::Value unlinkFarcasterAccount(jsi::Runtime &rt, jsi::String userID, jsi::String deviceID, jsi::String accessToken) override {
       static_assert(
           bridging::getParameterCount(&T::unlinkFarcasterAccount) == 4,
           "Expected unlinkFarcasterAccount(...) to have 4 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::unlinkFarcasterAccount, jsInvoker_, instance_, std::move(userID), std::move(deviceID), std::move(accessToken));
     }
     jsi::Value findUserIdentities(jsi::Runtime &rt, jsi::String authUserID, jsi::String authDeviceID, jsi::String authAccessToken, jsi::Array userIDs) override {
       static_assert(
           bridging::getParameterCount(&T::findUserIdentities) == 5,
           "Expected findUserIdentities(...) to have 5 parameters");
 
       return bridging::callFromJs<jsi::Value>(
           rt, &T::findUserIdentities, jsInvoker_, instance_, std::move(authUserID), std::move(authDeviceID), std::move(authAccessToken), std::move(userIDs));
     }
 
   private:
     T *instance_;
   };
 
   Delegate delegate_;
 };
 
 } // namespace react
 } // namespace facebook
diff --git a/native/native_rust_library/src/identity/device_list.rs b/native/native_rust_library/src/identity/device_list.rs
index f3c760018..9e2350f98 100644
--- a/native/native_rust_library/src/identity/device_list.rs
+++ b/native/native_rust_library/src/identity/device_list.rs
@@ -1,205 +1,240 @@
 use grpc_clients::identity::get_auth_client;
 use grpc_clients::identity::protos::auth::{
   GetDeviceListRequest, PeersDeviceListsRequest, PeersDeviceListsResponse,
   UpdateDeviceListRequest,
 };
+use grpc_clients::identity::protos::unauth::Empty;
 use std::collections::HashMap;
 
 use super::PLATFORM_METADATA;
 use crate::identity::AuthInfo;
 use crate::utils::jsi_callbacks::{
   handle_string_result_as_callback, handle_void_result_as_callback,
 };
 use crate::{Error, IDENTITY_SOCKET_ADDR, RUNTIME};
 use serde::Serialize;
 
 pub mod ffi {
   use super::*;
 
   pub fn get_device_list_for_user(
     auth_user_id: String,
     auth_device_id: String,
     auth_access_token: String,
     user_id: String,
     since_timestamp: i64,
     promise_id: u32,
   ) {
     RUNTIME.spawn(async move {
       let auth_info = AuthInfo {
         access_token: auth_access_token,
         user_id: auth_user_id,
         device_id: auth_device_id,
       };
       let since_timestamp = Option::from(since_timestamp).filter(|&t| t > 0);
       let result =
         get_device_list_for_user_helper(auth_info, user_id, since_timestamp)
           .await;
       handle_string_result_as_callback(result, promise_id);
     });
   }
 
   pub fn get_device_lists_for_users(
     auth_user_id: String,
     auth_device_id: String,
     auth_access_token: String,
     user_ids: Vec<String>,
     promise_id: u32,
   ) {
     RUNTIME.spawn(async move {
       let auth_info = AuthInfo {
         access_token: auth_access_token,
         user_id: auth_user_id,
         device_id: auth_device_id,
       };
       let result = get_device_lists_for_users_helper(auth_info, user_ids).await;
       handle_string_result_as_callback(result, promise_id);
     });
   }
 
   pub fn update_device_list(
     auth_user_id: String,
     auth_device_id: String,
     auth_access_token: String,
     update_payload: String,
     promise_id: u32,
   ) {
     RUNTIME.spawn(async move {
       let auth_info = AuthInfo {
         access_token: auth_access_token,
         user_id: auth_user_id,
         device_id: auth_device_id,
       };
       let result = update_device_list_helper(auth_info, update_payload).await;
       handle_void_result_as_callback(result, promise_id);
     });
   }
+
+  pub fn sync_platform_details(
+    auth_user_id: String,
+    auth_device_id: String,
+    auth_access_token: String,
+    promise_id: u32,
+  ) {
+    RUNTIME.spawn(async move {
+      let auth_info = AuthInfo {
+        access_token: auth_access_token,
+        user_id: auth_user_id,
+        device_id: auth_device_id,
+      };
+      let result = sync_platform_details_helper(auth_info).await;
+      handle_void_result_as_callback(result, promise_id);
+    });
+  }
 }
 
 async fn get_device_list_for_user_helper(
   auth_info: AuthInfo,
   user_id: String,
   since_timestamp: Option<i64>,
 ) -> Result<String, Error> {
   let mut identity_client = get_auth_client(
     IDENTITY_SOCKET_ADDR,
     auth_info.user_id,
     auth_info.device_id,
     auth_info.access_token,
     PLATFORM_METADATA.clone(),
   )
   .await?;
 
   let response = identity_client
     .get_device_list_for_user(GetDeviceListRequest {
       user_id,
       since_timestamp,
     })
     .await?
     .into_inner();
 
   let payload = serde_json::to_string(&response.device_list_updates)?;
   Ok(payload)
 }
 
 async fn get_device_lists_for_users_helper(
   auth_info: AuthInfo,
   user_ids: Vec<String>,
 ) -> Result<String, Error> {
   let mut identity_client = get_auth_client(
     IDENTITY_SOCKET_ADDR,
     auth_info.user_id,
     auth_info.device_id,
     auth_info.access_token,
     PLATFORM_METADATA.clone(),
   )
   .await?;
 
   let PeersDeviceListsResponse {
     users_device_lists,
     users_devices_platform_details,
   } = identity_client
     .get_device_lists_for_users(PeersDeviceListsRequest { user_ids })
     .await?
     .into_inner();
 
   let nested_users_devices_platform_details: HashMap<
     String,
     HashMap<String, PlatformDetails>,
   > = users_devices_platform_details
     .into_iter()
     .map(|(user_id, user_devices_platform_details)| {
       (
         user_id,
         user_devices_platform_details
           .devices_platform_details
           .into_iter()
           .map(|(device_id, platform_details)| {
             (device_id, platform_details.into())
           })
           .collect(),
       )
     })
     .collect();
 
   let result = PeersDeviceLists {
     users_device_lists: users_device_lists,
     users_devices_platform_details: nested_users_devices_platform_details,
   };
 
   let payload = serde_json::to_string(&result)?;
   Ok(payload)
 }
 
 async fn update_device_list_helper(
   auth_info: AuthInfo,
   update_payload: String,
 ) -> Result<(), Error> {
   let mut identity_client = get_auth_client(
     IDENTITY_SOCKET_ADDR,
     auth_info.user_id,
     auth_info.device_id,
     auth_info.access_token,
     PLATFORM_METADATA.clone(),
   )
   .await?;
 
   let update_request = UpdateDeviceListRequest {
     new_device_list: update_payload,
   };
 
   identity_client.update_device_list(update_request).await?;
 
   Ok(())
 }
 
+async fn sync_platform_details_helper(
+  auth_info: AuthInfo,
+) -> Result<(), Error> {
+  let mut identity_client = get_auth_client(
+    IDENTITY_SOCKET_ADDR,
+    auth_info.user_id,
+    auth_info.device_id,
+    auth_info.access_token,
+    PLATFORM_METADATA.clone(),
+  )
+  .await?;
+
+  identity_client.sync_platform_details(Empty {}).await?;
+
+  Ok(())
+}
+
 #[derive(Debug, Serialize)]
 #[serde(rename_all = "camelCase")]
 struct PlatformDetails {
   device_type: i32,
   code_version: u64,
   state_version: Option<u64>,
   major_desktop_version: Option<u64>,
 }
 
 impl From<grpc_clients::identity::protos::auth::PlatformDetails>
   for PlatformDetails
 {
   fn from(
     value: grpc_clients::identity::protos::auth::PlatformDetails,
   ) -> Self {
     Self {
       device_type: value.device_type,
       code_version: value.code_version,
       state_version: value.state_version,
       major_desktop_version: value.major_desktop_version,
     }
   }
 }
 
 #[derive(Debug, Serialize)]
 #[serde(rename_all = "camelCase")]
 struct PeersDeviceLists {
   users_device_lists: HashMap<String, String>,
   users_devices_platform_details:
     HashMap<String, HashMap<String, PlatformDetails>>,
 }
diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs
index 96bd46832..3528928dc 100644
--- a/native/native_rust_library/src/lib.rs
+++ b/native/native_rust_library/src/lib.rs
@@ -1,536 +1,544 @@
 use comm_opaque2::grpc::opaque_error_to_grpc_status as handle_error;
 use grpc_clients::identity::protos::unauth::DeviceType;
 use lazy_static::lazy_static;
 use std::sync::Arc;
 use tokio::runtime::{Builder, Runtime};
 use tonic::Status;
 
 mod argon2_tools;
 mod backup;
 mod constants;
 mod identity;
 mod utils;
 
 use crate::argon2_tools::compute_backup_key_str;
 use crate::utils::jsi_callbacks::{
   handle_string_result_as_callback, handle_void_result_as_callback,
 };
 
 mod generated {
   // We get the CODE_VERSION from this generated file
   include!(concat!(env!("OUT_DIR"), "/version.rs"));
   // We get the IDENTITY_SOCKET_ADDR from this generated file
   include!(concat!(env!("OUT_DIR"), "/socket_config.rs"));
 }
 
 pub use generated::CODE_VERSION;
 pub use generated::{BACKUP_SOCKET_ADDR, IDENTITY_SOCKET_ADDR};
 
 #[cfg(not(target_os = "android"))]
 pub const DEVICE_TYPE: DeviceType = DeviceType::Ios;
 #[cfg(target_os = "android")]
 pub const DEVICE_TYPE: DeviceType = DeviceType::Android;
 
 lazy_static! {
   static ref RUNTIME: Arc<Runtime> =
     Arc::new(Builder::new_multi_thread().enable_all().build().unwrap());
 }
 
 // ffi uses
 use backup::ffi::*;
 use identity::ffi::*;
 use utils::future_manager::ffi::*;
 
 #[allow(clippy::too_many_arguments)]
 #[cxx::bridge]
 mod ffi {
 
   // Identity Service APIs
   extern "Rust" {
     #[cxx_name = "identityRegisterPasswordUser"]
     fn register_password_user(
       username: String,
       password: String,
       key_payload: String,
       key_payload_signature: String,
       content_prekey: String,
       content_prekey_signature: String,
       notif_prekey: String,
       notif_prekey_signature: String,
       content_one_time_keys: Vec<String>,
       notif_one_time_keys: Vec<String>,
       farcaster_id: String,
       initial_device_list: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityRegisterReservedPasswordUser"]
     fn register_reserved_password_user(
       username: String,
       password: String,
       key_payload: String,
       key_payload_signature: String,
       content_prekey: String,
       content_prekey_signature: String,
       notif_prekey: String,
       notif_prekey_signature: String,
       content_one_time_keys: Vec<String>,
       notif_one_time_keys: Vec<String>,
       keyserver_message: String,
       keyserver_signature: String,
       initial_device_list: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityLogInPasswordUser"]
     fn log_in_password_user(
       username: String,
       password: String,
       key_payload: String,
       key_payload_signature: String,
       content_prekey: String,
       content_prekey_signature: String,
       notif_prekey: String,
       notif_prekey_signature: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityRegisterWalletUser"]
     fn register_wallet_user(
       siwe_message: String,
       siwe_signature: String,
       key_payload: String,
       key_payload_signature: String,
       content_prekey: String,
       content_prekey_signature: String,
       notif_prekey: String,
       notif_prekey_signature: String,
       content_one_time_keys: Vec<String>,
       notif_one_time_keys: Vec<String>,
       farcaster_id: String,
       initial_device_list: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityRegisterReservedWalletUser"]
     fn register_reserved_wallet_user(
       siwe_message: String,
       siwe_signature: String,
       key_payload: String,
       key_payload_signature: String,
       content_prekey: String,
       content_prekey_signature: String,
       notif_prekey: String,
       notif_prekey_signature: String,
       content_one_time_keys: Vec<String>,
       notif_one_time_keys: Vec<String>,
       keyserver_message: String,
       keyserver_signature: String,
       initial_device_list: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityLogInWalletUser"]
     fn log_in_wallet_user(
       siwe_message: String,
       siwe_signature: String,
       key_payload: String,
       key_payload_signature: String,
       content_prekey: String,
       content_prekey_signature: String,
       notif_prekey: String,
       notif_prekey_signature: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityUpdateUserPassword"]
     fn update_user_password(
       user_id: String,
       device_id: String,
       access_token: String,
       password: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityDeleteWalletUser"]
     fn delete_wallet_user(
       user_id: String,
       device_id: String,
       access_token: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityDeletePasswordUser"]
     fn delete_password_user(
       user_id: String,
       device_id: String,
       access_token: String,
       password: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityLogOut"]
     fn log_out(
       user_id: String,
       device_id: String,
       access_token: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityLogOutSecondaryDevice"]
     fn log_out_secondary_device(
       user_id: String,
       device_id: String,
       access_token: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityGetOutboundKeysForUser"]
     fn get_outbound_keys_for_user(
       auth_user_id: String,
       auth_device_id: String,
       auth_access_token: String,
       user_id: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityGetInboundKeysForUser"]
     fn get_inbound_keys_for_user(
       auth_user_id: String,
       auth_device_id: String,
       auth_access_token: String,
       user_id: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityRefreshUserPrekeys"]
     fn refresh_user_prekeys(
       auth_user_id: String,
       auth_device_id: String,
       auth_access_token: String,
       content_prekey: String,
       content_prekey_signature: String,
       notif_prekey: String,
       notif_prekey_signature: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityGenerateNonce"]
     fn generate_nonce(promise_id: u32);
 
     #[cxx_name = "identityVersionSupported"]
     fn version_supported(promise_id: u32);
 
     #[cxx_name = "identityUploadOneTimeKeys"]
     fn upload_one_time_keys(
       auth_user_id: String,
       auth_device_id: String,
       auth_access_token: String,
       content_one_time_keys: Vec<String>,
       notif_one_time_keys: Vec<String>,
       promise_id: u32,
     );
 
     #[cxx_name = "identityGetKeyserverKeys"]
     fn get_keyserver_keys(
       user_id: String,
       device_id: String,
       access_token: String,
       keyserver_id: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityGetDeviceListForUser"]
     fn get_device_list_for_user(
       auth_user_id: String,
       auth_device_id: String,
       auth_access_token: String,
       user_id: String,
       since_timestamp: i64,
       promise_id: u32,
     );
 
     #[cxx_name = "identityGetDeviceListsForUsers"]
     fn get_device_lists_for_users(
       auth_user_id: String,
       auth_device_id: String,
       auth_access_token: String,
       user_ids: Vec<String>,
       promise_id: u32,
     );
 
     #[cxx_name = "identityUpdateDeviceList"]
     fn update_device_list(
       auth_user_id: String,
       auth_device_id: String,
       auth_access_token: String,
       update_payload: String,
       promise_id: u32,
     );
 
+    #[cxx_name = "identitySyncPlatformDetails"]
+    fn sync_platform_details(
+      auth_user_id: String,
+      auth_device_id: String,
+      auth_access_token: String,
+      promise_id: u32,
+    );
+
     #[cxx_name = "identityUploadSecondaryDeviceKeysAndLogIn"]
     fn upload_secondary_device_keys_and_log_in(
       user_id: String,
       nonce: String,
       nonce_signature: String,
       key_payload: String,
       key_payload_signature: String,
       content_prekey: String,
       content_prekey_signature: String,
       notif_prekey: String,
       notif_prekey_signature: String,
       content_one_time_keys: Vec<String>,
       notif_one_time_keys: Vec<String>,
       promise_id: u32,
     );
 
     #[cxx_name = "identityLogInExistingDevice"]
     fn log_in_existing_device(
       user_id: String,
       device_id: String,
       nonce: String,
       nonce_signature: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityFindUserIDForWalletAddress"]
     fn find_user_id_for_wallet_address(wallet_address: String, promise_id: u32);
 
     #[cxx_name = "identityFindUserIDForUsername"]
     fn find_user_id_for_username(username: String, promise_id: u32);
 
     // Farcaster
     #[cxx_name = "identityGetFarcasterUsers"]
     fn get_farcaster_users(farcaster_ids: Vec<String>, promise_id: u32);
 
     #[cxx_name = "identityLinkFarcasterAccount"]
     fn link_farcaster_account(
       user_id: String,
       device_id: String,
       access_token: String,
       farcaster_id: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityUnlinkFarcasterAccount"]
     fn unlink_farcaster_account(
       user_id: String,
       device_id: String,
       access_token: String,
       promise_id: u32,
     );
 
     #[cxx_name = "identityFindUserIdentities"]
     fn find_user_identities(
       user_id: String,
       device_id: String,
       access_token: String,
       user_ids: Vec<String>,
       promise_id: u32,
     );
 
     // Argon2
     #[cxx_name = "compute_backup_key"]
     fn compute_backup_key_str(
       password: &str,
       backup_id: &str,
     ) -> Result<[u8; 32]>;
   }
 
   unsafe extern "C++" {
     include!("RustCallback.h");
     #[namespace = "comm"]
     #[cxx_name = "stringCallback"]
     fn string_callback(error: String, promise_id: u32, ret: String);
 
     #[namespace = "comm"]
     #[cxx_name = "voidCallback"]
     fn void_callback(error: String, promise_id: u32);
 
     #[namespace = "comm"]
     #[cxx_name = "boolCallback"]
     fn bool_callback(error: String, promise_id: u32, ret: bool);
   }
 
   // AES cryptography
   #[namespace = "comm"]
   unsafe extern "C++" {
     include!("RustAESCrypto.h");
 
     #[allow(unused)]
     #[cxx_name = "aesGenerateKey"]
     fn generate_key(buffer: &mut [u8]) -> Result<()>;
 
     /// The first two argument aren't mutated but creation of Java ByteBuffer
     /// requires the underlying bytes to be mutable.
     #[allow(unused)]
     #[cxx_name = "aesEncrypt"]
     fn encrypt(
       key: &mut [u8],
       plaintext: &mut [u8],
       sealed_data: &mut [u8],
     ) -> Result<()>;
 
     /// The first two argument aren't mutated but creation of Java ByteBuffer
     /// requires the underlying bytes to be mutable.
     #[allow(unused)]
     #[cxx_name = "aesDecrypt"]
     fn decrypt(
       key: &mut [u8],
       sealed_data: &mut [u8],
       plaintext: &mut [u8],
     ) -> Result<()>;
   }
 
   // Comm Services Auth Metadata Emission
   #[namespace = "comm"]
   unsafe extern "C++" {
     include!("RustCSAMetadataEmitter.h");
 
     #[allow(unused)]
     #[cxx_name = "sendAuthMetadataToJS"]
     fn send_auth_metadata_to_js(
       access_token: String,
       user_id: String,
     ) -> Result<()>;
   }
 
   // Backup
   extern "Rust" {
     #[cxx_name = "startBackupHandler"]
     fn start_backup_handler() -> Result<()>;
     #[cxx_name = "stopBackupHandler"]
     fn stop_backup_handler() -> Result<()>;
 
     #[cxx_name = "triggerBackupFileUpload"]
     fn trigger_backup_file_upload();
 
     #[cxx_name = "createBackup"]
     fn create_backup(
       backup_id: String,
       backup_secret: String,
       pickle_key: String,
       pickled_account: String,
       siwe_backup_msg: String,
       promise_id: u32,
     );
 
     #[cxx_name = "restoreBackup"]
     fn restore_backup(
       backup_secret: String,
       backup_id: String,
       max_version: String,
       promise_id: u32,
     );
 
     #[cxx_name = "restoreBackupData"]
     fn restore_backup_data(
       backup_id: String,
       backup_data_key: String,
       backup_log_data_key: String,
       max_version: String,
       promise_id: u32,
     );
 
     #[cxx_name = "retrieveBackupKeys"]
     fn retrieve_backup_keys(backup_secret: String, promise_id: u32);
 
     #[cxx_name = "retrieveLatestSIWEBackupData"]
     fn retrieve_latest_siwe_backup_data(promise_id: u32);
   }
 
   // Secure store
   #[namespace = "comm"]
   unsafe extern "C++" {
     include!("RustSecureStore.h");
 
     #[allow(unused)]
     #[cxx_name = "secureStoreSet"]
     fn secure_store_set(key: &str, value: String) -> Result<()>;
 
     #[cxx_name = "secureStoreGet"]
     fn secure_store_get(key: &str) -> Result<String>;
   }
 
   // C++ Backup creation
   #[namespace = "comm"]
   unsafe extern "C++" {
     include!("RustBackupExecutor.h");
 
     #[cxx_name = "getBackupDirectoryPath"]
     fn get_backup_directory_path() -> Result<String>;
 
     #[cxx_name = "getBackupFilePath"]
     fn get_backup_file_path(
       backup_id: &str,
       is_attachments: bool,
     ) -> Result<String>;
 
     #[cxx_name = "getBackupLogFilePath"]
     fn get_backup_log_file_path(
       backup_id: &str,
       log_id: &str,
       is_attachments: bool,
     ) -> Result<String>;
 
     #[cxx_name = "getBackupUserKeysFilePath"]
     fn get_backup_user_keys_file_path(backup_id: &str) -> Result<String>;
 
     #[cxx_name = "getSIWEBackupMessagePath"]
     fn get_siwe_backup_message_path(backup_id: &str) -> Result<String>;
 
     #[cxx_name = "createMainCompaction"]
     fn create_main_compaction(backup_id: &str, future_id: usize);
 
     #[cxx_name = "restoreFromMainCompaction"]
     fn restore_from_main_compaction(
       main_compaction_path: &str,
       main_compaction_encryption_key: &str,
       max_version: &str,
       future_id: usize,
     );
 
     #[cxx_name = "restoreFromBackupLog"]
     fn restore_from_backup_log(backup_log: Vec<u8>, future_id: usize);
   }
 
   // Future handling from C++
   extern "Rust" {
     #[cxx_name = "resolveUnitFuture"]
     fn resolve_unit_future(future_id: usize);
 
     #[cxx_name = "rejectFuture"]
     fn reject_future(future_id: usize, error: String);
   }
 }
 
 #[derive(
   Debug, derive_more::Display, derive_more::From, derive_more::Error,
 )]
 pub enum Error {
   #[display(fmt = "{}", "_0.message()")]
   TonicGRPC(Status),
   #[display(fmt = "{}", "_0")]
   SerdeJson(serde_json::Error),
   #[display(fmt = "Missing response data")]
   MissingResponseData,
   #[display(fmt = "{}", "_0")]
   GRPClient(grpc_clients::error::Error),
 }
 
 #[cfg(test)]
 #[allow(clippy::assertions_on_constants)]
 mod tests {
   use super::{BACKUP_SOCKET_ADDR, CODE_VERSION, IDENTITY_SOCKET_ADDR};
 
   #[test]
   fn test_code_version_exists() {
     assert!(CODE_VERSION > 0);
   }
 
   #[test]
   fn test_identity_socket_addr_exists() {
     assert!(!IDENTITY_SOCKET_ADDR.is_empty());
     assert!(!BACKUP_SOCKET_ADDR.is_empty());
   }
 }
diff --git a/native/schema/CommRustModuleSchema.js b/native/schema/CommRustModuleSchema.js
index 35cfb656f..7406652ce 100644
--- a/native/schema/CommRustModuleSchema.js
+++ b/native/schema/CommRustModuleSchema.js
@@ -1,203 +1,208 @@
 // @flow
 
 'use strict';
 
 import { TurboModuleRegistry } from 'react-native';
 import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport.js';
 
 export interface Spec extends TurboModule {
   +generateNonce: () => Promise<string>;
   +registerPasswordUser: (
     username: string,
     password: string,
     keyPayload: string,
     keyPayloadSignature: string,
     contentPrekey: string,
     contentPrekeySignature: string,
     notifPrekey: string,
     notifPrekeySignature: string,
     contentOneTimeKeys: $ReadOnlyArray<string>,
     notifOneTimeKeys: $ReadOnlyArray<string>,
     farcasterID: string,
     initialDeviceList: string,
   ) => Promise<string>;
   +registerReservedPasswordUser: (
     username: string,
     password: string,
     keyPayload: string,
     keyPayloadSignature: string,
     contentPrekey: string,
     contentPrekeySignature: string,
     notifPrekey: string,
     notifPrekeySignature: string,
     contentOneTimeKeys: $ReadOnlyArray<string>,
     notifOneTimeKeys: $ReadOnlyArray<string>,
     keyserverMessage: string,
     keyserverSignature: string,
     initialDeviceList: string,
   ) => Promise<string>;
   +logInPasswordUser: (
     username: string,
     password: string,
     keyPayload: string,
     keyPayloadSignature: string,
     contentPrekey: string,
     contentPrekeySignature: string,
     notifPrekey: string,
     notifPrekeySignature: string,
   ) => Promise<string>;
   +registerWalletUser: (
     siweMessage: string,
     siweSignature: string,
     keyPayload: string,
     keyPayloadSignature: string,
     contentPrekey: string,
     contentPrekeySignature: string,
     notifPrekey: string,
     notifPrekeySignature: string,
     contentOneTimeKeys: $ReadOnlyArray<string>,
     notifOneTimeKeys: $ReadOnlyArray<string>,
     farcasterID: string,
     initialDeviceList: string,
   ) => Promise<string>;
   +registerReservedWalletUser: (
     siweMessage: string,
     siweSignature: string,
     keyPayload: string,
     keyPayloadSignature: string,
     contentPrekey: string,
     contentPrekeySignature: string,
     notifPrekey: string,
     notifPrekeySignature: string,
     contentOneTimeKeys: $ReadOnlyArray<string>,
     notifOneTimeKeys: $ReadOnlyArray<string>,
     keyserverMessage: string,
     keyserverSignature: string,
     initialDeviceList: string,
   ) => Promise<string>;
   +logInWalletUser: (
     siweMessage: string,
     siweSignature: string,
     keyPayload: string,
     keyPayloadSignature: string,
     contentPrekey: string,
     contentPrekeySignature: string,
     notifPrekey: string,
     notifPrekeySignature: string,
   ) => Promise<string>;
   +updatePassword: (
     userID: string,
     deviceID: string,
     accessToken: string,
     password: string,
   ) => Promise<void>;
   +deletePasswordUser: (
     userID: string,
     deviceID: string,
     accessToken: string,
     password: string,
   ) => Promise<void>;
   +deleteWalletUser: (
     userID: string,
     deviceID: string,
     accessToken: string,
   ) => Promise<void>;
   +logOut: (
     userID: string,
     deviceID: string,
     accessToken: string,
   ) => Promise<void>;
   +logOutSecondaryDevice: (
     userID: string,
     deviceID: string,
     accessToken: string,
   ) => Promise<void>;
   +getOutboundKeysForUser: (
     authUserID: string,
     authDeviceID: string,
     authAccessToken: string,
     userID: string,
   ) => Promise<string>;
   +getInboundKeysForUser: (
     authUserID: string,
     authDeviceID: string,
     authAccessToken: string,
     userID: string,
   ) => Promise<string>;
   +versionSupported: () => Promise<boolean>;
   +uploadOneTimeKeys: (
     authUserID: string,
     authDeviceID: string,
     authAccessToken: string,
     contentOneTimePreKeys: $ReadOnlyArray<string>,
     notifOneTimePreKeys: $ReadOnlyArray<string>,
   ) => Promise<void>;
   +getKeyserverKeys: (
     authUserID: string,
     authDeviceID: string,
     authAccessToken: string,
     keyserverID: string,
   ) => Promise<string>;
   +getDeviceListForUser: (
     authUserID: string,
     authDeviceID: string,
     authAccessToken: string,
     userID: string,
     sinceTimestamp: ?number,
   ) => Promise<string>;
   +getDeviceListsForUsers: (
     authUserID: string,
     authDeviceID: string,
     authAccessToken: string,
     userIDs: $ReadOnlyArray<string>,
   ) => Promise<string>;
   +updateDeviceList: (
     authUserID: string,
     authDeviceID: string,
     authAccessToken: string,
     updatePayload: string,
   ) => Promise<void>;
+  +syncPlatformDetails: (
+    authUserID: string,
+    authDeviceID: string,
+    authAccessToken: string,
+  ) => Promise<void>;
   +uploadSecondaryDeviceKeysAndLogIn: (
     userID: string,
     nonce: string,
     nonceSignature: string,
     keyPayload: string,
     keyPayloadSignature: string,
     contentPrekey: string,
     contentPrekeySignature: string,
     notifPrekey: string,
     notifPrekeySignature: string,
     contentOneTimeKeys: $ReadOnlyArray<string>,
     notifOneTimeKeys: $ReadOnlyArray<string>,
   ) => Promise<string>;
   +logInExistingDevice: (
     userID: string,
     deviceID: string,
     nonce: string,
     nonceSignature: string,
   ) => Promise<string>;
   +findUserIDForWalletAddress: (walletAddress: string) => Promise<string>;
   +findUserIDForUsername: (username: string) => Promise<string>;
   +getFarcasterUsers: (farcasterIDs: $ReadOnlyArray<string>) => Promise<string>;
   +linkFarcasterAccount: (
     userID: string,
     deviceID: string,
     accessToken: string,
     farcasterID: string,
   ) => Promise<void>;
   +unlinkFarcasterAccount: (
     userID: string,
     deviceID: string,
     accessToken: string,
   ) => Promise<void>;
   +findUserIdentities: (
     authUserID: string,
     authDeviceID: string,
     authAccessToken: string,
     userIDs: $ReadOnlyArray<string>,
   ) => Promise<string>;
 }
 
 export default (TurboModuleRegistry.getEnforcing<Spec>(
   'CommRustTurboModule',
 ): Spec);