> For the complete documentation index, see [llms.txt](https://docs.tronsave.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tronsave.io/chinese/developers/code-examples/extend-with-private-key.md).

# v2 — 使用私钥延长

这是一个完整的、可运行的示例，演示如何使用 v2 Extend Orders API 延长现有的资源代理（委托），同时通过本地用你的私钥签名的交易来支付费用。

整个流程包含两次 API 调用：

1. **`POST /v2/get-extendable-delegates`** — 预估哪些代理（委托）可以延长，以及需要花费多少 TRX（`totalEstimateTrx`）。
2. **`POST /v2/extend-request`** — 提交延长请求，并附上一笔向 TronSave 接收地址支付预估金额的 `signedTx`。

在这两次调用之间，你需要用自己的私钥构建并签名一笔发往 TronSave 接收地址的 TRX 转账，因此 TronSave 永远不会持有你的资金。

{% hint style="info" %}
本示例使用 TronWeb 来构建并签名转账。需要 **TronWeb 5.3.2 版本**。

```bash
npm i tronweb@5.3.2 @noble/secp256k1@1.7.1
```

了解更多：<https://tronweb.network/docu/docs/5.3.2/Release%20Note/>
{% endhint %}

## 配置

在运行之前，请设置以下值：

<table><thead><tr><th width="260">常量</th><th>说明</th></tr></thead><tbody><tr><td><code>TRONSAVE_API_URL</code></td><td>TronSave API 基础 URL。主网：<code>https://api.tronsave.io</code>。</td></tr><tr><td><code>RECEIVER</code></td><td>接收延长后资源代理（委托）的地址。</td></tr><tr><td><code>RESOURCE_TYPE</code></td><td><code>ENERGY</code> 或 <code>BANDWIDTH</code>。可选 — 默认为 <code>ENERGY</code>。</td></tr><tr><td><code>REQUESTER_ADDRESS</code></td><td>请求（并支付）延长费用的地址。</td></tr><tr><td><code>PRIVATE_KEY</code></td><td><code>REQUESTER_ADDRESS</code> 的私钥，用于在本地签名 TRX 转账。</td></tr><tr><td><code>TRON_FULL_NODE</code></td><td>TronWeb 用于构建交易的 TRON 全节点（例如 <code>https://api.trongrid.io</code>）。</td></tr><tr><td><code>TRONSAVE_RECEIVER_ADDRESS</code></td><td>接收你付款的 TronSave 地址。主网：<code>TWZEhq5JuUVvGtutNgnRBATbF8BnHGyn4S</code>。测试网：<code>TATT1UzHRikft98bRFqApFTsaSw73ycfoS</code>。</td></tr></tbody></table>

{% hint style="warning" %}
请妥善保管你的私钥。仅在受信任的服务器环境中运行此代码 — 切勿在客户端或浏览器代码中暴露 `PRIVATE_KEY`。
{% endhint %}

完整的主网和测试网端点列表请参阅 [环境](/chinese/developers/environments.md)，端点详情请参阅 [Extend Orders API 参考](/chinese/developers/api-reference/extend-orders.md)。

## 完整示例

{% tabs %}
{% tab title="JavaScript" %}

```javascript
const TronWeb = require('tronweb')

const TRONSAVE_API_URL = "https://api.tronsave.io"
const RECEIVER = "your-receiver-address"
const RESOURCE_TYPE = "ENERGY"
const REQUESTER_ADDRESS = "TFwUFWr3QV376677Z8VWXxGUAMFSrq1MbM"
const PRIVATE_KEY = "your-private-key"
const TRON_FULL_NODE = "https://api.trongrid.io"
const TRONSAVE_RECEIVER_ADDRESS = "TWZEhq5JuUVvGtutNgnRBATbF8BnHGyn4S"; //in testnet mode change it to "TATT1UzHRikft98bRFqApFTsaSw73ycfoS"


// Initialize TronWeb instance
const tronWeb = new TronWeb({
    fullNode: TRON_FULL_NODE,
    solidityNode: TRON_FULL_NODE,
    eventServer: TRON_FULL_NODE,
});

const GetEstimateExtendData = async (requester, extendTo, maxPriceAccepted) => {
    const url = TRONSAVE_API_URL + `/v2/get-extendable-delegates`
    const body = {
        extendTo, //time in seconds you want to extend to
        receiver: RECEIVER,   //the address that receives the resource delegate
        requester, //the address that requests the resource delegate
        maxPriceAccepted, //Optional. Number the maximum price you want to pay to extend
        resourceType: RESOURCE_TYPE, //ENERGY or BANDWIDTH. optional. The default is ENERGY
    }
    const data = await fetch(url, {
        method: "POST",
        headers: {
            "content-type": "application/json",
        },
        body: JSON.stringify(body)
    })
    const response = await data.json()
    /**
     * Example response 
     * @link  
       {
            "error": false,
            "message": "Success",
            "data": {
                "extendOrderBook": [
                    {
                        "price": 784,
                        "value": 1002
                    }
                ],
                "totalDelegateAmount": 5003,
                "totalAvailableExtendAmount": 5003,
                "totalEstimateTrx": 4085783,
                "isAbleToExtend": true,
                "yourBalance": 2377366851,
                "extendData": [
                    {
                        "delegator": "TGGVrYaT8Xoos...6dmSZkohGGcouYL4",
                        "isExtend": true,
                        "extraAmount": 0,
                        "extendTo": 1745833276
                    },
                    {
                        "delegator": "TQBV7xU489Rq8Z...zBhJMdrDr51wA2",
                        "isExtend": true,
                        "extraAmount": 0,
                        "extendTo": 1745833276
                    },
                    {
                        "delegator": "TSHZv6xsYHMRCbdVh...qNozxaPPjDR6",
                        "isExtend": true,
                        "extraAmount": 0,
                        "extendTo": 1745833276
                    }
                ]
            }
        }
     */
    return response
}


const GetSignedTx = async (totalEstimateTrx) => {
    const dataSendTrx = await tronWeb.transactionBuilder.sendTrx(TRONSAVE_RECEIVER_ADDRESS, totalEstimateTrx, REQUESTER_ADDRESS);
    const signedTx = await tronWeb.trx.sign(dataSendTrx, PRIVATE_KEY);
    return signedTx;
};
/**
 * @param {number} extendTo time in seconds you want to extend to
 * @param {boolean} maxPriceAccepted number maximum price you want to pay to extend
 * @returns 
 */
const SendExtendRequest = async (extendTo, maxPriceAccepted) => {
    const url = TRONSAVE_API_URL + `/v2/extend-request`
    // Get estimate extendable delegates
    const estimateResponse = await GetEstimateExtendData(REQUESTER_ADDRESS, extendTo, maxPriceAccepted)
    const extendData = estimateResponse.data?.extendData
    // check if there are extendable delegates
    if (extendData && extendData.length) { 
        const totalEstimateTrx = estimateResponse.data?.totalEstimateTrx
        // Build a signed transaction by using the private key
        const signedTx = await GetSignedTx(totalEstimateTrx)
        const body = {
            extendData: extendData,
            receiver: RECEIVER,
            signedTx
        }
        const data = await fetch(url, {
            method: "POST",
            headers: {
                "content-type": "application/json",
            },
            body: JSON.stringify(body)
        })
        const response = await data.json()
        /**
         * Example response 
         {
            error: false,
            message: 'Success',
            data: { orderId: '680b5ac7b09a385fb3d582ff' }
            }
         */
        return response
    }
    return []
}

//Example run code
const ClientCode = async () => { 
    const extendTo = Math.floor(new Date().getTime() / 1000) + 3 * 86400 //Extend to 3 next days
    const maxPriceAccepted = 900
    const response = await SendExtendRequest(extendTo, maxPriceAccepted)
    console.log(response)
}


ClientCode()
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

// Configuration
const TRONSAVE_API_URL = "https://api.tronsave.io";
const RECEIVER = "your-receiver-address";
const RESOURCE_TYPE = "ENERGY";
const REQUESTER_ADDRESS = "TFwUFWr3QV376677Z8VWXxGUAMFSrq1MbM";
const PRIVATE_KEY = "your-private-key";
const TRON_FULL_NODE = "https://api.trongrid.io";
const TRONSAVE_RECEIVER_ADDRESS = "TWZEhq5JuUVvGtutNgnRBATbF8BnHGyn4S";

/**
 * Get estimate extend data
 * @param string $requester
 * @param int $extendTo
 * @param int $maxPriceAccepted
 * @return array
 */
function getEstimateExtendData(string $requester, int $extendTo, int $maxPriceAccepted): array {
    $url = TRONSAVE_API_URL . "/v2/get-extendable-delegates";
    $body = [
        'extendTo' => $extendTo,
        'receiver' => RECEIVER,
        'requester' => $requester,
        'maxPriceAccepted' => $maxPriceAccepted,
        'resourceType' => RESOURCE_TYPE,
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json'
    ]);
    $response = curl_exec($ch);
    curl_close($ch);
    return json_decode($response, true);
}

/**
 * Get signed transaction
 * @param int $totalEstimateTrx
 * @return array
 */
function getSignedTx(int $totalEstimateTrx): array {
    // This is a placeholder. In real implementation, you would use TronWeb PHP SDK
    return [
        'visible' => false,
        'txID' => '...',
        'raw_data' => [
            'contract' => [
                [
                    'parameter' => [
                        'value' => [
                            'amount' => $totalEstimateTrx,
                            'owner_address' => REQUESTER_ADDRESS,
                            'to_address' => TRONSAVE_RECEIVER_ADDRESS
                        ],
                        'type_url' => 'type.googleapis.com/protocol.TransferContract'
                    ],
                    'type' => 'TransferContract'
                ]
            ]
        ]
    ];
}

/**
 * Send extend request
 * @param int $extendTo
 * @param int $maxPriceAccepted
 * @return array
 */
function sendExtendRequest(int $extendTo, int $maxPriceAccepted): array {
    $url = TRONSAVE_API_URL . "/v2/extend-request";
    $estimateResponse = getEstimateExtendData(REQUESTER_ADDRESS, $extendTo, $maxPriceAccepted);
    $extendData = $estimateResponse['data']['extendData'] ?? [];

    if (!empty($extendData)) {
        $totalEstimateTrx = $estimateResponse['data']['totalEstimateTrx'];
        $signedTx = getSignedTx($totalEstimateTrx);

        $body = [
            'extendData' => $extendData,
            'receiver' => RECEIVER,
            'signedTx' => $signedTx
        ];

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json'
        ]);
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }

    return [];
}

// Example run code
try {
    $extendTo = time() + (3 * 86400); // Extend to 3 next days
    $maxPriceAccepted = 900;
    $response = sendExtendRequest($extendTo, $maxPriceAccepted);
    print_r($response);
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
} 
```

{% hint style="warning" %}
上面的 PHP `getSignedTx()` 函数只是一个占位符。PHP 没有官方的 TronWeb SDK，因此在发送延长请求之前，你必须使用一个兼容 TRON 的签名库来构建并签名 TRX 转账。
{% endhint %}
{% endtab %}

{% tab title="Python" %}

```python
//import time
import requests
from typing import Dict, Any, Optional

# Configuration
TRONSAVE_API_URL = "https://api.tronsave.io"
RECEIVER = "your-receiver-address"
RESOURCE_TYPE = "ENERGY"
REQUESTER_ADDRESS = "TFwUFWr3QV376677Z8VWXxGUAMFSrq1MbM"
PRIVATE_KEY = "your-private-key"
TRON_FULL_NODE = "https://api.trongrid.io"
TRONSAVE_RECEIVER_ADDRESS = "TWZEhq5JuUVvGtutNgnRBATbF8BnHGyn4S"

def get_estimate_extend_data(requester: str, extend_to: int, max_price_accepted: int) -> Dict[str, Any]:
    """Get estimate extend data"""
    url = f"{TRONSAVE_API_URL}/v2/get-extendable-delegates"
    body = {
        'extendTo': extend_to,
        'receiver': RECEIVER,
        'requester': requester,
        'maxPriceAccepted': max_price_accepted,
        'resourceType': RESOURCE_TYPE,
    }
    
    response = requests.post(url, json=body)
    return response.json()

def get_signed_tx(total_estimate_trx: int) -> Dict[str, Any]:
    """Get signed transaction"""
    # This is a placeholder. In real implementation, you would use TronWeb Python SDK
    return {
        'visible': False,
        'txID': '...',
        'raw_data': {
            'contract': [{
                'parameter': {
                    'value': {
                        'amount': total_estimate_trx,
                        'owner_address': REQUESTER_ADDRESS,
                        'to_address': TRONSAVE_RECEIVER_ADDRESS
                    },
                    'type_url': 'type.googleapis.com/protocol.TransferContract'
                },
                'type': 'TransferContract'
            }]
        }
    }

def send_extend_request(extend_to: int, max_price_accepted: int) -> Dict[str, Any]:
    """Send extend request"""
    url = f"{TRONSAVE_API_URL}/v2/extend-request"
    
    estimate_response = get_estimate_extend_data(REQUESTER_ADDRESS, extend_to, max_price_accepted)
    extend_data = estimate_response.get('data', {}).get('extendData', [])

    if extend_data:
        total_estimate_trx = estimate_response['data']['totalEstimateTrx']
        signed_tx = get_signed_tx(total_estimate_trx)

        body = {
            'extendData': extend_data,
            'receiver': RECEIVER,
            'signedTx': signed_tx
        }
        
        response = requests.post(url, json=body)
        return response.json()

    return {}

def main() -> None:
    """Main function"""
    try:
        extend_to = int(time.time()) + (3 * 86400)  # Extend to 3 next days
        max_price_accepted = 900
        response = send_extend_request(extend_to, max_price_accepted)
        print("Response:", response)
    except Exception as e:
        print(f"Error: {str(e)}")

if __name__ == "__main__":
    main() 
```

{% hint style="warning" %}
上面的 Python `get_signed_tx()` 函数只是一个占位符。在发送延长请求之前，请使用诸如 `tronpy` 之类的 TRON 签名库来构建并签名 TRX 转账。请注意，示例还引用了 `time.time()`，但 `import time` 这一行被注释掉了 — 运行前请取消注释或添加 `import time`。
{% endhint %}
{% endtab %}
{% endtabs %}

## 工作原理

1. **预估。** `GetEstimateExtendData` 使用 `extendTo`、`receiver`、`requester`、可选的 `maxPriceAccepted` 和 `resourceType` 调用 `/v2/get-extendable-delegates`。响应中包含 `extendData`（可延长的代理（委托））和 `totalEstimateTrx`（以 SUN 计的费用）。
2. **签名。** 如果 `extendData` 非空，`GetSignedTx` 会构建一笔从 `REQUESTER_ADDRESS` 发往 `TRONSAVE_RECEIVER_ADDRESS`、金额为 `totalEstimateTrx` 的 TRX 转账，并使用 `PRIVATE_KEY` 在本地对其签名。
3. **提交。** `SendExtendRequest` 将 `extendData`、`receiver` 和 `signedTx` 提交（POST）到 `/v2/extend-request`。成功时，响应中会包含一个 `orderId`。

{% hint style="info" %}
`maxPriceAccepted` 是你愿意为延长支付的价格上限（以 SUN 计）。如果订单簿价格超过该上限，`extendData` 中返回的代理（委托）可能会更少。
{% endhint %}

## 后续步骤

* [Extend Orders API 参考](/chinese/developers/api-reference/extend-orders.md) — `get-extendable-delegates` 和 `extend-request` 的完整请求和响应结构。
* [认证](/chinese/developers/authentication.md) — 将私钥/签名交易流程与 API 密钥流程进行对比。
* [订单类型](/chinese/concepts/order-types.md) — 了解延长订单与其他订单类型的关系。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.tronsave.io/chinese/developers/code-examples/extend-with-private-key.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
