Enhance user authentication by adding optional OwnerWalletAddress parameter in LoginRequest and UserService. Update UserController and related components to support the new wallet address functionality, ensuring better user profile management and validation in trading operations.
This commit is contained in:
@@ -44,7 +44,7 @@ public class UserController : BaseController
|
||||
[HttpPost("create-token")]
|
||||
public async Task<ActionResult<string>> CreateToken([FromBody] LoginRequest login)
|
||||
{
|
||||
var user = await _userService.Authenticate(login.Name, login.Address, login.Message, login.Signature);
|
||||
var user = await _userService.Authenticate(login.Name, login.Address, login.Message, login.Signature, login.OwnerWalletAddress);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
|
||||
@@ -12,4 +12,5 @@ public class LoginRequest
|
||||
public string Signature { get; set; }
|
||||
[Required]
|
||||
public string Message { get; set; }
|
||||
public string? OwnerWalletAddress { get; set; }
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Managing.Application.Abstractions.Services;
|
||||
|
||||
public interface IUserService
|
||||
{
|
||||
Task<User> Authenticate(string name, string address, string message, string signature);
|
||||
Task<User> Authenticate(string name, string address, string message, string signature, string? ownerWalletAddress = null);
|
||||
Task<User> GetUserByAddressAsync(string address, bool useCache = true);
|
||||
Task<User> UpdateAgentName(User user, string agentName);
|
||||
Task<User> UpdateAvatarUrl(User user, string avatarUrl);
|
||||
|
||||
@@ -163,25 +163,20 @@ namespace Managing.Application.ManageBot
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ValidateKudaiStakingRequirements(User user)
|
||||
private async Task ValidateKudaiStakingRequirements(User user)
|
||||
{
|
||||
// Use the user's wallet address directly
|
||||
if (string.IsNullOrEmpty(user.OwnerWalletAddress))
|
||||
{
|
||||
// Get user's accounts to find their wallet address
|
||||
var userAccounts = await _accountService.GetAccountsByUserAsync(user, true, true);
|
||||
var evmAccount = userAccounts.FirstOrDefault(acc =>
|
||||
acc.Exchange == TradingExchanges.Evm ||
|
||||
acc.Exchange == TradingExchanges.GmxV2);
|
||||
throw new InvalidOperationException(
|
||||
"To copy trade the Kudai strategy, you must have a wallet address configured in your profile.");
|
||||
}
|
||||
|
||||
if (evmAccount == null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"To copy trade the Kudai strategy, you must have an EVM-compatible account (GMX V2 or EVM exchange).");
|
||||
}
|
||||
// Check KUDAI staked balance
|
||||
var kudaiStakedBalance = await _evmManager.GetKudaiStakedBalance(user.OwnerWalletAddress);
|
||||
|
||||
// Check KUDAI staked balance
|
||||
var kudaiStakedBalance = await _evmManager.GetKudaiStakedBalance(evmAccount.Key);
|
||||
|
||||
// Check GBC staked NFT count
|
||||
var gbcStakedCount = await _evmManager.GetGbcStakedCount(evmAccount.Key);
|
||||
// Check GBC staked NFT count
|
||||
var gbcStakedCount = await _evmManager.GetGbcStakedCount(user.OwnerWalletAddress);
|
||||
|
||||
// Requirements: 100 million KUDAI OR 10 GBC NFTs
|
||||
const decimal requiredKudaiAmount = 100_000_000m; // 100 million
|
||||
|
||||
@@ -45,7 +45,7 @@ public class UserService : IUserService
|
||||
: authorizedAddressesString.Split(';', StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
public async Task<User> Authenticate(string name, string address, string message, string signature)
|
||||
public async Task<User> Authenticate(string name, string address, string message, string signature, string? ownerWalletAddress = null)
|
||||
{
|
||||
var recoveredAddress = _evmManager.VerifySignature(signature, message);
|
||||
|
||||
@@ -106,6 +106,13 @@ public class UserService : IUserService
|
||||
throw new Exception("Account not found for address " + recoveredAddress);
|
||||
}
|
||||
|
||||
// Update owner wallet address if provided and user doesn't have one set yet
|
||||
if (!string.IsNullOrEmpty(ownerWalletAddress) && string.IsNullOrEmpty(user.OwnerWalletAddress))
|
||||
{
|
||||
user.OwnerWalletAddress = ownerWalletAddress;
|
||||
await _userRepository.SaveOrUpdateUserAsync(user);
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
else
|
||||
@@ -113,7 +120,8 @@ public class UserService : IUserService
|
||||
// First login - create user first
|
||||
user = new User
|
||||
{
|
||||
Name = name
|
||||
Name = name,
|
||||
OwnerWalletAddress = ownerWalletAddress ?? string.Empty
|
||||
};
|
||||
|
||||
// Save the user first
|
||||
|
||||
@@ -18,5 +18,7 @@ public class User
|
||||
|
||||
[Id(5)] public string TelegramChannel { get; set; } = string.Empty;
|
||||
|
||||
[Id(6)] public bool IsAdmin { get; set; } = false;
|
||||
[Id(6)] public string OwnerWalletAddress { get; set; } = string.Empty;
|
||||
|
||||
[Id(7)] public bool IsAdmin { get; set; } = false;
|
||||
}
|
||||
1723
src/Managing.Infrastructure.Database/Migrations/20251117062104_UpdateKudaiStakingValidation.Designer.cs
generated
Normal file
1723
src/Managing.Infrastructure.Database/Migrations/20251117062104_UpdateKudaiStakingValidation.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Managing.Infrastructure.Databases.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class UpdateKudaiStakingValidation : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "OwnerWalletAddress",
|
||||
table: "Users",
|
||||
type: "text",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "OwnerWalletAddress",
|
||||
table: "Users");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1418,6 +1418,9 @@ namespace Managing.Infrastructure.Databases.Migrations
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("character varying(255)");
|
||||
|
||||
b.Property<string>("OwnerWalletAddress")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TelegramChannel")
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("character varying(255)");
|
||||
|
||||
@@ -13,6 +13,7 @@ public class UserEntity
|
||||
[MaxLength(255)] public string? AgentName { get; set; }
|
||||
public string? AvatarUrl { get; set; }
|
||||
public string? TelegramChannel { get; set; }
|
||||
public string? OwnerWalletAddress { get; set; }
|
||||
public bool IsAdmin { get; set; }
|
||||
|
||||
// Navigation properties
|
||||
|
||||
@@ -130,6 +130,7 @@ public static class PostgreSqlMappers
|
||||
AgentName = entity.AgentName,
|
||||
AvatarUrl = entity.AvatarUrl,
|
||||
TelegramChannel = entity.TelegramChannel,
|
||||
OwnerWalletAddress = entity.OwnerWalletAddress,
|
||||
Id = entity.Id, // Assuming Id is the primary key for UserEntity
|
||||
IsAdmin = entity.IsAdmin,
|
||||
Accounts = entity.Accounts?.Select(MapAccountWithoutUser).ToList() ?? new List<Account>()
|
||||
@@ -165,6 +166,7 @@ public static class PostgreSqlMappers
|
||||
AgentName = user.AgentName,
|
||||
AvatarUrl = user.AvatarUrl,
|
||||
TelegramChannel = user.TelegramChannel,
|
||||
OwnerWalletAddress = user.OwnerWalletAddress,
|
||||
IsAdmin = user.IsAdmin
|
||||
};
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ public class PostgreSqlUserRepository : BaseRepositoryWithLogging, IUserReposito
|
||||
Name = u.Name,
|
||||
AgentName = u.AgentName,
|
||||
AvatarUrl = u.AvatarUrl,
|
||||
TelegramChannel = u.TelegramChannel
|
||||
TelegramChannel = u.TelegramChannel,
|
||||
OwnerWalletAddress = u.OwnerWalletAddress
|
||||
})
|
||||
.FirstOrDefaultAsync()
|
||||
.ConfigureAwait(false);
|
||||
@@ -93,7 +94,8 @@ public class PostgreSqlUserRepository : BaseRepositoryWithLogging, IUserReposito
|
||||
Name = u.Name,
|
||||
AgentName = u.AgentName,
|
||||
AvatarUrl = u.AvatarUrl,
|
||||
TelegramChannel = u.TelegramChannel
|
||||
TelegramChannel = u.TelegramChannel,
|
||||
OwnerWalletAddress = u.OwnerWalletAddress
|
||||
})
|
||||
.FirstOrDefaultAsync()
|
||||
.ConfigureAwait(false);
|
||||
@@ -208,7 +210,8 @@ public class PostgreSqlUserRepository : BaseRepositoryWithLogging, IUserReposito
|
||||
Name = u.Name,
|
||||
AgentName = u.AgentName,
|
||||
AvatarUrl = u.AvatarUrl,
|
||||
TelegramChannel = u.TelegramChannel
|
||||
TelegramChannel = u.TelegramChannel,
|
||||
OwnerWalletAddress = u.OwnerWalletAddress
|
||||
})
|
||||
.ToListAsync()
|
||||
.ConfigureAwait(false);
|
||||
@@ -249,6 +252,7 @@ public class PostgreSqlUserRepository : BaseRepositoryWithLogging, IUserReposito
|
||||
existingUser.AgentName = user.AgentName;
|
||||
existingUser.AvatarUrl = user.AvatarUrl;
|
||||
existingUser.TelegramChannel = user.TelegramChannel;
|
||||
existingUser.OwnerWalletAddress = user.OwnerWalletAddress;
|
||||
existingUser.IsAdmin = user.IsAdmin;
|
||||
|
||||
_context.Users.Update(existingUser);
|
||||
|
||||
@@ -37,18 +37,21 @@ const LogIn = () => {
|
||||
|
||||
t.update('info', 'Creating token...')
|
||||
|
||||
// Use the Privy embedded wallet address
|
||||
const walletAddress = user.linkedAccounts[1]?.address
|
||||
// Use the Privy embedded wallet address for authentication
|
||||
const embeddedWalletAddress = user.linkedAccounts[1]?.address
|
||||
// Use the connected user wallet address as ownerWalletAddress
|
||||
const connectedWalletAddress = user.wallet?.address
|
||||
|
||||
if (signature && walletAddress) {
|
||||
if (signature && embeddedWalletAddress) {
|
||||
const userClient = new UserClient({}, apiUrl)
|
||||
|
||||
await userClient
|
||||
.user_CreateToken({
|
||||
address: walletAddress,
|
||||
address: embeddedWalletAddress,
|
||||
message: message,
|
||||
name: user?.id,
|
||||
signature: signature,
|
||||
ownerWalletAddress: connectedWalletAddress,
|
||||
})
|
||||
.then((data) => {
|
||||
setCookie('token', data, 1)
|
||||
|
||||
@@ -4523,6 +4523,7 @@ export interface User {
|
||||
agentName?: string | null;
|
||||
avatarUrl?: string | null;
|
||||
telegramChannel?: string | null;
|
||||
ownerWalletAddress?: string | null;
|
||||
isAdmin?: boolean;
|
||||
}
|
||||
|
||||
@@ -5863,6 +5864,7 @@ export interface LoginRequest {
|
||||
address: string;
|
||||
signature: string;
|
||||
message: string;
|
||||
ownerWalletAddress?: string | null;
|
||||
}
|
||||
|
||||
export interface PaginatedWhitelistAccountsResponse {
|
||||
|
||||
@@ -46,6 +46,7 @@ export interface User {
|
||||
agentName?: string | null;
|
||||
avatarUrl?: string | null;
|
||||
telegramChannel?: string | null;
|
||||
ownerWalletAddress?: string | null;
|
||||
isAdmin?: boolean;
|
||||
}
|
||||
|
||||
@@ -1386,6 +1387,7 @@ export interface LoginRequest {
|
||||
address: string;
|
||||
signature: string;
|
||||
message: string;
|
||||
ownerWalletAddress?: string | null;
|
||||
}
|
||||
|
||||
export interface PaginatedWhitelistAccountsResponse {
|
||||
|
||||
Reference in New Issue
Block a user