mirror of
https://github.com/status-im/nft-faucet.git
synced 2025-02-23 12:08:32 +00:00
95 lines
3.1 KiB
C#
95 lines
3.1 KiB
C#
using System.Text;
|
|
using NftFaucet.ApiClients;
|
|
using NftFaucet.ApiClients.Models;
|
|
using NftFaucet.Models;
|
|
using NftFaucet.Models.Enums;
|
|
using NftFaucet.Options;
|
|
using RestEase;
|
|
|
|
namespace NftFaucet.Services;
|
|
|
|
public class IpfsService : IIpfsService
|
|
{
|
|
private const string IpfsUrlPrefix = "ipfs://";
|
|
private readonly IpfsBlockchainContext _blockchainContext;
|
|
private readonly Settings _settings;
|
|
|
|
public IpfsService(IpfsBlockchainContext blockchainContext, Settings settings)
|
|
{
|
|
_blockchainContext = blockchainContext;
|
|
_settings = settings;
|
|
}
|
|
|
|
public Uri GetUrlToGateway(Uri ipfsUrl, IpfsGatewayType gateway)
|
|
{
|
|
if (ipfsUrl == null)
|
|
throw new ArgumentNullException(nameof(ipfsUrl));
|
|
|
|
if (!ipfsUrl.OriginalString.StartsWith(IpfsUrlPrefix, StringComparison.InvariantCultureIgnoreCase))
|
|
throw new ArgumentException(nameof(ipfsUrl));
|
|
|
|
if (gateway == IpfsGatewayType.None)
|
|
return ipfsUrl;
|
|
|
|
var options = _settings.GetIpfsGatewayOptions(gateway);
|
|
var prefix = options.BaseUrl;
|
|
if (!prefix.EndsWith("/"))
|
|
prefix += "/";
|
|
|
|
return new Uri(prefix + ipfsUrl.OriginalString.Replace(IpfsUrlPrefix, string.Empty));
|
|
}
|
|
|
|
public async Task<Uri> Upload(string fileName, string fileType, string url)
|
|
{
|
|
using var httpClient = new HttpClient();
|
|
var fileBytes = await httpClient.GetByteArrayAsync(new Uri(url));
|
|
return await Upload(fileName, fileType, fileBytes);
|
|
}
|
|
|
|
public async Task<Uri> Upload(string fileName, string fileType, byte[] fileBytes)
|
|
{
|
|
var fileUploadRequest = ToMultipartContent(fileName, fileType, fileBytes);
|
|
var uploadClient = RestClient.For<ICrustUploadApiClient>();
|
|
var authHeader = GenerateAuthHeader();
|
|
uploadClient.Auth = authHeader;
|
|
var response = await uploadClient.UploadFile(fileUploadRequest);
|
|
|
|
var pinningClient = RestClient.For<ICrustPinApiClient>();
|
|
pinningClient.Auth = authHeader;
|
|
var pinRequest = new PinRequest
|
|
{
|
|
cid = response.Hash,
|
|
name = fileName,
|
|
};
|
|
await pinningClient.PinFile(pinRequest);
|
|
|
|
var uri = IpfsUrlPrefix + response.Hash;
|
|
return new Uri(uri);
|
|
}
|
|
|
|
private MultipartContent ToMultipartContent(string fileName, string fileType, byte[] bytes)
|
|
{
|
|
var content = new MultipartFormDataContent();
|
|
|
|
var imageContent = new ByteArrayContent(bytes);
|
|
imageContent.Headers.Add("Content-Type", fileType);
|
|
content.Add(imageContent, "\"file\"", $"\"{fileName}\"");
|
|
|
|
return content;
|
|
}
|
|
|
|
private string GenerateAuthHeader()
|
|
{
|
|
if (!_blockchainContext.IsInitialized)
|
|
throw new InvalidOperationException("Blockchain context is not filled");
|
|
|
|
var user = $"eth-{_blockchainContext.Address.ToLower()}";
|
|
var password = _blockchainContext.SignedMessage;
|
|
var basicAuth = $"{user}:{password}";
|
|
var base64BasicAuth = Convert.ToBase64String(Encoding.UTF8.GetBytes(basicAuth));
|
|
var authHeader = $"Basic {base64BasicAuth}";
|
|
|
|
return authHeader;
|
|
}
|
|
}
|