Implement revoke all approvals functionality in TradingController and related services
- Added a new endpoint in TradingController to revoke all token approvals for a specified Privy wallet address, with permission checks for user access. - Implemented the revokeAllApprovals method in TradingService to handle the revocation logic, including error handling and logging. - Updated IWeb3ProxyService and Web3ProxyService to support revocation requests to the Privy service. - Introduced a new PrivyRevokeAllApprovalsResponse type for structured responses from the revocation process. - Enhanced the UI in account tables to allow users to revoke approvals directly from the interface, providing feedback on success or failure. - Updated appsettings.json to change the default model for Gemini integration.
This commit is contained in:
@@ -200,6 +200,49 @@ public class TradingController : BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Revokes all token approvals for a Privy wallet address.
|
||||||
|
/// Only admins can revoke approvals for any address, regular users can only revoke approvals for their own addresses.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="publicAddress">The public address of the Privy wallet to revoke approvals for.</param>
|
||||||
|
/// <returns>The revocation response containing success status and transaction hashes.</returns>
|
||||||
|
[HttpPost("RevokeAllApprovals")]
|
||||||
|
public async Task<ActionResult<Managing.Infrastructure.Evm.Models.Privy.PrivyRevokeAllApprovalsResponse>> RevokeAllApprovals([FromBody] string publicAddress)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(publicAddress))
|
||||||
|
{
|
||||||
|
return BadRequest("Public address cannot be null or empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var user = await GetUser();
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return Unauthorized("User not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has permission to revoke approvals for this address
|
||||||
|
if (!await CanUserInitializeAddress(user.Name, publicAddress))
|
||||||
|
{
|
||||||
|
return Forbid(
|
||||||
|
"You don't have permission to revoke approvals for this wallet address. You can only revoke approvals for your own wallet addresses.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await _tradingService.RevokeAllApprovals(publicAddress);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error revoking all approvals for Privy wallet address: {Address}", publicAddress);
|
||||||
|
return StatusCode(500, new Managing.Infrastructure.Evm.Models.Privy.PrivyRevokeAllApprovalsResponse
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Error = "An error occurred while revoking all approvals for the Privy wallet address."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the user can initialize the given public address.
|
/// Checks if the user can initialize the given public address.
|
||||||
/// Admins can initialize any address, regular users can only initialize their own addresses.
|
/// Admins can initialize any address, regular users can only initialize their own addresses.
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
"Llm": {
|
"Llm": {
|
||||||
"Gemini": {
|
"Gemini": {
|
||||||
"DefaultModel": "gemini-2.0-flash"
|
"DefaultModel": "gemini/gemini-3-flash-preview"
|
||||||
},
|
},
|
||||||
"OpenAI": {
|
"OpenAI": {
|
||||||
"DefaultModel": "gpt-4o"
|
"DefaultModel": "gpt-4o"
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ public interface ITradingService
|
|||||||
DateTime startDate,
|
DateTime startDate,
|
||||||
DateTime endDate,
|
DateTime endDate,
|
||||||
List<IndicatorRequest> indicators);
|
List<IndicatorRequest> indicators);
|
||||||
|
|
||||||
|
Task<Managing.Infrastructure.Evm.Models.Privy.PrivyRevokeAllApprovalsResponse> RevokeAllApprovals(string publicAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -41,5 +41,7 @@ namespace Managing.Application.Abstractions.Services
|
|||||||
string? ticker = null,
|
string? ticker = null,
|
||||||
DateTime? fromDate = null,
|
DateTime? fromDate = null,
|
||||||
DateTime? toDate = null);
|
DateTime? toDate = null);
|
||||||
|
|
||||||
|
Task<Managing.Infrastructure.Evm.Models.Privy.PrivyRevokeAllApprovalsResponse> RevokeAllApprovalsAsync(string address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -542,12 +542,39 @@ public class TradingService : ITradingService
|
|||||||
// Generate signals for the date range using rolling window approach
|
// Generate signals for the date range using rolling window approach
|
||||||
var signals = GenerateSignalsForDateRange(candlesList, scenario, indicatorsValues);
|
var signals = GenerateSignalsForDateRange(candlesList, scenario, indicatorsValues);
|
||||||
|
|
||||||
return new RefineIndicatorsResult
|
return new RefineIndicatorsResult
|
||||||
|
{
|
||||||
|
IndicatorsValues = indicatorsValues,
|
||||||
|
Signals = signals
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Managing.Infrastructure.Evm.Models.Privy.PrivyRevokeAllApprovalsResponse> RevokeAllApprovals(string publicAddress)
|
||||||
{
|
{
|
||||||
IndicatorsValues = indicatorsValues,
|
try
|
||||||
Signals = signals
|
{
|
||||||
};
|
if (string.IsNullOrEmpty(publicAddress))
|
||||||
}
|
{
|
||||||
|
_logger.LogWarning("Attempted to revoke approvals with null or empty public address");
|
||||||
|
return new Managing.Infrastructure.Evm.Models.Privy.PrivyRevokeAllApprovalsResponse
|
||||||
|
{ Success = false, Error = "Public address cannot be null or empty" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the Web3ProxyService to revoke all approvals
|
||||||
|
var result = await _web3ProxyService.RevokeAllApprovalsAsync(publicAddress);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error revoking all approvals for address {PublicAddress}", publicAddress);
|
||||||
|
return new Managing.Infrastructure.Evm.Models.Privy.PrivyRevokeAllApprovalsResponse
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
Error = ex.Message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maps IndicatorRequest list to a domain Scenario object.
|
/// Maps IndicatorRequest list to a domain Scenario object.
|
||||||
|
|||||||
18
src/Managing.Domain/Evm/PrivyRevokeAllApprovalsResponse.cs
Normal file
18
src/Managing.Domain/Evm/PrivyRevokeAllApprovalsResponse.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
namespace Managing.Infrastructure.Evm.Models.Privy;
|
||||||
|
|
||||||
|
public class PrivyRevokeAllApprovalsResponse
|
||||||
|
{
|
||||||
|
public bool Success { get; set; }
|
||||||
|
public string? OrderVaultUsdcHash { get; set; }
|
||||||
|
public string? OrderVaultWethHash { get; set; }
|
||||||
|
public string? ExchangeRouterUsdcHash { get; set; }
|
||||||
|
public string? ExchangeRouterWethHash { get; set; }
|
||||||
|
public string? SyntheticsRouterUsdcHash { get; set; }
|
||||||
|
public string? SyntheticsRouterWethHash { get; set; }
|
||||||
|
public string? DataStoreUsdcHash { get; set; }
|
||||||
|
public string? DataStoreWethHash { get; set; }
|
||||||
|
public string? DepositVaultUsdcHash { get; set; }
|
||||||
|
public string? DepositVaultWethHash { get; set; }
|
||||||
|
public string? Error { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
@@ -819,5 +819,19 @@ namespace Managing.Infrastructure.Evm.Services
|
|||||||
|
|
||||||
return positions;
|
return positions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Managing.Infrastructure.Evm.Models.Privy.PrivyRevokeAllApprovalsResponse> RevokeAllApprovalsAsync(string address)
|
||||||
|
{
|
||||||
|
var payload = new { address };
|
||||||
|
|
||||||
|
var response = await CallPrivyServiceAsync<Managing.Infrastructure.Evm.Models.Privy.PrivyRevokeAllApprovalsResponse>("/revoke-all-approvals", payload);
|
||||||
|
|
||||||
|
if (response == null)
|
||||||
|
{
|
||||||
|
throw new Web3ProxyException("Revoke all approvals response is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1444,40 +1444,6 @@ export interface JobStatusTypeSummary {
|
|||||||
count?: number;
|
count?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LlmProgressUpdate {
|
|
||||||
type?: string;
|
|
||||||
message?: string;
|
|
||||||
iteration?: number | null;
|
|
||||||
maxIterations?: number | null;
|
|
||||||
toolName?: string | null;
|
|
||||||
toolArguments?: { [key: string]: any; } | null;
|
|
||||||
content?: string | null;
|
|
||||||
response?: LlmChatResponse | null;
|
|
||||||
error?: string | null;
|
|
||||||
timestamp?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmChatResponse {
|
|
||||||
content?: string;
|
|
||||||
provider?: string;
|
|
||||||
model?: string;
|
|
||||||
toolCalls?: LlmToolCall[] | null;
|
|
||||||
usage?: LlmUsage | null;
|
|
||||||
requiresToolExecution?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmToolCall {
|
|
||||||
id?: string;
|
|
||||||
name?: string;
|
|
||||||
arguments?: { [key: string]: any; };
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmUsage {
|
|
||||||
promptTokens?: number;
|
|
||||||
completionTokens?: number;
|
|
||||||
totalTokens?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmChatRequest {
|
export interface LlmChatRequest {
|
||||||
messages?: LlmMessage[];
|
messages?: LlmMessage[];
|
||||||
provider?: string | null;
|
provider?: string | null;
|
||||||
@@ -1488,6 +1454,10 @@ export interface LlmChatRequest {
|
|||||||
tools?: McpToolDefinition[] | null;
|
tools?: McpToolDefinition[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LlmChatStreamRequest extends LlmChatRequest {
|
||||||
|
connectionId?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface LlmMessage {
|
export interface LlmMessage {
|
||||||
role?: string;
|
role?: string;
|
||||||
content?: string;
|
content?: string;
|
||||||
@@ -1495,6 +1465,12 @@ export interface LlmMessage {
|
|||||||
toolCallId?: string | null;
|
toolCallId?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LlmToolCall {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
arguments?: { [key: string]: any; };
|
||||||
|
}
|
||||||
|
|
||||||
export interface McpToolDefinition {
|
export interface McpToolDefinition {
|
||||||
name?: string;
|
name?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
@@ -1508,6 +1484,21 @@ export interface McpParameterDefinition {
|
|||||||
defaultValue?: any | null;
|
defaultValue?: any | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LlmChatResponse {
|
||||||
|
content?: string;
|
||||||
|
provider?: string;
|
||||||
|
model?: string;
|
||||||
|
toolCalls?: LlmToolCall[] | null;
|
||||||
|
usage?: LlmUsage | null;
|
||||||
|
requiresToolExecution?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LlmUsage {
|
||||||
|
promptTokens?: number;
|
||||||
|
completionTokens?: number;
|
||||||
|
totalTokens?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ScenarioViewModel {
|
export interface ScenarioViewModel {
|
||||||
name: string;
|
name: string;
|
||||||
indicators: IndicatorViewModel[];
|
indicators: IndicatorViewModel[];
|
||||||
@@ -1548,6 +1539,21 @@ export interface PrivyInitAddressResponse {
|
|||||||
isAlreadyInitialized?: boolean;
|
isAlreadyInitialized?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PrivyRevokeAllApprovalsResponse {
|
||||||
|
success?: boolean;
|
||||||
|
orderVaultUsdcHash?: string | null;
|
||||||
|
orderVaultWethHash?: string | null;
|
||||||
|
exchangeRouterUsdcHash?: string | null;
|
||||||
|
exchangeRouterWethHash?: string | null;
|
||||||
|
syntheticsRouterUsdcHash?: string | null;
|
||||||
|
syntheticsRouterWethHash?: string | null;
|
||||||
|
dataStoreUsdcHash?: string | null;
|
||||||
|
dataStoreWethHash?: string | null;
|
||||||
|
depositVaultUsdcHash?: string | null;
|
||||||
|
depositVaultWethHash?: string | null;
|
||||||
|
error?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IndicatorRequestDto {
|
export interface IndicatorRequestDto {
|
||||||
indicatorName: string;
|
indicatorName: string;
|
||||||
strategyDescription: string;
|
strategyDescription: string;
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ declare module 'fastify' {
|
|||||||
signPrivyMessage: typeof signPrivyMessage;
|
signPrivyMessage: typeof signPrivyMessage;
|
||||||
approveToken: typeof approveToken;
|
approveToken: typeof approveToken;
|
||||||
initAddress: typeof initAddress;
|
initAddress: typeof initAddress;
|
||||||
|
revokeAllApprovals: typeof revokeAllApprovals;
|
||||||
sendToken: typeof sendToken;
|
sendToken: typeof sendToken;
|
||||||
getWalletBalance: typeof getWalletBalance;
|
getWalletBalance: typeof getWalletBalance;
|
||||||
getTokenBalanceOnChain: typeof getTokenBalanceOnChain;
|
getTokenBalanceOnChain: typeof getTokenBalanceOnChain;
|
||||||
@@ -975,6 +976,277 @@ export async function initAddress(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revokes all token approvals for an address by setting approvals to 0 for all GMX contracts
|
||||||
|
* @param address The wallet address to revoke approvals for
|
||||||
|
* @returns Object containing transaction hashes for all revoked approvals
|
||||||
|
*/
|
||||||
|
export const revokeAllApprovalsImpl = async (
|
||||||
|
address: string,
|
||||||
|
fastify?: FastifyInstance
|
||||||
|
): Promise<{
|
||||||
|
orderVaultUsdcHash: string,
|
||||||
|
orderVaultWethHash: string,
|
||||||
|
exchangeRouterUsdcHash: string,
|
||||||
|
exchangeRouterWethHash: string,
|
||||||
|
syntheticsRouterUsdcHash: string,
|
||||||
|
syntheticsRouterWethHash: string,
|
||||||
|
dataStoreUsdcHash: string,
|
||||||
|
dataStoreWethHash: string,
|
||||||
|
depositVaultUsdcHash: string,
|
||||||
|
depositVaultWethHash: string
|
||||||
|
}> => {
|
||||||
|
try {
|
||||||
|
console.log('🚫 Starting revocation of all approvals for address:', address);
|
||||||
|
|
||||||
|
const sdk = await getClientForAddress(address);
|
||||||
|
const {tokensData} = await sdk.tokens.getTokensData();
|
||||||
|
const usdcTokenData = getTokenDataFromTicker(Ticker.USDC, tokensData);
|
||||||
|
const wrapperEtherData = getTokenDataFromTicker("WETH", tokensData);
|
||||||
|
|
||||||
|
// Revoke by setting approval to 0
|
||||||
|
const revokeAmount = BigInt(0);
|
||||||
|
console.log('📊 Revocation amount set to:', revokeAmount.toString());
|
||||||
|
|
||||||
|
// Get USDC and WETH token addresses
|
||||||
|
const usdcToken = GetToken('USDC');
|
||||||
|
console.log('💱 USDC Token Address:', usdcToken.address);
|
||||||
|
console.log('💱 WETH Token Address:', wrapperEtherData.address);
|
||||||
|
|
||||||
|
const results: any = {};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Revoke OrderVault Approvals
|
||||||
|
// ============================================================================
|
||||||
|
console.log('\n🔐 Step 1: Revoking OrderVault approvals...');
|
||||||
|
|
||||||
|
// USDC approval for OrderVault
|
||||||
|
console.log(' Revoking USDC -> OrderVault approval...');
|
||||||
|
results.orderVaultUsdcHash = await approveContractImpl(
|
||||||
|
address,
|
||||||
|
usdcToken.address,
|
||||||
|
CONTRACTS[ARBITRUM].OrderVault,
|
||||||
|
ARBITRUM,
|
||||||
|
revokeAmount,
|
||||||
|
true,
|
||||||
|
fastify
|
||||||
|
);
|
||||||
|
console.log(' ✅ USDC OrderVault revocation hash:', results.orderVaultUsdcHash);
|
||||||
|
|
||||||
|
// WETH approval for OrderVault
|
||||||
|
console.log(' Revoking WETH -> OrderVault approval...');
|
||||||
|
results.orderVaultWethHash = await approveContractImpl(
|
||||||
|
address,
|
||||||
|
wrapperEtherData.address,
|
||||||
|
CONTRACTS[ARBITRUM].OrderVault,
|
||||||
|
ARBITRUM,
|
||||||
|
revokeAmount,
|
||||||
|
true,
|
||||||
|
fastify
|
||||||
|
);
|
||||||
|
console.log(' ✅ WETH OrderVault revocation hash:', results.orderVaultWethHash);
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Revoke ExchangeRouter Approvals
|
||||||
|
// ============================================================================
|
||||||
|
console.log('\n🔐 Step 2: Revoking ExchangeRouter approvals...');
|
||||||
|
|
||||||
|
// USDC approval for ExchangeRouter
|
||||||
|
console.log(' Revoking USDC -> ExchangeRouter approval...');
|
||||||
|
results.exchangeRouterUsdcHash = await approveContractImpl(
|
||||||
|
address,
|
||||||
|
usdcToken.address,
|
||||||
|
CONTRACTS[ARBITRUM].ExchangeRouter,
|
||||||
|
ARBITRUM,
|
||||||
|
revokeAmount,
|
||||||
|
true,
|
||||||
|
fastify
|
||||||
|
);
|
||||||
|
console.log(' ✅ USDC ExchangeRouter revocation hash:', results.exchangeRouterUsdcHash);
|
||||||
|
|
||||||
|
// WETH approval for ExchangeRouter
|
||||||
|
console.log(' Revoking WETH -> ExchangeRouter approval...');
|
||||||
|
results.exchangeRouterWethHash = await approveContractImpl(
|
||||||
|
address,
|
||||||
|
wrapperEtherData.address,
|
||||||
|
CONTRACTS[ARBITRUM].ExchangeRouter,
|
||||||
|
ARBITRUM,
|
||||||
|
revokeAmount,
|
||||||
|
true,
|
||||||
|
fastify
|
||||||
|
);
|
||||||
|
console.log(' ✅ WETH ExchangeRouter revocation hash:', results.exchangeRouterWethHash);
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Revoke SyntheticsRouter Approvals
|
||||||
|
// ============================================================================
|
||||||
|
console.log('\n🔐 Step 3: Revoking SyntheticsRouter approvals...');
|
||||||
|
|
||||||
|
// USDC approval for SyntheticsRouter
|
||||||
|
console.log(' Revoking USDC -> SyntheticsRouter approval...');
|
||||||
|
results.syntheticsRouterUsdcHash = await approveContractImpl(
|
||||||
|
address,
|
||||||
|
usdcToken.address,
|
||||||
|
CONTRACTS[ARBITRUM].SyntheticsRouter,
|
||||||
|
ARBITRUM,
|
||||||
|
revokeAmount,
|
||||||
|
true,
|
||||||
|
fastify
|
||||||
|
);
|
||||||
|
console.log(' ✅ USDC SyntheticsRouter revocation hash:', results.syntheticsRouterUsdcHash);
|
||||||
|
|
||||||
|
// WETH approval for SyntheticsRouter
|
||||||
|
console.log(' Revoking WETH -> SyntheticsRouter approval...');
|
||||||
|
results.syntheticsRouterWethHash = await approveContractImpl(
|
||||||
|
address,
|
||||||
|
wrapperEtherData.address,
|
||||||
|
CONTRACTS[ARBITRUM].SyntheticsRouter,
|
||||||
|
ARBITRUM,
|
||||||
|
revokeAmount,
|
||||||
|
true,
|
||||||
|
fastify
|
||||||
|
);
|
||||||
|
console.log(' ✅ WETH SyntheticsRouter revocation hash:', results.syntheticsRouterWethHash);
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Revoke DataStore Approvals
|
||||||
|
// ============================================================================
|
||||||
|
console.log('\n🔐 Step 4: Revoking DataStore approvals...');
|
||||||
|
|
||||||
|
// USDC approval for DataStore
|
||||||
|
console.log(' Revoking USDC -> DataStore approval...');
|
||||||
|
results.dataStoreUsdcHash = await approveContractImpl(
|
||||||
|
address,
|
||||||
|
usdcToken.address,
|
||||||
|
CONTRACTS[ARBITRUM].DataStore,
|
||||||
|
ARBITRUM,
|
||||||
|
revokeAmount,
|
||||||
|
true,
|
||||||
|
fastify
|
||||||
|
);
|
||||||
|
console.log(' ✅ USDC DataStore revocation hash:', results.dataStoreUsdcHash);
|
||||||
|
|
||||||
|
// WETH approval for DataStore
|
||||||
|
console.log(' Revoking WETH -> DataStore approval...');
|
||||||
|
results.dataStoreWethHash = await approveContractImpl(
|
||||||
|
address,
|
||||||
|
wrapperEtherData.address,
|
||||||
|
CONTRACTS[ARBITRUM].DataStore,
|
||||||
|
ARBITRUM,
|
||||||
|
revokeAmount,
|
||||||
|
true,
|
||||||
|
fastify
|
||||||
|
);
|
||||||
|
console.log(' ✅ WETH DataStore revocation hash:', results.dataStoreWethHash);
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Revoke DepositVault Approvals
|
||||||
|
// ============================================================================
|
||||||
|
console.log('\n🔐 Step 5: Revoking DepositVault approvals...');
|
||||||
|
|
||||||
|
// USDC approval for DepositVault
|
||||||
|
console.log(' Revoking USDC -> DepositVault approval...');
|
||||||
|
results.depositVaultUsdcHash = await approveContractImpl(
|
||||||
|
address,
|
||||||
|
usdcToken.address,
|
||||||
|
CONTRACTS[ARBITRUM].DepositVault,
|
||||||
|
ARBITRUM,
|
||||||
|
revokeAmount,
|
||||||
|
true,
|
||||||
|
fastify
|
||||||
|
);
|
||||||
|
console.log(' ✅ USDC DepositVault revocation hash:', results.depositVaultUsdcHash);
|
||||||
|
|
||||||
|
// WETH approval for DepositVault
|
||||||
|
console.log(' Revoking WETH -> DepositVault approval...');
|
||||||
|
results.depositVaultWethHash = await approveContractImpl(
|
||||||
|
address,
|
||||||
|
wrapperEtherData.address,
|
||||||
|
CONTRACTS[ARBITRUM].DepositVault,
|
||||||
|
ARBITRUM,
|
||||||
|
revokeAmount,
|
||||||
|
true,
|
||||||
|
fastify
|
||||||
|
);
|
||||||
|
console.log(' ✅ WETH DepositVault revocation hash:', results.depositVaultWethHash);
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// SUMMARY: Final revocation status
|
||||||
|
// ============================================================================
|
||||||
|
console.log('\n📋 Final Revocation Summary:');
|
||||||
|
console.log(' OrderVault USDC:', results.orderVaultUsdcHash);
|
||||||
|
console.log(' OrderVault WETH:', results.orderVaultWethHash);
|
||||||
|
console.log(' ExchangeRouter USDC:', results.exchangeRouterUsdcHash);
|
||||||
|
console.log(' ExchangeRouter WETH:', results.exchangeRouterWethHash);
|
||||||
|
console.log(' SyntheticsRouter USDC:', results.syntheticsRouterUsdcHash);
|
||||||
|
console.log(' SyntheticsRouter WETH:', results.syntheticsRouterWethHash);
|
||||||
|
console.log(' DataStore USDC:', results.dataStoreUsdcHash);
|
||||||
|
console.log(' DataStore WETH:', results.dataStoreWethHash);
|
||||||
|
console.log(' DepositVault USDC:', results.depositVaultUsdcHash);
|
||||||
|
console.log(' DepositVault WETH:', results.depositVaultWethHash);
|
||||||
|
|
||||||
|
// Clear approval cache for this address since all approvals have been revoked
|
||||||
|
try {
|
||||||
|
const {clearApprovalCacheForAccount} = await import('../../utils/approvalCache.js');
|
||||||
|
await clearApprovalCacheForAccount(ARBITRUM, address);
|
||||||
|
console.log(' ✅ Approval cache cleared for address');
|
||||||
|
} catch (cacheError) {
|
||||||
|
console.warn(' ⚠️ Failed to clear approval cache:', cacheError);
|
||||||
|
// Don't fail the entire operation if cache clearing fails
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('\n✅ All approvals revoked successfully!');
|
||||||
|
|
||||||
|
return results;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Error revoking approvals:', error);
|
||||||
|
throw new Error(`Failed to revoke approvals: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revokes all token approvals for a wallet address
|
||||||
|
* @param this The FastifyRequest instance
|
||||||
|
* @param reply The FastifyReply instance
|
||||||
|
* @param address The wallet address to revoke approvals for
|
||||||
|
* @returns The response object with success status and transaction hashes
|
||||||
|
*/
|
||||||
|
export async function revokeAllApprovals(
|
||||||
|
this: FastifyRequest,
|
||||||
|
reply: FastifyReply,
|
||||||
|
address: string
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
if (!address) {
|
||||||
|
throw new Error('Wallet address is required for revocation');
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = await revokeAllApprovalsImpl(address, this.server);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
orderVaultUsdcHash: results.orderVaultUsdcHash,
|
||||||
|
orderVaultWethHash: results.orderVaultWethHash,
|
||||||
|
exchangeRouterUsdcHash: results.exchangeRouterUsdcHash,
|
||||||
|
exchangeRouterWethHash: results.exchangeRouterWethHash,
|
||||||
|
syntheticsRouterUsdcHash: results.syntheticsRouterUsdcHash,
|
||||||
|
syntheticsRouterWethHash: results.syntheticsRouterWethHash,
|
||||||
|
dataStoreUsdcHash: results.dataStoreUsdcHash,
|
||||||
|
dataStoreWethHash: results.dataStoreWethHash,
|
||||||
|
depositVaultUsdcHash: results.depositVaultUsdcHash,
|
||||||
|
depositVaultWethHash: results.depositVaultWethHash
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
this.log.error(error);
|
||||||
|
|
||||||
|
reply.status(500);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: error instanceof Error ? error.message : 'An unknown error occurred'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends tokens from one address to another using Privy wallet (implementation)
|
* Sends tokens from one address to another using Privy wallet (implementation)
|
||||||
* @param senderAddress The sender's wallet address
|
* @param senderAddress The sender's wallet address
|
||||||
@@ -1756,6 +2028,10 @@ export default fp(async (fastify) => {
|
|||||||
return initAddress.call(this, reply, address);
|
return initAddress.call(this, reply, address);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
fastify.decorateRequest('revokeAllApprovals', async function(this: FastifyRequest, reply: FastifyReply, address: string) {
|
||||||
|
return revokeAllApprovals.call(this, reply, address);
|
||||||
|
});
|
||||||
|
|
||||||
fastify.decorateRequest('sendToken', async function(this: FastifyRequest, reply: FastifyReply, senderAddress: string, recipientAddress: string, ticker: string, amount: string, chainId?: number) {
|
fastify.decorateRequest('sendToken', async function(this: FastifyRequest, reply: FastifyReply, senderAddress: string, recipientAddress: string, ticker: string, amount: string, chainId?: number) {
|
||||||
return sendToken.call(this, reply, senderAddress, recipientAddress, ticker, amount, chainId);
|
return sendToken.call(this, reply, senderAddress, recipientAddress, ticker, amount, chainId);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -77,6 +77,50 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fastify.post(
|
||||||
|
'/revoke-all-approvals',
|
||||||
|
{
|
||||||
|
schema: {
|
||||||
|
body: Type.Object({
|
||||||
|
address: Type.String()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: Type.Object({
|
||||||
|
success: Type.Boolean(),
|
||||||
|
orderVaultUsdcHash: Type.Optional(Type.String()),
|
||||||
|
orderVaultWethHash: Type.Optional(Type.String()),
|
||||||
|
exchangeRouterUsdcHash: Type.Optional(Type.String()),
|
||||||
|
exchangeRouterWethHash: Type.Optional(Type.String()),
|
||||||
|
syntheticsRouterUsdcHash: Type.Optional(Type.String()),
|
||||||
|
syntheticsRouterWethHash: Type.Optional(Type.String()),
|
||||||
|
dataStoreUsdcHash: Type.Optional(Type.String()),
|
||||||
|
dataStoreWethHash: Type.Optional(Type.String()),
|
||||||
|
depositVaultUsdcHash: Type.Optional(Type.String()),
|
||||||
|
depositVaultWethHash: Type.Optional(Type.String()),
|
||||||
|
error: Type.Optional(Type.String())
|
||||||
|
}),
|
||||||
|
400: Type.Object({
|
||||||
|
success: Type.Boolean(),
|
||||||
|
error: Type.String()
|
||||||
|
}),
|
||||||
|
500: Type.Object({
|
||||||
|
success: Type.Boolean(),
|
||||||
|
error: Type.String()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
tags: ['Privy']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async function (request, reply) {
|
||||||
|
try {
|
||||||
|
const { address } = request.body;
|
||||||
|
return await request.revokeAllApprovals(reply, address);
|
||||||
|
} catch (error) {
|
||||||
|
return handleError(request, reply, error, 'privy/revoke-all-approvals');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
fastify.post(
|
fastify.post(
|
||||||
'/send-token',
|
'/send-token',
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2910,7 +2910,7 @@ export class LlmClient extends AuthorizedApiBase {
|
|||||||
this.baseUrl = baseUrl ?? "http://localhost:5000";
|
this.baseUrl = baseUrl ?? "http://localhost:5000";
|
||||||
}
|
}
|
||||||
|
|
||||||
llm_ChatStream(request: LlmChatRequest): Promise<LlmProgressUpdate[]> {
|
llm_ChatStream(request: LlmChatStreamRequest): Promise<FileResponse> {
|
||||||
let url_ = this.baseUrl + "/Llm/ChatStream";
|
let url_ = this.baseUrl + "/Llm/ChatStream";
|
||||||
url_ = url_.replace(/[?&]$/, "");
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
@@ -2921,7 +2921,7 @@ export class LlmClient extends AuthorizedApiBase {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"Accept": "application/json"
|
"Accept": "application/octet-stream"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2932,21 +2932,26 @@ export class LlmClient extends AuthorizedApiBase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected processLlm_ChatStream(response: Response): Promise<LlmProgressUpdate[]> {
|
protected processLlm_ChatStream(response: Response): Promise<FileResponse> {
|
||||||
const status = response.status;
|
const status = response.status;
|
||||||
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
if (status === 200) {
|
if (status === 200 || status === 206) {
|
||||||
return response.text().then((_responseText) => {
|
const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined;
|
||||||
let result200: any = null;
|
let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined;
|
||||||
result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as LlmProgressUpdate[];
|
let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined;
|
||||||
return result200;
|
if (fileName) {
|
||||||
});
|
fileName = decodeURIComponent(fileName);
|
||||||
|
} else {
|
||||||
|
fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined;
|
||||||
|
fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined;
|
||||||
|
}
|
||||||
|
return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; });
|
||||||
} else if (status !== 200 && status !== 204) {
|
} else if (status !== 200 && status !== 204) {
|
||||||
return response.text().then((_responseText) => {
|
return response.text().then((_responseText) => {
|
||||||
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return Promise.resolve<LlmProgressUpdate[]>(null as any);
|
return Promise.resolve<FileResponse>(null as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
llm_Chat(request: LlmChatRequest): Promise<LlmChatResponse> {
|
llm_Chat(request: LlmChatRequest): Promise<LlmChatResponse> {
|
||||||
@@ -4262,6 +4267,45 @@ export class TradingClient extends AuthorizedApiBase {
|
|||||||
return Promise.resolve<PrivyInitAddressResponse>(null as any);
|
return Promise.resolve<PrivyInitAddressResponse>(null as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trading_RevokeAllApprovals(publicAddress: string): Promise<PrivyRevokeAllApprovalsResponse> {
|
||||||
|
let url_ = this.baseUrl + "/Trading/RevokeAllApprovals";
|
||||||
|
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_RevokeAllApprovals(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processTrading_RevokeAllApprovals(response: Response): Promise<PrivyRevokeAllApprovalsResponse> {
|
||||||
|
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 PrivyRevokeAllApprovalsResponse;
|
||||||
|
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<PrivyRevokeAllApprovalsResponse>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
trading_RequestIndicator(request: IndicatorRequestDto): Promise<FileResponse> {
|
trading_RequestIndicator(request: IndicatorRequestDto): Promise<FileResponse> {
|
||||||
let url_ = this.baseUrl + "/Trading/RequestIndicator";
|
let url_ = this.baseUrl + "/Trading/RequestIndicator";
|
||||||
url_ = url_.replace(/[?&]$/, "");
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
@@ -6272,40 +6316,6 @@ export interface JobStatusTypeSummary {
|
|||||||
count?: number;
|
count?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LlmProgressUpdate {
|
|
||||||
type?: string;
|
|
||||||
message?: string;
|
|
||||||
iteration?: number | null;
|
|
||||||
maxIterations?: number | null;
|
|
||||||
toolName?: string | null;
|
|
||||||
toolArguments?: { [key: string]: any; } | null;
|
|
||||||
content?: string | null;
|
|
||||||
response?: LlmChatResponse | null;
|
|
||||||
error?: string | null;
|
|
||||||
timestamp?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmChatResponse {
|
|
||||||
content?: string;
|
|
||||||
provider?: string;
|
|
||||||
model?: string;
|
|
||||||
toolCalls?: LlmToolCall[] | null;
|
|
||||||
usage?: LlmUsage | null;
|
|
||||||
requiresToolExecution?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmToolCall {
|
|
||||||
id?: string;
|
|
||||||
name?: string;
|
|
||||||
arguments?: { [key: string]: any; };
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmUsage {
|
|
||||||
promptTokens?: number;
|
|
||||||
completionTokens?: number;
|
|
||||||
totalTokens?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmChatRequest {
|
export interface LlmChatRequest {
|
||||||
messages?: LlmMessage[];
|
messages?: LlmMessage[];
|
||||||
provider?: string | null;
|
provider?: string | null;
|
||||||
@@ -6316,6 +6326,10 @@ export interface LlmChatRequest {
|
|||||||
tools?: McpToolDefinition[] | null;
|
tools?: McpToolDefinition[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LlmChatStreamRequest extends LlmChatRequest {
|
||||||
|
connectionId?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface LlmMessage {
|
export interface LlmMessage {
|
||||||
role?: string;
|
role?: string;
|
||||||
content?: string;
|
content?: string;
|
||||||
@@ -6323,6 +6337,12 @@ export interface LlmMessage {
|
|||||||
toolCallId?: string | null;
|
toolCallId?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LlmToolCall {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
arguments?: { [key: string]: any; };
|
||||||
|
}
|
||||||
|
|
||||||
export interface McpToolDefinition {
|
export interface McpToolDefinition {
|
||||||
name?: string;
|
name?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
@@ -6336,6 +6356,21 @@ export interface McpParameterDefinition {
|
|||||||
defaultValue?: any | null;
|
defaultValue?: any | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LlmChatResponse {
|
||||||
|
content?: string;
|
||||||
|
provider?: string;
|
||||||
|
model?: string;
|
||||||
|
toolCalls?: LlmToolCall[] | null;
|
||||||
|
usage?: LlmUsage | null;
|
||||||
|
requiresToolExecution?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LlmUsage {
|
||||||
|
promptTokens?: number;
|
||||||
|
completionTokens?: number;
|
||||||
|
totalTokens?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ScenarioViewModel {
|
export interface ScenarioViewModel {
|
||||||
name: string;
|
name: string;
|
||||||
indicators: IndicatorViewModel[];
|
indicators: IndicatorViewModel[];
|
||||||
@@ -6376,6 +6411,21 @@ export interface PrivyInitAddressResponse {
|
|||||||
isAlreadyInitialized?: boolean;
|
isAlreadyInitialized?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PrivyRevokeAllApprovalsResponse {
|
||||||
|
success?: boolean;
|
||||||
|
orderVaultUsdcHash?: string | null;
|
||||||
|
orderVaultWethHash?: string | null;
|
||||||
|
exchangeRouterUsdcHash?: string | null;
|
||||||
|
exchangeRouterWethHash?: string | null;
|
||||||
|
syntheticsRouterUsdcHash?: string | null;
|
||||||
|
syntheticsRouterWethHash?: string | null;
|
||||||
|
dataStoreUsdcHash?: string | null;
|
||||||
|
dataStoreWethHash?: string | null;
|
||||||
|
depositVaultUsdcHash?: string | null;
|
||||||
|
depositVaultWethHash?: string | null;
|
||||||
|
error?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IndicatorRequestDto {
|
export interface IndicatorRequestDto {
|
||||||
indicatorName: string;
|
indicatorName: string;
|
||||||
strategyDescription: string;
|
strategyDescription: string;
|
||||||
|
|||||||
@@ -1444,40 +1444,6 @@ export interface JobStatusTypeSummary {
|
|||||||
count?: number;
|
count?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LlmProgressUpdate {
|
|
||||||
type?: string;
|
|
||||||
message?: string;
|
|
||||||
iteration?: number | null;
|
|
||||||
maxIterations?: number | null;
|
|
||||||
toolName?: string | null;
|
|
||||||
toolArguments?: { [key: string]: any; } | null;
|
|
||||||
content?: string | null;
|
|
||||||
response?: LlmChatResponse | null;
|
|
||||||
error?: string | null;
|
|
||||||
timestamp?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmChatResponse {
|
|
||||||
content?: string;
|
|
||||||
provider?: string;
|
|
||||||
model?: string;
|
|
||||||
toolCalls?: LlmToolCall[] | null;
|
|
||||||
usage?: LlmUsage | null;
|
|
||||||
requiresToolExecution?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmToolCall {
|
|
||||||
id?: string;
|
|
||||||
name?: string;
|
|
||||||
arguments?: { [key: string]: any; };
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmUsage {
|
|
||||||
promptTokens?: number;
|
|
||||||
completionTokens?: number;
|
|
||||||
totalTokens?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LlmChatRequest {
|
export interface LlmChatRequest {
|
||||||
messages?: LlmMessage[];
|
messages?: LlmMessage[];
|
||||||
provider?: string | null;
|
provider?: string | null;
|
||||||
@@ -1488,6 +1454,10 @@ export interface LlmChatRequest {
|
|||||||
tools?: McpToolDefinition[] | null;
|
tools?: McpToolDefinition[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LlmChatStreamRequest extends LlmChatRequest {
|
||||||
|
connectionId?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface LlmMessage {
|
export interface LlmMessage {
|
||||||
role?: string;
|
role?: string;
|
||||||
content?: string;
|
content?: string;
|
||||||
@@ -1495,6 +1465,12 @@ export interface LlmMessage {
|
|||||||
toolCallId?: string | null;
|
toolCallId?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LlmToolCall {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
arguments?: { [key: string]: any; };
|
||||||
|
}
|
||||||
|
|
||||||
export interface McpToolDefinition {
|
export interface McpToolDefinition {
|
||||||
name?: string;
|
name?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
@@ -1508,6 +1484,21 @@ export interface McpParameterDefinition {
|
|||||||
defaultValue?: any | null;
|
defaultValue?: any | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface LlmChatResponse {
|
||||||
|
content?: string;
|
||||||
|
provider?: string;
|
||||||
|
model?: string;
|
||||||
|
toolCalls?: LlmToolCall[] | null;
|
||||||
|
usage?: LlmUsage | null;
|
||||||
|
requiresToolExecution?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LlmUsage {
|
||||||
|
promptTokens?: number;
|
||||||
|
completionTokens?: number;
|
||||||
|
totalTokens?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ScenarioViewModel {
|
export interface ScenarioViewModel {
|
||||||
name: string;
|
name: string;
|
||||||
indicators: IndicatorViewModel[];
|
indicators: IndicatorViewModel[];
|
||||||
@@ -1548,6 +1539,21 @@ export interface PrivyInitAddressResponse {
|
|||||||
isAlreadyInitialized?: boolean;
|
isAlreadyInitialized?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface PrivyRevokeAllApprovalsResponse {
|
||||||
|
success?: boolean;
|
||||||
|
orderVaultUsdcHash?: string | null;
|
||||||
|
orderVaultWethHash?: string | null;
|
||||||
|
exchangeRouterUsdcHash?: string | null;
|
||||||
|
exchangeRouterWethHash?: string | null;
|
||||||
|
syntheticsRouterUsdcHash?: string | null;
|
||||||
|
syntheticsRouterWethHash?: string | null;
|
||||||
|
dataStoreUsdcHash?: string | null;
|
||||||
|
dataStoreWethHash?: string | null;
|
||||||
|
depositVaultUsdcHash?: string | null;
|
||||||
|
depositVaultWethHash?: string | null;
|
||||||
|
error?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IndicatorRequestDto {
|
export interface IndicatorRequestDto {
|
||||||
indicatorName: string;
|
indicatorName: string;
|
||||||
strategyDescription: string;
|
strategyDescription: string;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {ChevronDownIcon, ChevronRightIcon,} from '@heroicons/react/solid'
|
import {ChevronDownIcon, ChevronRightIcon,} from '@heroicons/react/solid'
|
||||||
import React, {useEffect, useMemo, useState} from 'react'
|
import React, {useEffect, useMemo, useState} from 'react'
|
||||||
import {useNavigate} from 'react-router-dom'
|
import {useNavigate} from 'react-router-dom'
|
||||||
import {FiCopy, FiKey, FiPlay, FiTrash2, FiTrendingUp} from 'react-icons/fi'
|
import {FiCopy, FiKey, FiPlay, FiTrash2, FiTrendingUp, FiX} from 'react-icons/fi'
|
||||||
|
|
||||||
import useApiUrlStore from '../../../app/store/apiStore'
|
import useApiUrlStore from '../../../app/store/apiStore'
|
||||||
import {SelectColumnFilter, Table, Toast,} from '../../../components/mollecules'
|
import {SelectColumnFilter, Table, Toast,} from '../../../components/mollecules'
|
||||||
@@ -55,6 +55,22 @@ const AccountTable: React.FC<IAccountList> = ({ list, isFetching }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function revokeAllApprovals(publicAddress: string) {
|
||||||
|
const t = new Toast('Revoking all approvals')
|
||||||
|
const client = new TradingClient({}, apiUrl)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await client.trading_RevokeAllApprovals(publicAddress)
|
||||||
|
if (response.success) {
|
||||||
|
t.update('success', 'All approvals revoked successfully')
|
||||||
|
} else {
|
||||||
|
t.update('error', `Revocation failed: ${response.error || 'Unknown error'}`)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
t.update('error', 'Error: ' + err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function copyToClipboard(text: string) {
|
async function copyToClipboard(text: string) {
|
||||||
const t = new Toast('Copying to clipboard...')
|
const t = new Toast('Copying to clipboard...')
|
||||||
try {
|
try {
|
||||||
@@ -160,6 +176,14 @@ const AccountTable: React.FC<IAccountList> = ({ list, isFetching }) => {
|
|||||||
<span className="ml-1">Init</span>
|
<span className="ml-1">Init</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className="btn btn-sm btn-warning btn-outline"
|
||||||
|
onClick={() => revokeAllApprovals(account.key)}
|
||||||
|
>
|
||||||
|
<FiX />
|
||||||
|
<span className="ml-1">Revoke</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-success btn-outline"
|
className="btn btn-sm btn-success btn-outline"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {ChevronDownIcon, ChevronRightIcon,} from '@heroicons/react/solid'
|
import {ChevronDownIcon, ChevronRightIcon,} from '@heroicons/react/solid'
|
||||||
import React, {useEffect, useMemo, useState} from 'react'
|
import React, {useEffect, useMemo, useState} from 'react'
|
||||||
import {useNavigate} from 'react-router-dom'
|
import {useNavigate} from 'react-router-dom'
|
||||||
import {FiCopy, FiKey, FiPlay, FiTrash2, FiTrendingUp} from 'react-icons/fi'
|
import {FiCopy, FiKey, FiPlay, FiTrash2, FiTrendingUp, FiX} from 'react-icons/fi'
|
||||||
|
|
||||||
import useApiUrlStore from '../../../app/store/apiStore'
|
import useApiUrlStore from '../../../app/store/apiStore'
|
||||||
import {SelectColumnFilter, Table, Toast,} from '../../../components/mollecules'
|
import {SelectColumnFilter, Table, Toast,} from '../../../components/mollecules'
|
||||||
@@ -55,6 +55,22 @@ const AccountTable: React.FC<IAccountList> = ({ list, isFetching }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function revokeAllApprovals(publicAddress: string) {
|
||||||
|
const t = new Toast('Revoking all approvals')
|
||||||
|
const client = new TradingClient({}, apiUrl)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await client.trading_RevokeAllApprovals(publicAddress)
|
||||||
|
if (response.success) {
|
||||||
|
t.update('success', 'All approvals revoked successfully')
|
||||||
|
} else {
|
||||||
|
t.update('error', `Revocation failed: ${response.error || 'Unknown error'}`)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
t.update('error', 'Error: ' + err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function copyToClipboard(text: string) {
|
async function copyToClipboard(text: string) {
|
||||||
const t = new Toast('Copying to clipboard...')
|
const t = new Toast('Copying to clipboard...')
|
||||||
try {
|
try {
|
||||||
@@ -160,6 +176,14 @@ const AccountTable: React.FC<IAccountList> = ({ list, isFetching }) => {
|
|||||||
<span className="ml-1">Init</span>
|
<span className="ml-1">Init</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className="btn btn-sm btn-warning btn-outline"
|
||||||
|
onClick={() => revokeAllApprovals(account.key)}
|
||||||
|
>
|
||||||
|
<FiX />
|
||||||
|
<span className="ml-1">Revoke</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-success btn-outline"
|
className="btn btn-sm btn-success btn-outline"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user