fix: Implement Associated Token Account for USDC withdrawals
- Fixed PublicKey undefined error (derive from DRIFT_WALLET_PRIVATE_KEY) - Implemented ATA resolution using @solana/spl-token - Added comprehensive debug logging for withdrawal flow - Fixed AccountOwnedByWrongProgram error (need ATA not wallet address) - Successfully tested .58 withdrawal with on-chain confirmation - Updated .env with TOTAL_WITHDRAWN and LAST_WITHDRAWAL_TIME tracking Key changes: - lib/drift/withdraw.ts: Added getAssociatedTokenAddress() for USDC ATA - tsconfig.json: Excluded archive folders from compilation - package.json: Added bn.js as direct dependency Transaction: 4drNfMR1xBosGCQtfJ2a4r6oEawUByrT6L7Thyqu6QQWz555hX3QshFuJqiLZreL7KrheSgTdCEqMcXP26fi54JF Wallet: 3dG7wayp7b9NBMo92D2qL2sy1curSC4TTmskFpaGDrtA USDC ATA: 8ZEMwErnwxPNNNHJigUcMfrkBG14LCREDdKbqKm49YY7
This commit is contained in:
@@ -5,8 +5,10 @@
|
||||
*/
|
||||
|
||||
import BN from 'bn.js'
|
||||
import { PublicKey } from '@solana/web3.js'
|
||||
import { PublicKey, Keypair } from '@solana/web3.js'
|
||||
import { getAssociatedTokenAddress, TOKEN_PROGRAM_ID } from '@solana/spl-token'
|
||||
import { initializeDriftService } from './client'
|
||||
import bs58 from 'bs58'
|
||||
|
||||
export interface WithdrawalResult {
|
||||
success: boolean
|
||||
@@ -29,17 +31,62 @@ export async function withdrawFromDrift(
|
||||
|
||||
// Convert USD amount to token amount (USDC has 6 decimals)
|
||||
// $50.25 → 50,250,000 (raw token amount with 6 decimals)
|
||||
const tokenAmount = new BN(Math.floor(amountUSD * 1_000_000))
|
||||
const rawAmount = Math.floor(amountUSD * 1_000_000)
|
||||
console.log(`📊 Raw amount before BN: ${rawAmount} (type: ${typeof rawAmount})`)
|
||||
const tokenAmount = new BN(rawAmount.toString())
|
||||
|
||||
console.log(`📊 Withdrawal details:`)
|
||||
console.log(` Amount: $${amountUSD.toFixed(2)} USDC`)
|
||||
console.log(` Token amount: ${tokenAmount.toString()} (raw with 6 decimals)`)
|
||||
console.log(` Market index: ${usdcMarketIndex}`)
|
||||
|
||||
// Get destination address (default to wallet public key if not specified)
|
||||
const destination = destinationWallet
|
||||
? new PublicKey(destinationWallet)
|
||||
: new PublicKey(process.env.WALLET_PUBLIC_KEY!)
|
||||
// Get destination address
|
||||
// Need to get the Associated Token Account (ATA) for USDC, not just the wallet address
|
||||
let walletPublicKey: PublicKey
|
||||
let destination: PublicKey
|
||||
try {
|
||||
if (destinationWallet) {
|
||||
console.log(`🔑 Using provided destination wallet`)
|
||||
walletPublicKey = new PublicKey(destinationWallet)
|
||||
} else {
|
||||
console.log(`🔑 Deriving destination from private key`)
|
||||
// Derive public key from private key (same wallet as trader)
|
||||
const privateKeyStr = process.env.DRIFT_WALLET_PRIVATE_KEY
|
||||
if (!privateKeyStr) {
|
||||
throw new Error('DRIFT_WALLET_PRIVATE_KEY environment variable not set')
|
||||
}
|
||||
console.log(`🔑 Private key length: ${privateKeyStr.length}`)
|
||||
const privateKeyBytes = privateKeyStr.startsWith('[')
|
||||
? Uint8Array.from(JSON.parse(privateKeyStr))
|
||||
: bs58.decode(privateKeyStr)
|
||||
console.log(`🔑 Private key bytes length: ${privateKeyBytes.length}`)
|
||||
const keypair = Keypair.fromSecretKey(privateKeyBytes)
|
||||
walletPublicKey = keypair.publicKey
|
||||
console.log(`🔑 Derived wallet public key: ${walletPublicKey.toString()}`)
|
||||
}
|
||||
|
||||
// USDC mint address on Solana mainnet
|
||||
const usdcMint = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v')
|
||||
console.log(`🔑 USDC Mint: ${usdcMint.toString()}`)
|
||||
console.log(`🔑 Wallet public key: ${walletPublicKey.toString()}`)
|
||||
console.log(`🔑 About to call getAssociatedTokenAddress...`)
|
||||
|
||||
// Get the Associated Token Account for USDC
|
||||
destination = await getAssociatedTokenAddress(
|
||||
usdcMint,
|
||||
walletPublicKey,
|
||||
false, // allowOwnerOffCurve
|
||||
TOKEN_PROGRAM_ID
|
||||
)
|
||||
|
||||
console.log(`✅ Got ATA successfully!`)
|
||||
console.log(` Wallet: ${walletPublicKey.toString()}`)
|
||||
console.log(` USDC ATA: ${destination.toString()}`)
|
||||
|
||||
} catch (keyError: any) {
|
||||
console.error(`❌ Failed to get destination address:`, keyError)
|
||||
throw new Error(`Failed to derive destination address: ${keyError?.message || 'Unknown error'}`)
|
||||
}
|
||||
|
||||
console.log(` Destination: ${destination.toString()}`)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user