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))