Add initAddress api
This commit is contained in:
@@ -3,6 +3,7 @@ using Managing.Application.Abstractions.Services;
|
|||||||
using Managing.Application.Trading.Commands;
|
using Managing.Application.Trading.Commands;
|
||||||
using Managing.Domain.MoneyManagements;
|
using Managing.Domain.MoneyManagements;
|
||||||
using Managing.Domain.Trades;
|
using Managing.Domain.Trades;
|
||||||
|
using Managing.Infrastructure.Evm.Models.Privy;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
@@ -156,4 +157,33 @@ public class TradingController : BaseController
|
|||||||
var result = await _openTradeCommandHandler.Handle(command);
|
var result = await _openTradeCommandHandler.Handle(command);
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a Privy wallet address for the user.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="publicAddress">The public address of the Privy wallet to initialize.</param>
|
||||||
|
/// <returns>The initialization response containing success status and transaction hashes.</returns>
|
||||||
|
[HttpPost("InitPrivyWallet")]
|
||||||
|
public async Task<ActionResult<PrivyInitAddressResponse>> InitPrivyWallet([FromBody] string publicAddress)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(publicAddress))
|
||||||
|
{
|
||||||
|
return BadRequest("Public address cannot be null or empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _tradingService.InitPrivyWallet(publicAddress);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error initializing Privy wallet address: {Address}", publicAddress);
|
||||||
|
return StatusCode(500, new PrivyInitAddressResponse
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Error = "An error occurred while initializing the Privy wallet address."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ using Managing.Domain.Candles;
|
|||||||
using Managing.Domain.Evm;
|
using Managing.Domain.Evm;
|
||||||
using Managing.Domain.Statistics;
|
using Managing.Domain.Statistics;
|
||||||
using Managing.Domain.Trades;
|
using Managing.Domain.Trades;
|
||||||
|
using Managing.Infrastructure.Evm.Models.Privy;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
|
|
||||||
namespace Managing.Application.Abstractions.Repositories;
|
namespace Managing.Application.Abstractions.Repositories;
|
||||||
@@ -25,7 +26,7 @@ public interface IEvmManager
|
|||||||
decimal GetVolume(SubgraphProvider subgraphProvider, Ticker ticker);
|
decimal GetVolume(SubgraphProvider subgraphProvider, Ticker ticker);
|
||||||
Task<List<Ticker>> GetAvailableTicker();
|
Task<List<Ticker>> GetAvailableTicker();
|
||||||
Task<Candle> GetCandle(Ticker ticker);
|
Task<Candle> GetCandle(Ticker ticker);
|
||||||
Task<bool> InitAddress(string publicAddress);
|
Task<PrivyInitAddressResponse> InitAddress(string publicAddress);
|
||||||
|
|
||||||
Task<bool> Send(Chain chain, Ticker ticker, decimal amount, string publicAddress, string privateKey,
|
Task<bool> Send(Chain chain, Ticker ticker, decimal amount, string publicAddress, string privateKey,
|
||||||
string receiverAddress);
|
string receiverAddress);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Managing.Domain.Scenarios;
|
|||||||
using Managing.Domain.Statistics;
|
using Managing.Domain.Statistics;
|
||||||
using Managing.Domain.Strategies;
|
using Managing.Domain.Strategies;
|
||||||
using Managing.Domain.Trades;
|
using Managing.Domain.Trades;
|
||||||
|
using Managing.Infrastructure.Evm.Models.Privy;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
|
|
||||||
namespace Managing.Application.Abstractions.Services;
|
namespace Managing.Application.Abstractions.Services;
|
||||||
@@ -35,4 +36,5 @@ public interface ITradingService
|
|||||||
void UpdateScenario(Scenario scenario);
|
void UpdateScenario(Scenario scenario);
|
||||||
void UpdateStrategy(Strategy strategy);
|
void UpdateStrategy(Strategy strategy);
|
||||||
Task<IEnumerable<Position>> GetBrokerPositions(Account account);
|
Task<IEnumerable<Position>> GetBrokerPositions(Account account);
|
||||||
|
Task<PrivyInitAddressResponse> InitPrivyWallet(string publicAddress);
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using Managing.Application.Abstractions;
|
using Managing.Application.Abstractions.Repositories;
|
||||||
using Managing.Application.Abstractions.Repositories;
|
|
||||||
using Managing.Application.Abstractions.Services;
|
using Managing.Application.Abstractions.Services;
|
||||||
using Managing.Domain.Accounts;
|
using Managing.Domain.Accounts;
|
||||||
using Managing.Domain.Scenarios;
|
using Managing.Domain.Scenarios;
|
||||||
@@ -7,6 +6,7 @@ using Managing.Domain.Shared.Helpers;
|
|||||||
using Managing.Domain.Statistics;
|
using Managing.Domain.Statistics;
|
||||||
using Managing.Domain.Strategies;
|
using Managing.Domain.Strategies;
|
||||||
using Managing.Domain.Trades;
|
using Managing.Domain.Trades;
|
||||||
|
using Managing.Infrastructure.Evm.Models.Privy;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@ public class TradingService : ITradingService
|
|||||||
private readonly ICacheService _cacheService;
|
private readonly ICacheService _cacheService;
|
||||||
private readonly IMessengerService _messengerService;
|
private readonly IMessengerService _messengerService;
|
||||||
private readonly IStatisticRepository _statisticRepository;
|
private readonly IStatisticRepository _statisticRepository;
|
||||||
|
private readonly IEvmManager _evmManager;
|
||||||
private readonly ILogger<TradingService> _logger;
|
private readonly ILogger<TradingService> _logger;
|
||||||
|
|
||||||
public TradingService(
|
public TradingService(
|
||||||
@@ -29,7 +30,8 @@ public class TradingService : ITradingService
|
|||||||
IAccountService accountService,
|
IAccountService accountService,
|
||||||
ICacheService cacheService,
|
ICacheService cacheService,
|
||||||
IMessengerService messengerService,
|
IMessengerService messengerService,
|
||||||
IStatisticRepository statisticRepository)
|
IStatisticRepository statisticRepository,
|
||||||
|
IEvmManager evmManager)
|
||||||
{
|
{
|
||||||
_tradingRepository = tradingRepository;
|
_tradingRepository = tradingRepository;
|
||||||
_exchangeService = exchangeService;
|
_exchangeService = exchangeService;
|
||||||
@@ -38,6 +40,7 @@ public class TradingService : ITradingService
|
|||||||
_cacheService = cacheService;
|
_cacheService = cacheService;
|
||||||
_messengerService = messengerService;
|
_messengerService = messengerService;
|
||||||
_statisticRepository = statisticRepository;
|
_statisticRepository = statisticRepository;
|
||||||
|
_evmManager = evmManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DeleteScenario(string name)
|
public void DeleteScenario(string name)
|
||||||
@@ -374,4 +377,23 @@ public class TradingService : ITradingService
|
|||||||
public List<Trade> Trades { get; set; }
|
public List<Trade> Trades { get; set; }
|
||||||
public List<string> PositionIdentifiers { get; set; }
|
public List<string> PositionIdentifiers { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<PrivyInitAddressResponse> InitPrivyWallet(string publicAddress)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(publicAddress))
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Attempted to initialize Privy wallet with null or empty public address");
|
||||||
|
return new PrivyInitAddressResponse { Success = false, Error = "Public address cannot be null or empty" };
|
||||||
|
}
|
||||||
|
|
||||||
|
return await _evmManager.InitAddress(publicAddress);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error initializing Privy wallet for address {PublicAddress}", publicAddress);
|
||||||
|
return new PrivyInitAddressResponse { Success = false, Error = ex.Message };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -210,7 +210,7 @@ public class EvmManagerTests
|
|||||||
{
|
{
|
||||||
var accountInitilized = await _manager.InitAddress(PublicAddress);
|
var accountInitilized = await _manager.InitAddress(PublicAddress);
|
||||||
|
|
||||||
Assert.True(accountInitilized);
|
Assert.NotNull(accountInitilized);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Ignore]
|
[Ignore]
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ public class EvmManager : IEvmManager
|
|||||||
return cachedCandle;
|
return cachedCandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> InitAddress(string publicAddress)
|
public async Task<PrivyInitAddressResponse> InitAddress(string publicAddress)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -452,13 +452,17 @@ public class EvmManager : IEvmManager
|
|||||||
"/init-address",
|
"/init-address",
|
||||||
new { address = publicAddress });
|
new { address = publicAddress });
|
||||||
|
|
||||||
return response.Success;
|
return response;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Log the error
|
// Log the error
|
||||||
Console.Error.WriteLine($"Error initializing address: {ex.Message}");
|
Console.Error.WriteLine($"Error initializing address: {ex.Message}");
|
||||||
return false;
|
return new PrivyInitAddressResponse
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Error = ex.Message
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,6 +150,9 @@ export async function getClientForAddress(
|
|||||||
"0xdf034cd3df9a80eABFA0556232a91E03Ca67D5Cb": {
|
"0xdf034cd3df9a80eABFA0556232a91E03Ca67D5Cb": {
|
||||||
isListed: false,
|
isListed: false,
|
||||||
},
|
},
|
||||||
|
"0x9e79146b3A022Af44E0708c6794F03Ef798381A5": {
|
||||||
|
isListed: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2159,6 +2159,45 @@ export class TradingClient extends AuthorizedApiBase {
|
|||||||
}
|
}
|
||||||
return Promise.resolve<Position>(null as any);
|
return Promise.resolve<Position>(null as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trading_InitPrivyWallet(publicAddress: string): Promise<PrivyInitAddressResponse> {
|
||||||
|
let url_ = this.baseUrl + "/Trading/InitPrivyWallet";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
const content_ = JSON.stringify(publicAddress);
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
body: content_,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.transformOptions(options_).then(transformedOptions_ => {
|
||||||
|
return this.http.fetch(url_, transformedOptions_);
|
||||||
|
}).then((_response: Response) => {
|
||||||
|
return this.processTrading_InitPrivyWallet(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processTrading_InitPrivyWallet(response: Response): Promise<PrivyInitAddressResponse> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
let result200: any = null;
|
||||||
|
result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as PrivyInitAddressResponse;
|
||||||
|
return result200;
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<PrivyInitAddressResponse>(null as any);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserClient extends AuthorizedApiBase {
|
export class UserClient extends AuthorizedApiBase {
|
||||||
@@ -3072,6 +3111,14 @@ export enum RiskLevel {
|
|||||||
Adaptive = "Adaptive",
|
Adaptive = "Adaptive",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PrivyInitAddressResponse {
|
||||||
|
success?: boolean;
|
||||||
|
usdcHash?: string | null;
|
||||||
|
orderVaultHash?: string | null;
|
||||||
|
exchangeRouterHash?: string | null;
|
||||||
|
error?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface LoginRequest {
|
export interface LoginRequest {
|
||||||
name: string;
|
name: string;
|
||||||
address: string;
|
address: string;
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
import {
|
import {ChevronDownIcon, ChevronRightIcon,} from '@heroicons/react/solid'
|
||||||
ChevronDownIcon,
|
import React, {useEffect, useMemo, useState} from 'react'
|
||||||
ChevronRightIcon,
|
import {useNavigate} from 'react-router-dom'
|
||||||
ClipboardCopyIcon,
|
import {FiKey, FiPlay, FiTrash2, FiTrendingUp} from 'react-icons/fi'
|
||||||
TrashIcon,
|
|
||||||
} from '@heroicons/react/solid'
|
|
||||||
import React, { useEffect, useState, useMemo } from 'react'
|
|
||||||
import { useNavigate } from 'react-router-dom'
|
|
||||||
import { FiPlus, FiTrash2, FiKey, FiTrendingUp } from 'react-icons/fi'
|
|
||||||
|
|
||||||
import useApiUrlStore from '../../../app/store/apiStore'
|
import useApiUrlStore from '../../../app/store/apiStore'
|
||||||
import {
|
import {SelectColumnFilter, Table, Toast,} from '../../../components/mollecules'
|
||||||
SelectColumnFilter,
|
import type {Account} from '../../../generated/ManagingApi'
|
||||||
Table,
|
import {AccountClient, AccountType, TradingClient} from '../../../generated/ManagingApi'
|
||||||
Toast,
|
|
||||||
} from '../../../components/mollecules'
|
|
||||||
import type { Account } from '../../../generated/ManagingApi'
|
|
||||||
import { AccountClient, AccountType } from '../../../generated/ManagingApi'
|
|
||||||
|
|
||||||
import AccountRowDetails from './accountRowDetails'
|
import AccountRowDetails from './accountRowDetails'
|
||||||
import PrivyDelegationModal from './PrivyDelegationModal'
|
import PrivyDelegationModal from './PrivyDelegationModal'
|
||||||
@@ -48,6 +39,22 @@ const AccountTable: React.FC<IAccountList> = ({ list, isFetching }) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function initPrivyWallet(publicAddress: string) {
|
||||||
|
const t = new Toast('Initializing Privy wallet')
|
||||||
|
const client = new TradingClient({}, apiUrl)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await client.trading_InitPrivyWallet(publicAddress)
|
||||||
|
if (response.success) {
|
||||||
|
t.update('success', 'Privy wallet initialized successfully')
|
||||||
|
} else {
|
||||||
|
t.update('error', `Initialization failed: ${response.error || 'Unknown error'}`)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
t.update('error', 'Error: ' + err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
@@ -114,6 +121,7 @@ const AccountTable: React.FC<IAccountList> = ({ list, isFetching }) => {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{account.type === AccountType.Privy && (
|
{account.type === AccountType.Privy && (
|
||||||
|
<>
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-primary btn-outline"
|
className="btn btn-sm btn-primary btn-outline"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -124,9 +132,15 @@ const AccountTable: React.FC<IAccountList> = ({ list, isFetching }) => {
|
|||||||
<FiKey />
|
<FiKey />
|
||||||
<span className="ml-1">Delegate</span>
|
<span className="ml-1">Delegate</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
|
||||||
|
|
||||||
{account.type === AccountType.Privy && (
|
<button
|
||||||
|
className="btn btn-sm btn-info btn-outline"
|
||||||
|
onClick={() => initPrivyWallet(account.key)}
|
||||||
|
>
|
||||||
|
<FiPlay />
|
||||||
|
<span className="ml-1">Init</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-success btn-outline"
|
className="btn btn-sm btn-success btn-outline"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -137,6 +151,7 @@ const AccountTable: React.FC<IAccountList> = ({ list, isFetching }) => {
|
|||||||
<FiTrendingUp />
|
<FiTrendingUp />
|
||||||
<span className="ml-1">GMX</span>
|
<span className="ml-1">GMX</span>
|
||||||
</button>
|
</button>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user