Skip to content

Releases: thirdweb-dev/dotnet

v2.18.2

28 Feb 20:58
9faa319
Compare
Choose a tag to compare

What's Changed

  • ThirdwebInsight can now return additional rich NFT Metadata when using GetTokens_ERC721 or GetTokens_ERC1155.
    • limit, page and withMetadata optional arguments have been added.
    • The Token_ERC721 and Token_ERC1155 return types can now be converted into a base SDK NFT type
    • Extensions can be used with said NFT type.
// Fetch ERC721s with extra metadata returned
var erc721Tokens = await insight.GetTokens_ERC721(address, chains, withMetadata: true);

// Use ToNFT or ToNFTList extensions
var convertedNft = erc721Tokens[0].ToNFT();
var convertedNfts = erc721Tokens.ToNFTList();

// Use NFT Extensions (GetNFTImageBytes, or GetNFTSprite in Unity)
var imageBytes = await convertedNft.GetNFTImageBytes(client);
var pathToSave = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "nft.png");
await File.WriteAllBytesAsync(pathToSave, imageBytes);
Console.WriteLine($"NFT image saved to: {pathToSave}");

v2.18.1

21 Feb 22:53
a65e8c0
Compare
Choose a tag to compare

What's Changed

Similar filters to GetEvents available.

// Fetch transactions (great amount of optional filters available)
var transactions = await insight.GetTransactions(
    chainIds: new BigInteger[] { 1 }, // ethereum
    contractAddress: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d", // bored apes
    fromTimestamp: Utils.GetUnixTimeStampNow() - 3600, // last hour
    sortBy: SortBy.TransactionIndex, // block number, block timestamp or transaction index
    sortOrder: SortOrder.Desc, // latest first
    limit: 5 // last 5 transactions
);
Console.WriteLine($"Transactions: {JsonConvert.SerializeObject(transactions, Formatting.Indented)}");

v2.18.0

21 Feb 22:09
42a179c
Compare
Choose a tag to compare

What's Changed

Insight Indexer .NET Integration

Insight is an extremely useful and performant tool to query blockchain data and can decorate it quite nicely too.

Did you know that vitalik, on Ethereum, Polygon and Arbitrum alone owns 7811 ERC20s, 34,362 ERC721s and 2,818 ERC1155s?
Let's go through some examples!

Instantiation

using Thirdweb.Indexer;

// Create a ThirdwebInsight instance
var insight = await ThirdwebInsight.Create(client);

Simple Args

// Setup some filters
var address = await Utils.GetAddressFromENS(client, "vitalik.eth");
var chains = new BigInteger[] { 1, 137, 42161 };

Fetching all tokens owned by a given address

// Fetch all token types
var tokens = await insight.GetTokens(address, chains);
Console.WriteLine($"ERC20 Count: {tokens.erc20Tokens.Length} | ERC721 Count: {tokens.erc721Tokens.Length} | ERC1155 Count: {tokens.erc1155Tokens.Length}");

Fetching a specific type of token owned by a given address

// Fetch ERC20s only
var erc20Tokens = await insight.GetTokens_ERC20(address, chains);
Console.WriteLine($"ERC20 Tokens: {JsonConvert.SerializeObject(erc20Tokens, Formatting.Indented)}");

// Fetch ERC721s only
var erc721Tokens = await insight.GetTokens_ERC721(address, chains);
Console.WriteLine($"ERC721 Tokens: {JsonConvert.SerializeObject(erc721Tokens, Formatting.Indented)}");

// Fetch ERC1155s only
var erc1155Tokens = await insight.GetTokens_ERC1155(address, chains);
Console.WriteLine($"ERC1155 Tokens: {JsonConvert.SerializeObject(erc1155Tokens, Formatting.Indented)}");

Fetching Events
Note: most of these parameters are optional (and some are not showcased here)

// Fetch events (great amount of optional filters available)
var events = await insight.GetEvents(
    chainIds: new BigInteger[] { 1 }, // ethereum
    contractAddress: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d", // bored apes
    eventSignature: "Transfer(address,address,uint256)", // transfer event
    fromTimestamp: Utils.GetUnixTimeStampNow() - 3600, // last hour
    sortBy: SortBy.TransactionIndex, // block number, block timestamp or transaction index
    sortOrder: SortOrder.Desc, // latest first
    limit: 5 // last 5 transfers
);
Console.WriteLine($"Events: {JsonConvert.SerializeObject(events, Formatting.Indented)}");

Full Insight .NET Reference

Engine Blockchain API .NET Integration

Engine is one of thirdweb's most important products. We've created an EngineWallet class that can be used as an IThirdwebWallet and as such benefits from being compatible with the entire SDK!

Usage:

// EngineWallet is compatible with IThirdwebWallet and can be used with any SDK method/extension
var engineWallet = await EngineWallet.Create(
    client: client,
    engineUrl: Environment.GetEnvironmentVariable("ENGINE_URL"),
    authToken: Environment.GetEnvironmentVariable("ENGINE_ACCESS_TOKEN"),
    walletAddress: Environment.GetEnvironmentVariable("ENGINE_BACKEND_WALLET_ADDRESS"),
    timeoutSeconds: null, // no timeout
    additionalHeaders: null // can set things like x-account-address if using basic session keys
);

// Simple self transfer
var receipt = await engineWallet.Transfer(chainId: 11155111, toAddress: await engineWallet.GetAddress(), weiAmount: 0);
Console.WriteLine($"Receipt: {receipt}");

Integrated with last December's EIP-7702 release!

Additional Changes

  • Arbitrum, Arbitrum Nova and Arbitrum Sepolia gas price related methods now get shortcut early and return maxFeePerGas = maxPriorityFeePerGas = current gas price.
  • Utils.GetChainMetadata chain id related variables updated from int to BigInteger.

v2.17.2

13 Feb 20:52
0ba0ee9
Compare
Choose a tag to compare

What's Changed

  • Smart Wallet transaction receipt polling can now time out based on your client "Other" timeout options, similar to normal transactions.
  • Our dashboard now supports rotating your secret keys. Rotated secret keys are now supported in this version.
  • You can now call InAppWallet or EcosystemWallet's Create function and instantly login with a twAuthTokenOverride which would be an auth token/cookie that you would have retrieved from any other thirdweb app, such as a web app, electron launcher, or any app built using our various SDKs.
var forwardedWallet = await InAppWallet.Create(
    client: myClient, 
    authProvider: AuthProvider.Github, 
    twAuthTokenOverride: "my.auth.token"
);

Previously, it was only possible to go from .NET to other React apps using GenerateExternalLoginLink, this unlocks the other way.

v2.17.1

07 Feb 18:34
e527cf1
Compare
Choose a tag to compare

What's Changed

  • Fixed NFT.QuantityOwned for ERC1155 returning incorrect data in some cases when used through ERC1155_GetOwnedNFTs.

v2.17.0

24 Jan 22:15
4676030
Compare
Choose a tag to compare

What's Changed

Nebula AI .NET Integration (Beta) in #122

The last piece of the puzzle required to create .NET apps and games leveraging a blockchain-powered AI assistant or NPC that also has the power to fully execute transactions. Further enhanced when combined with Server Wallets and Account Abstraction.

Read, Write, Reason.
The best way to understand is to look at examples.

We'll prepare some context for the AI - here, we'll generate a basic PrivateKeyWallet and upgrade it to a SmartWallet on Sepolia.

// Prepare some context
var myChain = 11155111; // Sepolia
var mySigner = await PrivateKeyWallet.Generate(client);
var myWallet = await SmartWallet.Create(mySigner, myChain);
var myContractAddress = "0xe2cb0eb5147b42095c2FfA6F7ec953bb0bE347D8"; // DropERC1155
var usdcAddress = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"; // Sepolia USDC

A one liner creates a Nebula session.

// Create a Nebula session
var nebula = await ThirdwebNebula.Create(client);

You can Chat with Nebula. The Chat method accepts any IThirdwebWallet as an optional parameter, context will automatically be updated.

// Chat, passing wallet context
var response1 = await nebula.Chat(message: "What is my wallet address?", wallet: myWallet);
Console.WriteLine($"Response 1: {response1.Message}");

You may also pass it smart contract context.

// Chat, passing contract context
var response2 = await nebula.Chat(
    message: "What's the total supply of token id 0 for this contract?",
    context: new NebulaContext(contractAddresses: new List<string> { myContractAddress }, chainIds: new List<BigInteger> { myChain })
);
Console.WriteLine($"Response 2: {response2.Message}");

You can have a full on conversation with it with our Chat override accepting multiple messages.

// Chat, passing multiple messages and context
var response3 = await nebula.Chat(
    messages: new List<NebulaChatMessage>
    {
        new($"Tell me the name of this contract: {myContractAddress}", NebulaChatRole.User),
        new("The name of the contract is CatDrop", NebulaChatRole.Assistant),
        new("What's the symbol of this contract?", NebulaChatRole.User),
    },
    context: new NebulaContext(contractAddresses: new List<string> { myContractAddress }, chainIds: new List<BigInteger> { myChain })
);
Console.WriteLine($"Response 3: {response3.Message}");

Chatting is cool, but what if I just want it to do things and stop talking so much?

You can Execute transactions directly with a simple prompt.

// Execute, this directly sends transactions
var executionResult = await nebula.Execute("Approve 1 USDC to vitalik.eth", wallet: myWallet, context: new NebulaContext(contractAddresses: new List<string>() { usdcAddress }));
if (executionResult.TransactionReceipts != null && executionResult.TransactionReceipts.Count > 0)
{
    Console.WriteLine($"Receipt: {executionResult.TransactionReceipts[0]}");
}
else
{
    Console.WriteLine($"Message: {executionResult.Message}");
}

Similarly, Execute can take in multiple messages.

// Batch execute
var batchExecutionResult = await nebula.Execute(
    new List<NebulaChatMessage>
    {
        new("What's the address of vitalik.eth", NebulaChatRole.User),
        new("The address of vitalik.eth is 0xd8dA6BF26964aF8E437eEa5e3616511D7G3a3298", NebulaChatRole.Assistant),
        new("Approve 1 USDC to them", NebulaChatRole.User),
    },
    wallet: myWallet,
    context: new NebulaContext(contractAddresses: new List<string>() { usdcAddress })
);
if (batchExecutionResult.TransactionReceipts != null && batchExecutionResult.TransactionReceipts.Count > 0)
{
    Console.WriteLine($"Receipts: {JsonConvert.SerializeObject(batchExecutionResult.TransactionReceipts, Formatting.Indented)}");
}
else
{
    Console.WriteLine($"Message: {batchExecutionResult.Message}");
}

Full Reference

Enhanced Analytics in #125

We've added transaction and connection analytics that will show up on your thirdweb dashboard and give you a better sense of your users' activities - make sure you grab this version to get the benefits!

If you've read this far, access Nebula and start building cool things. You're early - a full stack blockchain integration powered by AI is not something you see in .NET land too often, make use of thirdweb to build next-gen applications, and reach out to us!

v2.16.0

17 Jan 19:38
5348711
Compare
Choose a tag to compare

What's Changed

AuthProvider.SiweExternal - SIWE, OAuth style

Depending on the framework, or on the external wallet platform support, you may not have direct access to every single wallet out there.
This new AuthProvider allows you to login to otherwise native-unavailable wallets such as Abstract Wallet & Coinbase Smart Wallet through a flow similar to OAuth, using SIWE.

It'll redirect you to static.thirdweb.com and use our React SDK and other wallet SDKs as needed, unlocking the ability to login (or link) with any wallet thirdweb supports on web, from runtime platforms that would otherwise be unsupported by said wallet, and create an In-App or Ecosystem Wallet out of it.

Windows Console Example:

var inAppWalletSiweExternal = await InAppWallet.Create(client: client, authProvider: AuthProvider.SiweExternal);
var address = await inAppWalletSiweExternal.LoginWithSiweExternal(
    isMobile: false,
    browserOpenAction: (url) =>
    {
        var psi = new ProcessStartInfo { FileName = url, UseShellExecute = true };
         _ = Process.Start(psi);
    },
    forceWalletIds: new List<string> { "io.metamask", "com.coinbase.wallet", "xyz.abs" }
);

You can now override the default session id used with Guest authentication

This is useful when you want your guest mode to be tied to a unique device identifier, and depending on your framework there may be various APIs to fetch such identifiers that you may want to use.

Example:

var guestWallet = await EcosystemWallet.Create(
    ecosystemId: "ecosystem.the-bonfire",
    client: client,
    authProvider: AuthProvider.Guest
);
var address = await guestWallet.LoginWithGuest(SomeSystemInfoAPI.deviceUniqueIdentifier);

v2.15.0

10 Jan 12:29
0c94da4
Compare
Choose a tag to compare

What's Changed

  • Unified AWS REST API interaction, and fixed potential edge cases where any inaccurate system time could result in an error logging in to In-App or Ecosystem wallets. The fallback introduced in 2.8.0 has been applied to other flows now too.

v2.14.0

10 Jan 11:23
e3a9e72
Compare
Choose a tag to compare

What's Changed

  • Added AuthProvider.Backend as a server-side way to create In-App or Ecosystem Wallets. Simply pass a walletSecret identifier.
var inAppWalletBackend = await InAppWallet.Create(
    client: client,
    authProvider: AuthProvider.Backend,
    walletSecret: "very-secret"
);
var address = await inAppWalletBackend.LoginWithBackend();

v2.13.0

06 Jan 11:45
aab098c
Compare
Choose a tag to compare

What's Changed

  • Added DropER721_Burn, DropERC1155_BurnBatch, TokenERC721_Burn, TokenERC1155_Burn, TokenERC1155_BurnBatch contract extensions.
  • Overriding default RPCs is now allowed through a new ThirdwebClient creation parameter rpcOverrides.
var client = ThirdwebClient.Create(
    clientId: "myepicclientid",
    bundleId: "my.bundle.id", // for native apps
    rpcOverrides: new()
    {
        { 1, "https://eth.llamarpc.com" },
        { 42161, "https://arbitrum.llamarpc.com" }
    }
);
  • Removed some leftover unnecessary logging.