diff --git a/LockDeal-NFT-API.sln b/LockDeal-NFT-API.sln index e4ccdc58..a06bd4de 100644 --- a/LockDeal-NFT-API.sln +++ b/LockDeal-NFT-API.sln @@ -5,14 +5,10 @@ VisualStudioVersion = 17.6.33829.357 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{FBF3AF2F-F3A8-407C-A68E-C129D08B59F2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageAPI", "src\ImageAPI\ImageAPI.csproj", "{813C6EB9-873A-4DC4-9D8B-E3830F0DF2E6}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetaDataAPI", "src\MetaDataAPI\MetaDataAPI.csproj", "{1087D093-685B-47A1-AE4C-510BEF8EB8FE}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{320AB552-0F05-4008-AD2B-F604D05FBD3C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageAPI.Test", "tests\ImageAPI.Test\ImageAPI.Test.csproj", "{88A9ADF0-F783-4442-BAA2-467693DD2048}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetaDataAPI.Tests", "tests\MetaDataAPI.Tests\MetaDataAPI.Tests.csproj", "{5C26358F-3DB2-4826-AD1A-98C264AA7FB0}" EndProject Global @@ -21,18 +17,10 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {813C6EB9-873A-4DC4-9D8B-E3830F0DF2E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {813C6EB9-873A-4DC4-9D8B-E3830F0DF2E6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {813C6EB9-873A-4DC4-9D8B-E3830F0DF2E6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {813C6EB9-873A-4DC4-9D8B-E3830F0DF2E6}.Release|Any CPU.Build.0 = Release|Any CPU {1087D093-685B-47A1-AE4C-510BEF8EB8FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1087D093-685B-47A1-AE4C-510BEF8EB8FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {1087D093-685B-47A1-AE4C-510BEF8EB8FE}.Release|Any CPU.ActiveCfg = Release|Any CPU {1087D093-685B-47A1-AE4C-510BEF8EB8FE}.Release|Any CPU.Build.0 = Release|Any CPU - {88A9ADF0-F783-4442-BAA2-467693DD2048}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {88A9ADF0-F783-4442-BAA2-467693DD2048}.Debug|Any CPU.Build.0 = Debug|Any CPU - {88A9ADF0-F783-4442-BAA2-467693DD2048}.Release|Any CPU.ActiveCfg = Release|Any CPU - {88A9ADF0-F783-4442-BAA2-467693DD2048}.Release|Any CPU.Build.0 = Release|Any CPU {5C26358F-3DB2-4826-AD1A-98C264AA7FB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5C26358F-3DB2-4826-AD1A-98C264AA7FB0}.Debug|Any CPU.Build.0 = Debug|Any CPU {5C26358F-3DB2-4826-AD1A-98C264AA7FB0}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -42,9 +30,7 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {813C6EB9-873A-4DC4-9D8B-E3830F0DF2E6} = {FBF3AF2F-F3A8-407C-A68E-C129D08B59F2} {1087D093-685B-47A1-AE4C-510BEF8EB8FE} = {FBF3AF2F-F3A8-407C-A68E-C129D08B59F2} - {88A9ADF0-F783-4442-BAA2-467693DD2048} = {320AB552-0F05-4008-AD2B-F604D05FBD3C} {5C26358F-3DB2-4826-AD1A-98C264AA7FB0} = {320AB552-0F05-4008-AD2B-F604D05FBD3C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/src/ImageAPI/ImageAPI.csproj b/src/ImageAPI/ImageAPI.csproj deleted file mode 100644 index 8a394a4c..00000000 --- a/src/ImageAPI/ImageAPI.csproj +++ /dev/null @@ -1,39 +0,0 @@ - - - net6.0 - enable - enable - true - Lambda - - true - - true - - - - - - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/ImageAPI/LICENSE.txt b/src/ImageAPI/LICENSE.txt deleted file mode 100644 index 8aa26455..00000000 --- a/src/ImageAPI/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) [year] [fullname] - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/src/ImageAPI/LambdaFunction.cs b/src/ImageAPI/LambdaFunction.cs deleted file mode 100644 index 843b54c3..00000000 --- a/src/ImageAPI/LambdaFunction.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Net; -using ImageAPI.Utils; -using Newtonsoft.Json; -using Amazon.Lambda.Core; -using ImageAPI.ProvidersImages; -using MetaDataAPI.Models.DynamoDb; -using Amazon.Lambda.APIGatewayEvents; - -[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))] - -namespace ImageAPI; - -public class LambdaFunction -{ - private readonly DynamoDb dynamoDb; - - public LambdaFunction() : this(new DynamoDb()) { } - - public LambdaFunction(DynamoDb dynamoDb) - { - this.dynamoDb = dynamoDb; - } - - public async Task RunAsync(APIGatewayProxyRequest input) - { - if (!input.QueryStringParameters.ContainsKey("hash")) - { - return ResponseBuilder.WrongInput(); - } - var hash = input.QueryStringParameters["hash"]; - - var databaseItem = await dynamoDb.GetItemAsync(hash); - - if (databaseItem.Item.Count == 0) - { - return ResponseBuilder.WrongHash(); - } - - if (databaseItem.Item.TryGetValue("Image", out var attributeValue)) - { - return ResponseBuilder.GetResponse(HttpStatusCode.OK, attributeValue.S, ProviderImage.ContentType, true); - } - - try - { - var attributes = JsonConvert.DeserializeObject(databaseItem.Item["Data"].S)!; - var providerImage = ProviderImageFactory.Create(attributes); - var image = providerImage.DrawOnImage(); - - var base64Image = ProviderImage.Base64FromImage(image); - - await dynamoDb.UpdateItemAsync(hash, base64Image); - - return ResponseBuilder.GetResponse(HttpStatusCode.OK, base64Image, ProviderImage.ContentType, true); - } - catch (Exception e) - { - Console.WriteLine($"Failed to process request: {e}"); - return ResponseBuilder.GeneralError(); - } - } -} diff --git a/src/ImageAPI/Processing/BadgeDrawer.cs b/src/ImageAPI/Processing/BadgeDrawer.cs deleted file mode 100644 index 1e6b3461..00000000 --- a/src/ImageAPI/Processing/BadgeDrawer.cs +++ /dev/null @@ -1,90 +0,0 @@ -using SixLabors.Fonts; -using ImageAPI.Settings; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.Drawing; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Drawing.Processing; - -namespace ImageAPI.Processing; - -public static class BadgeDrawer -{ - public static void DrawTokenBadge(this Image drawOn, string currencyName) - { - drawOn.DrawCurrencyBadge(currencyName, new PointF(554, 270), 16f); - } - - public static void DrawRefundBadge(this Image drawOn, string currencyName) - { - drawOn.DrawCurrencyBadge(currencyName, new PointF(554, 445), 16f); - } - - public static void DrawCurrencyBadge(this Image drawOn, string currencyName, PointF coordinates, float fontSize, float penWidth = 2f) - { - const int widthPadding = 20; - const int heightPadding = 8; - - var textOptions = new RichTextOptions(Resources.Font(fontSize)) - { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - }; - var text = $"${currencyName}"; - var textSize = TextMeasurer.MeasureAdvance(text, textOptions); - - var rectWidth = textSize.Width + widthPadding; - var rectHeight = textSize.Height + heightPadding; - var rectangle = new RectangleF( - coordinates.X - penWidth, - coordinates.Y - penWidth, - rectWidth, - rectHeight - ); - - var cornerRadius = (textSize.Height + heightPadding) / 2; - var roundedRectPath = CreateRoundedRectanglePath(rectangle, cornerRadius); - - drawOn.Mutate(x => x.Fill(ColorPalette.White, roundedRectPath)); - - textOptions.Origin = new PointF( - rectangle.Left - penWidth + (rectangle.Width / 2), - rectangle.Top - penWidth + (rectangle.Height / 2) - ); - drawOn.Mutate(x => x.DrawText(textOptions, text, Pens.Solid(ColorPalette.Black, penWidth))); - } - - private static IPath CreateRoundedRectanglePath(RectangleF rect, float cornerRadius) - { - var topLeft = new PointF(rect.Left, rect.Top); - var topRight = new PointF(rect.Right, rect.Top); - var bottomRight = new PointF(rect.Right, rect.Bottom); - var bottomLeft = new PointF(rect.Left, rect.Bottom); - - var pathBuilder = new PathBuilder(); - - pathBuilder.MoveTo(new PointF(topLeft.X + cornerRadius, topLeft.Y)); - pathBuilder.LineTo(new PointF(topRight.X - cornerRadius, topRight.Y)); - - var topRightCorner = new PointF(topRight.X - cornerRadius, topRight.Y + cornerRadius); - pathBuilder.AddArc(topRightCorner, cornerRadius, cornerRadius, 0, 270, 90); - - pathBuilder.LineTo(new PointF(bottomRight.X, bottomRight.Y - cornerRadius)); - - var bottomRightCorner = new PointF(bottomRight.X - cornerRadius, bottomRight.Y - cornerRadius); - pathBuilder.AddArc(bottomRightCorner, cornerRadius, cornerRadius, 0, 0, 90); - - pathBuilder.LineTo(new PointF(bottomLeft.X + cornerRadius, bottomLeft.Y)); - - var bottomLeftCorner = new PointF(bottomLeft.X + cornerRadius, bottomLeft.Y - cornerRadius); - pathBuilder.AddArc(bottomLeftCorner, cornerRadius, cornerRadius, 0, 90, 90); - - pathBuilder.LineTo(new PointF(topLeft.X, topLeft.Y + cornerRadius)); - - var topLeftCorner = new PointF(topLeft.X + cornerRadius, topLeft.Y + cornerRadius); - pathBuilder.AddArc(topLeftCorner, cornerRadius, cornerRadius, 0, 180, 90); - - pathBuilder.CloseFigure(); - - return pathBuilder.Build(); - } -} \ No newline at end of file diff --git a/src/ImageAPI/Processing/DateTimeDrawer.cs b/src/ImageAPI/Processing/DateTimeDrawer.cs deleted file mode 100644 index ed9910ef..00000000 --- a/src/ImageAPI/Processing/DateTimeDrawer.cs +++ /dev/null @@ -1,32 +0,0 @@ -using MetaDataAPI.Utils; -using System.Globalization; -using SixLabors.ImageSharp; - -namespace ImageAPI.Processing; - -public static class DateTimeDrawer -{ - public static void DrawStartTime(this Image drawOn, object startTime) - { - drawOn.DrawHeader("Start Time", new PointF(48, 274)); - drawOn.DrawDate(startTime, new PointF(48, 298), 32f); - drawOn.DrawTime(startTime, new PointF(48, 340), 32f); - } - - public static void DrawFinishTime(this Image drawOn, object finishTime) - { - drawOn.DrawHeader("Finish Time", new PointF(276, 274)); - drawOn.DrawDate(finishTime, new PointF(276, 298), 32f); - drawOn.DrawTime(finishTime, new PointF(276, 340), 32f); - } - - public static void DrawDate(this Image drawOn, object dateTime, PointF coordinates, float fontSize) - { - drawOn.DrawText(TimeUtils.FromUnixTimestamp((long)dateTime).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), coordinates, fontSize); - } - - public static void DrawTime(this Image drawOn, object dateTime, PointF coordinates, float fontSize) - { - drawOn.DrawText(TimeUtils.FromUnixTimestamp((long)dateTime).ToString("HH:mm:ss", CultureInfo.InvariantCulture), coordinates, fontSize); - } -} \ No newline at end of file diff --git a/src/ImageAPI/Processing/TextDrawer.cs b/src/ImageAPI/Processing/TextDrawer.cs deleted file mode 100644 index d60dbfc3..00000000 --- a/src/ImageAPI/Processing/TextDrawer.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.Numerics; -using SixLabors.Fonts; -using ImageAPI.Settings; -using SixLabors.ImageSharp; -using System.Text.RegularExpressions; -using SixLabors.ImageSharp.Processing; -using SixLabors.ImageSharp.Drawing.Processing; - -namespace ImageAPI.Processing; - -public static class TextDrawer -{ - public static void DrawText(this Image drawOn, string text, PointF coordinates, float fontSize, FontStyle fontStyle = FontStyle.Regular, float penWidth = 2f, Color color = default) - { - color = color == default ? ColorPalette.White : color; - var textOptions = new RichTextOptions(Resources.Font(fontSize, fontStyle)) - { - HorizontalAlignment = HorizontalAlignment.Left, - Origin = new PointF(coordinates.X - penWidth, coordinates.Y - penWidth) - }; - - drawOn.Mutate(x => x.DrawText( - textOptions, - text, - Brushes.Solid(color), - Pens.Solid(color, penWidth) - )); - } - - public static void DrawHeader(this Image drawOn, string text, PointF coordinates) - { - drawOn.DrawText(text, coordinates, 16f); - } - - public static void DrawProviderName(this Image drawOn, string providerName) - { - drawOn.DrawText(Regex.Replace(providerName, "(? dotIndex + 3) - { - return number[..(dotIndex + 3)] + "..."; - } - return number; - } -} \ No newline at end of file diff --git a/src/ImageAPI/Properties/launchSettings.json b/src/ImageAPI/Properties/launchSettings.json deleted file mode 100644 index a82d4042..00000000 --- a/src/ImageAPI/Properties/launchSettings.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "profiles": { - "Mock Lambda Test Tool": { - "commandName": "Executable", - "commandLineArgs": "--port 5050", - "workingDirectory": ".\\bin\\$(Configuration)\\net6.0", - "executablePath": "%USERPROFILE%\\.dotnet\\tools\\dotnet-lambda-test-tool-6.0.exe" - } - } -} \ No newline at end of file diff --git a/src/ImageAPI/ProvidersImages/Advanced/CollateralProviderImage.cs b/src/ImageAPI/ProvidersImages/Advanced/CollateralProviderImage.cs deleted file mode 100644 index 17bd447c..00000000 --- a/src/ImageAPI/ProvidersImages/Advanced/CollateralProviderImage.cs +++ /dev/null @@ -1,17 +0,0 @@ -using ImageAPI.Processing; -using SixLabors.ImageSharp; -using MetaDataAPI.Models.DynamoDb; - -namespace ImageAPI.ProvidersImages.Advanced; - -public class CollateralProviderImage : ProviderImage -{ - public CollateralProviderImage(IReadOnlyList dynamoDbItems) - : base(dynamoDbItems[0]) - { } - - protected override IEnumerable> DrawingActions() - { - yield return drawOn => drawOn.DrawLeftAmount(GetAttributeValue("LeftAmount")); - } -} \ No newline at end of file diff --git a/src/ImageAPI/ProvidersImages/Advanced/RefundProviderImage.cs b/src/ImageAPI/ProvidersImages/Advanced/RefundProviderImage.cs deleted file mode 100644 index 08aed8b0..00000000 --- a/src/ImageAPI/ProvidersImages/Advanced/RefundProviderImage.cs +++ /dev/null @@ -1,19 +0,0 @@ -using ImageAPI.Settings; -using ImageAPI.Processing; -using SixLabors.ImageSharp; -using MetaDataAPI.Models.DynamoDb; - -namespace ImageAPI.ProvidersImages.Advanced; - -public class RefundProviderImage : ProviderImage -{ - public RefundProviderImage(IReadOnlyList dynamoDbItems) - : base(dynamoDbItems[0]) - { } - - protected override IEnumerable> DrawingActions() - { - yield return drawOn => drawOn.DrawLeftAmount(GetAttributeValue("MainCoinAmount")); - yield return drawOn => drawOn.DrawText("MainCoin", new PointF(Resources.BackgroundImage.Width - 400, Resources.BackgroundImage.Height - 330), 16f); - } -} \ No newline at end of file diff --git a/src/ImageAPI/ProvidersImages/DelayVault/DelayVaultProviderImage.cs b/src/ImageAPI/ProvidersImages/DelayVault/DelayVaultProviderImage.cs deleted file mode 100644 index 84718a73..00000000 --- a/src/ImageAPI/ProvidersImages/DelayVault/DelayVaultProviderImage.cs +++ /dev/null @@ -1,19 +0,0 @@ -using ImageAPI.Processing; -using SixLabors.ImageSharp; -using MetaDataAPI.Models.DynamoDb; - -namespace ImageAPI.ProvidersImages.DelayVault; - -public class DelayVaultProviderImage : ProviderImage -{ - protected override string ProviderName => "Leader Board"; - - public DelayVaultProviderImage(IReadOnlyList dynamoDbItems) - : base(dynamoDbItems[0]) - { } - - protected override IEnumerable> DrawingActions() - { - yield return drawOn => drawOn.DrawLeftAmount(GetAttributeValue("LeftAmount")); - } -} \ No newline at end of file diff --git a/src/ImageAPI/ProvidersImages/ProviderImage.cs b/src/ImageAPI/ProvidersImages/ProviderImage.cs deleted file mode 100644 index c6f42b79..00000000 --- a/src/ImageAPI/ProvidersImages/ProviderImage.cs +++ /dev/null @@ -1,55 +0,0 @@ -using ImageAPI.Settings; -using ImageAPI.Processing; -using SixLabors.ImageSharp; -using MetaDataAPI.Models.DynamoDb; -using MetaDataAPI.Models.Response; -using SixLabors.ImageSharp.Processing; - -namespace ImageAPI.ProvidersImages; - -public abstract class ProviderImage -{ - public const string ContentType = "image/png"; - protected readonly DynamoDbItem dynamoDbItem; - protected virtual string ProviderName => dynamoDbItem.ProviderName; - - protected ProviderImage(DynamoDbItem dynamoDbItem) - { - this.dynamoDbItem = dynamoDbItem; - } - - protected abstract IEnumerable> DrawingActions(); - - public Image DrawOnImage() - { - var actions = new List>(DrawingActions()) - { - drawOn => drawOn.DrawProviderName(ProviderName), - drawOn => drawOn.DrawPoolId(dynamoDbItem.PoolId), - drawOn => drawOn.DrawTokenBadge(dynamoDbItem.TokenSymbol) - }; - - var image = Resources.BackgroundImage.Clone(_ => { }); - actions.ForEach(action => action(image)); - return image; - } - - public static string Base64FromImage(Image image) - { -#if DEBUG - image.SaveAsPng("result.png"); -#endif - using var outputStream = new MemoryStream(); - image.SaveAsPngAsync(outputStream) - .GetAwaiter() - .GetResult(); - var imageBytes = outputStream.ToArray(); - return Convert.ToBase64String(imageBytes); - } - - protected object GetAttributeValue(string traitType) => - dynamoDbItem.Attributes.FirstOrDefault( - x => x.TraitType == traitType, - new Erc721Attribute(traitType, $"{traitType} not found.") - ).Value; -} \ No newline at end of file diff --git a/src/ImageAPI/ProvidersImages/ProviderImageFactory.cs b/src/ImageAPI/ProvidersImages/ProviderImageFactory.cs deleted file mode 100644 index 23f2c2c8..00000000 --- a/src/ImageAPI/ProvidersImages/ProviderImageFactory.cs +++ /dev/null @@ -1,27 +0,0 @@ -using MetaDataAPI.Providers; -using MetaDataAPI.Models.DynamoDb; -using ImageAPI.ProvidersImages.Simple; -using ImageAPI.ProvidersImages.Advanced; -using ImageAPI.ProvidersImages.DelayVault; - -namespace ImageAPI.ProvidersImages; - -public static class ProviderImageFactory -{ - public static ProviderImage Create(DynamoDbItem[] attributes) - { - var providerName = attributes[0].ProviderName; - - return Providers(attributes)[providerName](); - } - - private static Dictionary> Providers(IReadOnlyList dynamoDbItems) => new() - { - { nameof(DealProvider), () => new DealProviderImage(dynamoDbItems) }, - { nameof(LockDealProvider), () => new LockDealProviderImage(dynamoDbItems) }, - { nameof(TimedDealProvider), () => new TimedDealProviderImage(dynamoDbItems) }, - { nameof(CollateralProvider), () => new CollateralProviderImage(dynamoDbItems) }, - { nameof(RefundProvider), () => new RefundProviderImage(dynamoDbItems) }, - { nameof(DelayVaultProvider), () => new DelayVaultProviderImage(dynamoDbItems) }, - }; -} \ No newline at end of file diff --git a/src/ImageAPI/ProvidersImages/Simple/DealProviderImage.cs b/src/ImageAPI/ProvidersImages/Simple/DealProviderImage.cs deleted file mode 100644 index 4f66e2e6..00000000 --- a/src/ImageAPI/ProvidersImages/Simple/DealProviderImage.cs +++ /dev/null @@ -1,17 +0,0 @@ -using ImageAPI.Processing; -using SixLabors.ImageSharp; -using MetaDataAPI.Models.DynamoDb; - -namespace ImageAPI.ProvidersImages.Simple; - -public class DealProviderImage : ProviderImage -{ - public DealProviderImage(IReadOnlyList dynamoDbItems) - : base(dynamoDbItems[0]) - { } - - protected override IEnumerable> DrawingActions() - { - yield return drawOn => drawOn.DrawLeftAmount(GetAttributeValue("LeftAmount")); - } -} \ No newline at end of file diff --git a/src/ImageAPI/ProvidersImages/Simple/LockDealProviderImage.cs b/src/ImageAPI/ProvidersImages/Simple/LockDealProviderImage.cs deleted file mode 100644 index 19fb88fc..00000000 --- a/src/ImageAPI/ProvidersImages/Simple/LockDealProviderImage.cs +++ /dev/null @@ -1,21 +0,0 @@ -using ImageAPI.Processing; -using SixLabors.ImageSharp; -using MetaDataAPI.Models.DynamoDb; - -namespace ImageAPI.ProvidersImages.Simple; - -public class LockDealProviderImage : DealProviderImage -{ - public LockDealProviderImage(IReadOnlyList dynamoDbItems) - : base(dynamoDbItems) - { } - - protected override IEnumerable> DrawingActions() - { - foreach (var action in base.DrawingActions()) - { - yield return action; - } - yield return drawOn => drawOn.DrawStartTime(GetAttributeValue("StartTime")); - } -} \ No newline at end of file diff --git a/src/ImageAPI/ProvidersImages/Simple/TimedDealProviderImage.cs b/src/ImageAPI/ProvidersImages/Simple/TimedDealProviderImage.cs deleted file mode 100644 index c926ff6a..00000000 --- a/src/ImageAPI/ProvidersImages/Simple/TimedDealProviderImage.cs +++ /dev/null @@ -1,21 +0,0 @@ -using ImageAPI.Processing; -using SixLabors.ImageSharp; -using MetaDataAPI.Models.DynamoDb; - -namespace ImageAPI.ProvidersImages.Simple; - -public class TimedDealProviderImage : LockDealProviderImage -{ - public TimedDealProviderImage(IReadOnlyList dynamoDbItems) - : base(dynamoDbItems) - { } - - protected override IEnumerable> DrawingActions() - { - foreach (var action in base.DrawingActions()) - { - yield return action; - } - yield return drawOn => drawOn.DrawFinishTime(GetAttributeValue("FinishTime")); - } -} \ No newline at end of file diff --git a/src/ImageAPI/Readme.md b/src/ImageAPI/Readme.md deleted file mode 100644 index 0f8106f8..00000000 --- a/src/ImageAPI/Readme.md +++ /dev/null @@ -1,31 +0,0 @@ -# ImageAPI - -## Overview -The ImageAPI Lambda function is responsible for creating an NFT image based on attributes fetched from a DynamoDB database. -The attributes are fetched using a hash, which is the unique identifier of the NFT. - -## Flow -1. `API Invocation`: The client invokes the API by making a GET request to `https://nft.poolz.finance/test/image?id=HASH_HERE`, where `HASH_HERE` is the unique identifier for the NFT attributes. - -2. `Input Validation`: The function first validates the provided `hash` from the query string. If it's missing or invalid, a `400 Bad Request` status code is returned. - -3. `DynamoDB Query`: The DynamoDb class is used to asynchronously fetch NFT attributes from the DynamoDB table named `MetaDataCache`. -This table is queried using the hash value provided as primary key. - -4. `Resource Loading`: The ResourcesLoader class loads the image and font resources required for generating the NFT image. These resources are embedded in the project. - -5. `Text Rendering`: The ImageProcessor class takes the fetched attributes and draws them on the loaded image using the loaded font. -Drawing options are created using the `CreateTextOptions` method, which sets the origin, tab width, wrapping length, and alignment of the text. - -6. `Image Generation`: The ImageProcessor then generates the final NFT image in PNG format and converts it into a Base64 encoded string. - -7. `API Response`: Finally, a `200 OK` status code is returned, with the generated Base64 encoded string in the body. In the event of any error, a `500 Internal Server Error` status code is returned. - -## Exception Handling -- 400 Bad Request: Returned if the `hash` parameter in the query string is missing or invalid. - -- 500 Internal Server Error: Returned if any exception occurs while processing the request, e.g., failing to fetch data from DynamoDB, issues during image rendering, etc. - -## API URL - -- https://nft.poolz.finance/test/image?id=HASH_HERE diff --git a/src/ImageAPI/ResourceLoaders/FontFamilyLoader.cs b/src/ImageAPI/ResourceLoaders/FontFamilyLoader.cs deleted file mode 100644 index dc67d69f..00000000 --- a/src/ImageAPI/ResourceLoaders/FontFamilyLoader.cs +++ /dev/null @@ -1,21 +0,0 @@ -using SixLabors.Fonts; - -namespace ImageAPI.ResourceLoaders; - -public sealed class FontFamilyLoader : ResourceLoader -{ - public override FontFamily Resource { get; } - - public FontFamilyLoader() - : base("ImageAPI.Resources.ABCNormal.otf") - { - Resource = Load(); - } - - public override FontFamily Load() - { - using var fontStream = ResourceStream(); - var fontCollection = new FontCollection(); - return fontCollection.Add(fontStream); - } -} \ No newline at end of file diff --git a/src/ImageAPI/ResourceLoaders/ImageLoader.cs b/src/ImageAPI/ResourceLoaders/ImageLoader.cs deleted file mode 100644 index 5c0c9e06..00000000 --- a/src/ImageAPI/ResourceLoaders/ImageLoader.cs +++ /dev/null @@ -1,20 +0,0 @@ -using SixLabors.ImageSharp; - -namespace ImageAPI.ResourceLoaders; - -public sealed class ImageLoader : ResourceLoader -{ - public override Image Resource { get; } - - public ImageLoader() - : base("ImageAPI.Resources.background.png") - { - Resource = Load(); - } - - public override Image Load() - { - using var imageStream = ResourceStream(); - return Image.Load(imageStream); - } -} \ No newline at end of file diff --git a/src/ImageAPI/ResourceLoaders/ResourceLoader.cs b/src/ImageAPI/ResourceLoaders/ResourceLoader.cs deleted file mode 100644 index ee0e0564..00000000 --- a/src/ImageAPI/ResourceLoaders/ResourceLoader.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Reflection; - -namespace ImageAPI.ResourceLoaders; - -public abstract class ResourceLoader -{ - private readonly string resourceName; - public abstract TResource Resource { get; } - - protected ResourceLoader(string resourceName) - { - this.resourceName = resourceName; - } - - public abstract TResource Load(); - - protected Stream ResourceStream() => - Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName) ?? throw new FileNotFoundException(ErrorMessage()); - - private string ErrorMessage() => - $"Could not find the embedded resource '{resourceName}'. Make sure the resource exists and its 'Build Action' is set to 'Embedded Resource'."; -} \ No newline at end of file diff --git a/src/ImageAPI/Resources/ABCNormal.otf b/src/ImageAPI/Resources/ABCNormal.otf deleted file mode 100644 index ce3ed075..00000000 Binary files a/src/ImageAPI/Resources/ABCNormal.otf and /dev/null differ diff --git a/src/ImageAPI/Resources/background.png b/src/ImageAPI/Resources/background.png deleted file mode 100644 index 423f00d3..00000000 Binary files a/src/ImageAPI/Resources/background.png and /dev/null differ diff --git a/src/ImageAPI/Resources/background.svg b/src/ImageAPI/Resources/background.svg deleted file mode 100644 index 0b05ba00..00000000 --- a/src/ImageAPI/Resources/background.svg +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/ImageAPI/Settings/ColorPalette.cs b/src/ImageAPI/Settings/ColorPalette.cs deleted file mode 100644 index 40c38d7f..00000000 --- a/src/ImageAPI/Settings/ColorPalette.cs +++ /dev/null @@ -1,9 +0,0 @@ -using SixLabors.ImageSharp; - -namespace ImageAPI.Settings; - -public static class ColorPalette -{ - public static readonly Color White = Color.ParseHex("#FDFDFD"); - public static readonly Color Black = Color.ParseHex("#010013"); -} \ No newline at end of file diff --git a/src/ImageAPI/Settings/Resources.cs b/src/ImageAPI/Settings/Resources.cs deleted file mode 100644 index 6dca8b9d..00000000 --- a/src/ImageAPI/Settings/Resources.cs +++ /dev/null @@ -1,15 +0,0 @@ -using SixLabors.Fonts; -using SixLabors.ImageSharp; -using ImageAPI.ResourceLoaders; - -namespace ImageAPI.Settings; - -public static class Resources -{ - private static readonly ImageLoader imageLoader = new(); - private static readonly FontFamilyLoader fontFamilyLoader = new(); - private static readonly FontFamily fontFamily = fontFamilyLoader.Resource; - - public static Image BackgroundImage => imageLoader.Resource; - public static Font Font(float fontSize, FontStyle fontStyle = FontStyle.Regular) => new(fontFamily, fontSize, fontStyle); -} \ No newline at end of file diff --git a/src/ImageAPI/Utils/DynamoDb.cs b/src/ImageAPI/Utils/DynamoDb.cs deleted file mode 100644 index 8902708e..00000000 --- a/src/ImageAPI/Utils/DynamoDb.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Amazon.DynamoDBv2; -using Amazon.DynamoDBv2.Model; - -namespace ImageAPI.Utils; - -public class DynamoDb -{ - private const string TableName = "MetaDataCache"; - private const string PrimaryKey = "HashKey"; - private readonly IAmazonDynamoDB client; - - public DynamoDb() - : this(new AmazonDynamoDBClient()) - { } - - public DynamoDb(IAmazonDynamoDB client) - { - this.client = client; - } - - public virtual async Task GetItemAsync(string hash) - { - return await client.GetItemAsync(new GetItemRequest - { - TableName = TableName, - Key = new Dictionary - { - { PrimaryKey, new AttributeValue { S = hash } } - } - }); - } - - public virtual async Task UpdateItemAsync(string hash, string base64Image) - { - var request = new UpdateItemRequest - { - TableName = TableName, - Key = new Dictionary - { - { PrimaryKey, new AttributeValue { S = hash } } - }, - AttributeUpdates = new Dictionary - { - { - "Image", new AttributeValueUpdate - { - Action = AttributeAction.PUT, - Value = new AttributeValue { S = base64Image } - } - } - } - }; - - await client.UpdateItemAsync(request); - } -} \ No newline at end of file diff --git a/src/ImageAPI/Utils/ResponseBuilder.cs b/src/ImageAPI/Utils/ResponseBuilder.cs deleted file mode 100644 index 3ec6f699..00000000 --- a/src/ImageAPI/Utils/ResponseBuilder.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Net; -using Amazon.Lambda.APIGatewayEvents; - -namespace ImageAPI.Utils; - -public static class ResponseBuilder -{ - public const string MissingHashMessage = "Missing 'hash' parameter."; - public const string ItemNotFoundMessage = "Item by provided 'hash' not found."; - public const string GeneralErrorMessage = "Something went wrong."; - public static APIGatewayProxyResponse GetResponse(HttpStatusCode statusCode, string body, string contentType, bool isBase64Encoded) => new() - { - IsBase64Encoded = isBase64Encoded, - StatusCode = (int)statusCode, - Body = body, - Headers = new Dictionary - { - { "Content-Type", contentType } - } - }; - public static APIGatewayProxyResponse WrongInput() => GetResponse(HttpStatusCode.BadRequest, MissingHashMessage, "text/plain", false); - public static APIGatewayProxyResponse WrongHash() => GetResponse(HttpStatusCode.NotFound, ItemNotFoundMessage, "text/plain", false); - public static APIGatewayProxyResponse GeneralError() => GetResponse(HttpStatusCode.InternalServerError, GeneralErrorMessage, "text/plain", false); -} diff --git a/tests/ImageAPI.Test/ImageAPI.Test.csproj b/tests/ImageAPI.Test/ImageAPI.Test.csproj deleted file mode 100644 index ac7d2d9c..00000000 --- a/tests/ImageAPI.Test/ImageAPI.Test.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - net6.0 - enable - enable - - false - true - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - diff --git a/tests/ImageAPI.Test/LambdaFunctionTests.cs b/tests/ImageAPI.Test/LambdaFunctionTests.cs deleted file mode 100644 index 813942e6..00000000 --- a/tests/ImageAPI.Test/LambdaFunctionTests.cs +++ /dev/null @@ -1,168 +0,0 @@ -using Moq; -using Xunit; -using System.Net; -using ImageAPI.Utils; -using FluentAssertions; -using Amazon.DynamoDBv2.Model; -using Amazon.Lambda.APIGatewayEvents; - -namespace ImageAPI.Test; - -public class LambdaFunctionTests -{ - public static APIGatewayProxyResponse ValidResponse => new() - { - IsBase64Encoded = true, - StatusCode = (int)HttpStatusCode.OK, - Body = "base64_encoded_image_data", - Headers = new Dictionary - { - { "Content-Type", "image/png" } - } - }; - - public LambdaFunctionTests() - { - Environment.SetEnvironmentVariable("AWS_REGION", "us-west-2"); - } - - [Fact] - internal async Task RunAsync_DynamoDbContainsImage_ShouldReturnResponse() - { - var dynamoDb = new Mock(); - dynamoDb.Setup(x => x.GetItemAsync("0x1")) - .ReturnsAsync(new GetItemResponse - { - Item = new Dictionary - { - { - "Data", new AttributeValue - { - S = "[{\"trait_type\":\"ProviderName\",\"value\":\"DealProvider\"},{\"trait_type\":\"Collection\",\"value\":0},{\"trait_type\":\"LeftAmount\",\"value\":50.0}]" - } - }, - { - "Image", new AttributeValue - { - S = ValidResponse.Body - } - } - } - }); - var request = new APIGatewayProxyRequest - { - QueryStringParameters = new Dictionary - { - { "hash", "0x1" } - } - }; - - var result = await new LambdaFunction(dynamoDb.Object).RunAsync(request); - - result.Body.Should().Be(ValidResponse.Body); - result.Headers.Should().BeEquivalentTo(ValidResponse.Headers); - result.IsBase64Encoded.Should().Be(ValidResponse.IsBase64Encoded); - result.StatusCode.Should().Be(ValidResponse.StatusCode); - } - - [Fact] - internal async Task RunAsync_BuildImage_ShouldReturnResponse() - { - var dynamoDb = new Mock(); - dynamoDb.Setup(x => x.GetItemAsync("0x1")) - .ReturnsAsync(new GetItemResponse - { - Item = new Dictionary - { - { - "Data", new AttributeValue - { - S = "[{\"ProviderName\":\"DealProvider\",\"Attributes\":[{\"trait_type\":\"Collection\",\"value\":2},{\"trait_type\":\"LeftAmount\",\"value\":13572.37461}]}]" - } - } - } - }); - var request = new APIGatewayProxyRequest - { - QueryStringParameters = new Dictionary - { - { "hash", "0x1" } - } - }; - - var result = await new LambdaFunction(dynamoDb.Object).RunAsync(request); - - result.Body.Should().NotBe(string.Empty); - result.Headers.Should().BeEquivalentTo(ValidResponse.Headers); - result.IsBase64Encoded.Should().Be(ValidResponse.IsBase64Encoded); - result.StatusCode.Should().Be(ValidResponse.StatusCode); - } - - [Fact] - internal async Task RunAsync_ShouldReturnResponse_WrongInput() - { - var request = new APIGatewayProxyRequest - { - QueryStringParameters = new Dictionary - { - { "not-hash", "value" } - } - }; - - var result = await new LambdaFunction().RunAsync(request); - - result.Should().BeEquivalentTo(ResponseBuilder.WrongInput()); - } - - [Fact] - internal async Task RunAsync_ShouldReturnResponse_WrongHash() - { - var dynamoDb = new Mock(); - dynamoDb.Setup(x => x.GetItemAsync(It.IsAny())) - .ReturnsAsync(new GetItemResponse - { - Item = new Dictionary() - }); - var request = new APIGatewayProxyRequest - { - QueryStringParameters = new Dictionary - { - { "hash", "0x1" } - } - }; - - var result = await new LambdaFunction(dynamoDb.Object).RunAsync(request); - - result.Should().BeEquivalentTo(ResponseBuilder.WrongHash()); - } - - [Fact] - internal async Task RunAsync_ShouldReturnResponse_GeneralError() - { - var dynamoDb = new Mock(); - dynamoDb.Setup(x => x.GetItemAsync("0x1")) - .ReturnsAsync(new GetItemResponse - { - Item = new Dictionary - { - { - "Data", new AttributeValue - { - S = "[{\"trait_type\":\"Collection\",\"value\":0},{\"trait_type\":\"LeftAmount\",\"value\":50.0}]" - } - } - } - }); - var request = new APIGatewayProxyRequest - { - QueryStringParameters = new Dictionary - { - { "hash", "0x1" } - } - }; - - var result = await new LambdaFunction(dynamoDb.Object).RunAsync(request); - - result.Should().BeEquivalentTo(ResponseBuilder.GeneralError()); - } -} \ No newline at end of file diff --git a/tests/ImageAPI.Test/Utils/DynamoDbTests.cs b/tests/ImageAPI.Test/Utils/DynamoDbTests.cs deleted file mode 100644 index 2623f7b8..00000000 --- a/tests/ImageAPI.Test/Utils/DynamoDbTests.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Moq; -using Xunit; -using ImageAPI.Utils; -using FluentAssertions; -using Amazon.DynamoDBv2; -using Amazon.DynamoDBv2.Model; - -namespace ImageAPI.Test.Utils; - -public class DynamoDbTests -{ - [Fact] - internal void Ctor_Default() - { - Environment.SetEnvironmentVariable("AWS_REGION", "us-west-2"); - var dynamoDb = new DynamoDb(); - - dynamoDb.Should().NotBeNull(); - } - - [Fact] - internal async Task GetItemAsync() - { - var hash = Guid.NewGuid().ToString(); - var expected = new GetItemResponse - { - Item = new Dictionary - { - { "HashKey", new AttributeValue { S = hash } } - } - }; - var client = new Mock(); - client.Setup(x => x.GetItemAsync( - It.Is(req => req.TableName == "MetaDataCache" && req.Key["HashKey"].S == hash), - It.IsAny()) - ).ReturnsAsync(expected); - - var result = await new DynamoDb(client.Object).GetItemAsync(hash); - - result.Should().BeEquivalentTo(expected); - } - - [Fact] - internal async Task UpdateItemAsync() - { - var hash = Guid.NewGuid().ToString(); - var base64Image = Guid.NewGuid().ToString(); - var client = new Mock(); - - var testCode = async () => await new DynamoDb(client.Object).UpdateItemAsync(hash, base64Image); - - await testCode.Should().NotThrowAsync(); - } -} \ No newline at end of file