Skip to content

Commit d24392c

Browse files
committed
ThirdwebWallet -> SmarterWallet + fix yParity geth
1 parent 77f8944 commit d24392c

File tree

5 files changed

+72
-73
lines changed

5 files changed

+72
-73
lines changed

Thirdweb.Console/Program.cs

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -326,35 +326,34 @@
326326

327327
#region EIP-7702
328328

329-
// var chain = 11155111; // sepolia
330-
331-
// // Connect to EOA
332-
// var userWallet = await InAppWallet.Create(client, authProvider: AuthProvider.Github);
333-
// if (!await userWallet.IsConnected())
334-
// {
335-
// _ = await userWallet.LoginWithOauth(
336-
// isMobile: false,
337-
// browserOpenAction: (url) =>
338-
// {
339-
// var psi = new ProcessStartInfo { FileName = url, UseShellExecute = true };
340-
// _ = Process.Start(psi);
341-
// }
342-
// );
343-
// }
344-
// Console.WriteLine($"User Wallet address: {await userWallet.GetAddress()}");
345-
346-
// // Upgrade EOA - This wallet explicitly uses EIP-7702 delegation to the thirdweb MinimalAccount (will delegate upon first tx)
347-
// var thirdwebWallet = await ThirdwebWallet.Create(client, chain, userWallet, ExecutionMode.EIP7702);
348-
// var thirdwebWalletAddress = await thirdwebWallet.GetAddress();
349-
// Console.WriteLine($"Thirdweb Wallet address: {thirdwebWalletAddress}"); // same as userWallet address, unlike when using EIP-4337
350-
351-
// // Transact, will upgrade EOA
352-
// var receipt = await thirdwebWallet.Transfer(chainId: chain, toAddress: await Utils.GetAddressFromENS(client, "vitalik.eth"), weiAmount: 0);
353-
// Console.WriteLine($"Transfer Receipt: {receipt.TransactionHash}");
354-
355-
// // Double check that it was upgraded
356-
// var isDelegated = await Utils.IsDelegatedAccount(client, chain, thirdwebWalletAddress);
357-
// Console.WriteLine($"Is delegated: {isDelegated}");
329+
var chain = 11155111; // sepolia
330+
331+
// Connect to EOA
332+
var userWallet = await InAppWallet.Create(client, email: "[email protected]");
333+
if (!await userWallet.IsConnected())
334+
{
335+
await userWallet.SendOTP();
336+
Console.WriteLine("Enter OTP:");
337+
var otp = Console.ReadLine();
338+
_ = await userWallet.LoginWithOtp(otp: otp);
339+
}
340+
Console.WriteLine($"User Wallet address: {await userWallet.GetAddress()}");
341+
342+
Console.WriteLine("Send it some gas if testing with ExecutionMode.EOA");
343+
Console.ReadLine();
344+
345+
// Upgrade EOA - This wallet explicitly uses EIP-7702 delegation to the thirdweb MinimalAccount (will delegate upon first tx)
346+
var smarterWallet = await SmarterWallet.Create(client, chain, userWallet, ExecutionMode.EOA);
347+
var smarterWalletAddress = await smarterWallet.GetAddress();
348+
Console.WriteLine($"Thirdweb Wallet address: {smarterWalletAddress}"); // same as userWallet address, unlike when using EIP-4337
349+
350+
// Transact, will upgrade EOA
351+
var receipt = await smarterWallet.Transfer(chainId: chain, toAddress: await Utils.GetAddressFromENS(client, "vitalik.eth"), weiAmount: 0);
352+
Console.WriteLine($"Transfer Receipt: {receipt.TransactionHash}");
353+
354+
// Double check that it was upgraded
355+
var isDelegated = await Utils.IsDelegatedAccount(client, chain, smarterWalletAddress);
356+
Console.WriteLine($"Is delegated: {isDelegated}");
358357

359358
#endregion
360359

Thirdweb/Thirdweb.RPC/ThirdwebRPC.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ private ThirdwebRPC(ThirdwebClient client, BigInteger chainId)
168168
private async Task SendBatchAsync(List<RpcRequest> batch)
169169
{
170170
var batchJson = JsonConvert.SerializeObject(batch);
171+
Console.WriteLine($"Sending batch request: {batchJson}");
171172
var content = new StringContent(batchJson, Encoding.UTF8, "application/json");
172173

173174
try
@@ -182,6 +183,7 @@ private async Task SendBatchAsync(List<RpcRequest> batch)
182183
}
183184

184185
var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
186+
Console.WriteLine(responseContent);
185187
if (responseContent.Equals("Unauthorized", StringComparison.OrdinalIgnoreCase))
186188
{
187189
throw new HttpRequestException("Unauthorized");

Thirdweb/Thirdweb.Transactions/ThirdwebTransactionInput.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ public EIP7702Authorization(BigInteger chainId, string address, BigInteger nonce
214214
this.ChainId = new HexBigInteger(chainId).HexValue;
215215
this.Address = address;
216216
this.Nonce = new HexBigInteger(nonce).HexValue;
217-
this.YParity = yParity.BytesToHex();
217+
this.YParity = yParity.BytesToHex() == "0x00" ? "0x0" : "0x1";
218218
this.R = r.BytesToHex();
219219
this.S = s.BytesToHex();
220220
}

Thirdweb/Thirdweb.Wallets/PrivateKeyWallet/PrivateKeyWallet.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ public virtual Task<string> SignTransaction(ThirdwebTransactionInput transaction
356356
RLP.EncodeElement(authorizationList.ChainId.HexToNumber().ToByteArrayForRLPEncoding()),
357357
RLP.EncodeElement(authorizationList.Address.HexToBytes()),
358358
RLP.EncodeElement(authorizationList.Nonce.HexToNumber().ToByteArrayForRLPEncoding()),
359-
RLP.EncodeElement(authorizationList.YParity == "0x00" ? Array.Empty<byte>() : authorizationList.YParity.HexToBytes()),
359+
RLP.EncodeElement(authorizationList.YParity is "0x00" or "0x0" or "0x" ? Array.Empty<byte>() : authorizationList.YParity.HexToBytes()),
360360
RLP.EncodeElement(authorizationList.R.HexToBytes().TrimZeroes()),
361361
RLP.EncodeElement(authorizationList.S.HexToBytes().TrimZeroes())
362362
};

Thirdweb/Thirdweb.Wallets/ThirdwebWallet.cs renamed to Thirdweb/Thirdweb.Wallets/SmarterWallet.cs

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ public enum ExecutionMode
88
{
99
EOA,
1010
EIP7702,
11-
EIP7702Sponsored
1211
}
1312

1413
/// <summary>
1514
/// Represents a 7702 delegated wallet with granular session key permissions and automatic session key execution.
1615
/// </summary>
17-
public class ThirdwebWallet : IThirdwebWallet
16+
public class SmarterWallet : IThirdwebWallet
1817
{
19-
public string WalletId => "thirdweb";
18+
public string WalletId => "smarter";
2019

2120
public ThirdwebClient Client { get; }
2221
public ThirdwebAccountType AccountType => ThirdwebAccountType.ExternalAccount;
@@ -28,7 +27,7 @@ public class ThirdwebWallet : IThirdwebWallet
2827

2928
private EIP7702Authorization? Authorization { get; set; }
3029

31-
internal ThirdwebWallet(ThirdwebClient client, BigInteger chainId, IThirdwebWallet userWallet, ThirdwebContract userContract, EIP7702Authorization? authorization, ExecutionMode executionMode)
30+
internal SmarterWallet(ThirdwebClient client, BigInteger chainId, IThirdwebWallet userWallet, ThirdwebContract userContract, EIP7702Authorization? authorization, ExecutionMode executionMode)
3231
{
3332
this.Client = client;
3433
this.ChainId = chainId;
@@ -38,15 +37,15 @@ internal ThirdwebWallet(ThirdwebClient client, BigInteger chainId, IThirdwebWall
3837
this.ExecutionMode = executionMode;
3938
}
4039

41-
public static async Task<ThirdwebWallet> Create(ThirdwebClient client, BigInteger chainId, IThirdwebWallet userWallet, ExecutionMode executionMode)
40+
public static async Task<SmarterWallet> Create(ThirdwebClient client, BigInteger chainId, IThirdwebWallet userWallet, ExecutionMode executionMode)
4241
{
4342
var userWalletAddress = await userWallet.GetAddress();
4443
var userContract = await ThirdwebContract.Create(client, userWalletAddress, chainId, Constants.MINIMAL_ACCOUNT_7702_ABI);
4544
var needsDelegation = !await Utils.IsDelegatedAccount(client, chainId, userWalletAddress);
4645
EIP7702Authorization? authorization = needsDelegation
47-
? await userWallet.SignAuthorization(chainId, Constants.MINIMAL_ACCOUNT_7702, willSelfExecute: executionMode != ExecutionMode.EIP7702Sponsored)
46+
? await userWallet.SignAuthorization(chainId, Constants.MINIMAL_ACCOUNT_7702, willSelfExecute: executionMode != ExecutionMode.EIP7702)
4847
: null;
49-
var wallet = new ThirdwebWallet(client, chainId, userWallet, userContract, authorization, executionMode);
48+
var wallet = new SmarterWallet(client, chainId, userWallet, userContract, authorization, executionMode);
5049
Utils.TrackConnection(wallet);
5150
return wallet;
5251
}
@@ -130,54 +129,53 @@ public Task<string> SignTransaction(ThirdwebTransactionInput transaction)
130129

131130
public async Task<string> SendTransaction(ThirdwebTransactionInput transaction)
132131
{
133-
// TODO: managed execution - executeWithSig
134-
if (this.ExecutionMode == ExecutionMode.EIP7702Sponsored)
132+
ThirdwebTransaction finalTx;
133+
switch (this.ExecutionMode)
135134
{
136-
throw new NotImplementedException("EIP7702 Sponsored Execution mode is not yet implemented.");
137-
135+
case ExecutionMode.EIP7702:
136+
throw new NotImplementedException("EIP7702 Sponsored Execution mode is not yet implemented.");
138137
// 1. Create payload with eoa address, wrapped calls, signature and optional authorizationList
139138
// 2. Send to https://{chainId}.bundler.thirdweb.com as RpcRequest w/ method tw_execute
140139
// 3. Retrieve tx hash or queue id from response
141140
// 4. Return tx hash
142-
}
143-
else if (this.ExecutionMode == ExecutionMode.EIP7702)
144-
{
145-
var calls = new List<Call>
146-
{
147-
new()
141+
case ExecutionMode.EOA:
142+
// Direct Call struct
143+
var calls = new List<Call>
148144
{
149-
Target = transaction.To,
150-
Value = transaction.Value?.Value ?? BigInteger.Zero,
151-
Data = transaction.Data.HexToBytes()
145+
new()
146+
{
147+
Target = transaction.To,
148+
Value = transaction.Value?.Value ?? BigInteger.Zero,
149+
Data = transaction.Data.HexToBytes()
150+
}
151+
};
152+
// Add up values of all calls
153+
BigInteger totalValue = 0;
154+
foreach (var call in calls)
155+
{
156+
totalValue += call.Value;
152157
}
153-
};
158+
// 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;
161+
default:
162+
throw new NotImplementedException($"Execution mode {this.ExecutionMode} is not supported.");
163+
}
154164

155-
BigInteger totalValue = 0;
156-
foreach (var call in calls)
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()))
157169
{
158-
totalValue += call.Value;
170+
finalTx.Input.AuthorizationList = new List<EIP7702Authorization>() { this.Authorization.Value };
159171
}
160-
161-
var tx = await this.UserContract.Prepare(wallet: this.UserWallet, method: "execute", weiValue: totalValue, parameters: new object[] { calls });
162-
163-
if (this.Authorization != null)
172+
else
164173
{
165-
if (!await Utils.IsDelegatedAccount(this.Client, this.ChainId, await this.UserWallet.GetAddress()))
166-
{
167-
tx.Input.AuthorizationList = new List<EIP7702Authorization>() { this.Authorization.Value };
168-
}
169-
else
170-
{
171-
this.Authorization = null;
172-
}
174+
this.Authorization = null;
173175
}
174-
175-
return await ThirdwebTransaction.Send(tx);
176-
}
177-
else
178-
{
179-
return await this.UserWallet.SendTransaction(transaction);
180176
}
177+
// Send the transaction and return the
178+
return await ThirdwebTransaction.Send(finalTx);
181179
}
182180

183181
public async Task<ThirdwebTransactionReceipt> ExecuteTransaction(ThirdwebTransactionInput transaction)

0 commit comments

Comments
 (0)