Skip to content

Commit

Permalink
feat: add support for dot deposit addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
CumpsD committed Feb 2, 2024
1 parent d571507 commit 45d2bba
Show file tree
Hide file tree
Showing 11 changed files with 311 additions and 208 deletions.
46 changes: 46 additions & 0 deletions swappy-bot/Commands/AssetInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
namespace SwappyBot.Commands
{
using System;

public class AssetInfo
{
public string Id { get; }
public string Ticker { get; }
public string Name { get; }
public string Network { get; }
public int Decimals { get; }
public double MinimumAmount { get; }
public double MaximumAmount { get; }
public double[] SuggestedAmounts { get; }
public string FormatString { get; }
public Func<string, bool> AddressValidator { get; }
public Func<string, string> AddressConverter { get; }

public AssetInfo(
string id,
string ticker,
string name,
string network,
int decimals,
double minimumAmount,
double maximumAmount,
double[] suggestedAmounts,
Func<string, bool> addressValidator,
Func<string, string> addressConverter)
{
Id = id;
Ticker = ticker;
Name = name;
Network = network;
Decimals = decimals;
MinimumAmount = minimumAmount;
MaximumAmount = maximumAmount;
SuggestedAmounts = suggestedAmounts;
AddressValidator = addressValidator;
AddressConverter = addressConverter;

FormatString = $"0.00{new string('#', decimals - 2)}";

}
}
}
97 changes: 97 additions & 0 deletions swappy-bot/Commands/Assets.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
namespace SwappyBot.Commands
{
using System.Collections.Generic;
using Nethereum.Util;
using SwappyBot.Commands.Swap;
using SwappyBot.Infrastructure;

public static class Assets
{
public static readonly Dictionary<string, AssetInfo> SupportedAssets = new()
{
{
"btc",
new AssetInfo(
"btc",
"BTC",
"Bitcoin",
"Bitcoin",
8,
0.0007,
0.65,
[0.001, 0.002, 0.005, 0.01, 0.02, 0.05, 0.1, 0.2, 0.5],
x => AddressValidator.IsValidAddress(x, "btc"),
x => x)
},

{
"dot",
new AssetInfo(
"dot",
"DOT",
"Polkadot",
"Polkadot",
10,
4,
4_100,
[10, 20, 50, 150, 300, 700, 1000, 2000, 4000],
x => true,
hex => hex.ConvertToSs58())
},

{
"eth",
new AssetInfo(
"eth",
"ETH",
"Ethereum",
"Ethereum",
18,
0.01,
11,
[0.02, 0.04, 0.1, 0.2, 0.5, 1, 2, 5, 10],
x => AddressUtil.Current.IsNotAnEmptyAddress(x) &&
AddressUtil.Current.IsValidAddressLength(x) &&
AddressUtil.Current.IsValidEthereumAddressHexFormat(x) &&
(AddressUtil.Current.IsChecksumAddress(x) || x == x.ToLower() || x[2..] == x[2..].ToUpper()),
x => x)
},

{
"flip",
new AssetInfo(
"flip",
"FLIP",
"Chainflip",
"Ethereum",
18,
4,
5_700,
[10, 20, 50, 150, 300, 1000, 2000, 4000, 5500],
x => AddressUtil.Current.IsNotAnEmptyAddress(x) &&
AddressUtil.Current.IsValidAddressLength(x) &&
AddressUtil.Current.IsValidEthereumAddressHexFormat(x) &&
(AddressUtil.Current.IsChecksumAddress(x) || x == x.ToLower() || x[2..] == x[2..].ToUpper()),
x => x)
},

{
"usdc",
new AssetInfo(
"usdc",
"USDC",
"ethUSDC",
"Ethereum",
6,
20,
25_000,
[25, 50, 100, 500, 1000, 2500, 5000, 10000, 20000],
x => AddressUtil.Current.IsNotAnEmptyAddress(x) &&
AddressUtil.Current.IsValidAddressLength(x) &&
AddressUtil.Current.IsValidEthereumAddressHexFormat(x) &&
(AddressUtil.Current.IsChecksumAddress(x) || x == x.ToLower() || x[2..] == x[2..].ToUpper()),
x => x)
},
};
}
}
50 changes: 50 additions & 0 deletions swappy-bot/Commands/ConvertToSs58Extension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace SwappyBot.Commands
{
using System;
using System.Linq;
using SimpleBase;

public static class ConvertToSs58Extension
{
// First 00 = Polkadot
// Console.WriteLine("008dc56c5e01ddbbea748ab139d18e5cfc894955967a62599311d3ad7bb7571dca".ConvertToSs58());
// 14CtQ8HLKxSwtwYGc7mvSMEW7wt6maGhhEqrWezg8Y3XpZuV

// Console.WriteLine("00d513a8eb412b6bdffb39d9ebbe4edd7afad16b7bf9fa89fa225e084896757b35".ConvertToSs58());
// 15pP3JL915qcrRpYu7H1dqn87MS3WE8nc6ivKYabD54HaBcu

public static string ConvertToSs58(this string hex)
{
var publicKeyBytes = StringToByteArray(hex);
var ss58AddressBytes = Ss58Hash(publicKeyBytes);
return Base58.Bitcoin.Encode(ss58AddressBytes);
}

private static byte[] StringToByteArray(string hex) =>
Enumerable
.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();

private static byte[] Ss58Hash(byte[] data)
{
var dataLength = data.Length;
const int prefixLength = 7;
var ssPrefix = "SS58PRE"u8.ToArray();

var ssPrefixed = new byte[dataLength + prefixLength];
Buffer.BlockCopy(ssPrefix, 0, ssPrefixed, 0, prefixLength);
Buffer.BlockCopy(data, 0, ssPrefixed, prefixLength, dataLength);

var hash = Blake2Core.Blake2B.ComputeHash(ssPrefixed);

var ss58 = new byte[data.Length + 2];
Buffer.BlockCopy(data, 0, ss58, 0, dataLength);
ss58[dataLength] = hash[0];
ss58[dataLength + 1] = hash[1];

return ss58;
}
}
}
80 changes: 80 additions & 0 deletions swappy-bot/Commands/Quote.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
namespace SwappyBot.Commands
{
using System;
using System.Globalization;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using SwappyBot.Configuration;

public static class Quote
{
public static async Task<QuoteResponse?> GetQuoteAsync(
ILogger logger,
BotConfiguration configuration,
IHttpClientFactory httpClientFactory,
double amount,
AssetInfo assetFrom,
AssetInfo assetTo)
{
// https://chainflip-swap.chainflip.io/quote?amount=1500000000000000000&srcAsset=ETH&destAsset=BTC
using var client = httpClientFactory.CreateClient("Quote");

var commissionPercent = (double)configuration.CommissionBps / 100;
var commission = amount * (commissionPercent / 100);
var ingressAmount = amount - commission;
var convertedAmount = ingressAmount * Math.Pow(10, assetFrom.Decimals);

var quoteRequest =
$"quote?amount={convertedAmount:0}&srcAsset={assetFrom.Ticker}&destAsset={assetTo.Ticker}";
var quoteResponse = await client.GetAsync(quoteRequest);

if (quoteResponse.IsSuccessStatusCode)
{
var quote = await quoteResponse.Content.ReadFromJsonAsync<QuoteResponse>();
quote.IngressAmount = convertedAmount.ToString(CultureInfo.InvariantCulture);
return quote;
}

logger.LogError(
"Quote API returned {StatusCode}: {Error}\nRequest: {QuoteRequest}",
quoteResponse.StatusCode,
await quoteResponse.Content.ReadAsStringAsync(),
quoteRequest);

return null;
}
}

public class QuoteResponse
{
[JsonIgnore]
public string IngressAmount { get; set; }

[JsonPropertyName("egressAmount")]
public string EgressAmount { get; set; }

[JsonPropertyName("intermediateAmount")]
public string IntermediateAmount { get; set; }

[JsonPropertyName("includedFees")]
public QuoteFees[] Fees { get; set; }
}

public class QuoteFees
{
[JsonPropertyName("type")]
public string Type { get; set; }

[JsonPropertyName("chain")]
public string Chain { get; set; }

[JsonPropertyName("asset")]
public string Asset { get; set; }

[JsonPropertyName("amount")]
public string Amount { get; set; }
}
}
16 changes: 0 additions & 16 deletions swappy-bot/Commands/Swap/AssetInfo.cs

This file was deleted.

21 changes: 0 additions & 21 deletions swappy-bot/Commands/Swap/ChainId.cs

This file was deleted.

17 changes: 17 additions & 0 deletions swappy-bot/Commands/Swap/DepositAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,21 @@ public DepositAddressRequest(
];
}
}

public class ChainId
{
[JsonPropertyName("chain")]
public string Network { get; }

[JsonPropertyName("asset")]
public string Asset { get; }

public ChainId(
string network,
string asset)
{
Network = network;
Asset = asset;
}
}
}
34 changes: 0 additions & 34 deletions swappy-bot/Commands/Swap/Quote.cs

This file was deleted.

Loading

0 comments on commit 45d2bba

Please sign in to comment.