From 5d7f73a794bc639d4582e85ed2c6555fbe2f3e8f Mon Sep 17 00:00:00 2001 From: cryptooda Date: Wed, 27 Aug 2025 05:08:13 +0700 Subject: [PATCH] update contracts and approval logs --- .../src/generated/gmxsdk/configs/contracts.ts | 4 +- .../src/plugins/custom/privy.ts | 290 +++++++++++++----- .../test/plugins/close-orders.test.ts | 4 +- .../test/plugins/close-position.test.ts | 6 +- 4 files changed, 214 insertions(+), 90 deletions(-) diff --git a/src/Managing.Web3Proxy/src/generated/gmxsdk/configs/contracts.ts b/src/Managing.Web3Proxy/src/generated/gmxsdk/configs/contracts.ts index 87be7f0b..4ef23424 100644 --- a/src/Managing.Web3Proxy/src/generated/gmxsdk/configs/contracts.ts +++ b/src/Managing.Web3Proxy/src/generated/gmxsdk/configs/contracts.ts @@ -51,12 +51,12 @@ export const CONTRACTS = { DataStore: "0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8", EventEmitter: "0xC8ee91A54287DB53897056e12D9819156D3822Fb", SubaccountRouter: "0xa329221a77BE08485f59310b873b14815c82E10D", - ExchangeRouter: "0x5ac4e27341e4cccb3e5fd62f9e62db2adf43dd57", + ExchangeRouter: "0x602b805EedddBbD9ddff44A7dcBD46cb07849685", DepositVault: "0xF89e77e8Dc11691C9e8757e84aaFbCD8A67d7A55", WithdrawalVault: "0x0628D46b5D145f183AdB6Ef1f2c97eD1C4701C55", OrderVault: "0x31eF83a530Fde1B38EE9A18093A333D8Bbbc40D5", ShiftVault: "0xfe99609C4AA83ff6816b64563Bdffd7fa68753Ab", - SyntheticsReader: "0x0537C767cDAC0726c76Bb89e92904fe28fd02fE1", + SyntheticsReader: "0xcF2845Ab3866842A6b51Fb6a551b92dF58333574", SyntheticsRouter: "0x7452c558d45f8afC8c83dAe62C3f8A5BE19c71f6", GlvReader: "0x6a9505D0B44cFA863d9281EA5B0b34cB36243b45", diff --git a/src/Managing.Web3Proxy/src/plugins/custom/privy.ts b/src/Managing.Web3Proxy/src/plugins/custom/privy.ts index dd04c504..bc40dcc5 100644 --- a/src/Managing.Web3Proxy/src/plugins/custom/privy.ts +++ b/src/Managing.Web3Proxy/src/plugins/custom/privy.ts @@ -503,36 +503,35 @@ export const initAddressImpl = async ( address: string, ): Promise<{ usdcHash: string, orderVaultHash: string, exchangeRouterHash: string, wethSyntheticsRouterHash: string }> => { try { + console.log('šŸš€ Starting GMX V2 wallet initialization 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); - let approveAmount = usdcTokenData.prices.maxPrice; // Large enough amount for trading - - // Check approval for USDC (this first check is for general token approval, keeping original logic) + // Use maximum uint256 value for unlimited approval to ensure sufficient allowance for all trading scenarios + const approveAmount = ethers.MaxUint256; + console.log('šŸ“Š Approval amount set to:', approveAmount.toString()); + + // Get USDC token data for contract interactions const usdcToken = GetToken('USDC'); - const usdcAllowance = await getTokenAllowance(address, usdcToken.address, address); - - let usdcHash = ""; - if (usdcAllowance < approveAmount) { - // First approve USDC token for GMX trading - usdcHash = await approveTokenImpl( - address, - usdcToken.symbol, - ARBITRUM, - usdcTokenData.prices.maxPrice - ); - } else { - usdcHash = "Already allowed :" + usdcAllowance; - } - - const orderVaultAllowance = await getTokenAllowance(address, usdcToken.address, CONTRACTS[ARBITRUM].OrderVault); - - // Then approve GMX OrderVault with the correct amount + console.log('šŸ’± USDC Token Address:', usdcToken.address); + console.log('šŸ’± WETH Token Address:', wrapperEtherData.address); + + // ============================================================================ + // CRITICAL: OrderVault Approvals (Required for order creation) + // According to GMX V2 docs: "collateral needs to first be transferred to the OrderVault" + // ============================================================================ + console.log('\nšŸ” Step 1: Approving OrderVault contracts...'); + + // USDC approval for OrderVault + const orderVaultUsdcAllowance = await getTokenAllowance(address, usdcToken.address, CONTRACTS[ARBITRUM].OrderVault); + console.log(' USDC -> OrderVault allowance:', orderVaultUsdcAllowance.toString()); + let orderVaultHash = ""; - if (orderVaultAllowance < approveAmount) { + if (orderVaultUsdcAllowance < approveAmount) { + console.log(' āš ļø USDC allowance insufficient, approving OrderVault...'); orderVaultHash = await approveContractImpl( address, usdcToken.address, @@ -540,34 +539,45 @@ export const initAddressImpl = async ( ARBITRUM, approveAmount ); - }else{ - orderVaultHash = "Already allowed :" + orderVaultAllowance; + console.log(' āœ… USDC OrderVault approval hash:', orderVaultHash); + } else { + orderVaultHash = `Already approved: ${orderVaultUsdcAllowance.toString()}`; + console.log(' āœ… USDC already approved for OrderVault'); } - - const wrapperEtherAllowance = await getTokenAllowance(address, wrapperEtherData.address, CONTRACTS[ARBITRUM].OrderVault); - - let wrapperEtherHash = ""; - if (wrapperEtherAllowance < approveAmount) { - wrapperEtherHash = await approveContractImpl( + + // WETH approval for OrderVault + const orderVaultWethAllowance = await getTokenAllowance(address, wrapperEtherData.address, CONTRACTS[ARBITRUM].OrderVault); + console.log(' WETH -> OrderVault allowance:', orderVaultWethAllowance.toString()); + + let orderVaultWethHash = ""; + if (orderVaultWethAllowance < approveAmount) { + console.log(' āš ļø WETH allowance insufficient, approving OrderVault...'); + orderVaultWethHash = await approveContractImpl( address, wrapperEtherData.address, CONTRACTS[ARBITRUM].OrderVault, ARBITRUM, approveAmount ); - }else{ - wrapperEtherHash = "Already allowed :" + wrapperEtherAllowance; + console.log(' āœ… WETH OrderVault approval hash:', orderVaultWethHash); + } else { + orderVaultWethHash = `Already approved: ${orderVaultWethAllowance.toString()}`; + console.log(' āœ… WETH already approved for OrderVault'); } - - console.log('wrapperEtherAllowance', wrapperEtherAllowance) - - const exchangeRouterAllowance = await getTokenAllowance(address, usdcToken.address, CONTRACTS[ARBITRUM].ExchangeRouter); - - console.log('exchangeRouterAllowance', exchangeRouterAllowance) + + // ============================================================================ + // CRITICAL: ExchangeRouter Approvals (Required for createOrder calls) + // According to GMX V2 docs: "ExchangeRouter.createOrder can then be called after" + // ============================================================================ + console.log('\nšŸ” Step 2: Approving ExchangeRouter contracts...'); + + // USDC approval for ExchangeRouter + const exchangeRouterUsdcAllowance = await getTokenAllowance(address, usdcToken.address, CONTRACTS[ARBITRUM].ExchangeRouter); + console.log(' USDC -> ExchangeRouter allowance:', exchangeRouterUsdcAllowance.toString()); let exchangeRouterHash = ""; - console.log('approveAmount', approveAmount) - if (exchangeRouterAllowance < approveAmount) { + if (exchangeRouterUsdcAllowance < approveAmount) { + console.log(' āš ļø USDC allowance insufficient, approving ExchangeRouter...'); exchangeRouterHash = await approveContractImpl( address, usdcToken.address, @@ -575,49 +585,64 @@ export const initAddressImpl = async ( ARBITRUM, approveAmount ); - }else{ - exchangeRouterHash = "Already allowed :" + exchangeRouterAllowance; + console.log(' āœ… USDC ExchangeRouter approval hash:', exchangeRouterHash); + } else { + exchangeRouterHash = `Already approved: ${exchangeRouterUsdcAllowance.toString()}`; + console.log(' āœ… USDC already approved for ExchangeRouter'); } - - const wrapperEtherExchangeAllowance = await getTokenAllowance(address, wrapperEtherData.address, CONTRACTS[ARBITRUM].ExchangeRouter); - - let wrapperEtherExchangeHash = ""; - if (wrapperEtherExchangeAllowance < approveAmount) { - wrapperEtherExchangeHash = await approveContractImpl( + + // WETH approval for ExchangeRouter + const exchangeRouterWethAllowance = await getTokenAllowance(address, wrapperEtherData.address, CONTRACTS[ARBITRUM].ExchangeRouter); + console.log(' WETH -> ExchangeRouter allowance:', exchangeRouterWethAllowance.toString()); + + let exchangeRouterWethHash = ""; + if (exchangeRouterWethAllowance < approveAmount) { + console.log(' āš ļø WETH allowance insufficient, approving ExchangeRouter...'); + exchangeRouterWethHash = await approveContractImpl( address, wrapperEtherData.address, CONTRACTS[ARBITRUM].ExchangeRouter, ARBITRUM, approveAmount ); - }else{ - wrapperEtherExchangeHash = "Already allowed :" + wrapperEtherExchangeAllowance; + console.log(' āœ… WETH ExchangeRouter approval hash:', exchangeRouterWethHash); + } else { + exchangeRouterWethHash = `Already approved: ${exchangeRouterWethAllowance.toString()}`; + console.log(' āœ… WETH already approved for ExchangeRouter'); } - - console.log('wrapperEtherExchangeAllowance', wrapperEtherExchangeAllowance) - - const usdcSyntheticRouterAllowance = await getTokenAllowance(address, usdcToken.address, CONTRACTS[ARBITRUM].SyntheticsRouter); - - let usdcSyntheticRouterHash = ""; - if (usdcSyntheticRouterAllowance < approveAmount) { - usdcSyntheticRouterHash = await approveContractImpl( + + // ============================================================================ + // OPTIONAL: SyntheticsRouter Approvals (For synthetic positions) + // ============================================================================ + console.log('\nšŸ” Step 3: Approving SyntheticsRouter contracts...'); + + // USDC approval for SyntheticsRouter + const syntheticsRouterUsdcAllowance = await getTokenAllowance(address, usdcToken.address, CONTRACTS[ARBITRUM].SyntheticsRouter); + console.log(' USDC -> SyntheticsRouter allowance:', syntheticsRouterUsdcAllowance.toString()); + + let syntheticsRouterUsdcHash = ""; + if (syntheticsRouterUsdcAllowance < approveAmount) { + console.log(' āš ļø USDC allowance insufficient, approving SyntheticsRouter...'); + syntheticsRouterUsdcHash = await approveContractImpl( address, usdcToken.address, CONTRACTS[ARBITRUM].SyntheticsRouter, ARBITRUM, approveAmount ); - }else{ - usdcSyntheticRouterHash = "Already allowed :" + usdcSyntheticRouterAllowance; + console.log(' āœ… USDC SyntheticsRouter approval hash:', syntheticsRouterUsdcHash); + } else { + syntheticsRouterUsdcHash = `Already approved: ${syntheticsRouterUsdcAllowance.toString()}`; + console.log(' āœ… USDC already approved for SyntheticsRouter'); } - - console.log('usdcSyntheticRouterAllowance', usdcSyntheticRouterAllowance) - - // Also approve WETH for SyntheticsRouter (required for ETH positions) - const wethSyntheticsRouterAllowance = await getTokenAllowance(address, wrapperEtherData.address, CONTRACTS[ARBITRUM].SyntheticsRouter); - + + // WETH approval for SyntheticsRouter + const syntheticsRouterWethAllowance = await getTokenAllowance(address, wrapperEtherData.address, CONTRACTS[ARBITRUM].SyntheticsRouter); + console.log(' WETH -> SyntheticsRouter allowance:', syntheticsRouterWethAllowance.toString()); + let wethSyntheticsRouterHash = ""; - if (wethSyntheticsRouterAllowance < approveAmount) { + if (syntheticsRouterWethAllowance < approveAmount) { + console.log(' āš ļø WETH allowance insufficient, approving SyntheticsRouter...'); wethSyntheticsRouterHash = await approveContractImpl( address, wrapperEtherData.address, @@ -625,26 +650,125 @@ export const initAddressImpl = async ( ARBITRUM, approveAmount ); + console.log(' āœ… WETH SyntheticsRouter approval hash:', wethSyntheticsRouterHash); } else { - wethSyntheticsRouterHash = "Already allowed :" + wethSyntheticsRouterAllowance; + wethSyntheticsRouterHash = `Already approved: ${syntheticsRouterWethAllowance.toString()}`; + console.log(' āœ… WETH already approved for SyntheticsRouter'); } - - console.log('wethSyntheticsRouterAllowance', wethSyntheticsRouterAllowance) - - console.log('usdcHash', usdcHash) - console.log('orderVaultHash', orderVaultHash) - console.log('exchangeRouterHash', exchangeRouterHash) - console.log('wethSyntheticsRouterHash', wethSyntheticsRouterHash) - + + // ============================================================================ + // CRITICAL: Additional GMX V2 Contract Approvals + // These contracts might be needed for order creation and execution + // ============================================================================ + console.log('\nšŸ” Step 4: Approving additional GMX V2 contracts...'); + + // USDC approval for DataStore (required for order execution) + const dataStoreUsdcAllowance = await getTokenAllowance(address, usdcToken.address, CONTRACTS[ARBITRUM].DataStore); + console.log(' USDC -> DataStore allowance:', dataStoreUsdcAllowance.toString()); + + let dataStoreUsdcHash = ""; + if (dataStoreUsdcAllowance < approveAmount) { + console.log(' āš ļø USDC allowance insufficient, approving DataStore...'); + dataStoreUsdcHash = await approveContractImpl( + address, + usdcToken.address, + CONTRACTS[ARBITRUM].DataStore, + ARBITRUM, + approveAmount + ); + console.log(' āœ… USDC DataStore approval hash:', dataStoreUsdcHash); + } else { + dataStoreUsdcHash = `Already approved: ${dataStoreUsdcAllowance.toString()}`; + console.log(' āœ… USDC already approved for DataStore'); + } + + // WETH approval for DataStore + const dataStoreWethAllowance = await getTokenAllowance(address, wrapperEtherData.address, CONTRACTS[ARBITRUM].DataStore); + console.log(' WETH -> DataStore allowance:', dataStoreWethAllowance.toString()); + + let dataStoreWethHash = ""; + if (dataStoreWethAllowance < approveAmount) { + console.log(' āš ļø WETH allowance insufficient, approving DataStore...'); + dataStoreWethHash = await approveContractImpl( + address, + wrapperEtherData.address, + CONTRACTS[ARBITRUM].DataStore, + ARBITRUM, + approveAmount + ); + console.log(' āœ… WETH DataStore approval hash:', dataStoreWethHash); + } else { + dataStoreWethHash = `Already approved: ${dataStoreWethAllowance.toString()}`; + console.log(' āœ… WETH already approved for DataStore'); + } + + // USDC approval for DepositVault (for deposits) + const depositVaultUsdcAllowance = await getTokenAllowance(address, usdcToken.address, CONTRACTS[ARBITRUM].DepositVault); + console.log(' USDC -> DepositVault allowance:', depositVaultUsdcAllowance.toString()); + + let depositVaultUsdcHash = ""; + if (depositVaultUsdcAllowance < approveAmount) { + console.log(' āš ļø USDC allowance insufficient, approving DepositVault...'); + depositVaultUsdcHash = await approveContractImpl( + address, + usdcToken.address, + CONTRACTS[ARBITRUM].DepositVault, + ARBITRUM, + approveAmount + ); + console.log(' āœ… USDC DepositVault approval hash:', depositVaultUsdcHash); + } else { + depositVaultUsdcHash = `Already approved: ${depositVaultUsdcAllowance.toString()}`; + console.log(' āœ… USDC already approved for DepositVault'); + } + + // WETH approval for DepositVault + const depositVaultWethAllowance = await getTokenAllowance(address, wrapperEtherData.address, CONTRACTS[ARBITRUM].DepositVault); + console.log(' WETH -> DepositVault allowance:', depositVaultWethAllowance.toString()); + + let depositVaultWethHash = ""; + if (depositVaultWethAllowance < approveAmount) { + console.log(' āš ļø WETH allowance insufficient, approving DepositVault...'); + depositVaultWethHash = await approveContractImpl( + address, + wrapperEtherData.address, + CONTRACTS[ARBITRUM].DepositVault, + ARBITRUM, + approveAmount + ); + console.log(' āœ… WETH DepositVault approval hash:', depositVaultWethHash); + } else { + depositVaultWethHash = `Already approved: ${depositVaultWethAllowance.toString()}`; + console.log(' āœ… WETH already approved for DepositVault'); + } + + // ============================================================================ + // SUMMARY: Final approval status + // ============================================================================ + console.log('\nšŸ“‹ Final Approval Summary:'); + console.log(' OrderVault USDC:', orderVaultHash); + console.log(' OrderVault WETH:', orderVaultWethHash); + console.log(' ExchangeRouter USDC:', exchangeRouterHash); + console.log(' ExchangeRouter WETH:', exchangeRouterWethHash); + console.log(' SyntheticsRouter USDC:', syntheticsRouterUsdcHash); + console.log(' SyntheticsRouter WETH:', wethSyntheticsRouterHash); + console.log(' DataStore USDC:', dataStoreUsdcHash); + console.log(' DataStore WETH:', dataStoreWethHash); + console.log(' DepositVault USDC:', depositVaultUsdcHash); + console.log(' DepositVault WETH:', depositVaultWethHash); + + console.log('\nāœ… GMX V2 wallet initialization completed successfully!'); + console.log(' All necessary contracts are now approved for trading.'); + return { - usdcHash, - orderVaultHash, - exchangeRouterHash, - wethSyntheticsRouterHash + usdcHash: `OrderVault: ${orderVaultHash}, ExchangeRouter: ${exchangeRouterHash}, SyntheticsRouter: ${syntheticsRouterUsdcHash}, DataStore: ${dataStoreUsdcHash}, DepositVault: ${depositVaultUsdcHash}`, + orderVaultHash: `USDC: ${orderVaultHash}, WETH: ${orderVaultWethHash}`, + exchangeRouterHash: `USDC: ${exchangeRouterHash}, WETH: ${exchangeRouterWethHash}`, + wethSyntheticsRouterHash: `SyntheticsRouter: ${wethSyntheticsRouterHash}, DataStore: ${dataStoreWethHash}, DepositVault: ${depositVaultWethHash}` }; } catch (error) { - console.error('Error initializing address:', error); - throw new Error(`Failed to initialize address: ${error instanceof Error ? error.message : 'Unknown error'}`); + console.error('āŒ Error initializing GMX V2 wallet:', error); + throw new Error(`Failed to initialize GMX V2 wallet: ${error instanceof Error ? error.message : 'Unknown error'}`); } }; diff --git a/src/Managing.Web3Proxy/test/plugins/close-orders.test.ts b/src/Managing.Web3Proxy/test/plugins/close-orders.test.ts index 28da7829..e7e235f7 100644 --- a/src/Managing.Web3Proxy/test/plugins/close-orders.test.ts +++ b/src/Managing.Web3Proxy/test/plugins/close-orders.test.ts @@ -5,11 +5,11 @@ import {Ticker} from '../../src/generated/ManagingApiTypes' test('GMX Orders Closing', async (t) => { await t.test('should close all orders for BTC', async () => { - const sdk = await getClientForAddress('0x932167388dD9aad41149b3cA23eBD489E2E2DD78') + const sdk = await getClientForAddress('0x0b4A132cb6ed8fa66953bf61a53D0B91DaCaAd78') const result = await cancelGmxOrdersImpl( sdk, - Ticker.ETH + Ticker.BTC ) console.log('Orders closing result:', result) assert.ok(result, 'Orders closing result should be defined') diff --git a/src/Managing.Web3Proxy/test/plugins/close-position.test.ts b/src/Managing.Web3Proxy/test/plugins/close-position.test.ts index ea8a2480..29872c2a 100644 --- a/src/Managing.Web3Proxy/test/plugins/close-position.test.ts +++ b/src/Managing.Web3Proxy/test/plugins/close-position.test.ts @@ -5,12 +5,12 @@ import {TradeDirection} from '../../src/generated/ManagingApiTypes' test('GMX Position Closing', async (t) => { await t.test('should close a long position for BTC', async () => { - const sdk = await getClientForAddress('0x932167388dD9aad41149b3cA23eBD489E2E2DD78') + const sdk = await getClientForAddress('0x0b4A132cb6ed8fa66953bf61a53D0B91DaCaAd78') const result = await closeGmxPositionImpl( sdk, - "SUI", - TradeDirection.Short + "BTC", + TradeDirection.Long ) console.log('Position closing result:', result) assert.ok(result, 'Position closing result should be defined')