⚠️Blast API (blastapi.io) ends Oct 31. Migrate to Dwellir and skip Alchemy's expensive compute units.
Switch Today →
Skip to main content

wallet/unfreezebalancev2

Unstake (unfreeze) TRX to reclaim bandwidth or energy resources using TRON's Stake 2.0 mechanism.

Endpoint

POST /wallet/unfreezebalancev2

Parameters

Required Parameters

ParameterTypeDescription
owner_addressstringAccount address initiating unstaking (base58)
resourcestringResource type: "BANDWIDTH" or "ENERGY"
unfreeze_balancenumberAmount to unstake in SUN (1 TRX = 1,000,000 SUN)

Optional Parameters

ParameterTypeDescription
receiver_addressstringAddress that received the delegation (if unstaking delegated resources)
permission_idnumberPermission ID for multi-signature (default: 0)
visiblebooleanReturn base58 addresses (default: false returns hex)

Response

Returns unsigned transaction containing the unstaking operation. Transaction must be signed and broadcast.

Response Fields

  • txID - Transaction hash
  • raw_data - Transaction raw data
    • contract - Unstaking contract details
    • expiration - Transaction expiration timestamp
    • timestamp - Transaction creation timestamp
  • visible - Address format indicator

Important Notes

Unstaking Process

  1. 14-Day Waiting Period: After unstaking, TRX enters a 14-day withdrawal period
  2. No Resources During Wait: Resources are lost immediately, TRX remains locked
  3. Manual Withdrawal: After 14 days, must call withdrawexpireunfreeze to claim TRX
  4. Partial Unstaking: Can unstake portions of staked amount

Resource Implications

  • Bandwidth/Energy is removed immediately upon unstaking
  • Cannot re-stake the same TRX during withdrawal period
  • Consider keeping minimum stake for basic operations

Implementation Examples

class TronUnstakingManager {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = `https://api-tron-mainnet.n.dwellir.com/${apiKey}`;
}

// Create unstaking transaction
async createUnstakeTransaction(ownerAddress, resource, amountTRX) {
const response = await fetch(`${this.baseUrl}/wallet/unfreezebalancev2`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
owner_address: ownerAddress,
resource: resource,
unfreeze_balance: amountTRX * 1000000, // Convert TRX to SUN
visible: true
})
});

if (!response.ok) {
throw new Error(`Unstaking failed: ${response.statusText}`);
}

return response.json();
}

// Check pending withdrawals
async getPendingWithdrawals(address) {
const response = await fetch(`${this.baseUrl}/wallet/getaccount`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
address: address,
visible: true
})
});

const account = await response.json();

// Parse unfreezing information
const unfreezing = account.unfrozenV2 || [];
return unfreezing.map(item => ({
type: item.type,
amount: item.unfreeze_amount / 1000000, // Convert to TRX
expireTime: new Date(item.unfreeze_expire_time),
canWithdraw: Date.now() > item.unfreeze_expire_time
}));
}

// Calculate optimal unstaking amount
async calculateOptimalUnstake(address, targetResourceReduction) {
const response = await fetch(`${this.baseUrl}/wallet/getaccountresource`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
address: address,
visible: true
})
});

const resources = await response.json();

// Calculate based on current resource usage
const energyStaked = resources.EnergyLimit || 0;
const bandwidthStaked = resources.NetLimit || 0;

return {
energy: {
current: energyStaked,
toUnstake: Math.floor(energyStaked * targetResourceReduction),
remaining: energyStaked * (1 - targetResourceReduction)
},
bandwidth: {
current: bandwidthStaked,
toUnstake: Math.floor(bandwidthStaked * targetResourceReduction),
remaining: bandwidthStaked * (1 - targetResourceReduction)
}
};
}

// Withdraw expired unfrozen balance
async withdrawExpiredBalance(ownerAddress) {
const response = await fetch(`${this.baseUrl}/wallet/withdrawexpireunfreeze`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
owner_address: ownerAddress,
visible: true
})
});

if (!response.ok) {
throw new Error(`Withdrawal failed: ${response.statusText}`);
}

return response.json();
}
}

// Example usage
async function manageUnstaking() {
const manager = new TronUnstakingManager('YOUR_API_KEY');

try {
// Check pending withdrawals first
const pending = await manager.getPendingWithdrawals('TYourAddress...');
console.log('Pending withdrawals:', pending);

// Withdraw any expired funds
const withdrawable = pending.filter(p => p.canWithdraw);
if (withdrawable.length > 0) {
const withdrawal = await manager.withdrawExpiredBalance('TYourAddress...');
console.log('Withdrawal transaction:', withdrawal);
}

// Calculate optimal unstaking (reduce resources by 30%)
const optimal = await manager.calculateOptimalUnstake('TYourAddress...', 0.3);
console.log('Optimal unstaking amounts:', optimal);

// Create unstaking transaction for energy
const unstakeTx = await manager.createUnstakeTransaction(
'TYourAddress...',
'ENERGY',
optimal.energy.toUnstake / 28.5 // Convert energy to TRX (approximate ratio)
);

console.log('Unstaking transaction created:', unstakeTx.txID);
console.log('Sign and broadcast this transaction to complete unstaking');

} catch (error) {
console.error('Unstaking error:', error);
}
}

Example Response

{
"visible": true,
"txID": "8f3c4f9e2b8a7d6c5e4f3b2a1d9c8e7f6b5a4d3c2e1f9a8b7c6d5e4f3a2b1c9d",
"raw_data": {
"contract": [
{
"parameter": {
"value": {
"owner_address": "TYourAddress...",
"unfreeze_balance": 1000000000,
"resource": "ENERGY"
},
"type_url": "type.googleapis.com/protocol.UnfreezeBalanceV2Contract"
},
"type": "UnfreezeBalanceV2Contract"
}
],
"ref_block_bytes": "5a4b",
"ref_block_hash": "3c2d4f9e8b7a6d5c",
"expiration": 1702456849000,
"timestamp": 1702456789000
}
}

Unstaking Timeline

graph LR
A[Staked TRX] --> B[Initiate Unstaking]
B --> C[14-Day Waiting Period]
C --> D[Withdrawal Available]
D --> E[Execute Withdrawal]
E --> F[TRX in Wallet]

style A fill:#4CAF50
style C fill:#FF9800
style F fill:#2196F3

Best Practices

1. Plan Unstaking Carefully

  • Resources are lost immediately
  • Cannot re-stake during withdrawal period
  • Keep minimum stake for basic operations

2. Monitor Withdrawal Periods

  • Track 14-day waiting periods
  • Set reminders for withdrawal dates
  • Batch withdrawals for efficiency

3. Resource Management

// Keep minimum operational resources
const MIN_ENERGY_STAKE = 5000; // TRX
const MIN_BANDWIDTH_STAKE = 1000; // TRX

function calculateSafeUnstake(current, minimum) {
return Math.max(0, current - minimum);
}

4. Error Handling

  • Check account has staked balance
  • Verify resource type is correct
  • Handle insufficient stake errors

Common Errors

ErrorDescriptionSolution
No frozen balanceAccount has no staked TRXCheck staking status first
Invalid resource typeResource must be BANDWIDTH or ENERGYUse correct resource string
Insufficient frozen balanceTrying to unstake more than availableCheck current stake amount
Invalid addressMalformed TRON addressVerify base58 format

Use Cases

  • Resource Optimization: Unstake excess resources not being used
  • Liquidity Management: Free up TRX for trading or transfers
  • Delegation Cleanup: Reclaim delegated resources from inactive accounts
  • Portfolio Rebalancing: Adjust resource allocation between bandwidth/energy
  • Emergency Liquidity: Access staked TRX when needed (with 14-day delay)