Add port discovery for automatic daemon detection#13
Open
Nic-dorman wants to merge 20 commits intomainfrom
Open
Add port discovery for automatic daemon detection#13Nic-dorman wants to merge 20 commits intomainfrom
Nic-dorman wants to merge 20 commits intomainfrom
Conversation
antd now writes a daemon.port file on startup containing the REST and gRPC ports, enabling all SDK clients to auto-discover the daemon without hardcoded URLs. This supports managed mode where antd is spawned with --rest-port 0 for OS-assigned ports. Changes: - antd (Rust): port file lifecycle (atomic write/cleanup), --rest-port and --grpc-port CLI flags, pre-bound listeners for both servers - All 15 SDKs: discover module + auto-discover constructors for REST and gRPC clients - Default REST port corrected from 8080 to 8082 across all SDKs - ant-dev CLI: status/wallet/start commands use port-file discovery - Docs: README, llms.txt, llms-full.txt, skill.md updated Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Windows: remove target before rename (fs::rename fails if target exists on Windows, unlike Unix atomic replace) - Stale port file detection: antd now writes its PID as line 3 of the port file. Go SDK checks if the process is still alive before trusting the discovered ports (platform-specific: signal 0 on Unix, FindProcess on Windows) - Split Go processAlive into discover_unix.go / discover_windows.go with build tags for clean cross-compilation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
antd now writes its PID as line 3 of the port file. All SDKs validate
the PID before trusting discovered ports, preventing connections to
dead daemons after crashes.
Platform-specific approaches per language:
- Go: signal 0 (Unix), FindProcess (Windows) via build tags
- Python/MCP: os.kill(pid, 0) — cross-platform on Python 3
- Rust: kill -0 (Unix), tasklist (Windows) via cfg
- Java/Kotlin: ProcessHandle.of(pid).isPresent() — cross-platform
- C#: Process.GetProcessById — cross-platform on .NET 8+
- TypeScript: process.kill(pid, 0) — cross-platform in Node.js
- C++: kill(pid, 0) (Unix), OpenProcess (Windows) via ifdef
- Ruby: Process.kill(0, pid) — cross-platform
- Elixir: System.cmd("kill", ["-0", pid]) on Unix, trust on Windows
- Swift: kill(pid_t, 0) via C interop
- Dart: kill -0 on Unix, trust on Windows
- Lua: os.execute("kill -0") on Unix, trust on Windows
- PHP: posix_kill or /proc check on Unix, tasklist on Windows
- Zig: /proc check on Linux, trust on other platforms
All backward-compatible with 2-line port files (no PID).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CORS: Restrict allowed origin to http://127.0.0.1:{port} instead of permissive Any. Prevents cross-origin CSRF from malicious webpages. Non-browser clients (SDKs, CLI, AI agents) are unaffected as they don't send Origin headers. Matches approach from ant-client. Wallet: Add GET /v1/wallet/address and GET /v1/wallet/balance REST endpoints to antd. Returns 400 if no EVM wallet is configured. Also adds NotImplemented error variant (HTTP 501 / gRPC UNIMPLEMENTED) for stubbed endpoints. SDK bindings added for wallet_address() and wallet_balance() across all 15 language SDKs + MCP server (2 new MCP tools). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This was referenced Mar 25, 2026
Replace direct ant-node protocol handling with ant-core's high-level Client API. This eliminates ~200 lines of manual chunk orchestration (quote collection, payment proof building, protocol message encoding) and unblocks future data/file endpoint implementation. Changes: - Cargo.toml: ant-node path dep replaced with ant-core git dep - state.rs: AppState holds ant_core::data::Client instead of raw P2PNode + Wallet - main.rs: Construct Client::from_node().with_wallet() - chunks.rs: chunk_put/chunk_get use Client methods directly - grpc/service.rs: Same refactor for gRPC chunk handlers - error.rs: AntdError::from_core() replaces From<ProtocolError> - wallet.rs: Access wallet via client.wallet() Zero ant_node references remain in antd source code. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds optional payment_mode ("auto", "merkle", "single") to all data
and file upload methods across antd and all 15 SDKs.
antd types:
- DataPutRequest and FileUploadRequest now accept payment_mode
- DataPutPublicResponse returns chunks_stored and payment_mode_used
- parse_payment_mode/format_payment_mode helpers added
Data and file endpoints remain stubs (501 Not Implemented) due to an
upstream lifetime issue in ant-core's stream closures that prevents
the Client methods from being called in async axum handlers. The types
and parameter plumbing are in place for when ant-core is fixed.
AppState.client wrapped in Arc<Client> for Send + Sync compatibility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
With the upstream HRTB lifetime fix (ant-client#8), ant-core's Client
methods can now be called from async axum handlers via tokio::spawn.
Implemented endpoints:
- POST /v1/data/public — upload with self-encryption + merkle payments
- GET /v1/data/public/{addr} — download via data map
- POST /v1/data/private — upload, return data map to caller
- GET /v1/data/private — download using caller-provided data map
- POST /v1/files/upload/public — stream-encrypt file from disk
- POST /v1/files/download/public — download file to disk
- POST /v1/dirs/upload/public — upload directory
- POST /v1/dirs/download/public — download directory
All upload endpoints accept optional payment_mode parameter
("auto"/"merkle"/"single"). Default is "auto" which uses merkle
batch payments for 64+ chunks.
Still stubbed (501): archives, cost estimation, data streaming.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…d endpoints - MCP: store_data and upload_file tools now accept payment_mode parameter - README: Add Payment Modes section explaining auto/merkle/single - llms.txt: Document payment_mode on data/file PUT endpoints - llms-full.txt: Add Payment Modes section with SDK examples - skill.md: Add merkle guidance to data storage pattern - antd-go/README.md: Add payment mode configuration examples - antd-mcp/README.md: Update tool table and add Payment Modes section Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
antd: - Data cost: encrypts data to determine chunks, queries network for storage quotes, sums prices (skips already-stored chunks) - File cost: same approach for files on disk - Wallet approve: POST /v1/wallet/approve calls approve_token_spend() to authorize payment contracts (one-time before storage) - Added self_encryption dependency for cost estimation chunking SDK bindings added for wallet_approve() across all 15 languages + MCP. Documentation updated (llms.txt, llms-full.txt, skill.md, READMEs). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When antd is started without AUTONOMI_WALLET_KEY, write operations (chunk put, data put, file upload, wallet endpoints) now return 503 Service Unavailable instead of 400 Bad Request or 402 Payment Required. This correctly signals a server configuration issue rather than a client error — the request is valid but the server can't fulfil it without a wallet. - antd: Added ServiceUnavailable error variant (503 / gRPC UNAVAILABLE) - All 15 SDKs: Added ServiceUnavailableError exception type, mapped 503 - Docs: Updated error tables in llms.txt, llms-full.txt, skill.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Swift fixes: - AntdClientProtocol: add paymentMode parameter to 4 upload methods - AntdClient factory: default port 8080 → 8082 - AntdGrpcClient: add missing walletApprove stub Kotlin fixes: - AntdClient factory: default port 8080 → 8082 - AntdGrpcClient: add missing walletApprove stub Port 8080 → 8082 sweep across all remaining files: - Factory classes (C# AntdClientFactory, Java AsyncAntdClient) - READMEs (all 15 SDKs + antd) - OpenAPI spec, test scripts, examples, quickstart docs - Architecture docs Zero 8080 references remain in the repo. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The FFI was depending on the v1 autonomi crate (from maidsafe/autonomi) which has a completely different API, payment model, and type system from the v2 ant-core used by antd and all REST/gRPC SDKs. Fresh rewrite targeting ant-core: - client.rs: Client with connect(), connect_local(), connect_with_wallet() constructors. chunk_put/get, data_put/get (public+private), file_upload/download, wallet_approve — all using ant-core Client. - wallet.rs: Wallet with from_private_key(), address(), balance methods. - data.rs: PaymentMode parsing helpers shared with client. - lib.rs: UniFFI result types and error mapping from ant-core errors. Removed v1 modules (no equivalent in ant-core yet): - keys.rs, key_derivation.rs (BLS key operations) - graph.rs (graph entries not in ant-core) - files.rs (archive types not in ant-core) - network.rs, payment.rs (replaced by simpler wallet.rs) Payment model simplified: v1 required PaymentOption on every write call. v2 configures wallet at init time, handles payment internally, and supports payment_mode (auto/merkle/single). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- README: Remove outdated prerequisite to clone maidsafe/autonomi repo (antd now uses ant-core via git dependency, no sibling clone needed) - Ruby gemspec: Update author/email from MaidSafe to WithAutonomi Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enables applications like indelible to manage their own wallet keys without passing private keys to antd. The upload flow is split into prepare (encrypt + collect quotes) and finalize (submit proofs after external payment). antd changes: - POST /v1/upload/prepare — encrypts file, collects quotes, returns PaymentIntent with quote hashes, amounts, contract addresses, RPC URL - POST /v1/upload/finalize — accepts tx_hash map, builds proofs, uploads chunks, returns address - AppState holds pending uploads in-memory (server-side state since PreparedUpload contains non-serializable P2P types) - main.rs: configure EVM network even without wallet (with_evm_network) so prepare works in external-signer-only mode - Updated ant-core to b9c08d61 (includes PR #10 external signer) SDK bindings: prepare_upload() and finalize_upload() added to all 15 language SDKs + 2 new MCP tools. Docs updated. No private key crosses the REST API — the key stays in the external signer (WalletConnect, HSM, app key store). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
antd README: - Complete rewrite reflecting current state: ant-core dependency, port discovery, external signer endpoints, wallet/EVM config - Fixed stale references: antctl → ant dev, ANT_PEERS → ANTD_PEERS - Added all new endpoints: wallet, upload prepare/finalize, cost - Added --rest-port/--grpc-port flags, external signer mode docs - Corrected endpoint paths to match actual routes - Updated project structure (port_file.rs, upload.rs, wallet.rs) - Marked graph and archive endpoints as stubs Root README: - Added ant-node as prerequisite for local testnet Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
antd was passing None for merkle_payments_address to evmlib::Network::new_custom, which meant merkle batch payments couldn't work on local testnets. The devnet manifest includes the merkle contract address but it wasn't being forwarded. Fixes: - antd main.rs: read EVM_MERKLE_PAYMENTS_ADDRESS env var, pass to Network::new_custom (both wallet and external-signer paths) - scripts/start-local.sh: extract merkle_payments_address from devnet manifest, pass as env var - scripts/start-local.ps1: same - ant-dev cmd_start.py: pass all EVM env vars (was only passing ANTD_PEERS and AUTONOMI_WALLET_KEY — missing rpc_url, token addr, payments addr, and merkle addr) - antd README: document EVM_MERKLE_PAYMENTS_ADDRESS Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The wallet private key was being: - Written to ~/.ant-dev/state.json in plaintext - Printed (first 10 chars) to console on startup - Displayed in full via `ant dev wallet show` While these are ephemeral Anvil test keys on local devnet, the pattern is unsafe if someone uses a real key. Fixes: - State file: store "wallet_configured": true instead of the key - Console: show "Wallet: configured" instead of key prefix - `ant dev wallet show`: queries antd for address/balance via REST instead of reading the key from state - Scripts: same change for start-local.sh and start-local.ps1 The private key remains only in the AUTONOMI_WALLET_KEY env var passed to the antd process — it never touches disk or console. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
With ant-core PR #15 merged (data_prepare_upload), the external signer flow now works for both files and raw data. antd: - POST /v1/data/prepare: accepts base64 data, encrypts, collects quotes, returns PaymentIntent (same response as /v1/upload/prepare) - Uses same finalize endpoint (POST /v1/upload/finalize) - Updated ant-core to 7bcb6cbc (includes data_prepare_upload) SDK bindings: prepare_data_upload() added across all 15 languages + MCP server. Returns same PrepareUploadResult type — finalize_upload() works for both file and data uploads unchanged. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FFI now exposes the two-phase upload flow for Android/iOS apps that manage their own wallet keys: - prepare_data_upload(data) — encrypt + collect quotes, returns PaymentEntry list with quote hashes, amounts, addresses - prepare_file_upload(path) — same for files on disk - finalize_upload(upload_id, tx_hashes) — build proofs + store chunks PreparedUpload state held in-process via Mutex<HashMap> since it contains non-serializable P2P types (same pattern as antd). New types: PaymentEntry, PrepareUploadResult, FinalizeUploadResult. Updated ant-core to 7bcb6cbc. Added rand dependency for upload IDs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Graph entries (DAG nodes) are being removed from the initial launch scope. This removes all graph functionality across the entire SDK: - antd: REST routes, gRPC service, handler, types, proto file, build.rs - All 15 SDK clients: REST + gRPC methods, model types - MCP server: 4 graph tools removed - Tests: graph test cases removed across Go, Python, Rust, Java, C#, Dart, Ruby, Lua, PHP - Examples: graph example files deleted (Python, TypeScript, Java, C#, Dart, Kotlin, Lua) - Docs: graph removed from llms.txt, llms-full.txt, skill.md, architecture.md, all quickstart guides, data primitives table - Scripts: graph test steps removed from test-api.sh/.ps1 - Proto: graph.proto and generated Go bindings deleted Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
daemon.portfile on startup (atomic write via temp+rename), cleans up on shutdown. Adds--rest-port/--grpc-portCLI flags supporting--rest-port 0for OS-assigned dynamic ports. Pre-binds both REST and gRPC listeners to capture actual ports before serving.%APPDATA%\ant\on Windows,~/.local/share/ant/on Linux,~/Library/Application Support/ant/on macOS).status,wallet, andstartcommands now use port-file discovery.Port file format is two lines (REST port, gRPC port). Single-line files are forward-compatible (gRPC falls back to default 50051).
Enables managed mode for consumers like indelible that spawn antd as a child process with a dynamic port.
Test plan
cargo checkpasses for antd (Rust)go test ./...passes for antd-go (8 discovery tests + existing suite)daemon.portfile written--rest-port 0, verify auto-discover connects🤖 Generated with Claude Code