Skip to content

Commit a6afc39

Browse files
authored
Improve Analytics (#125)
1 parent 5348711 commit a6afc39

File tree

10 files changed

+107
-44
lines changed

10 files changed

+107
-44
lines changed

Directory.Packages.props

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
88
<PrivateAssets>all</PrivateAssets>
99
</PackageVersion>
10+
<PackageVersion Include="Moq" Version="4.20.72" />
1011
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
1112
<PackageVersion Include="dotenv.net" Version="3.1.3" />
1213
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.7.1" />

Thirdweb.Console/Program.cs

+5-21
Original file line numberDiff line numberDiff line change
@@ -44,32 +44,16 @@
4444

4545
#region AA 0.6
4646

47-
// var smartWallet06 = await SmartWallet.Create(
48-
// personalWallet: privateKeyWallet,
49-
// chainId: 421614,
50-
// gasless: true,
51-
// factoryAddress: "0xa8deE7854fb1eA8c13b713585C81d91ea86dAD84",
52-
// entryPoint: Constants.ENTRYPOINT_ADDRESS_V06
53-
// );
54-
55-
// var receipt06 = await smartWallet06.ExecuteTransaction(new ThirdwebTransactionInput(chainId: 421614, to: await smartWallet06.GetAddress(), value: 0, data: "0x"));
56-
47+
// var smartWallet06 = await SmartWallet.Create(personalWallet: privateKeyWallet, chainId: 421614, gasless: true);
48+
// var receipt06 = await smartWallet06.Transfer(chainId: 421614, toAddress: await smartWallet06.GetAddress(), weiAmount: 0);
5749
// Console.WriteLine($"Receipt: {receipt06}");
5850

5951
#endregion
6052

6153
#region AA 0.7
6254

63-
// var smartWallet07 = await SmartWallet.Create(
64-
// personalWallet: privateKeyWallet,
65-
// chainId: 421614,
66-
// gasless: true,
67-
// factoryAddress: "0x4f4e40E8F66e3Cc0FD7423E2fbd62A769ff551FB",
68-
// entryPoint: Constants.ENTRYPOINT_ADDRESS_V07
69-
// );
70-
71-
// var receipt07 = await smartWallet07.ExecuteTransaction(new ThirdwebTransactionInput(chainId: 421614, to: await smartWallet07.GetAddress(), value: 0, data: "0x"));
72-
55+
// var smartWallet07 = await SmartWallet.Create(personalWallet: privateKeyWallet, chainId: 421614, gasless: true, entryPoint: Constants.ENTRYPOINT_ADDRESS_V07);
56+
// var receipt07 = await smartWallet07.Transfer(chainId: 421614, toAddress: await smartWallet07.GetAddress(), weiAmount: 0);
7357
// Console.WriteLine($"Receipt: {receipt07}");
7458

7559
#endregion
@@ -179,7 +163,7 @@
179163

180164
#region Smart Ecosystem Wallet
181165

182-
// var eco = await EcosystemWallet.Create(client: client, ecosystemId: "ecosystem.the-bonfire", authProvider: AuthProvider.Twitch);
166+
// var eco = await EcosystemWallet.Create(client: client, ecosystemId: "ecosystem.the-bonfire", authProvider: AuthProvider.Github);
183167
// if (!await eco.IsConnected())
184168
// {
185169
// _ = await eco.LoginWithOauth(

Thirdweb.Tests/Thirdweb.Tests.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<PrivateAssets>all</PrivateAssets>
2222
</PackageReference>
2323
<PackageReference Include="dotenv.net" />
24+
<PackageReference Include="Moq" />
2425
</ItemGroup>
2526

2627
<ItemGroup>

Thirdweb/Thirdweb.Transactions/ThirdwebTransaction.cs

+19-18
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ public class ThirdwebTransaction
3030
{
3131
public ThirdwebTransactionInput Input { get; }
3232

33-
private readonly IThirdwebWallet _wallet;
33+
internal readonly IThirdwebWallet Wallet;
3434

3535
private ThirdwebTransaction(IThirdwebWallet wallet, ThirdwebTransactionInput txInput)
3636
{
3737
this.Input = txInput;
38-
this._wallet = wallet;
38+
this.Wallet = wallet;
3939
}
4040

4141
/// <summary>
@@ -215,7 +215,7 @@ public static async Task<TotalCosts> EstimateTotalCosts(ThirdwebTransaction tran
215215
/// <returns>The estimated gas price.</returns>
216216
public static async Task<BigInteger> EstimateGasPrice(ThirdwebTransaction transaction, bool withBump = true)
217217
{
218-
return await Utils.FetchGasPrice(transaction._wallet.Client, transaction.Input.ChainId.Value, withBump).ConfigureAwait(false);
218+
return await Utils.FetchGasPrice(transaction.Wallet.Client, transaction.Input.ChainId.Value, withBump).ConfigureAwait(false);
219219
}
220220

221221
/// <summary>
@@ -226,10 +226,10 @@ public static async Task<BigInteger> EstimateGasPrice(ThirdwebTransaction transa
226226
/// <returns>The estimated maximum fee per gas and maximum priority fee per gas.</returns>
227227
public static async Task<(BigInteger maxFeePerGas, BigInteger maxPriorityFeePerGas)> EstimateGasFees(ThirdwebTransaction transaction, bool withBump = true)
228228
{
229-
var rpc = ThirdwebRPC.GetRpcInstance(transaction._wallet.Client, transaction.Input.ChainId.Value);
229+
var rpc = ThirdwebRPC.GetRpcInstance(transaction.Wallet.Client, transaction.Input.ChainId.Value);
230230
var chainId = transaction.Input.ChainId.Value;
231231

232-
if (await Utils.IsZkSync(transaction._wallet.Client, transaction.Input.ChainId.Value).ConfigureAwait(false))
232+
if (await Utils.IsZkSync(transaction.Wallet.Client, transaction.Input.ChainId.Value).ConfigureAwait(false))
233233
{
234234
var fees = await rpc.SendRequestAsync<JToken>("zks_estimateFee", transaction.Input).ConfigureAwait(false);
235235
var maxFee = fees["max_fee_per_gas"].ToObject<HexBigInteger>().Value;
@@ -238,7 +238,7 @@ public static async Task<BigInteger> EstimateGasPrice(ThirdwebTransaction transa
238238
}
239239
else
240240
{
241-
return await Utils.FetchGasFees(transaction._wallet.Client, chainId, withBump).ConfigureAwait(false);
241+
return await Utils.FetchGasFees(transaction.Wallet.Client, chainId, withBump).ConfigureAwait(false);
242242
}
243243
}
244244

@@ -249,7 +249,7 @@ public static async Task<BigInteger> EstimateGasPrice(ThirdwebTransaction transa
249249
/// <returns>The result of the simulation.</returns>
250250
public static async Task<string> Simulate(ThirdwebTransaction transaction)
251251
{
252-
var rpc = ThirdwebRPC.GetRpcInstance(transaction._wallet.Client, transaction.Input.ChainId.Value);
252+
var rpc = ThirdwebRPC.GetRpcInstance(transaction.Wallet.Client, transaction.Input.ChainId.Value);
253253
return await rpc.SendRequestAsync<string>("eth_call", transaction.Input, "latest");
254254
}
255255

@@ -260,8 +260,8 @@ public static async Task<string> Simulate(ThirdwebTransaction transaction)
260260
/// <returns>The estimated gas limit.</returns>
261261
public static async Task<BigInteger> EstimateGasLimit(ThirdwebTransaction transaction)
262262
{
263-
var rpc = ThirdwebRPC.GetRpcInstance(transaction._wallet.Client, transaction.Input.ChainId.Value);
264-
var isZkSync = await Utils.IsZkSync(transaction._wallet.Client, transaction.Input.ChainId.Value).ConfigureAwait(false);
263+
var rpc = ThirdwebRPC.GetRpcInstance(transaction.Wallet.Client, transaction.Input.ChainId.Value);
264+
var isZkSync = await Utils.IsZkSync(transaction.Wallet.Client, transaction.Input.ChainId.Value).ConfigureAwait(false);
265265
BigInteger divider = isZkSync
266266
? 7
267267
: transaction.Input.AuthorizationList == null
@@ -288,12 +288,12 @@ public static async Task<BigInteger> EstimateGasLimit(ThirdwebTransaction transa
288288
/// <returns>The nonce.</returns>
289289
public static async Task<BigInteger> GetNonce(ThirdwebTransaction transaction)
290290
{
291-
return await transaction._wallet.GetTransactionCount(chainId: transaction.Input.ChainId, blocktag: "pending").ConfigureAwait(false);
291+
return await transaction.Wallet.GetTransactionCount(chainId: transaction.Input.ChainId, blocktag: "pending").ConfigureAwait(false);
292292
}
293293

294294
private static async Task<BigInteger> GetGasPerPubData(ThirdwebTransaction transaction)
295295
{
296-
var rpc = ThirdwebRPC.GetRpcInstance(transaction._wallet.Client, transaction.Input.ChainId.Value);
296+
var rpc = ThirdwebRPC.GetRpcInstance(transaction.Wallet.Client, transaction.Input.ChainId.Value);
297297
var hex = (await rpc.SendRequestAsync<JToken>("zks_estimateFee", transaction.Input).ConfigureAwait(false))["gas_per_pubdata_limit"].ToString();
298298
var finalGasPerPubData = new HexBigInteger(hex).Value * 10 / 5;
299299
return finalGasPerPubData < 10000 ? 10000 : finalGasPerPubData;
@@ -306,7 +306,7 @@ private static async Task<BigInteger> GetGasPerPubData(ThirdwebTransaction trans
306306
/// <returns>The signed transaction.</returns>
307307
public static async Task<string> Sign(ThirdwebTransaction transaction)
308308
{
309-
return await transaction._wallet.SignTransaction(transaction.Input).ConfigureAwait(false);
309+
return await transaction.Wallet.SignTransaction(transaction.Input).ConfigureAwait(false);
310310
}
311311

312312
/// <summary>
@@ -362,31 +362,32 @@ public static async Task<string> Send(ThirdwebTransaction transaction)
362362
{
363363
transaction = await Prepare(transaction).ConfigureAwait(false);
364364

365-
var rpc = ThirdwebRPC.GetRpcInstance(transaction._wallet.Client, transaction.Input.ChainId.Value);
365+
var rpc = ThirdwebRPC.GetRpcInstance(transaction.Wallet.Client, transaction.Input.ChainId.Value);
366366
string hash;
367367

368-
if (await Utils.IsZkSync(transaction._wallet.Client, transaction.Input.ChainId.Value).ConfigureAwait(false) && transaction.Input.ZkSync.HasValue)
368+
if (await Utils.IsZkSync(transaction.Wallet.Client, transaction.Input.ChainId.Value).ConfigureAwait(false) && transaction.Input.ZkSync.HasValue)
369369
{
370370
var zkTx = await ConvertToZkSyncTransaction(transaction).ConfigureAwait(false);
371-
var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction._wallet).ConfigureAwait(false);
371+
var zkTxSigned = await EIP712.GenerateSignature_ZkSyncTransaction("zkSync", "2", transaction.Input.ChainId.Value, zkTx, transaction.Wallet).ConfigureAwait(false);
372372
hash = await rpc.SendRequestAsync<string>("eth_sendRawTransaction", zkTxSigned).ConfigureAwait(false);
373373
}
374374
else
375375
{
376-
switch (transaction._wallet.AccountType)
376+
switch (transaction.Wallet.AccountType)
377377
{
378378
case ThirdwebAccountType.PrivateKeyAccount:
379379
var signedTx = await Sign(transaction);
380380
hash = await rpc.SendRequestAsync<string>("eth_sendRawTransaction", signedTx).ConfigureAwait(false);
381381
break;
382382
case ThirdwebAccountType.SmartAccount:
383383
case ThirdwebAccountType.ExternalAccount:
384-
hash = await transaction._wallet.SendTransaction(transaction.Input).ConfigureAwait(false);
384+
hash = await transaction.Wallet.SendTransaction(transaction.Input).ConfigureAwait(false);
385385
break;
386386
default:
387387
throw new NotImplementedException("Account type not supported");
388388
}
389389
}
390+
Utils.TrackTransaction(transaction, hash);
390391
return hash;
391392
}
392393

@@ -398,7 +399,7 @@ public static async Task<string> Send(ThirdwebTransaction transaction)
398399
public static async Task<ThirdwebTransactionReceipt> SendAndWaitForTransactionReceipt(ThirdwebTransaction transaction)
399400
{
400401
var txHash = await Send(transaction).ConfigureAwait(false);
401-
return await WaitForTransactionReceipt(transaction._wallet.Client, transaction.Input.ChainId.Value, txHash).ConfigureAwait(false);
402+
return await WaitForTransactionReceipt(transaction.Wallet.Client, transaction.Input.ChainId.Value, txHash).ConfigureAwait(false);
402403
}
403404

404405
/// <summary>

Thirdweb/Thirdweb.Utils/Utils.cs

+56
Original file line numberDiff line numberDiff line change
@@ -1191,4 +1191,60 @@ internal static byte[] ToByteArrayForRLPEncoding(this BigInteger value)
11911191

11921192
return value.ToBytesForRLPEncoding();
11931193
}
1194+
1195+
internal static async void TrackTransaction(ThirdwebTransaction transaction, string transactionHash)
1196+
{
1197+
try
1198+
{
1199+
var wallet = transaction.Wallet;
1200+
var content = new StringContent(
1201+
JsonConvert.SerializeObject(
1202+
new
1203+
{
1204+
source = "sdk",
1205+
action = "transaction:sent",
1206+
clientId = wallet.Client.ClientId,
1207+
chainId = transaction.Input.ChainId.Value,
1208+
transactionHash,
1209+
walletAddress = await wallet.GetAddress().ConfigureAwait(false),
1210+
walletType = wallet.WalletId,
1211+
contractAddress = transaction.Input.To,
1212+
gasPrice = transaction.Input.GasPrice?.Value ?? transaction.Input.MaxFeePerGas?.Value
1213+
}
1214+
),
1215+
Encoding.UTF8,
1216+
"application/json"
1217+
);
1218+
_ = await wallet.Client.HttpClient.PostAsync("https://c.thirdweb.com/event", content);
1219+
}
1220+
catch
1221+
{
1222+
// Ignore
1223+
}
1224+
}
1225+
1226+
internal static async void TrackConnection(IThirdwebWallet wallet)
1227+
{
1228+
try
1229+
{
1230+
var content = new StringContent(
1231+
JsonConvert.SerializeObject(
1232+
new
1233+
{
1234+
source = "connectWallet",
1235+
action = "connect",
1236+
walletAddress = await wallet.GetAddress().ConfigureAwait(false),
1237+
walletType = wallet.WalletId,
1238+
}
1239+
),
1240+
Encoding.UTF8,
1241+
"application/json"
1242+
);
1243+
_ = await wallet.Client.HttpClient.PostAsync("https://c.thirdweb.com/event", content);
1244+
}
1245+
catch
1246+
{
1247+
// Ignore
1248+
}
1249+
}
11941250
}

Thirdweb/Thirdweb.Wallets/IThirdwebWallet.cs

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ public interface IThirdwebWallet
1919
/// </summary>
2020
public ThirdwebAccountType AccountType { get; }
2121

22+
/// <summary>
23+
/// String identifier for the wallet to be used in analytics.
24+
/// </summary>
25+
public string WalletId { get; }
26+
2227
/// <summary>
2328
/// Gets the address of the wallet.
2429
/// </summary>

Thirdweb/Thirdweb.Wallets/InAppWallet/EcosystemWallet/EcosystemWallet.cs

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public partial class EcosystemWallet : IThirdwebWallet
1717
{
1818
public ThirdwebClient Client { get; }
1919
public ThirdwebAccountType AccountType => ThirdwebAccountType.PrivateKeyAccount;
20+
public virtual string WalletId => "ecosystem";
2021

2122
internal readonly EmbeddedWallet EmbeddedWallet;
2223
internal readonly IThirdwebHttpClient HttpClient;
@@ -259,6 +260,7 @@ private async Task<string> PostAuth(Server.VerifyResult result)
259260
{
260261
CreateEnclaveSession(this.EmbeddedWallet, result.AuthToken, this.Email, this.PhoneNumber, this.AuthProvider, result.AuthIdentifier);
261262
this.Address = address.ToChecksumAddress();
263+
Utils.TrackConnection(this);
262264
return this.Address;
263265
}
264266
}

Thirdweb/Thirdweb.Wallets/InAppWallet/InAppWallet.cs

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ namespace Thirdweb;
77
/// </summary>
88
public class InAppWallet : EcosystemWallet
99
{
10+
public override string WalletId => "inApp";
11+
1012
internal InAppWallet(
1113
ThirdwebClient client,
1214
EmbeddedWallet embeddedWallet,

Thirdweb/Thirdweb.Wallets/PrivateKeyWallet/PrivateKeyWallet.cs

+11-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public class PrivateKeyWallet : IThirdwebWallet
1717

1818
public ThirdwebAccountType AccountType => ThirdwebAccountType.PrivateKeyAccount;
1919

20+
public string WalletId => "privateKey";
21+
2022
protected EthECKey EcKey { get; set; }
2123

2224
protected PrivateKeyWallet(ThirdwebClient client, EthECKey key)
@@ -44,7 +46,9 @@ public static Task<PrivateKeyWallet> Create(ThirdwebClient client, string privat
4446
throw new ArgumentNullException(nameof(privateKeyHex), "Private key cannot be null or empty.");
4547
}
4648

47-
return Task.FromResult(new PrivateKeyWallet(client, new EthECKey(privateKeyHex)));
49+
var wallet = new PrivateKeyWallet(client, new EthECKey(privateKeyHex));
50+
Utils.TrackConnection(wallet);
51+
return Task.FromResult(wallet);
4852
}
4953

5054
#region PrivateKeyWallet Specific
@@ -61,8 +65,9 @@ public static Task<PrivateKeyWallet> Generate(ThirdwebClient client)
6165
{
6266
throw new ArgumentNullException(nameof(client));
6367
}
64-
65-
return Task.FromResult(new PrivateKeyWallet(client, EthECKey.GenerateKey()));
68+
var wallet = new PrivateKeyWallet(client, EthECKey.GenerateKey());
69+
Utils.TrackConnection(wallet);
70+
return Task.FromResult(wallet);
6671
}
6772

6873
/// <summary>
@@ -83,7 +88,9 @@ public static async Task<PrivateKeyWallet> LoadOrGenerate(ThirdwebClient client)
8388
if (File.Exists(path))
8489
{
8590
var privateKey = await File.ReadAllTextAsync(path);
86-
return new PrivateKeyWallet(client, new EthECKey(privateKey));
91+
var wallet = new PrivateKeyWallet(client, new EthECKey(privateKey));
92+
Utils.TrackConnection(wallet);
93+
return wallet;
8794
}
8895
else
8996
{

Thirdweb/Thirdweb.Wallets/SmartWallet/SmartWallet.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public class SmartWallet : IThirdwebWallet
2525

2626
public ThirdwebAccountType AccountType => ThirdwebAccountType.SmartAccount;
2727

28+
public string WalletId => "smart";
29+
2830
public bool IsDeploying { get; private set; }
2931

3032
public BigInteger ActiveChainId { get; private set; }
@@ -215,7 +217,7 @@ public static async Task<SmartWallet> Create(
215217
}
216218
}
217219

218-
return new SmartWallet(
220+
var smartWallet = new SmartWallet(
219221
personalWallet,
220222
gasless.Value,
221223
chainId,
@@ -228,6 +230,8 @@ public static async Task<SmartWallet> Create(
228230
erc20PmInfo.TokenAddress,
229231
erc20PmInfo.BalanceStorageSlot
230232
);
233+
Utils.TrackConnection(smartWallet);
234+
return smartWallet;
231235
}
232236

233237
#endregion

0 commit comments

Comments
 (0)