diff --git a/Thirdweb.Console/Program.cs b/Thirdweb.Console/Program.cs index 45caf81..a6af2e0 100644 --- a/Thirdweb.Console/Program.cs +++ b/Thirdweb.Console/Program.cs @@ -25,7 +25,7 @@ var privateKeyWallet = await PrivateKeyWallet.Create(client: client, privateKeyHex: privateKey); // var inAppWallet = await InAppWallet.Create(client: client, email: "firekeeper+7121271d@thirdweb.com"); // or email: null, phoneNumber: "+1234567890" -var inAppWallet = await InAppWallet.Create(client: client, authprovider: AuthProvider.Google); // or email: null, phoneNumber: "+1234567890" +// var inAppWallet = await InAppWallet.Create(client: client, authprovider: AuthProvider.Google); // or email: null, phoneNumber: "+1234567890" // Reset InAppWallet (optional step for testing login flow) // if (await inAppWallet.IsConnected()) @@ -34,35 +34,35 @@ // } // Relog if InAppWallet not logged in -if (!await inAppWallet.IsConnected()) -{ - var address = await inAppWallet.LoginWithOauth( - isMobile: false, - (url) => - { - var psi = new ProcessStartInfo { FileName = url, UseShellExecute = true }; - _ = Process.Start(psi); - }, - "thirdweb://", - new InAppWalletBrowser() - ); - Console.WriteLine($"InAppWallet address: {address}"); - // await inAppWallet.SendOTP(); - // Console.WriteLine("Please submit the OTP."); - // var otp = Console.ReadLine(); - // (var inAppWalletAddress, var canRetry) = await inAppWallet.SubmitOTP(otp); - // if (inAppWalletAddress == null && canRetry) - // { - // Console.WriteLine("Please submit the OTP again."); - // otp = Console.ReadLine(); - // (inAppWalletAddress, _) = await inAppWallet.SubmitOTP(otp); - // } - // if (inAppWalletAddress == null) - // { - // Console.WriteLine("OTP login failed. Please try again."); - // return; - // } -} +// if (!await inAppWallet.IsConnected()) +// { +// var address = await inAppWallet.LoginWithOauth( +// isMobile: false, +// (url) => +// { +// var psi = new ProcessStartInfo { FileName = url, UseShellExecute = true }; +// _ = Process.Start(psi); +// }, +// "thirdweb://", +// new InAppWalletBrowser() +// ); +// Console.WriteLine($"InAppWallet address: {address}"); +// await inAppWallet.SendOTP(); +// Console.WriteLine("Please submit the OTP."); +// var otp = Console.ReadLine(); +// (var inAppWalletAddress, var canRetry) = await inAppWallet.SubmitOTP(otp); +// if (inAppWalletAddress == null && canRetry) +// { +// Console.WriteLine("Please submit the OTP again."); +// otp = Console.ReadLine(); +// (inAppWalletAddress, _) = await inAppWallet.SubmitOTP(otp); +// } +// if (inAppWalletAddress == null) +// { +// Console.WriteLine("OTP login failed. Please try again."); +// return; +// } +// } // Prepare a transaction directly, or with Contract.Prepare // var tx = await ThirdwebTransaction.Create( @@ -92,6 +92,7 @@ // Console.WriteLine($"Transaction hash: {txHash}"); var zkSmartWallet = await SmartWallet.Create(client: client, personalWallet: privateKeyWallet, chainId: 300, gasless: true); +Console.WriteLine($"Smart wallet address: {await zkSmartWallet.GetAddress()}"); var zkSyncSignatureBasedAaTxHash = await zkSmartWallet.SendTransaction( new ThirdwebTransactionInput() { @@ -99,6 +100,7 @@ To = await zkSmartWallet.GetAddress(), Value = new HexBigInteger(BigInteger.Zero), Data = "0x", + Gas = new HexBigInteger(25000000) } ); Console.WriteLine($"Transaction hash: {zkSyncSignatureBasedAaTxHash}"); diff --git a/Thirdweb/Thirdweb.Utils/Constants.cs b/Thirdweb/Thirdweb.Utils/Constants.cs index b3de839..0caca27 100644 --- a/Thirdweb/Thirdweb.Utils/Constants.cs +++ b/Thirdweb/Thirdweb.Utils/Constants.cs @@ -14,6 +14,5 @@ public static class Constants "0x0101010101010101010101010101010101010101000000000000000000000000000000000000000000000000000001010101010100000000000000000000000000000000000000000000000000000000000000000101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"; internal const string FALLBACK_IPFS_GATEWAY = "https://ipfs.io/ipfs/"; internal const string PIN_URI = "https://storage.thirdweb.com/ipfs/upload"; - internal const string ZKSYNC_SIGNATUREBASED_PAYMASTER = "0xE74eA4e1785F74016e0076754B5ca6d8ADC10934"; } } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs index 3e14a6e..7d6c494 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs @@ -24,7 +24,6 @@ public class SmartWallet : IThirdwebWallet protected BigInteger _chainId; protected string _bundlerUrl; protected string _paymasterUrl; - protected ThirdwebContract _zkSyncPaymaster; protected bool IsZkSync => _chainId == 324 || _chainId == 300; protected SmartWallet( @@ -36,8 +35,7 @@ protected SmartWallet( string paymasterUrl, ThirdwebContract entryPointContract, ThirdwebContract factoryContract, - ThirdwebContract accountContract, - ThirdwebContract zkSyncPaymaster + ThirdwebContract accountContract ) { _client = client; @@ -49,7 +47,6 @@ ThirdwebContract zkSyncPaymaster _entryPointContract = entryPointContract; _factoryContract = factoryContract; _accountContract = accountContract; - _zkSyncPaymaster = zkSyncPaymaster; } public static async Task Create( @@ -76,18 +73,8 @@ public static async Task Create( ThirdwebContract entryPointContract = null; ThirdwebContract factoryContract = null; ThirdwebContract accountContract = null; - ThirdwebContract zkSyncPaymasterContract = null; - if (chainId == 324 || chainId == 300) - { - zkSyncPaymasterContract = await ThirdwebContract.Create( - client, - Constants.ZKSYNC_SIGNATUREBASED_PAYMASTER, - chainId, - "[{\"type\": \"constructor\",\"name\": \"\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"error\",\"name\": \"InvalidShortString\",\"inputs\": [],\"outputs\": []},{\"type\": \"error\",\"name\": \"StringTooLong\",\"inputs\": [{\"type\": \"string\",\"name\": \"str\",\"internalType\": \"string\"}],\"outputs\": []},{\"type\": \"event\",\"name\": \"EIP712DomainChanged\",\"inputs\": [],\"outputs\": [],\"anonymous\": false},{\"type\": \"event\",\"name\": \"OwnershipTransferred\",\"inputs\": [{\"type\": \"address\",\"name\": \"previousOwner\",\"indexed\": true,\"internalType\": \"address\"},{\"type\": \"address\",\"name\": \"newOwner\",\"indexed\": true,\"internalType\": \"address\"}],\"outputs\": [],\"anonymous\": false},{\"type\": \"function\",\"name\": \"SIGNATURE_TYPEHASH\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"cancelNonce\",\"inputs\": [{\"type\": \"address\",\"name\": \"_userAddress\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"changeSigner\",\"inputs\": [{\"type\": \"address\",\"name\": \"_signer\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"domainSeparator\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"eip712Domain\",\"inputs\": [],\"outputs\": [{\"type\": \"bytes1\",\"name\": \"fields\",\"internalType\": \"bytes1\"},{\"type\": \"string\",\"name\": \"name\",\"internalType\": \"string\"},{\"type\": \"string\",\"name\": \"version\",\"internalType\": \"string\"},{\"type\": \"uint256\",\"name\": \"chainId\",\"internalType\": \"uint256\"},{\"type\": \"address\",\"name\": \"verifyingContract\",\"internalType\": \"address\"},{\"type\": \"bytes32\",\"name\": \"salt\",\"internalType\": \"bytes32\"},{\"type\": \"uint256[]\",\"name\": \"extensions\",\"internalType\": \"uint256[]\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"nonces\",\"inputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"outputs\": [{\"type\": \"uint256\",\"name\": \"\",\"internalType\": \"uint256\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"owner\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"postTransaction\",\"inputs\": [{\"type\": \"bytes\",\"name\": \"_context\",\"internalType\": \"bytes\"},{\"type\": \"tuple\",\"name\": \"_transaction\",\"components\": [{\"type\": \"uint256\",\"name\": \"txType\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"from\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"to\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasPerPubdataByteLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxPriorityFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"paymaster\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"nonce\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"value\",\"internalType\": \"uint256\"},{\"type\": \"uint256[4]\",\"name\": \"reserved\",\"internalType\": \"uint256[4]\"},{\"type\": \"bytes\",\"name\": \"data\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"signature\",\"internalType\": \"bytes\"},{\"type\": \"bytes32[]\",\"name\": \"factoryDeps\",\"internalType\": \"bytes32[]\"},{\"type\": \"bytes\",\"name\": \"paymasterInput\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"reservedDynamic\",\"internalType\": \"bytes\"}],\"internalType\": \"struct Transaction\"},{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"uint8\",\"name\": \"_txResult\",\"internalType\": \"enum ExecutionResult\"},{\"type\": \"uint256\",\"name\": \"_maxRefundedGas\",\"internalType\": \"uint256\"}],\"outputs\": [],\"stateMutability\": \"payable\"},{\"type\": \"function\",\"name\": \"renounceOwnership\",\"inputs\": [],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"signer\",\"inputs\": [],\"outputs\": [{\"type\": \"address\",\"name\": \"\",\"internalType\": \"address\"}],\"stateMutability\": \"view\"},{\"type\": \"function\",\"name\": \"transferOwnership\",\"inputs\": [{\"type\": \"address\",\"name\": \"newOwner\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"function\",\"name\": \"validateAndPayForPaymasterTransaction\",\"inputs\": [{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"bytes32\",\"name\": \"\",\"internalType\": \"bytes32\"},{\"type\": \"tuple\",\"name\": \"_transaction\",\"components\": [{\"type\": \"uint256\",\"name\": \"txType\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"from\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"to\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"gasPerPubdataByteLimit\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"maxPriorityFeePerGas\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"paymaster\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"nonce\",\"internalType\": \"uint256\"},{\"type\": \"uint256\",\"name\": \"value\",\"internalType\": \"uint256\"},{\"type\": \"uint256[4]\",\"name\": \"reserved\",\"internalType\": \"uint256[4]\"},{\"type\": \"bytes\",\"name\": \"data\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"signature\",\"internalType\": \"bytes\"},{\"type\": \"bytes32[]\",\"name\": \"factoryDeps\",\"internalType\": \"bytes32[]\"},{\"type\": \"bytes\",\"name\": \"paymasterInput\",\"internalType\": \"bytes\"},{\"type\": \"bytes\",\"name\": \"reservedDynamic\",\"internalType\": \"bytes\"}],\"internalType\": \"struct Transaction\"}],\"outputs\": [{\"type\": \"bytes4\",\"name\": \"magic\",\"internalType\": \"bytes4\"},{\"type\": \"bytes\",\"name\": \"context\",\"internalType\": \"bytes\"}],\"stateMutability\": \"payable\"},{\"type\": \"function\",\"name\": \"withdraw\",\"inputs\": [{\"type\": \"address\",\"name\": \"_to\",\"internalType\": \"address\"}],\"outputs\": [],\"stateMutability\": \"nonpayable\"},{\"type\": \"receive\",\"name\": \"\",\"inputs\": [],\"outputs\": [],\"stateMutability\": \"payable\"}]" - ); - } - else + if (chainId != 324 && chainId != 300) { entryPointContract = await ThirdwebContract.Create( client, @@ -110,7 +97,7 @@ public static async Task Create( ); } - return new SmartWallet(client, personalWallet, gasless, chainId, bundlerUrl, paymasterUrl, entryPointContract, factoryContract, accountContract, zkSyncPaymasterContract); + return new SmartWallet(client, personalWallet, gasless, chainId, bundlerUrl, paymasterUrl, entryPointContract, factoryContract, accountContract); } public async Task IsDeployed() @@ -136,9 +123,8 @@ public async Task SendTransaction(ThirdwebTransactionInput transactionIn var transaction = await ThirdwebTransaction.Create(_client, _personalAccount, transactionInput, _chainId); if (_gasless) { - var paymaster = _zkSyncPaymaster.Address; - var paymasterInput = await GetPaymasterInput(transactionInput); - transaction = transaction.SetZkSyncOptions(new ZkSyncOptions(paymaster: paymaster, paymasterInput: Utils.BytesToHex(paymasterInput))); + (var paymaster, var paymasterInput) = await GetPaymasterInput(transactionInput); + transaction = transaction.SetZkSyncOptions(new ZkSyncOptions(paymaster: paymaster, paymasterInput: paymasterInput)); } return await ThirdwebTransaction.Send(transaction); } @@ -247,16 +233,16 @@ private async Task GetNonce() return await ThirdwebContract.Read(_entryPointContract, "getNonce", await GetAddress(), randomInt192); } - private async Task GetPaymasterInput(ThirdwebTransactionInput transactionInput) + private async Task<(string, string)> GetPaymasterInput(ThirdwebTransactionInput transactionInput) { if (_gasless) { var paymasterInput = await BundlerClient.PMSponsorTransaction(_client, _paymasterUrl, 1, transactionInput); - return paymasterInput.paymasterInput.HexToByteArray(); + return (paymasterInput.paymaster, paymasterInput.paymasterInput); } else { - return new byte[] { }; + return (null, null); } } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs index 0fff7a6..53b9c5f 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/AATypes.cs @@ -93,6 +93,7 @@ public class PMSponsorOperationResponse public class PMSponsorTransactionResponse { + public string paymaster { get; set; } public string paymasterInput { get; set; } } diff --git a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs index 33a0818..d1d8a7c 100644 --- a/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs +++ b/Thirdweb/Thirdweb.Wallets/SmartWallet/Thirdweb.AccountAbstraction/BundlerClient.cs @@ -57,15 +57,8 @@ public static async Task PMSponsorUserOperation(Thir public static async Task PMSponsorTransaction(ThirdwebClient client, string paymasterUrl, object requestId, ThirdwebTransactionInput txInput) { - var response = await BundlerRequest(client, paymasterUrl, requestId, "pm_sponsorTransaction", txInput); - try - { - return JsonConvert.DeserializeObject(response.Result.ToString()); - } - catch - { - return new PMSponsorTransactionResponse() { paymasterInput = response.Result.ToString() }; - } + var response = await BundlerRequest(client, "http://127.0.0.1:8787?chain=300", requestId, "pm_sponsorTransaction", txInput); + return JsonConvert.DeserializeObject(response.Result.ToString()); } // Request