Add initAddress api
This commit is contained in:
@@ -3,6 +3,7 @@ using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Trading.Commands;
|
||||
using Managing.Domain.MoneyManagements;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Infrastructure.Evm.Models.Privy;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -156,4 +157,33 @@ public class TradingController : BaseController
|
||||
var result = await _openTradeCommandHandler.Handle(command);
|
||||
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.Statistics;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Infrastructure.Evm.Models.Privy;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.Abstractions.Repositories;
|
||||
@@ -25,7 +26,7 @@ public interface IEvmManager
|
||||
decimal GetVolume(SubgraphProvider subgraphProvider, Ticker ticker);
|
||||
Task<List<Ticker>> GetAvailableTicker();
|
||||
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,
|
||||
string receiverAddress);
|
||||
|
||||
@@ -3,6 +3,7 @@ using Managing.Domain.Scenarios;
|
||||
using Managing.Domain.Statistics;
|
||||
using Managing.Domain.Strategies;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Infrastructure.Evm.Models.Privy;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Application.Abstractions.Services;
|
||||
@@ -35,4 +36,5 @@ public interface ITradingService
|
||||
void UpdateScenario(Scenario scenario);
|
||||
void UpdateStrategy(Strategy strategy);
|
||||
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.Domain.Accounts;
|
||||
using Managing.Domain.Scenarios;
|
||||
@@ -7,6 +6,7 @@ using Managing.Domain.Shared.Helpers;
|
||||
using Managing.Domain.Statistics;
|
||||
using Managing.Domain.Strategies;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Infrastructure.Evm.Models.Privy;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
@@ -20,6 +20,7 @@ public class TradingService : ITradingService
|
||||
private readonly ICacheService _cacheService;
|
||||
private readonly IMessengerService _messengerService;
|
||||
private readonly IStatisticRepository _statisticRepository;
|
||||
private readonly IEvmManager _evmManager;
|
||||
private readonly ILogger<TradingService> _logger;
|
||||
|
||||
public TradingService(
|
||||
@@ -29,7 +30,8 @@ public class TradingService : ITradingService
|
||||
IAccountService accountService,
|
||||
ICacheService cacheService,
|
||||
IMessengerService messengerService,
|
||||
IStatisticRepository statisticRepository)
|
||||
IStatisticRepository statisticRepository,
|
||||
IEvmManager evmManager)
|
||||
{
|
||||
_tradingRepository = tradingRepository;
|
||||
_exchangeService = exchangeService;
|
||||
@@ -38,6 +40,7 @@ public class TradingService : ITradingService
|
||||
_cacheService = cacheService;
|
||||
_messengerService = messengerService;
|
||||
_statisticRepository = statisticRepository;
|
||||
_evmManager = evmManager;
|
||||
}
|
||||
|
||||
public void DeleteScenario(string name)
|
||||
@@ -374,4 +377,23 @@ public class TradingService : ITradingService
|
||||
public List<Trade> Trades { 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);
|
||||
|
||||
Assert.True(accountInitilized);
|
||||
Assert.NotNull(accountInitilized);
|
||||
}
|
||||
|
||||
[Ignore]
|
||||
|
||||
@@ -444,7 +444,7 @@ public class EvmManager : IEvmManager
|
||||
return cachedCandle;
|
||||
}
|
||||
|
||||
public async Task<bool> InitAddress(string publicAddress)
|
||||
public async Task<PrivyInitAddressResponse> InitAddress(string publicAddress)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -452,13 +452,17 @@ public class EvmManager : IEvmManager
|
||||
"/init-address",
|
||||
new { address = publicAddress });
|
||||
|
||||
return response.Success;
|
||||
return response;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log the error
|
||||
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": {
|
||||
isListed: false,
|
||||
},
|
||||
"0x9e79146b3A022Af44E0708c6794F03Ef798381A5": {
|
||||
isListed: false,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2159,6 +2159,45 @@ export class TradingClient extends AuthorizedApiBase {
|
||||
}
|
||||
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 {
|
||||
@@ -3072,6 +3111,14 @@ export enum RiskLevel {
|
||||
Adaptive = "Adaptive",
|
||||
}
|
||||
|
||||
export interface PrivyInitAddressResponse {
|
||||
success?: boolean;
|
||||
usdcHash?: string | null;
|
||||
orderVaultHash?: string | null;
|
||||
exchangeRouterHash?: string | null;
|
||||
error?: string | null;
|
||||
}
|
||||
|
||||
export interface LoginRequest {
|
||||
name: string;
|
||||
address: string;
|
||||
|
||||
@@ -1,21 +1,12 @@
|
||||
import {
|
||||
ChevronDownIcon,
|
||||
ChevronRightIcon,
|
||||
ClipboardCopyIcon,
|
||||
TrashIcon,
|
||||
} from '@heroicons/react/solid'
|
||||
import React, { useEffect, useState, useMemo } from 'react'
|
||||
import {ChevronDownIcon, ChevronRightIcon,} from '@heroicons/react/solid'
|
||||
import React, {useEffect, useMemo, useState} from 'react'
|
||||
import {useNavigate} from 'react-router-dom'
|
||||
import { FiPlus, FiTrash2, FiKey, FiTrendingUp } from 'react-icons/fi'
|
||||
import {FiKey, FiPlay, FiTrash2, FiTrendingUp} from 'react-icons/fi'
|
||||
|
||||
import useApiUrlStore from '../../../app/store/apiStore'
|
||||
import {
|
||||
SelectColumnFilter,
|
||||
Table,
|
||||
Toast,
|
||||
} from '../../../components/mollecules'
|
||||
import {SelectColumnFilter, Table, Toast,} from '../../../components/mollecules'
|
||||
import type {Account} from '../../../generated/ManagingApi'
|
||||
import { AccountClient, AccountType } from '../../../generated/ManagingApi'
|
||||
import {AccountClient, AccountType, TradingClient} from '../../../generated/ManagingApi'
|
||||
|
||||
import AccountRowDetails from './accountRowDetails'
|
||||
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(
|
||||
() => [
|
||||
{
|
||||
@@ -114,6 +121,7 @@ const AccountTable: React.FC<IAccountList> = ({ list, isFetching }) => {
|
||||
</button>
|
||||
|
||||
{account.type === AccountType.Privy && (
|
||||
<>
|
||||
<button
|
||||
className="btn btn-sm btn-primary btn-outline"
|
||||
onClick={() => {
|
||||
@@ -124,9 +132,15 @@ const AccountTable: React.FC<IAccountList> = ({ list, isFetching }) => {
|
||||
<FiKey />
|
||||
<span className="ml-1">Delegate</span>
|
||||
</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
|
||||
className="btn btn-sm btn-success btn-outline"
|
||||
onClick={() => {
|
||||
@@ -137,6 +151,7 @@ const AccountTable: React.FC<IAccountList> = ({ list, isFetching }) => {
|
||||
<FiTrendingUp />
|
||||
<span className="ml-1">GMX</span>
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user