|
1 | 1 | using System.Numerics; |
2 | 2 | using Nethereum.ABI.EIP712; |
| 3 | +using Nethereum.Util; |
3 | 4 | using Thirdweb.AccountAbstraction; |
4 | 5 |
|
5 | 6 | namespace Thirdweb; |
@@ -42,9 +43,7 @@ public static async Task<SmarterWallet> Create(ThirdwebClient client, BigInteger |
42 | 43 | var userWalletAddress = await userWallet.GetAddress(); |
43 | 44 | var userContract = await ThirdwebContract.Create(client, userWalletAddress, chainId, Constants.MINIMAL_ACCOUNT_7702_ABI); |
44 | 45 | var needsDelegation = !await Utils.IsDelegatedAccount(client, chainId, userWalletAddress); |
45 | | - EIP7702Authorization? authorization = needsDelegation |
46 | | - ? await userWallet.SignAuthorization(chainId, Constants.MINIMAL_ACCOUNT_7702, willSelfExecute: executionMode != ExecutionMode.EIP7702) |
47 | | - : null; |
| 46 | + EIP7702Authorization? authorization = needsDelegation ? await userWallet.SignAuthorization(chainId, Constants.MINIMAL_ACCOUNT_7702, willSelfExecute: executionMode == ExecutionMode.EOA) : null; |
48 | 47 | var wallet = new SmarterWallet(client, chainId, userWallet, userContract, authorization, executionMode); |
49 | 48 | Utils.TrackConnection(wallet); |
50 | 49 | return wallet; |
@@ -129,53 +128,76 @@ public Task<string> SignTransaction(ThirdwebTransactionInput transaction) |
129 | 128 |
|
130 | 129 | public async Task<string> SendTransaction(ThirdwebTransactionInput transaction) |
131 | 130 | { |
132 | | - ThirdwebTransaction finalTx; |
| 131 | + var userWalletAddress = await this.UserWallet.GetAddress(); |
| 132 | + |
| 133 | + if (this.Authorization != null && await Utils.IsDelegatedAccount(this.Client, this.ChainId, userWalletAddress)) |
| 134 | + { |
| 135 | + this.Authorization = null; |
| 136 | + } |
| 137 | + |
| 138 | + var calls = new List<Call> |
| 139 | + { |
| 140 | + new() |
| 141 | + { |
| 142 | + Target = transaction.To, |
| 143 | + Value = transaction.Value?.Value ?? BigInteger.Zero, |
| 144 | + Data = transaction.Data.HexToBytes() |
| 145 | + } |
| 146 | + }; |
| 147 | + |
133 | 148 | switch (this.ExecutionMode) |
134 | 149 | { |
135 | 150 | case ExecutionMode.EIP7702: |
136 | | - throw new NotImplementedException("EIP7702 Sponsored Execution mode is not yet implemented."); |
137 | | - // 1. Create payload with eoa address, wrapped calls, signature and optional authorizationList |
138 | | - // 2. Send to https://{chainId}.bundler.thirdweb.com as RpcRequest w/ method tw_execute |
139 | | - // 3. Retrieve tx hash or queue id from response |
140 | | - // 4. Return tx hash |
| 151 | + var wrappedCalls = new WrappedCalls() { Calls = calls, Uid = Guid.NewGuid().ToByteArray().PadTo32Bytes() }; |
| 152 | + var signature = await EIP712.GenerateSignature_SmartAccount_7702_WrappedCalls("MinimalAccount", "1", this.ChainId, userWalletAddress, wrappedCalls, this.UserWallet); |
| 153 | + var response = await BundlerClient.TwExecute( |
| 154 | + client: this.Client, |
| 155 | + // url: $"{this.ChainId}.bundler.thirdweb.com", |
| 156 | + url: "http://localhost:8787?chain=11155111", |
| 157 | + requestId: 7702, |
| 158 | + eoaAddress: userWalletAddress, |
| 159 | + wrappedCalls: wrappedCalls, |
| 160 | + signature: signature, |
| 161 | + authorization: this.Authorization != null && !await Utils.IsDelegatedAccount(this.Client, this.ChainId, userWalletAddress) ? this.Authorization : null |
| 162 | + ); |
| 163 | + throw new NotImplementedException($"EIP-7702 transaction execution is not done, here's the queue id: {response.QueueId}"); |
| 164 | + // string txHash = null; |
| 165 | + // var ct = new CancellationTokenSource(this.Client.FetchTimeoutOptions.GetTimeout(TimeoutType.Other)); |
| 166 | + // try |
| 167 | + // { |
| 168 | + // while (txHash == null) |
| 169 | + // { |
| 170 | + // ct.Token.ThrowIfCancellationRequested(); |
| 171 | + |
| 172 | + // var txReceipt = await BundlerClient.TwGetTransactionReceipt(client: this.Client, url: $"{this.ChainId}.bundler.thirdweb.com", requestId: 7702, queueId).ConfigureAwait(false); |
| 173 | + |
| 174 | + // txHash = txReceipt?.Receipt?.TransactionHash; |
| 175 | + // await ThirdwebTask.Delay(100, ct.Token).ConfigureAwait(false); |
| 176 | + // } |
| 177 | + // } |
| 178 | + // catch (OperationCanceledException) |
| 179 | + // { |
| 180 | + // throw new Exception($"EIP-7702 sponsored transaction timed out with queue id: {queueId}"); |
| 181 | + // } |
| 182 | + // break; |
141 | 183 | case ExecutionMode.EOA: |
142 | | - // Direct Call struct |
143 | | - var calls = new List<Call> |
144 | | - { |
145 | | - new() |
146 | | - { |
147 | | - Target = transaction.To, |
148 | | - Value = transaction.Value?.Value ?? BigInteger.Zero, |
149 | | - Data = transaction.Data.HexToBytes() |
150 | | - } |
151 | | - }; |
152 | 184 | // Add up values of all calls |
153 | 185 | BigInteger totalValue = 0; |
154 | 186 | foreach (var call in calls) |
155 | 187 | { |
156 | 188 | totalValue += call.Value; |
157 | 189 | } |
158 | 190 | // Prepare a tx using the user wallet as the executor |
159 | | - finalTx = await this.UserContract.Prepare(wallet: this.UserWallet, method: "execute", weiValue: totalValue, parameters: new object[] { calls }); |
160 | | - break; |
| 191 | + var finalTx = await this.UserContract.Prepare(wallet: this.UserWallet, method: "execute", weiValue: totalValue, parameters: new object[] { calls }); |
| 192 | + finalTx.Input.AuthorizationList = this.Authorization != null ? new List<EIP7702Authorization>() { this.Authorization.Value } : null; |
| 193 | + |
| 194 | + // Append authorization if not delegated yet |
| 195 | + |
| 196 | + // Send the transaction and return the |
| 197 | + return await ThirdwebTransaction.Send(finalTx); |
161 | 198 | default: |
162 | 199 | throw new NotImplementedException($"Execution mode {this.ExecutionMode} is not supported."); |
163 | 200 | } |
164 | | - |
165 | | - // Append authorization if not delegated yet |
166 | | - if (this.Authorization != null) |
167 | | - { |
168 | | - if (!await Utils.IsDelegatedAccount(this.Client, this.ChainId, await this.UserWallet.GetAddress())) |
169 | | - { |
170 | | - finalTx.Input.AuthorizationList = new List<EIP7702Authorization>() { this.Authorization.Value }; |
171 | | - } |
172 | | - else |
173 | | - { |
174 | | - this.Authorization = null; |
175 | | - } |
176 | | - } |
177 | | - // Send the transaction and return the |
178 | | - return await ThirdwebTransaction.Send(finalTx); |
179 | 201 | } |
180 | 202 |
|
181 | 203 | public async Task<ThirdwebTransactionReceipt> ExecuteTransaction(ThirdwebTransactionInput transaction) |
|
0 commit comments