chain.withdraw.v1.AutoWithdrawService
PreviewAutoWithdrawRun
Preview the account's next auto-withdraw run from its balances now: when it starts, whether it would pay, and per asset what it would pay, what would stay and why, its USD value and the expected network fee. It plans exactly as the run does; balances, prices and fees can change before the run starts. A price that is not current leaves the value unset instead of failing the read. When prices cannot be read at all, the values stay unset too, unless the rule has a USD minimum: prices then decide what pays, so the read answers UNAVAILABLE and can be retried. An API key needs READ_AUTO_WITHDRAW in its policy and reads only its own account. Both refusals answer PERMISSION_DENIED: a key whose policy lacks the action gets "api key policy does not allow READ_AUTO_WITHDRAW", and a key that names an account other than its own, such as a root-account key naming a subaccount, gets "api key target scope mismatch".
Request
curl --request POST \ \
--url 'https://api.testnet.polyester.com/chain.withdraw.v1.AutoWithdrawService/PreviewAutoWithdrawRun' \
--header 'Content-Type: application/json' \
--header 'Connect-Protocol-Version: 1' \
--data '{
"subaccountId": "6789012345678"
}'Responses
{
"assets": [
{
"assetId": 100,
"availableE18": {
"hi": "1",
"lo": "1"
},
"destinationAddress": "0x3333333333333333333333333333333333333333",
"destinationChainId": "1",
"heldBackE18": {
"hi": "1",
"lo": "1"
},
"holdReason": "value",
"minimumE18": {
"hi": "1",
"lo": "1"
},
"networkFeeE18": {
"hi": "1",
"lo": "1"
},
"networkFeeSampledAt": "2025-01-01T00:00:00Z",
"payableE18": {
"hi": "1",
"lo": "1"
},
"payableFrom": "2025-01-01T00:00:00Z",
"pricedAt": "2025-01-01T00:00:00Z",
"valueUsdE18": {
"hi": "1",
"lo": "1"
}
}
],
"computedAt": "2025-01-01T00:00:00Z",
"minUsdValueE18": {
"hi": "1",
"lo": "1"
},
"nextRunAt": "2025-01-01T00:00:00Z",
"pause": {
"assetId": 100,
"pausedAt": "2025-01-01T00:00:00Z",
"reason": "value"
},
"ruleVersion": 1,
"status": "WILL_PAY"
}chain.withdraw.v1.PreviewAutoWithdrawRunRequestchain.withdraw.v1.PreviewAutoWithdrawRunResponsePublic subaccount ID; omit for the root account. Public ID. ConnectRPC carries it as fixed64 (a decimal string in JSON).
Whether the next run would pay.
When the next run starts: its UTC slot, or, while a due slot waits for the scheduler, that slot. For an hourly rule, the next hourly check. Unset when the account has no rule or the rule is paused.
The latest rule version; zero when the account has no rule.
Asset whose payout paused the rule; zero when no payout did.
Machine-readable reason: destination_not_whitelisted when the destination left the account's external withdraw whitelist, destination_invalid when it is no longer a valid destination, or authority_revoked when the person who set the rule may no longer change it or withdraw from the account. On a broker vault the rule pauses with authority_revoked as soon as its author's broker role changes in any way: removed, demoted, or promoted (for example Finance to Owner), and also when the author is removed and added back. An Owner or Finance member resumes it with a fresh step-up.
When the rule was paused.
Most significant 64 bits.
Least significant 64 bits.
Ledger asset.
External destination chain identifier; zero when the rule has no destination for the asset.
Canonical destination address; empty when the rule has no destination for the asset.
Most significant 64 bits.
Least significant 64 bits.
Most significant 64 bits.
Least significant 64 bits.
Most significant 64 bits.
Least significant 64 bits.
Why held_back_e18 stays, or why nothing pays: below_minimum (below minimum_e18 or the rule's min_usd_value_e18), price_unavailable (the rule has a USD minimum and no current price values the asset), no_destination (the rule pays no destination for the asset), destination_cooling_down (a broker vault pays a destination only once it has been on the vault's external withdraw whitelist for 24 hours; see payable_from), above_max (the balance above max_amount_e18 stays) or dust (less than one whole on-chain unit stays); empty when the whole balance pays.
Most significant 64 bits.
Least significant 64 bits.
Most significant 64 bits.
Least significant 64 bits.
When the price behind value_usd_e18 was observed; unset with it.
Most significant 64 bits.
Least significant 64 bits.
When network_fee_e18 was sampled; unset with it.
Set only on a broker vault while the destination is cooling down: when it can be paid, 24 hours after it was added to the vault's external withdraw whitelist. Unset with hold_reason destination_cooling_down when that time is not known yet.
When the balances, prices and fees the preview used were read.
| Key | HTTP status | Connect code | Error | When |
|---|---|---|---|---|
| account-shard-unavailable | 503 | unavailable | Account Shard Unavailable | The account shard cannot currently accept fund movement. |
| amount-below-minimum | 400 | invalid_argument | Amount Below Minimum | The withdraw amount is below the configured minimum including fees. |
| amount-exceeds-route-precision | 400 | invalid_argument | Amount Exceeds Route Precision | The withdraw amount has more decimal places than the destination network's token supports. |
| amount-exceeds-supply | 400 | invalid_argument | Amount Exceeds Supply | The withdraw amount exceeds the available zipped-asset supply. |
| api-key-binding-invalid | 403 | permission_denied | API Key Binding Invalid | API-key authorization binding verification failed. |
| api-key-binding-public-key-mismatch | 403 | permission_denied | API Key Binding Public Key Mismatch | The API-key authorization binding does not match the configured public key. |
| api-key-binding-scope-mismatch | 403 | permission_denied | API Key Binding Scope Mismatch | The API-key authorization binding does not cover the requested scope. |
| api-key-not-found | 403 | permission_denied | API Key Not Found | The API key could not be resolved. |
| auth-authentication-required | 401 | unauthenticated | Authentication Required | Authentication is required. |
| auth-session-kind-not-allowed | 403 | permission_denied | Interactive Session Required | This operation accepts only an interactive session; API keys are refused. |
| capital-view-unavailable | 503 | unavailable | Capital View Unavailable | The authoritative capital view is not ready. |
| chain-metadata-unavailable | 503 | unavailable | Chain Metadata Unavailable | Required chain or contract metadata is unavailable. |
| conflict | 409 | aborted | Conflict | The request conflicts with existing state. |
| destination-invalid | 400 | invalid_argument | Destination Invalid | The auto-withdraw destination address is not a valid withdrawal destination on its chain. |
| destination-validation-unavailable | 503 | unavailable | Destination Validation Unavailable | Destination validation is temporarily unavailable. |
| external-destination-cooling-down | 400 | failed_precondition | External Destination Cooling Down | The broker vault pays this destination only once it has been on the vault's external withdraw whitelist for 24 hours. |
| external-destination-not-whitelisted | 403 | permission_denied | External Destination Not Whitelisted | The external destination is not whitelisted. |
| failed-precondition | 400 | failed_precondition | Failed Precondition | A required withdraw precondition was not satisfied. |
| fee-unavailable | 503 | unavailable | Fee Unavailable | Required network fee data is unavailable. |
| funds-lock-conflict | 409 | aborted | Funds Lock Conflict | The funds lock conflicts with an existing or finalized reservation. |
| idempotency-conflict | 409 | already_exists | Idempotency Conflict | The idempotency key was reused with different request data. |
| insufficient-funds | 400 | failed_precondition | Insufficient Funds | The source account does not have enough available Trading balance. |
| internal-error | 500 | internal | Internal Error | The withdraw failed because of an unexpected server error. |
| internal-recipient-not-whitelisted | 403 | permission_denied | Internal Recipient Not Whitelisted | The internal funding recipient is not whitelisted. |
| invalid-action | 400 | invalid_argument | Invalid Withdraw Action | The withdraw action is invalid for this endpoint. |
| invalid-amount | 400 | invalid_argument | Invalid Amount | The withdraw amount is invalid. |
| invalid-auto-withdraw-schedule | 400 | invalid_argument | Invalid Auto-Withdraw Schedule | The auto-withdraw schedule is invalid for its cadence. |
| invalid-destination-address | 400 | invalid_argument | Invalid Destination Address | The destination address is invalid. |
| invalid-destination-chain | 400 | invalid_argument | Invalid Destination Chain | The destination chain is invalid. |
| invalid-request | 400 | invalid_argument | Invalid Request | The request payload or one of its fields is invalid. |
| invalid-subaccount-id | 400 | invalid_argument | Invalid Subaccount | The selected subaccount identifier is invalid. |
| min-amount-below-floor | 400 | invalid_argument | Minimum Amount Below Floor | The auto-withdraw destination's minimum is below the least amount a payout to it can pay. |
| not-found | 404 | not_found | Not Found | The requested resource was not found. |
| permission-denied | 403 | permission_denied | Permission Denied | The caller is not permitted to perform this withdraw operation. |
| rate-limit-exceeded | 429 | resource_exhausted | Rate Limit Exceeded | The withdraw admission rate limit was exceeded. |
| route-unsupported | 400 | invalid_argument | Route Unsupported | No enabled withdrawal route pays the asset to the destination chain. |
| service-unavailable | 503 | unavailable | Service Unavailable | A required service is temporarily unavailable. |
| signature-required | 400 | invalid_argument | Signature Required | A payload signature is required. |
| signature-scheme-unsupported | 400 | invalid_argument | Signature Scheme Unsupported | The signature scheme is unsupported. |
| signer-wallet-invalid | 400 | invalid_argument | Invalid Signer Wallet | The signer wallet is invalid. |
| source-smart-account-unavailable | 400 | failed_precondition | Source Smart Account Unavailable | The source smart-account address is unavailable. |
| step-up-unavailable | 503 | unavailable | Step-Up Unavailable | Fresh step-up verification is temporarily unavailable. |
| subaccount-not-found | 404 | not_found | Subaccount Not Found | The selected subaccount does not exist. |
| supply-unavailable | 503 | unavailable | Supply Unavailable | Required zipped-asset supply data is unavailable. |
| unauthenticated | 401 | unauthenticated | Unauthenticated | Authentication is required. |
| unsupported-asset | 400 | invalid_argument | Unsupported Asset | The requested asset or withdraw route is not supported. |
| unsupported-ledger | 400 | invalid_argument | Unsupported Ledger | The requested ledger is not supported for withdrawals. |
| version-conflict | 409 | aborted | Version Conflict | The expected version is not the auto-withdraw rule's latest version. |
| wallet-binding-invalid | 403 | permission_denied | Wallet Binding Invalid | Wallet authorization binding verification failed. |
| wallet-binding-scope-mismatch | 403 | permission_denied | Wallet Binding Scope Mismatch | The wallet authorization binding does not cover the requested scope. |
| wallet-binding-signer-mismatch | 403 | permission_denied | Wallet Binding Signer Mismatch | The wallet authorization binding does not match the signer. |