Use External Signers for Upload Payments
Use the two-phase upload flow when your application needs a wallet outside antd to sign and submit upload payments.
This is the right approach when:
your users pay for their own uploads
your app should not custody a wallet key for them
you need to integrate with an external signer or wallet stack
Prerequisites
antdrunning withoutAUTONOMI_WALLET_KEY(see Start the Local Daemon)EVM configuration available to the daemon for the target network
An external signer or wallet stack that can submit the required payment transactions
Steps
1. Start antd without a wallet key
The daemon does not have an --external-signer flag. External-signer mode is the absence of AUTONOMI_WALLET_KEY plus the use of the prepare/finalize endpoints.
From the ant-sdk/antd build directory, run:
EVM_RPC_URL=https://your-rpc-endpoint \
EVM_PAYMENT_TOKEN_ADDRESS=0x... \
EVM_PAYMENT_VAULT_ADDRESS=0x... \
./target/release/antdIf antd is already on your PATH, replace ./target/release/antd with antd.
Use EVM_PAYMENT_VAULT_ADDRESS for both wave-batch and Merkle uploads in the external-signer flow.
2. Prepare the upload
For in-memory data, call POST /v1/data/prepare.
The in-memory data prepare endpoint supports only private uploads: visibility is accepted but "public" returns 501. To prepare a public upload with an external signer, use POST /v1/upload/prepare with a file path and "visibility":"public" instead.
The prepare endpoints return a payment_type discriminator. Use that value to decide which on-chain call to make and which finalize payload to send back.
The daemon returns wave_batch for uploads under 64 chunks and merkle for uploads with 64 or more chunks.
Wave-batch prepare response:
Merkle prepare response:
Each pool_commitments entry contains exactly 16 candidate payments. The sample above shows one candidate for brevity.
For file uploads, the equivalent is POST /v1/upload/prepare with a local path field instead of data. To make the upload publicly retrievable by address, add "visibility":"public" to the prepare request — the daemon bundles the serialized DataMap chunk into the same payment batch, and the finalize response includes a data_map_address field with its network address.
3. Submit the payment externally
Use your signer stack to submit the EVM payment transaction described by the prepare response.
antd does not sign or broadcast those transactions in this flow.
For
wave_batch, callpayForQuotes()with the returnedpaymentsand keep the resulting transaction hashes keyed byquote_hash.For
merkle, callpayForMerkleTree()withdepth,pool_commitments, andmerkle_payment_timestamp, then keep thewinner_pool_hashfrom theMerklePaymentMadeevent.
Both calls use the payment_vault_address returned by the prepare step.
4. Finalize the upload
After the external payment is on-chain, call POST /v1/upload/finalize with the matching fields for the prepared upload.
Wave-batch finalize request:
Merkle finalize request:
Expected response shape:
address is only present when store_data_map is true; that path uses the daemon's own wallet to store the DataMap. data_map_address is only present when the upload was prepared with visibility:"public" — it is the network address of the DataMap chunk whose payment was included in the same external-signer batch.
5. Use SDK helpers when available
The daemon SDKs follow the same prepare/finalize split. Merkle-capable bindings expose payment_type on prepare results and a finalize_merkle_upload helper for the Merkle path.
Use the REST API when you need the full finalize response surface, such as the raw data_map value or explicit store_data_map control on wave-batch finalize requests.
If you are building in Rust with ant-core instead of the daemon, the library exposes native external-payment helpers such as data_prepare_upload, data_prepare_upload_with_visibility, file_prepare_upload, prepare_merkle_batch_external, and finalize_merkle_batch. Use data_prepare_upload_with_visibility(content, Visibility::Public) to bundle the DataMap chunk into the payment batch for a public in-memory upload. Progress-aware variants such as file_prepare_upload_with_progress, finalize_upload_with_progress, and finalize_upload_merkle_with_progress are also available when you need UI feedback during long-running uploads.
Verify it worked
Finalize succeeds when the daemon accepts the upload_id plus either the tx_hashes map or the winner_pool_hash, then returns upload metadata. If you requested store_data_map: true, you can retrieve the stored content again through the returned address.
Common errors
404 Not Found: The upload_id is missing, expired, or already finalized.
400 Bad Request: Check whether the prepared upload expects tx_hashes or winner_pool_hash, and validate the hex formatting of those values.
503 Service Unavailable: You accidentally started the daemon in direct-wallet mode or without the required network configuration.
Next steps
Last updated