mirror of
https://github.com/status-im/nft-faucet.git
synced 2025-02-23 03:58:23 +00:00
Add Mint dialog
This commit is contained in:
parent
4a0cbb6c66
commit
6795de500f
7
NftFaucetRadzen/Models/Balance.cs
Normal file
7
NftFaucetRadzen/Models/Balance.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace NftFaucetRadzen.Models;
|
||||||
|
|
||||||
|
public class Balance
|
||||||
|
{
|
||||||
|
public decimal Amount { get; set; }
|
||||||
|
public string Currency { get; set; }
|
||||||
|
}
|
10
NftFaucetRadzen/Models/MintingState.cs
Normal file
10
NftFaucetRadzen/Models/MintingState.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace NftFaucetRadzen.Models;
|
||||||
|
|
||||||
|
public enum MintingState
|
||||||
|
{
|
||||||
|
CheckingNetwork,
|
||||||
|
CheckingAddress,
|
||||||
|
CheckingBalance,
|
||||||
|
SendingTransaction,
|
||||||
|
Done,
|
||||||
|
}
|
93
NftFaucetRadzen/Pages/MintDialog.razor
Normal file
93
NftFaucetRadzen/Pages/MintDialog.razor
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
@page "/mint/in-progress"
|
||||||
|
@using NftFaucetRadzen.Models
|
||||||
|
@inherits BasicComponent
|
||||||
|
|
||||||
|
<PageTitle>Minting...</PageTitle>
|
||||||
|
|
||||||
|
@if (!string.IsNullOrEmpty(ProgressBarText))
|
||||||
|
{
|
||||||
|
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">@ProgressBarText</RadzenText>
|
||||||
|
<RadzenProgressBar Value="100" ShowValue="false" Mode="ProgressBarMode.Indeterminate" />
|
||||||
|
}
|
||||||
|
else if (State == MintingState.CheckingNetwork)
|
||||||
|
{
|
||||||
|
<RadzenContent Container="main">
|
||||||
|
<h4>Network mismatch!</h4>
|
||||||
|
<p>
|
||||||
|
<text style="font-weight: bold;">Selected network: </text>
|
||||||
|
<text style="color: green;">@(AppState?.SelectedNetwork?.Name ?? "<unknown>")</text>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<text style="font-weight: bold;">Provider network: </text>
|
||||||
|
<text style="color: red;">@(ProviderNetwork?.Name ?? "<unknown>")</text>
|
||||||
|
</p>
|
||||||
|
<div style="display: flex; justify-content: end;">
|
||||||
|
<RadzenButton Click="@(async (args) => await CheckNetwork())" Text="Try again" Disabled="@(!string.IsNullOrEmpty(ProgressBarText))" />
|
||||||
|
</div>
|
||||||
|
</RadzenContent>
|
||||||
|
} else if (State == MintingState.CheckingAddress)
|
||||||
|
{
|
||||||
|
<RadzenContent Container="main">
|
||||||
|
<h3>Address is not available!</h3>
|
||||||
|
<p>
|
||||||
|
<text style="font-weight: bold;">Provider address: </text>
|
||||||
|
@if (!string.IsNullOrEmpty(SourceAddress))
|
||||||
|
{
|
||||||
|
@:<text style="color: green;">@SourceAddress</text>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@:<text style="color: red;"><null></text>
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
<div style="display: flex; justify-content: end;">
|
||||||
|
<RadzenButton Click="@(async (args) => await CheckNetwork())" Text="Try again" Disabled="@(!string.IsNullOrEmpty(ProgressBarText))" />
|
||||||
|
</div>
|
||||||
|
</RadzenContent>
|
||||||
|
} else if (State == MintingState.CheckingBalance)
|
||||||
|
{
|
||||||
|
<RadzenContent Container="main">
|
||||||
|
<h3>Not enough balance!</h3>
|
||||||
|
<p>
|
||||||
|
<text style="font-weight: bold;">Balance: </text>
|
||||||
|
@if (Balance != null)
|
||||||
|
{
|
||||||
|
@:<text style="color: red;">@(Balance.Amount + " " + Balance.Currency)</text>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@:<text style="color: red;"><unknown></text>
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
<div style="display: flex; justify-content: end;">
|
||||||
|
<RadzenButton Click="@(async (args) => await CheckNetwork())" Text="Try again" Disabled="@(!string.IsNullOrEmpty(ProgressBarText))" />
|
||||||
|
</div>
|
||||||
|
</RadzenContent>
|
||||||
|
} else if (State == MintingState.SendingTransaction)
|
||||||
|
{
|
||||||
|
<RadzenContent Container="main">
|
||||||
|
<h3>Failed to send transaction!</h3>
|
||||||
|
<p>
|
||||||
|
<text>Error message:</text>
|
||||||
|
<br/>
|
||||||
|
<text style="font-weight: bold; color: red;">@SendTransactionError</text>
|
||||||
|
</p>
|
||||||
|
<div style="display: flex; justify-content: end;">
|
||||||
|
<RadzenButton Click="@(async (args) => await CheckNetwork())" Text="Try again" Disabled="@(!string.IsNullOrEmpty(ProgressBarText))" />
|
||||||
|
</div>
|
||||||
|
</RadzenContent>
|
||||||
|
} else if (State == MintingState.Done)
|
||||||
|
{
|
||||||
|
<RadzenContent Container="main">
|
||||||
|
<h3>Success</h3>
|
||||||
|
<p>
|
||||||
|
<text style="font-weight: bold;">Token minted!</text>
|
||||||
|
<br/>
|
||||||
|
<text style="font-weight: bold;">Transaction hash: </text>
|
||||||
|
<text style="color: green;">@TransactionHash</text>
|
||||||
|
</p>
|
||||||
|
<div style="display: flex; justify-content: end;">
|
||||||
|
<RadzenButton Click="@(async (args) => await Close())" Text="Close" Disabled="@(!string.IsNullOrEmpty(ProgressBarText))" />
|
||||||
|
</div>
|
||||||
|
</RadzenContent>
|
||||||
|
}
|
146
NftFaucetRadzen/Pages/MintDialog.razor.cs
Normal file
146
NftFaucetRadzen/Pages/MintDialog.razor.cs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
using NftFaucetRadzen.Components;
|
||||||
|
using NftFaucetRadzen.Models;
|
||||||
|
using NftFaucetRadzen.Plugins.NetworkPlugins;
|
||||||
|
using NftFaucetRadzen.Utils;
|
||||||
|
|
||||||
|
namespace NftFaucetRadzen.Pages;
|
||||||
|
|
||||||
|
public partial class MintDialog : BasicComponent
|
||||||
|
{
|
||||||
|
private const int MinDelayInMilliseconds = 300;
|
||||||
|
|
||||||
|
private string ProgressBarText { get; set; } = "Checking network...";
|
||||||
|
private MintingState State { get; set; } = MintingState.CheckingNetwork;
|
||||||
|
private INetwork ProviderNetwork { get; set; }
|
||||||
|
private string SourceAddress { get; set; }
|
||||||
|
private Balance Balance { get; set; }
|
||||||
|
private string TransactionHash { get; set; }
|
||||||
|
private string SendTransactionError { get; set; }
|
||||||
|
|
||||||
|
protected override Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
CheckNetwork();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CheckNetwork()
|
||||||
|
{
|
||||||
|
State = MintingState.CheckingNetwork;
|
||||||
|
ProgressBarText = "Checking network...";
|
||||||
|
RefreshMediator.NotifyStateHasChangedSafe();
|
||||||
|
|
||||||
|
var providerNetworkResult = await ResultWrapper.Wrap(async () =>
|
||||||
|
{
|
||||||
|
var task1 = AppState.SelectedProvider.GetNetwork(AppState.PluginStorage.Networks.ToArray(), AppState.SelectedNetwork);
|
||||||
|
var task2 = Task.Delay(TimeSpan.FromMilliseconds(MinDelayInMilliseconds));
|
||||||
|
await Task.WhenAll(task1, task2);
|
||||||
|
return task1.Result;
|
||||||
|
});
|
||||||
|
ProviderNetwork = providerNetworkResult.IsSuccess ? providerNetworkResult.Value : null;
|
||||||
|
|
||||||
|
if (ProviderNetwork?.Id == AppState.SelectedNetwork.Id)
|
||||||
|
{
|
||||||
|
CheckAddress();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ProgressBarText = null;
|
||||||
|
RefreshMediator.NotifyStateHasChangedSafe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CheckAddress()
|
||||||
|
{
|
||||||
|
State = MintingState.CheckingAddress;
|
||||||
|
ProgressBarText = "Checking address...";
|
||||||
|
RefreshMediator.NotifyStateHasChangedSafe();
|
||||||
|
|
||||||
|
var sourceAddressResult = await ResultWrapper.Wrap(async () =>
|
||||||
|
{
|
||||||
|
var task1 = AppState.SelectedProvider.GetAddress();
|
||||||
|
var task2 = Task.Delay(TimeSpan.FromMilliseconds(MinDelayInMilliseconds));
|
||||||
|
await Task.WhenAll(task1, task2);
|
||||||
|
return task1.Result;
|
||||||
|
});
|
||||||
|
SourceAddress = sourceAddressResult.IsSuccess ? sourceAddressResult.Value : null;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(SourceAddress))
|
||||||
|
{
|
||||||
|
CheckBalance();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ProgressBarText = null;
|
||||||
|
RefreshMediator.NotifyStateHasChangedSafe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CheckBalance()
|
||||||
|
{
|
||||||
|
State = MintingState.CheckingBalance;
|
||||||
|
ProgressBarText = "Checking balance...";
|
||||||
|
RefreshMediator.NotifyStateHasChangedSafe();
|
||||||
|
|
||||||
|
var balanceResult = await ResultWrapper.Wrap(async () =>
|
||||||
|
{
|
||||||
|
var task1 = AppState.SelectedProvider.GetBalance(AppState.SelectedNetwork);
|
||||||
|
var task2 = Task.Delay(TimeSpan.FromMilliseconds(MinDelayInMilliseconds));
|
||||||
|
await Task.WhenAll(task1, task2);
|
||||||
|
return task1.Result;
|
||||||
|
});
|
||||||
|
Balance = balanceResult.IsSuccess ? balanceResult.Value : null;
|
||||||
|
var amount = Math.Max(Balance?.Amount ?? 0, 0);
|
||||||
|
|
||||||
|
if (amount != 0)
|
||||||
|
{
|
||||||
|
SendTransaction();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ProgressBarText = null;
|
||||||
|
RefreshMediator.NotifyStateHasChangedSafe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SendTransaction()
|
||||||
|
{
|
||||||
|
State = MintingState.SendingTransaction;
|
||||||
|
ProgressBarText = "Sending transaction...";
|
||||||
|
RefreshMediator.NotifyStateHasChangedSafe();
|
||||||
|
|
||||||
|
var sendTransactionResult = await ResultWrapper.Wrap(async () =>
|
||||||
|
{
|
||||||
|
var mintRequest = new MintRequest(AppState.SelectedNetwork, AppState.SelectedProvider,
|
||||||
|
AppState.SelectedContract, AppState.SelectedToken, AppState.SelectedUploadLocation,
|
||||||
|
AppState.UserStorage.DestinationAddress, AppState.UserStorage.TokenAmount);
|
||||||
|
var task1 = AppState.SelectedProvider.Mint(mintRequest);
|
||||||
|
var task2 = Task.Delay(TimeSpan.FromMilliseconds(MinDelayInMilliseconds));
|
||||||
|
await Task.WhenAll(task1, task2);
|
||||||
|
return task1.Result;
|
||||||
|
});
|
||||||
|
if (sendTransactionResult.IsSuccess)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(sendTransactionResult.Value))
|
||||||
|
{
|
||||||
|
TransactionHash = sendTransactionResult.Value;
|
||||||
|
State = MintingState.Done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendTransactionError = "Tx hash is null or empty";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendTransactionError = sendTransactionResult.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBarText = null;
|
||||||
|
RefreshMediator.NotifyStateHasChangedSafe();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Close()
|
||||||
|
{
|
||||||
|
DialogService.Close(TransactionHash);
|
||||||
|
}
|
||||||
|
}
|
@ -26,34 +26,6 @@
|
|||||||
{
|
{
|
||||||
@:<text style="color: red;">NOT CONFIGURED</text>
|
@:<text style="color: red;">NOT CONFIGURED</text>
|
||||||
}
|
}
|
||||||
else if (!NetworkMatches)
|
|
||||||
{
|
|
||||||
@:<text style="color: red;">NETWORK MISMATCH</text>
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
@:<text style="color: green;">OK</text>
|
|
||||||
}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
@if (string.IsNullOrEmpty(SourceAddress))
|
|
||||||
{
|
|
||||||
@:<text style="font-weight: bold;">Balance: </text>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@:<text style="font-weight: bold;">Balance</text>
|
|
||||||
@:<text> (@SourceAddress)</text>
|
|
||||||
@:<text style="font-weight: bold;">: </text>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (AppState?.SelectedProvider == null || !AppState.SelectedProvider.IsConfigured || string.IsNullOrEmpty(SourceAddress))
|
|
||||||
{
|
|
||||||
@:<text style="color: red;">UNKNOWN</text>
|
|
||||||
}
|
|
||||||
else if (BalanceIsZero)
|
|
||||||
{
|
|
||||||
@:<text style="color: red;">ZERO</text>
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@:<text style="color: green;">OK</text>
|
@:<text style="color: green;">OK</text>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using CSharpFunctionalExtensions;
|
using CSharpFunctionalExtensions;
|
||||||
using NftFaucetRadzen.Components;
|
using NftFaucetRadzen.Components;
|
||||||
using NftFaucetRadzen.Models;
|
|
||||||
using NftFaucetRadzen.Utils;
|
using NftFaucetRadzen.Utils;
|
||||||
using Radzen;
|
using Radzen;
|
||||||
|
|
||||||
@ -9,8 +8,6 @@ namespace NftFaucetRadzen.Pages;
|
|||||||
public partial class MintPage : BasicComponent
|
public partial class MintPage : BasicComponent
|
||||||
{
|
{
|
||||||
private string SourceAddress { get; set; }
|
private string SourceAddress { get; set; }
|
||||||
private bool NetworkMatches { get; set; }
|
|
||||||
private bool BalanceIsZero { get; set; } = true;
|
|
||||||
private bool IsReadyToMint => AppState != null &&
|
private bool IsReadyToMint => AppState != null &&
|
||||||
AppState.SelectedNetwork != null &&
|
AppState.SelectedNetwork != null &&
|
||||||
AppState.SelectedProvider != null &&
|
AppState.SelectedProvider != null &&
|
||||||
@ -18,9 +15,7 @@ public partial class MintPage : BasicComponent
|
|||||||
AppState.SelectedContract != null &&
|
AppState.SelectedContract != null &&
|
||||||
AppState.SelectedToken != null &&
|
AppState.SelectedToken != null &&
|
||||||
AppState.SelectedUploadLocation != null &&
|
AppState.SelectedUploadLocation != null &&
|
||||||
!string.IsNullOrEmpty(SourceAddress) &&
|
AppState.UserStorage.DestinationAddress != null;
|
||||||
NetworkMatches &&
|
|
||||||
!BalanceIsZero;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
@ -28,35 +23,13 @@ public partial class MintPage : BasicComponent
|
|||||||
{
|
{
|
||||||
SourceAddress = await ResultWrapper.Wrap(() => AppState.SelectedProvider.GetAddress()).Match(x => x, _ => null);
|
SourceAddress = await ResultWrapper.Wrap(() => AppState.SelectedProvider.GetAddress()).Match(x => x, _ => null);
|
||||||
AppState.UserStorage.DestinationAddress = SourceAddress;
|
AppState.UserStorage.DestinationAddress = SourceAddress;
|
||||||
if (string.IsNullOrEmpty(SourceAddress) || AppState.SelectedNetwork == null)
|
|
||||||
{
|
|
||||||
BalanceIsZero = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var balance = await ResultWrapper.Wrap(() => AppState.SelectedProvider.GetBalance(AppState.SelectedNetwork)).Match(x => x, _ => 0);
|
|
||||||
BalanceIsZero = balance == 0;
|
|
||||||
}
|
|
||||||
if (AppState.SelectedNetwork != null)
|
|
||||||
{
|
|
||||||
NetworkMatches = await ResultWrapper.Wrap(() => AppState.SelectedProvider.EnsureNetworkMatches(AppState.SelectedNetwork)).Match(x => x, _ => false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Mint()
|
private async Task Mint()
|
||||||
{
|
{
|
||||||
var mintRequest = new MintRequest(AppState.SelectedNetwork, AppState.SelectedProvider,
|
await DialogService.OpenAsync<MintDialog>("Minting...",
|
||||||
AppState.SelectedContract, AppState.SelectedToken, AppState.SelectedUploadLocation,
|
new Dictionary<string, object>(),
|
||||||
AppState.UserStorage.DestinationAddress, AppState.UserStorage.TokenAmount);
|
new DialogOptions() { Width = "700px", Height = "570px", Resizable = true, Draggable = true });
|
||||||
var result = await AppState.SelectedProvider.Mint(mintRequest);
|
|
||||||
if (result.IsSuccess)
|
|
||||||
{
|
|
||||||
NotificationService.Notify(NotificationSeverity.Success, "Minting finished", result.Value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NotificationService.Notify(NotificationSeverity.Error, "Failed to mint", result.Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
using CSharpFunctionalExtensions;
|
|
||||||
using NftFaucetRadzen.Components.CardList;
|
using NftFaucetRadzen.Components.CardList;
|
||||||
using NftFaucetRadzen.Models;
|
using NftFaucetRadzen.Models;
|
||||||
using NftFaucetRadzen.Plugins.NetworkPlugins;
|
using NftFaucetRadzen.Plugins.NetworkPlugins;
|
||||||
@ -19,9 +18,9 @@ public interface IProvider
|
|||||||
public CardListItemConfiguration GetConfiguration();
|
public CardListItemConfiguration GetConfiguration();
|
||||||
public bool IsNetworkSupported(INetwork network);
|
public bool IsNetworkSupported(INetwork network);
|
||||||
public Task<string> GetAddress();
|
public Task<string> GetAddress();
|
||||||
public Task<long?> GetBalance(INetwork network);
|
public Task<Balance> GetBalance(INetwork network);
|
||||||
public Task<bool> EnsureNetworkMatches(INetwork network);
|
public Task<INetwork> GetNetwork(IReadOnlyCollection<INetwork> allKnownNetworks, INetwork selectedNetwork);
|
||||||
public Task<Result<string>> Mint(MintRequest mintRequest);
|
public Task<string> Mint(MintRequest mintRequest);
|
||||||
public Task<string> GetState();
|
public Task<string> GetState();
|
||||||
public Task SetState(string state);
|
public Task SetState(string state);
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ public class EthereumKeygenProvider : IProvider
|
|||||||
public Task<string> GetAddress()
|
public Task<string> GetAddress()
|
||||||
=> Task.FromResult(Key?.Address);
|
=> Task.FromResult(Key?.Address);
|
||||||
|
|
||||||
public async Task<long?> GetBalance(INetwork network)
|
public async Task<Balance> GetBalance(INetwork network)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(Key?.Address))
|
if (string.IsNullOrEmpty(Key?.Address))
|
||||||
return null;
|
return null;
|
||||||
@ -93,13 +93,24 @@ public class EthereumKeygenProvider : IProvider
|
|||||||
var web3 = new Web3(network.PublicRpcUrl.OriginalString);
|
var web3 = new Web3(network.PublicRpcUrl.OriginalString);
|
||||||
var hexBalance = await web3.Eth.GetBalance.SendRequestAsync(Key.Address);
|
var hexBalance = await web3.Eth.GetBalance.SendRequestAsync(Key.Address);
|
||||||
var balance = (long) hexBalance.Value;
|
var balance = (long) hexBalance.Value;
|
||||||
return balance;
|
return new Balance
|
||||||
|
{
|
||||||
|
Amount = balance,
|
||||||
|
Currency = "wei",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> EnsureNetworkMatches(INetwork network)
|
public Task<INetwork> GetNetwork(IReadOnlyCollection<INetwork> allKnownNetworks, INetwork selectedNetwork)
|
||||||
=> Task.FromResult(network.Type == NetworkType.Ethereum);
|
{
|
||||||
|
if (selectedNetwork != null && selectedNetwork.Type == NetworkType.Ethereum)
|
||||||
|
return Task.FromResult(selectedNetwork);
|
||||||
|
|
||||||
public async Task<Result<string>> Mint(MintRequest mintRequest)
|
var matchingNetwork = allKnownNetworks.FirstOrDefault(x => x.Type == NetworkType.Ethereum && x.IsSupported) ??
|
||||||
|
allKnownNetworks.FirstOrDefault(x => x.Type == NetworkType.Ethereum);
|
||||||
|
return Task.FromResult(matchingNetwork);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> Mint(MintRequest mintRequest)
|
||||||
{
|
{
|
||||||
if (mintRequest.Network.Type != NetworkType.Ethereum)
|
if (mintRequest.Network.Type != NetworkType.Ethereum)
|
||||||
{
|
{
|
||||||
@ -123,34 +134,31 @@ public class EthereumKeygenProvider : IProvider
|
|||||||
_ => throw new ArgumentOutOfRangeException(),
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return await ResultWrapper.Wrap(async () =>
|
var data = transfer.Encode();
|
||||||
|
var client = new RpcClient(mintRequest.Network.PublicRpcUrl);
|
||||||
|
var account = new Account(Key.PrivateKey);
|
||||||
|
var transactionManager = new AccountSignerTransactionManager(client, account);
|
||||||
|
var txInput = new TransactionInput
|
||||||
{
|
{
|
||||||
var data = transfer.Encode();
|
From = Key.Address,
|
||||||
var client = new RpcClient(mintRequest.Network.PublicRpcUrl);
|
To = mintRequest.Contract.Address,
|
||||||
var account = new Account(Key.PrivateKey);
|
Data = data,
|
||||||
var transactionManager = new AccountSignerTransactionManager(client, account);
|
ChainId = new HexBigInteger(new BigInteger(mintRequest.Network.ChainId!.Value)),
|
||||||
var txInput = new TransactionInput
|
Type = new HexBigInteger(TransactionType.EIP1559.AsByte()),
|
||||||
{
|
};
|
||||||
From = Key.Address,
|
txInput.Nonce = await transactionManager.GetNonceAsync(txInput);
|
||||||
To = mintRequest.Contract.Address,
|
var fee1559 = await transactionManager.CalculateFee1559Async();
|
||||||
Data = data,
|
txInput.MaxFeePerGas = new HexBigInteger(fee1559.MaxFeePerGas!.Value);
|
||||||
ChainId = new HexBigInteger(new BigInteger(mintRequest.Network.ChainId!.Value)),
|
txInput.MaxPriorityFeePerGas = new HexBigInteger(fee1559.MaxPriorityFeePerGas!.Value);
|
||||||
Type = new HexBigInteger(TransactionType.EIP1559.AsByte()),
|
txInput.Gas = await transactionManager.EstimateGasAsync(txInput);
|
||||||
};
|
txInput.Gas = new HexBigInteger(new BigInteger((long)txInput.Gas.Value * 1.3));
|
||||||
txInput.Nonce = await transactionManager.GetNonceAsync(txInput);
|
var transactionHash = await transactionManager.SendTransactionAsync(txInput);
|
||||||
var fee1559 = await transactionManager.CalculateFee1559Async();
|
if (string.IsNullOrEmpty(transactionHash))
|
||||||
txInput.MaxFeePerGas = new HexBigInteger(fee1559.MaxFeePerGas!.Value);
|
{
|
||||||
txInput.MaxPriorityFeePerGas = new HexBigInteger(fee1559.MaxPriorityFeePerGas!.Value);
|
throw new Exception("Operation was cancelled or RPC node failure");
|
||||||
txInput.Gas = await transactionManager.EstimateGasAsync(txInput);
|
}
|
||||||
txInput.Gas = new HexBigInteger(new BigInteger((long)txInput.Gas.Value * 1.3));
|
|
||||||
var transactionHash = await transactionManager.SendTransactionAsync(txInput);
|
|
||||||
if (string.IsNullOrEmpty(transactionHash))
|
|
||||||
{
|
|
||||||
throw new Exception("Operation was cancelled or RPC node failure");
|
|
||||||
}
|
|
||||||
|
|
||||||
return transactionHash;
|
return transactionHash;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<string> GetState()
|
public Task<string> GetState()
|
||||||
|
@ -101,7 +101,7 @@ public class SolanaKeygenProvider : IProvider
|
|||||||
public Task<string> GetAddress()
|
public Task<string> GetAddress()
|
||||||
=> Task.FromResult(Key?.Address);
|
=> Task.FromResult(Key?.Address);
|
||||||
|
|
||||||
public async Task<long?> GetBalance(INetwork network)
|
public async Task<Balance> GetBalance(INetwork network)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(Key?.Address))
|
if (string.IsNullOrEmpty(Key?.Address))
|
||||||
return null;
|
return null;
|
||||||
@ -112,13 +112,24 @@ public class SolanaKeygenProvider : IProvider
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
var balance = (long) balanceResult.Result.Value;
|
var balance = (long) balanceResult.Result.Value;
|
||||||
return balance;
|
return new Balance
|
||||||
|
{
|
||||||
|
Amount = balance,
|
||||||
|
Currency = "lamport",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> EnsureNetworkMatches(INetwork network)
|
public Task<INetwork> GetNetwork(IReadOnlyCollection<INetwork> allKnownNetworks, INetwork selectedNetwork)
|
||||||
=> Task.FromResult(network.Type == NetworkType.Solana);
|
{
|
||||||
|
if (selectedNetwork != null && selectedNetwork.Type == NetworkType.Solana)
|
||||||
|
return Task.FromResult(selectedNetwork);
|
||||||
|
|
||||||
public async Task<Result<string>> Mint(MintRequest mintRequest)
|
var matchingNetwork = allKnownNetworks.FirstOrDefault(x => x.Type == NetworkType.Solana && x.IsSupported) ??
|
||||||
|
allKnownNetworks.FirstOrDefault(x => x.Type == NetworkType.Solana);
|
||||||
|
return Task.FromResult(matchingNetwork);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> Mint(MintRequest mintRequest)
|
||||||
{
|
{
|
||||||
var client = ClientFactory.GetClient(mintRequest.Network.PublicRpcUrl.OriginalString);
|
var client = ClientFactory.GetClient(mintRequest.Network.PublicRpcUrl.OriginalString);
|
||||||
var rentExemption = await client.GetMinimumBalanceForRentExemptionAsync(TokenProgram.MintAccountDataSize);
|
var rentExemption = await client.GetMinimumBalanceForRentExemptionAsync(TokenProgram.MintAccountDataSize);
|
||||||
|
@ -133,83 +133,58 @@ public class MetamaskProvider : IProvider
|
|||||||
public async Task<string> GetAddress()
|
public async Task<string> GetAddress()
|
||||||
=> Address ?? await MetaMaskService.GetSelectedAccountAsync();
|
=> Address ?? await MetaMaskService.GetSelectedAccountAsync();
|
||||||
|
|
||||||
public async Task<long?> GetBalance(INetwork network)
|
public async Task<Balance> GetBalance(INetwork network)
|
||||||
{
|
{
|
||||||
if (!IsConfigured)
|
if (!IsConfigured)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var balance = (long) await MetaMaskService.GetBalanceAsync();
|
var balance = (long) await MetaMaskService.GetBalanceAsync();
|
||||||
return balance;
|
return new Balance
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> EnsureNetworkMatches(INetwork network)
|
|
||||||
=> network.Type == NetworkType.Ethereum && network.ChainId != null && network.ChainId == await GetChainId();
|
|
||||||
|
|
||||||
private async Task<ulong?> GetChainId()
|
|
||||||
{
|
|
||||||
var chainHex = await MetaMaskService.GetSelectedChainAsync();
|
|
||||||
if (string.IsNullOrEmpty(chainHex) || chainHex == "0x")
|
|
||||||
{
|
{
|
||||||
return null;
|
Amount = balance,
|
||||||
}
|
Currency = "wei",
|
||||||
|
};
|
||||||
var chainId = (ulong) Convert.ToInt64(chainHex, 16);
|
|
||||||
return chainId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Result<string>> Mint(MintRequest mintRequest)
|
public Task<INetwork> GetNetwork(IReadOnlyCollection<INetwork> allKnownNetworks, INetwork selectedNetwork)
|
||||||
|
{
|
||||||
|
var chainId = Convert.ToUInt64(ChainId, 16);
|
||||||
|
var matchingNetwork = allKnownNetworks.FirstOrDefault(x => x.ChainId != null && x.ChainId.Value == chainId);
|
||||||
|
return Task.FromResult(matchingNetwork);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> Mint(MintRequest mintRequest)
|
||||||
{
|
{
|
||||||
if (mintRequest.Network.Type != NetworkType.Ethereum)
|
if (mintRequest.Network.Type != NetworkType.Ethereum)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Invalid network type for this provider");
|
throw new InvalidOperationException("Invalid network type for this provider");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mintRequest.Contract.Type)
|
Function transfer = mintRequest.Contract.Type switch
|
||||||
{
|
{
|
||||||
case ContractType.Erc721:
|
ContractType.Erc721 => new Erc721MintFunction
|
||||||
{
|
{
|
||||||
return await ResultWrapper.Wrap(async () =>
|
To = mintRequest.DestinationAddress,
|
||||||
{
|
Uri = mintRequest.UploadLocation.Location,
|
||||||
var contractAddress = mintRequest.Contract.Address;
|
},
|
||||||
var transfer = new Erc721MintFunction
|
ContractType.Erc1155 => new Erc1155MintFunction
|
||||||
{
|
|
||||||
To = mintRequest.DestinationAddress,
|
|
||||||
Uri = mintRequest.UploadLocation.Location,
|
|
||||||
};
|
|
||||||
var data = transfer.Encode();
|
|
||||||
var transactionHash = await MetaMaskService.SendTransactionAsync(contractAddress, 0, data);
|
|
||||||
if (string.IsNullOrEmpty(transactionHash))
|
|
||||||
{
|
|
||||||
throw new Exception("Operation was cancelled or RPC node failure");
|
|
||||||
}
|
|
||||||
|
|
||||||
return transactionHash;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
case ContractType.Erc1155:
|
|
||||||
{
|
{
|
||||||
return await ResultWrapper.Wrap(async () =>
|
To = mintRequest.DestinationAddress,
|
||||||
{
|
Amount = mintRequest.TokensAmount,
|
||||||
var contractAddress = mintRequest.Contract.Address;
|
Uri = mintRequest.UploadLocation.Location,
|
||||||
var transfer = new Erc1155MintFunction
|
},
|
||||||
{
|
_ => throw new ArgumentOutOfRangeException(),
|
||||||
To = mintRequest.DestinationAddress,
|
};
|
||||||
Amount = mintRequest.TokensAmount,
|
|
||||||
Uri = mintRequest.UploadLocation.Location,
|
|
||||||
};
|
|
||||||
var data = transfer.Encode();
|
|
||||||
var transactionHash = await MetaMaskService.SendTransactionAsync(contractAddress, 0, data);
|
|
||||||
if (string.IsNullOrEmpty(transactionHash))
|
|
||||||
{
|
|
||||||
throw new Exception("Operation was cancelled or RPC node failure");
|
|
||||||
}
|
|
||||||
|
|
||||||
return transactionHash;
|
var contractAddress = mintRequest.Contract.Address;
|
||||||
});
|
var data = transfer.Encode();
|
||||||
}
|
var transactionHash = await MetaMaskService.SendTransactionAsync(contractAddress, 0, data);
|
||||||
default:
|
if (string.IsNullOrEmpty(transactionHash))
|
||||||
throw new ArgumentOutOfRangeException();
|
{
|
||||||
|
throw new Exception("Operation was cancelled or RPC node failure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return transactionHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<string> GetState()
|
public Task<string> GetState()
|
||||||
|
@ -49,7 +49,12 @@ public class PhantomProvider : IProvider
|
|||||||
public Task<string> GetAddress()
|
public Task<string> GetAddress()
|
||||||
=> throw new NotImplementedException();
|
=> throw new NotImplementedException();
|
||||||
|
|
||||||
public Task<long?> GetBalance(INetwork network)
|
public Task<Balance> GetBalance(INetwork network)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<INetwork> GetNetwork(IReadOnlyCollection<INetwork> allKnownNetworks, INetwork selectedNetwork)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
@ -59,7 +64,7 @@ public class PhantomProvider : IProvider
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<Result<string>> Mint(MintRequest mintRequest)
|
public Task<string> Mint(MintRequest mintRequest)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user