From d171fc7ce4e86c7d3228359e8777528f12ce3ffa Mon Sep 17 00:00:00 2001 From: 0xFirekeeper <0xFirekeeper@gmail.com> Date: Tue, 7 Jan 2025 07:00:00 +0700 Subject: [PATCH] Autoconnect Feature Flag under ThirdwebManager > Preferences. If enabled, Thirdweb will automatically connect to the last connected wallet on initialization (this behavior does not apply to the WalletConnectWallet provider option). If a wallet was connected as a non smart wallet, then later upgraded, the smart wallet is saved as the last wallet, and the next session will autoconnect to the smart wallet. Any failure during this entire flow should not throw. --- .../Thirdweb/Editor/ThirdwebManagerEditor.cs | 7 + .../Thirdweb/Runtime/Unity/ThirdwebManager.cs | 129 ++++++++++++++++-- 2 files changed, 121 insertions(+), 15 deletions(-) diff --git a/Assets/Thirdweb/Editor/ThirdwebManagerEditor.cs b/Assets/Thirdweb/Editor/ThirdwebManagerEditor.cs index 9a48383b..af8b9403 100644 --- a/Assets/Thirdweb/Editor/ThirdwebManagerEditor.cs +++ b/Assets/Thirdweb/Editor/ThirdwebManagerEditor.cs @@ -13,6 +13,7 @@ public class ThirdwebManagerEditor : UnityEditor.Editor private SerializedProperty initializeOnAwakeProp; private SerializedProperty showDebugLogsProp; private SerializedProperty optOutUsageAnalyticsProp; + private SerializedProperty autoConnectLastWallet; private SerializedProperty supportedChainsProp; private SerializedProperty includedWalletIdsProp; private SerializedProperty redirectPageHtmlOverrideProp; @@ -33,6 +34,7 @@ private void OnEnable() initializeOnAwakeProp = FindProperty("InitializeOnAwake"); showDebugLogsProp = FindProperty("ShowDebugLogs"); optOutUsageAnalyticsProp = FindProperty("OptOutUsageAnalytics"); + autoConnectLastWallet = FindProperty("AutoConnectLastWallet"); supportedChainsProp = FindProperty("SupportedChains"); includedWalletIdsProp = FindProperty("IncludedWalletIds"); redirectPageHtmlOverrideProp = FindProperty("RedirectPageHtmlOverride"); @@ -158,6 +160,11 @@ private void DrawPreferencesTab() DrawProperty(initializeOnAwakeProp, "Initialize On Awake", "If enabled, Thirdweb will initialize on Awake. If disabled, you must call ThirdwebManager.Instance.Initialize() manually."); DrawProperty(showDebugLogsProp, "Show Debug Logs", "If enabled, Thirdweb will log debug messages to the console."); DrawProperty(optOutUsageAnalyticsProp, "Opt-Out of Usage Analytics", "If enabled, you may see inconsistent stats in your Thirdweb Dashboard."); + DrawProperty( + autoConnectLastWallet, + "Auto-Connect Last Wallet", + "If enabled, Thirdweb will automatically connect to the last connected wallet on initialization (this behavior does not apply to the WalletConnectWallet provider option)." + ); } private void DrawMiscTab() diff --git a/Assets/Thirdweb/Runtime/Unity/ThirdwebManager.cs b/Assets/Thirdweb/Runtime/Unity/ThirdwebManager.cs index 96852618..ae5d4a64 100644 --- a/Assets/Thirdweb/Runtime/Unity/ThirdwebManager.cs +++ b/Assets/Thirdweb/Runtime/Unity/ThirdwebManager.cs @@ -5,9 +5,11 @@ using System.Linq; using System; using System.IO; +using Newtonsoft.Json; namespace Thirdweb.Unity { + [Serializable] public enum WalletProvider { PrivateKeyWallet, @@ -17,6 +19,7 @@ public enum WalletProvider EcosystemWallet } + [Serializable] public class InAppWalletOptions : EcosystemWalletOptions { public InAppWalletOptions( @@ -39,16 +42,34 @@ public InAppWalletOptions( ) { } } + [Serializable] public class EcosystemWalletOptions { + [JsonProperty("ecosystemId")] public string EcosystemId; + + [JsonProperty("ecosystemPartnerId")] public string EcosystemPartnerId; + + [JsonProperty("email")] public string Email; + + [JsonProperty("phoneNumber")] public string PhoneNumber; + + [JsonProperty("authProvider")] public AuthProvider AuthProvider; + + [JsonProperty("jwtOrPayload")] public string JwtOrPayload; + + [JsonProperty("storageDirectoryPath")] public string StorageDirectoryPath; + + [JsonProperty("siweSigner")] public IThirdwebWallet SiweSigner; + + [JsonProperty("legacyEncryptionKey")] public string LegacyEncryptionKey; public EcosystemWalletOptions( @@ -75,14 +96,28 @@ public EcosystemWalletOptions( } } + [Serializable] public class SmartWalletOptions { + [JsonProperty("sponsorGas")] public bool SponsorGas; + + [JsonProperty("factoryAddress")] public string FactoryAddress; + + [JsonProperty("accountAddressOverride")] public string AccountAddressOverride; + + [JsonProperty("entryPoint")] public string EntryPoint; + + [JsonProperty("bundlerUrl")] public string BundlerUrl; + + [JsonProperty("paymasterUrl")] public string PaymasterUrl; + + [JsonProperty("tokenPaymaster")] public TokenPaymaster TokenPaymaster; public SmartWalletOptions( @@ -105,12 +140,22 @@ public SmartWalletOptions( } } + [Serializable] public class WalletOptions { + [JsonProperty("provider")] public WalletProvider Provider; + + [JsonProperty("chainId")] public BigInteger ChainId; + + [JsonProperty("inAppWalletOptions")] public InAppWalletOptions InAppWalletOptions; + + [JsonProperty("ecosystemWalletOptions", NullValueHandling = NullValueHandling.Ignore)] public EcosystemWalletOptions EcosystemWalletOptions; + + [JsonProperty("smartWalletOptions", NullValueHandling = NullValueHandling.Ignore)] public SmartWalletOptions SmartWalletOptions; public WalletOptions( @@ -154,6 +199,9 @@ public class ThirdwebManager : MonoBehaviour [field: SerializeField] private bool OptOutUsageAnalytics { get; set; } = false; + [field: SerializeField] + private bool AutoConnectLastWallet { get; set; } = false; + [field: SerializeField] private ulong[] SupportedChains { get; set; } = new ulong[] { 421614 }; @@ -170,11 +218,13 @@ public class ThirdwebManager : MonoBehaviour public IThirdwebWallet ActiveWallet { get; private set; } + public bool Initialized { get; private set; } + public static ThirdwebManager Instance { get; private set; } public static readonly string THIRDWEB_UNITY_SDK_VERSION = "5.14.0"; - private bool _initialized; + private const string THIRDWEB_AUTO_CONNECT_OPTIONS_KEY = "ThirdwebAutoConnectOptions"; private Dictionary _walletMapping; @@ -199,7 +249,7 @@ private void Awake() } } - public void Initialize() + public async void Initialize() { if (string.IsNullOrEmpty(ClientId)) { @@ -229,12 +279,26 @@ public void Initialize() _walletMapping = new Dictionary(); - _initialized = true; + if (AutoConnectLastWallet && GetAutoConnectOptions(out var lastWalletOptions)) + { + ThirdwebDebug.Log("Auto-connecting to last wallet."); + try + { + _ = await ConnectWallet(lastWalletOptions); + ThirdwebDebug.Log("Auto-connected to last wallet."); + } + catch (Exception e) + { + ThirdwebDebug.LogError("Failed to auto-connect to last wallet: " + e.Message); + } + } + + Initialized = true; } public async Task GetContract(string address, BigInteger chainId, string abi = null) { - if (!_initialized) + if (!Initialized) { throw new InvalidOperationException("ThirdwebManager is not initialized."); } @@ -279,11 +343,6 @@ public void RemoveWallet(string address) public async Task ConnectWallet(WalletOptions walletOptions) { - if (!_initialized) - { - throw new InvalidOperationException("ThirdwebManager is not initialized."); - } - if (walletOptions == null) { throw new ArgumentNullException(nameof(walletOptions)); @@ -420,7 +479,6 @@ public async Task ConnectWallet(WalletOptions walletOptions) } var address = await wallet.GetAddress(); - ThirdwebDebug.Log($"Wallet address: {address}"); var isSmartWallet = walletOptions.SmartWalletOptions != null; @@ -429,6 +487,8 @@ public async Task ConnectWallet(WalletOptions walletOptions) TrackUsage("connectWallet", "connect", isSmartWallet ? "smartWallet" : walletOptions.Provider.ToString()[..1].ToLower() + walletOptions.Provider.ToString()[1..], address); } + SetAutoConnectOptions(walletOptions); + if (isSmartWallet) { ThirdwebDebug.Log("Upgrading to SmartWallet."); @@ -444,11 +504,6 @@ public async Task ConnectWallet(WalletOptions walletOptions) public async Task UpgradeToSmartWallet(IThirdwebWallet personalWallet, BigInteger chainId, SmartWalletOptions smartWalletOptions) { - if (!_initialized) - { - throw new InvalidOperationException("ThirdwebManager is not initialized."); - } - if (personalWallet.AccountType == ThirdwebAccountType.SmartAccount) { ThirdwebDebug.LogWarning("Wallet is already a SmartWallet."); @@ -480,6 +535,12 @@ public async Task UpgradeToSmartWallet(IThirdwebWallet personalWall await AddWallet(wallet); SetActiveWallet(wallet); + if (AutoConnectLastWallet && GetAutoConnectOptions(out var lastWalletOptions)) + { + lastWalletOptions.SmartWalletOptions = smartWalletOptions; + SetAutoConnectOptions(lastWalletOptions); + } + return wallet; } @@ -498,6 +559,44 @@ public async Task> LinkAccount(IThirdwebWallet mainWallet, I ); } + private bool GetAutoConnectOptions(out WalletOptions lastWalletOptions) + { + var connectOptionsStr = PlayerPrefs.GetString(THIRDWEB_AUTO_CONNECT_OPTIONS_KEY, null); + if (!string.IsNullOrEmpty(connectOptionsStr)) + { + try + { + lastWalletOptions = JsonConvert.DeserializeObject(connectOptionsStr); + return true; + } + catch + { + ThirdwebDebug.LogWarning("Failed to load last wallet options."); + PlayerPrefs.DeleteKey(THIRDWEB_AUTO_CONNECT_OPTIONS_KEY); + lastWalletOptions = null; + return false; + } + } + lastWalletOptions = null; + return false; + } + + private void SetAutoConnectOptions(WalletOptions walletOptions) + { + if (AutoConnectLastWallet && walletOptions.Provider != WalletProvider.WalletConnectWallet) + { + try + { + PlayerPrefs.SetString(THIRDWEB_AUTO_CONNECT_OPTIONS_KEY, JsonConvert.SerializeObject(walletOptions)); + } + catch + { + ThirdwebDebug.LogWarning("Failed to save last wallet options."); + PlayerPrefs.DeleteKey(THIRDWEB_AUTO_CONNECT_OPTIONS_KEY); + } + } + } + private async void TrackUsage(string source, string action, string walletType, string walletAddress) { if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(action) || string.IsNullOrEmpty(walletType) || string.IsNullOrEmpty(walletAddress))