# Release Stuck Transactions

Network congestion or low transaction fees may prevent a transaction sent to the node from being included in a block. If a transaction remains unprocessed for a certain period after submission (10 minutes on EVM chain, 60 minutes on Bitcoin), Fordefi marks it as STUCK. Fordefi provides two ways to resolve a stuck transaction:

- **Accelerate**: Resend the original transaction with a higher fee.
- **Cancel**: Replace the original transaction with a higher-fee transaction that sends funds back to yourself, effectively nullifying the original.


These methods, collectively referred to as **releasing** the transaction, are available on **EVM chains** and on **Bitcoin**.  The underlying mechanics are similar across the two chain types:

- On EVM chains, the replacement transaction uses the same nonce as the original and a higher gas price.
- On Bitcoin, the replacement transaction uses the same UTXOs, a higher sequence number, and an increased fee per byte. To cancel a transaction on Bitcoin, the replacement transaction spends the same UTXOs but sends the funds back to your own address, effectively nullifying the original.


In both cases, the higher fee incentivizes miners to include the replacement transaction in a block, making it more likely to be mined than the original. Once the replacement is mined, the original becomes ineligible to be mined and is dropped by nodes.

### Release a stuck transaction

Learn more about [releasing](/user-guide/manage-transactions/release-transaction) transactions using the Fordefi web console.

To programmatically release a transaction, you need to call the [Release Transaction](/api/openapi/transactions/release_transaction_api_v1_transactions__id__release_post) API by sending a `POST` request to the `/api/v1/transactions/{id}/release` endpoint, where `{id}` is the ID of the original transaction.

Since releasing a transacton creates a new transaction, it is a sensitive operation and thus requires [signing the request](/developers/authentication#request-signing). The following examples demonstrate how to release a transaction in different programming languages:


```shell Shell
#!bash
 
ACCESS_TOKEN='<Your API User Access Token>'
PRIVATE_KEY_FILE='<Path of your private key PEM file>'
ENDPOINT=''
BODY=''

TIMESTAMP="$(($(date +%s) * 1000))"
SIGNATURE="$(echo -n "${ENDPOINT}|${TIMESTAMP}|${BODY}" | openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} | base64 | tr -d \\n)"

echo -n "${ENDPOINT}|${TIMESTAMP}|${BODY}"

curl -v "https://api.fordefi.com${ENDPOINT}" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-H "x-signature: ${SIGNATURE}" \
-H "x-timestamp: ${TIMESTAMP}" \
-d "${BODY}"
```


```py Python
import requests
import base64
import json
import datetime
import ecdsa
import hashlib

access_token = "<API User Access Token>"
private_key_file = "<Path of your private key PEM file>"
path = ""
request_json = 

timestamp = str(int(datetime.datetime.now(datetime.timezone.utc).timestamp()))

request_body = json.dumps(request_json)
payload = f"{path}|{timestamp}|{request_body}"

with open(private_key_file, "r") as f:
    signing_key = ecdsa.SigningKey.from_pem(f.read())

signature = signing_key.sign(
    data=payload.encode(),
    hashfunc=hashlib.sha256,
    sigencode=ecdsa.util.sigencode_der
)

resp_tx = requests.post(
    f"https://api.fordefi.com{path}",
    headers={
        "Authorization": f"Bearer {access_token}",
        "x-signature": base64.b64encode(signature),
        "x-timestamp": timestamp.encode(),
    },
    data=request_body,
)
```


```js Javascript
const crypto = require("crypto");
const fs = require('fs');

const accessToken = "<Your API User Access Token>"
const privateKeyFile = "<Path of your private key PEM file>"
const path = ""
const requestJson = 

const gatewayHost = "api.fordefi.com"
const requestBody = JSON.stringify(requestJson)
const timestamp = new Date().getTime();
const payload = `${path}|${timestamp}|${requestBody}`;

const secretPem = fs.readFileSync(privateKeyFile, 'utf8');
const privateKey = crypto.createPrivateKey(secretPem);
const sign = crypto.createSign('SHA256').update(payload, 'utf8').end();
const signature = sign.sign(privateKey, 'base64');

fetch(`https://${gatewayHost}${path}`, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        "Authorization": `Bearer ${accessToken}`,
        'X-Timestamp': timestamp,
        'X-Signature': signature,
    },
    body: requestBody,
}).then((response) => response.text())
    .then((json) => console.log(json));
```


```rust Rust
// Using crate p256 = { version = "0.12.0", features = ["pem"] }
use base64::{engine::general_purpose, Engine as _};
use p256::ecdsa::{signature::Signer, Signature, SigningKey};
use std::fs;
use std::time::{SystemTime, UNIX_EPOCH};

// This is the main function
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let access_token = "<Your API User Access Token>";
    let private_key_file = "<Path of your private key PEM file>";
    let path = "";
    let request_body = r#"
"#;

    let gateway_host = "api.fordefi.com";
    let timestamp = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_millis()
        .to_string();
    let payload = format!("{path}|{timestamp}|{request_body}");

    let priv_pem = fs::read_to_string(private_key_file).expect("Failed to read pem file");
    let private_key = p256::SecretKey::from_sec1_pem(&priv_pem).expect("Failed to decode pem key");
    let signing_key: SigningKey = private_key.into();

    let signature: Signature = signing_key.sign(payload.as_bytes());
    let formatted_signature = general_purpose::STANDARD.encode(signature.to_der().to_bytes());
    let client = reqwest::blocking::Client::new();
    let res = client
        .post(format!("https://{gateway_host}{path}"))
        .body(request_body)
        .bearer_auth(access_token)
        .header("Content-Type", "application/json")
        .header("X-Timestamp", timestamp)
        .header("X-Signature", formatted_signature)
        .send()?
        .text()?;

    println!("Result: {res}");
    Ok(())
}
```

#### Transaction information

Once cancelled or accelerated, the original transaction includes a `child_transaction_id` field, which contains the id of the newly created replacement transaction. The replacement transactions points back to the original transaction in its `parent_transaction_id` field and also has its `is_cancelation` or `is_acceleration` fields set. You can obtain the transaction objects that contain these data using the [Get Transaction endpoint](/api/openapi/transactions/get_transaction_api_v1_transactions__id__get).

### Release a stuck transaction - advanced method for EVM chains

Acceleration is usually the preferred method for releasing a stuck transaction. However, when the original stuck transaction is no longer relevant, canceling it is the simplest solution. The downside of canceling is that it sends an "empty" transaction, which still incurs gas fees.

To avoid paying this fee, you can replace the stuck transaction with a different transaction instead of an empty one. Create your desired transaction and use the `custom_nonce` field in the [Create Transaction](https://documentation.fordefi.com/redoc#operation/create_transaction_api_v1_transactions_post) call to reuse the nonce from the stuck transaction. This new transaction will then replace the stuck transaction.

Here's how:


```json
{
    "vault_id": "16b5aa12-509e-4944-b656-cf096515d627",
    "signer_type": "api_signer",
    "type": "evm_transaction",
    "details": {
        "type": "evm_raw_transaction",
        "chain": "ethereum_mainnet",
        "to": "0x565697B5DD1F7Bdc61f774807057D058E5A27cbC",
        "value": "0",
        "data": {
            "type": "hex",
            "hex_data": "0x0d1d7ae50000000000000000000000000000000000000000000000000000000000000006"
        },
        "custom_nonce": "47890",
    }
}
```