diff --git a/content/foundations/meta.json b/content/foundations/meta.json index 935015f45..23485dacc 100644 --- a/content/foundations/meta.json +++ b/content/foundations/meta.json @@ -17,7 +17,6 @@ "limits", "config", "network", - "web3", "proofs", "system", "precompiled", diff --git a/content/foundations/web3/meta.json b/content/foundations/web3/meta.json index 423ef23f1..1d3f31208 100644 --- a/content/foundations/web3/meta.json +++ b/content/foundations/web3/meta.json @@ -6,6 +6,8 @@ "ton-dns", "ton-storage", "ton-proxy", - "ton-sites" + "ton-tunnel", + "ton-sites", + "payment-network" ] } diff --git a/content/foundations/web3/overview.mdx b/content/foundations/web3/overview.mdx index 8ed37f33c..dcf849b8a 100644 --- a/content/foundations/web3/overview.mdx +++ b/content/foundations/web3/overview.mdx @@ -3,52 +3,63 @@ title: "Web3 services" sidebarTitle: "Overview" --- -Although many people refer to TON only as a blockchain, _The Open Network_ is a combination of the following components: +The Open Network (TON) combines a blockchain with a peer-to-peer network and services for naming, file storage, web access, and off-chain payments. Applications can use these components together or select the ones they need. -- A flexible multi-blockchain platform with Turing-complete smart contracts (TON Blockchain) -- A peer-to-peer network used by Blockchain Nodes (TON Network) -- A distributed file storage technology (TON Storage) -- A network proxy/anonymizer layer (TON Proxy) -- A Kademlia-like distributed hash table (TON DHT) -- A service for assigning human-readable names to accounts, smart contracts, services, and network nodes (TON DNS) -- A platform for micro-payments (TON Payments) - -This article provides a general overview of TON Services, beyond the blockchain. +Smart contracts manage on-chain state and enforce contract rules. Files, HTTP requests, and application processing can remain off-chain. For example, a website can serve its content over the TON network, use an on-chain domain record, and accept payments through payment channels. ## TON Network -TON Network is a peer-to-peer network used for accessing the TON Blockchain, sending transactions, and receiving updates. Also, it can support arbitrary distributed services, blockchain-related or not. The cornerstone in TON networking is the ADNL protocol, built on top of the TCP/UDP stack. +The TON network carries communication between blockchain nodes and supports services beyond the blockchain. + +The [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl) identifies peers by cryptographic addresses and provides encrypted communication. The [distributed hash table (DHT)](/foundations/network/dht) helps locate peers and discover nodes participating in services such as TON Storage. -The TON Distributed Hash Table (DHT) plays a crucial role in the networking component of the TON Project, as it is used to locate other nodes in the network. You can think of it as a big, persistent key-value data storage. The keys of the TON DHT are simply 256-bit integers. In most cases, they are computed as sha256 hashes of a TL-serialized objects. The values assigned to these 256-bit keys are essentially arbitrary byte strings of limited length. +These networking components let applications exchange data without recording each exchange as a blockchain transaction. adnl +## TON DNS + +[TON DNS](/foundations/web3/ton-dns) associates human-readable domain names with addresses and services. Records stored in smart contracts can identify payment recipients, TON Sites, files on TON Storage, or another resolver responsible for subdomains. + +A domain such as `example.ton` can have several records for different purposes. Applications request the record they need, then use the returned address or content identifier to access the destination. + ## TON Storage -[TON Storage](/foundations/web3/ton-storage) allows users to share and store files using _The Open Network_. Since storing files on-chain isn't practical, TON Storage only stores Merkle proofs for file content on-chain. It uses TON DHT to find the nodes that have a copy of a required file (e.g., a snapshot of the state of a shardchain, or an old block). Then, one might essentially create a torrent for this file and use TON DHT as a "distributed torrent tracker" for this torrent. +[TON Storage](/foundations/web3/ton-storage) distributes files between peers. Files are grouped into a bag, identified by a BagID, which allows recipients to verify the downloaded content. The files remain on peers' disks. + +Sharing files does not require an on-chain transaction. Optional storage contracts let clients pay providers to retain data and submit storage proofs. File availability still depends on peers retaining and serving the content. ## TON Proxy -[TON Proxy](/foundations/web3/ton-proxy) provides a protocol where nodes wishing to offer their services (with or without compensation) as tunnels for ADNL network traffic can register. Those needing them can then choose one of these nodes based on the price, latency, and bandwidth offered. Since ADNL traffic is encrypted, Proxy can't access tunneled data, meaning that this protocol is secure. +[TON Proxy](/foundations/web3/ton-proxy) connects HTTP clients and servers through the TON network. -Running TON Proxy allows you to visit [TON Sites](/foundations/web3/ton-sites) (HTTP over ADNL). This can be combined with TON DNS and other TON Services, forming together what is called "Open Network". +A forward proxy accepts requests from a browser or another HTTP client and sends them over the Reliable Large Datagram Protocol (RLDP), which runs over ADNL. A reverse proxy receives these requests and forwards them to an HTTP server. -## TON DNS +Compatible forward proxies also provide access to files on TON Storage. + +## TON Tunnel + +[TON Tunnel](/foundations/web3/ton-tunnel) routes ADNL traffic through intermediate nodes. Applications with tunnel support can use relays instead of communicating directly from their own network endpoints. + +Relays can forward traffic for free or charge through TON Payment Network. Tunnel routing applies to the traffic sent through the application's integration. + +## TON Sites -[TON DNS](/foundations/web3/ton-dns) is a service that translates human-readable domain names like `test.ton` or `mysite.temp.ton` into TON smart contract addresses, ADNL addresses used by services on the TON Network such as TON Sites, and more. The standard is implemented using smart contracts and config parameters. +[TON Sites](/foundations/web3/ton-sites) are websites and HTTP applications accessible through the TON network. They can be published in two ways: -TON Domain names are well-established in the ecosystem - various wallet applications and explorers recognize them. +- Connect an HTTP server through a reverse proxy to serve static files or dynamically generated responses. +- Publish static files as a bag on TON Storage. -TON Domains can be assigned to any ADNL address, meaning that it is possible to assign names to TON Storage files (bags). +TON DNS can associate a domain with either the reverse proxy's ADNL address or the storage BagID. Visitors access the site through a compatible client or a browser configured with a forward proxy. ## TON Payments -TON Payments platform enables "instant payments" - a way to transfer monetary values without the need to commit all transactions to the blockchain. This protocol is built on top of TON Blockchain, using a system of smart contracts. +[TON Payment Network](/foundations/web3/payment-network) supports off-chain payments through interconnected payment channels. -The core idea for such a "lightning network" is point-to-point **payment channels**. Two parties create a shared "money pool" and then update the balance inside it. +Participants fund channels on-chain, then exchange signed state updates without submitting each payment to the blockchain. Smart contracts provide settlement and dispute procedures. Payments can also pass through intermediate nodes when a route has sufficient capacity. -The overall overhead of such instant payments is so small that one can use them for micro-payments. For example, a TON file-storing service might charge the user for every 128 KiB of downloaded data, or a paid TON Proxy might require some tiny micro-payment for every 128 KiB of traffic relayed. +Applications can use these channels for repeated small payments, including payments to TON Tunnel relays. diff --git a/content/foundations/web3/payment-network/browser.mdx b/content/foundations/web3/payment-network/browser.mdx new file mode 100644 index 000000000..e7f03a374 --- /dev/null +++ b/content/foundations/web3/payment-network/browser.mdx @@ -0,0 +1,90 @@ +--- +title: "How to run Payment Network in a browser" +sidebarTitle: "Run in a browser" +description: "Build the supplied WebAssembly example and connect it to a payment node" +--- + +Build the browser example included in TON Payment Network v1.3.2 and connect it to a payment node. The example includes wallet callbacks, browser storage, and channel controls. + +## Prerequisites + +- The v1.3.2 repository and a configured mainnet node from [Run a payment node](/foundations/web3/payment-network/run-node) +- [Go 1.26.1](https://go.dev/dl/), [Node.js 22.23.2](https://nodejs.org/en/download), and npm 10.9.8 for the build below +- A mainnet wallet compatible with [TON Connect](/applications/ton-connect/how-to/connect) for the interactive channel workflow + +The commands require a POSIX shell. The build below uses the standard Go compiler and its matching JavaScript runtime. The repository also provides TinyGo build targets; do not mix their runtime files with this build. + + + The client stores configuration and private keys in localStorage and channel state in IndexedDB, associated with the wallet address. Preserve the browser profile and origin while channels are active. Clearing site data can remove state needed to continue or settle channels; connecting the same wallet in another browser does not restore it. + + +## Enable the node's web transport + +Stop the payment node and set [`WebTransportListenAddr`](/foundations/web3/payment-network/reference#configuration-fields) to `127.0.0.1:7161` in its existing configuration. Preserve its keys, network, and database settings, then restart it. + +From the repository root, print its public browser initializer with [`-web-conn-info`](/foundations/web3/payment-network/reference#cli-options): + +```bash +./build/payment-node -config payment-network-config.json -web-conn-info +``` + +Copy the two public keys into the `window.startPaymentNetwork(...)` call in `cmd/web/web-payments-frontend/src/App.tsx`, replacing the bundled demonstration keys. The first key identifies the node's [Abstract Datagram Network Layer (ADNL) transport](/foundations/network/adnl-udp); the second identifies its payment node. + +The supplied `src/setupProxy.js` forwards `/web-channel/api/` requests to `http://localhost:7161`. This is the node's web transport, not its administration API. + +## Run the example locally + +From the repository root: + +```bash +GOOS=js GOARCH=wasm go build -o cmd/web/web-payments-frontend/public/web.wasm ./cmd/web +cp "$(go env GOROOT)/lib/wasm/wasm_exec.js" cmd/web/web-payments-frontend/public/wasm_exec.js +cd cmd/web/web-payments-frontend +npm ci --legacy-peer-deps +``` + +Set the URLs in `public/tonconnect-manifest.json` to match the served application, then start the local development server with its API forwarding: + +```bash +PORT=3001 npm start +``` + +Open `http://localhost:3001`. For a wallet on another device, use a reachable deployment and manifest URL following the [TON Connect setup guide](/applications/ton-connect/how-to/connect); that wallet cannot reach the development computer through its own `localhost`. + +The example also contains demonstration asset and trading settings. Review them before enabling assets or deploying the application; they are not a list of supported mainnet assets for the node. + +## Build for production (optional) + + + +After setting the deployment URLs in `public/tonconnect-manifest.json`, run from the frontend directory: + +```bash +npm run build +``` + +The output is written to `build/`. The static build does not include `src/setupProxy.js`; configure `/web-channel/api/` forwarding to the node's web transport separately on the deployment. + +## Verify + +Check that `web.wasm` and `wasm_exec.js` load successfully. With a connected wallet, the page starts the payment node and displays channel information. Ensure that the wallet and backend node use mainnet before requesting an on-chain action. + + + Mainnet transactions are irreversible. Verify the destination and amount before confirming in the wallet. + + +Use the example's channel controls to open and fund a channel and send a payment. Check wallet transaction details before confirming, then inspect the resulting channel balances. + +## Troubleshoot + +| Problem | Check | +| ------------------------------------------ | ----------------------------------------------------------------------- | +| WebAssembly fails to load | Build `web.wasm` and copy `wasm_exec.js` from the same Go installation. | +| Browser cannot reach the payment node | Check the web transport listener and `/web-channel/api/` forwarding. | +| Peer authentication or channel setup fails | Replace both bundled keys with values from the node's initializer. | +| Wallet rejects the application manifest | Check that its URLs match a deployment reachable by the wallet. | diff --git a/content/foundations/web3/payment-network/channels.mdx b/content/foundations/web3/payment-network/channels.mdx new file mode 100644 index 000000000..4d81247d5 --- /dev/null +++ b/content/foundations/web3/payment-network/channels.mdx @@ -0,0 +1,86 @@ +--- +title: "Payment channels and routed payments" +sidebarTitle: "Channels and routing" +description: "Signed states, payment capacity, virtual channels, and on-chain settlement" +--- + +TON Payment Network records payments as signed commitments between participants. Funds held in smart contracts back those commitments, while virtual channels extend payments across a route of connected participants. + +## Channel participants and funds + +A payment channel connects two payment nodes. Each participant has a wallet for funding and a channel contract for on-chain operations. The nodes exchange and store signed states off-chain; the contracts enforce settlement on-chain. + +[Channel initialization](/foundations/web3/payment-network/use-channels#initialize-the-channel) first establishes the participants' signed configuration. Deployment, activation, and deposits involve blockchain transactions. An initialized off-chain channel is therefore different from a funded channel ready for payments. + +The node's wallet balance is separate from its channel funds. Adding funds to the wallet does not itself increase a channel's capacity unless the node deposits those funds into the channel. + +## Signed states and available capacity + +An agreed channel state includes a sequence number and commitments to each participant's conditional obligations and actions. Both participants sign the state. Subsequent updates advance the sequence number, allowing settlement to distinguish newer agreements from older ones. + +Conditional obligations reserve funds for payments whose final amount or settlement is still pending. Actions describe operations such as transfers that the contract can execute. Signed commitments allow these obligations to change without submitting every update to the blockchain. + +Available outgoing capacity accounts for deposits, action balances, funds on hold, and capacity reserved for conditionals. A wallet balance or on-chain deposit alone does not describe how much the node can spend through a channel. + +For example, assume a participant has 3 GRAM in a channel, no action balance adjustments, and 1 GRAM reserved for a conditional payment. With no other holds, 2 GRAM remains available for further commitments. This illustrates capacity accounting, not a required deposit amount. + +Capacity is directional. Sending through a peer uses local outgoing capacity; receiving through that peer requires capacity on its side. Each [asset](/foundations/web3/payment-network/reference#assets-and-amounts) has its own balance accounting and acceptance policy. + +The node preserves signed states and their associated action and conditional data in its database. Keeping both this data and the private keys is necessary to continue operating the channel and participate in settlement. + +## Routed payments and virtual channels + +A sender does not need a direct funded channel with every recipient. A virtual channel connects the sender and recipient through conditional commitments in existing channels. + +```mermaid +flowchart LR + A[Alice] -->|Existing channel| M[Intermediary] + M -->|Existing channel| B[Bob] + A -. Virtual channel .-> B +``` + +In this route, Alice needs outgoing capacity toward the intermediary, and the intermediary needs outgoing capacity toward Bob. Opening the virtual channel reserves the required capacity along the route, including the agreed fees. It does not deploy a new channel contract between Alice and Bob. + +Each intermediary accepts forwarding terms and a deadline for its conditional commitment. The route must leave enough time for settlement under the underlying channels' closure rules. A route can fail even when the sender's wallet is funded: a required channel, asset, or outgoing capacity may be unavailable. + +An intermediary can charge for [providing capacity](/foundations/web3/payment-network/use-channels#send-a-payment). These fees are separate from blockchain transaction fees. + +## Repeated payments and virtual-channel settlement + +A reusable virtual channel has a capacity, a deadline, and a signing key. The sender signs states containing the cumulative payment amount. A valid update cannot reduce that amount or exceed the channel's capacity. + +The recipient receives the signed state, not the sender's private signing key. + +To settle, the recipient supplies the signed state. The nodes validate it and convert the signed amount into a transfer commitment, accounting for the agreed fees and any prepayment. This updates the balances calculated off-chain without an immediate blockchain transfer. The resulting balances determine the capacity available for subsequent payments. + +Settling a virtual channel does not close the underlying payment channels. The one-shot transfer flow settles its virtual payment automatically; a reusable virtual channel allows successive signed updates before settlement. Command semantics are in [Virtual-channel commands](/foundations/web3/payment-network/reference#virtual-channel-commands). + +[TON Tunnel](/foundations/web3/ton-tunnel/architecture#traffic-payments) uses virtual-channel updates to prepay relay traffic. Packet-credit accounting belongs to Tunnel rather than the payment-channel protocol. + +## On-chain settlement and closure + +Off-chain settlement updates the participants' agreed balances. Executing payment actions, closing the channel, and withdrawing remaining funds are separate operations. + +When the participants cooperate, both sign the required operation. A cooperative commit executes agreed actions on-chain; cooperative closure ends the channel. These are distinct operations. + +Without cooperation, a participant can initiate closure using the supported signed state. The contract enters a quarantine period during which a newer valid state can challenge an older submission. Conditional settlement and action execution then follow the contract's deadlines before final closure. + +```mermaid +flowchart TD + O[Open channel] -->|Both participants cooperate| C[Cooperative closure] + O -->|Unilateral request| Q[Quarantine and state challenges] + Q --> S[Conditional settlement] + S --> A[Action execution and final closure] +``` + +The [unilateral process](/foundations/web3/payment-network/use-channels#close-the-channel) requires the relevant state and action data, transaction fees, and timely processing of [settlement steps](/foundations/web3/payment-network/reference#closure-settings). Submitting a closure request does not mean the funds have already returned. + +## Sources + +- [Channel operations and virtual-channel settlement](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/tonpayments/api.go#L366-L550) +- [Channel state updates and signatures](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/tonpayments/state.go#L754-L797) +- [Channel structures and available balance calculation](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/pkg/payments/types.go#L497-L521) +- [Off-chain channel balance accounting](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/tonpayments/db/types.go#L285-L386) +- [Virtual-channel states, capacity checks, and execution](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/pkg/payments/conditionals/channel.go#L415-L623) +- [Conditional settlement dispatch](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/tonpayments/conditional_settlement.go#L11-L22) +- [Universal channel contract](https://github.com/xssnick/payment-channel-contract/blob/9704af6a04b4dfedebb56f4261a07bd5578b667d/contracts/universal/payment-channel-contract.tolk#L180-L312) diff --git a/content/foundations/web3/payment-network/index.mdx b/content/foundations/web3/payment-network/index.mdx new file mode 100644 index 000000000..eaff4d348 --- /dev/null +++ b/content/foundations/web3/payment-network/index.mdx @@ -0,0 +1,41 @@ +--- +title: "TON Payment Network overview" +sidebarTitle: "Overview" +description: "Off-chain payments through interconnected payment channels on TON" +--- + +TON Payment Network enables participants to exchange payments off-chain through interconnected payment channels. [Smart contracts](/foundations/glossary#smart-contract) on TON secure the funds and provide mechanisms for on-chain settlement. + +## Payment channels + +A payment channel connects two participants. They exchange signed state updates to account for payments without submitting each payment as a separate blockchain transaction. + +Funding and settlement involve on-chain operations. Participants can withdraw funds or close channels through the supported contract procedures. When the parties cannot cooperate, settlement follows the contract's dispute process and deadlines. + +A node's wallet balance is separate from the funds available in its payment channels. + +## Routed payments + +Participants can pay through intermediate nodes instead of opening a direct channel with every recipient. Virtual channels connect the participants across a route of existing channels. + +A route needs sufficient available capacity for the selected asset. Intermediaries can charge fees for providing this capacity and forwarding payments. + +## Assets and fees + +The implementation supports the native currency, [jettons](/contracts/standard/tokens/jettons/overview), and extra-currencies. Each node configures the assets it accepts and their associated fees and limits. Support for an asset does not guarantee that a suitable funded route is available. + +Off-chain payments avoid a blockchain transaction for each payment, but are not necessarily free. Node fees and on-chain transaction fees are separate costs. + +## Applications + +The implementation provides a standalone Go node, an HTTP API, and a WebAssembly client that can run in a browser. + +[TON Tunnel](/foundations/web3/ton-tunnel) uses Payment Network to pay relays for traffic. Channel operations are covered in this section; relay pricing and configuration are covered in [Run a relay](/foundations/web3/ton-tunnel/run-relay#configure-prices). + +[Payment processing](/applications/payments/overview) covers monitoring ordinary blockchain deposits and withdrawals. + +## Next steps + +- [Run a payment node](/foundations/web3/payment-network/run-node) to connect to Payment Network. +- [Use payment channels](/foundations/web3/payment-network/use-channels) to fund channels, send payments, and withdraw funds. +- [Run in a browser](/foundations/web3/payment-network/browser) to use the WebAssembly implementation. diff --git a/content/foundations/web3/payment-network/meta.json b/content/foundations/web3/payment-network/meta.json new file mode 100644 index 000000000..a8a65f2d6 --- /dev/null +++ b/content/foundations/web3/payment-network/meta.json @@ -0,0 +1,12 @@ +{ + "$schema": "../../../../meta-schema.json", + "title": "TON Payment Network", + "pages": [ + "index", + "channels", + "run-node", + "use-channels", + "browser", + "reference" + ] +} diff --git a/content/foundations/web3/payment-network/reference.mdx b/content/foundations/web3/payment-network/reference.mdx new file mode 100644 index 000000000..46ed5d147 --- /dev/null +++ b/content/foundations/web3/payment-network/reference.mdx @@ -0,0 +1,143 @@ +--- +title: "TON Payment Network reference" +sidebarTitle: "Reference" +description: "Node settings, CLI commands, API routes, and contract versions" +--- + +This reference describes the standalone node and browser example in TON Payment Network v1.3.2. Amount formats and identifiers differ between console commands and API requests. + +## Identifiers + +| Identifier | Use | +| ---------------------------- | -------------------------------------------------------------------------------- | +| Payment-node public key | Base64-encoded 32-byte key used by console commands to select a peer or route | +| ADNL transport public key | Network identity; first argument of the browser initializer | +| Wallet address | Receives on-chain funds for the node | +| Local channel address | Address shown as `address` by `list`; use for local channel operations | +| Peer-side channel address | Shown as `their_address`; not interchangeable with the local address | +| Virtual-channel private key | Base64-encoded 32-byte signing seed returned by `open`; keep secret | +| Signed virtual-channel state | Console `signed_state`: base64-encoded payment state encrypted for the recipient | + +## Node configuration + +### Configuration fields + +| Field | Purpose and generated default | +| ------------------------------ | ------------------------------------------------------------ | +| `NetworkConfigUrl` | Mainnet global configuration URL by default | +| `NodeListenAddr` | UDP listener; `0.0.0.0:17555` | +| `ExternalIP` | Advertised IPv4 address; empty for outbound mode | +| `DBPath` | Persistent channel state; `./payment-node-db` | +| `PaymentNodePrivateKey` | Payment identity's private seed | +| `ADNLServerKey` | Private seed for network transport | +| `WalletPrivateKey` | Private seed for the funding wallet | +| `ChannelConfig.SupportedCoins` | Assets, fees, capacity policy, and automatic balance control | +| `WebTransportListenAddr` | HTTP transport for browser nodes; disabled when empty | + +### CLI options + +| Option | Default | Purpose | +| ----------------------------- | ----------------------------- | -------------------------------------------------- | +| `-config ` | `payment-network-config.json` | Private configuration file | +| `-web-conn-info` | `false` | Print public browser initializer and exit | +| `-api
` | Disabled | Enable administration API at the specified address | +| `-api-login`, `-api-password` | Empty | API authentication; supply both together | +| `-daemon` | `false` | Disable interactive console input | + +The generated native-currency `BalanceControl` can automatically top up or withdraw channel funds. Set it to `null` for manual management. Preserve configuration keys and the database across restarts. + +## Assets and amounts + +`ChannelConfig.SupportedCoins` contains `Ton`, `Jettons` keyed by master address, and `ExtraCurrencies` keyed by numeric currency ID. Each asset has an `Enabled` setting, symbol, decimals, and fee/capacity policy. + +Console commands resolve the configured symbol and parse amounts in whole-coin units. The native currency uses the symbol `TON` and 9 decimals. HTTP top-up and withdrawal requests use `amount_nano`, a decimal string in the selected asset's smallest units. + +HTTP conditional requests use `capacity`, `amount`, and per-node `fee` strings in whole-coin units. Do not reuse the `amount_nano` representation for those fields. + +## Channel console commands + +Enter the command name in the running node, then answer its prompts separately. + +| Command | Inputs and behavior | +| -------------------- | ---------------------------------------------------------------------------------- | +| `list` | List active channels | +| `list_all` | Include closing and inactive channels | +| `show` | Local channel address; detailed state, balances, and obligations | +| `init` | Peer payment-node key in base64; initialize signed channel configuration off-chain | +| `topup` | Local channel address, currency, amount; first top-up can activate contracts | +| `withdraw` | Local channel address, destination address, currency, amount | +| `destroy` | Local channel address; request cooperative closure and schedule fallback | +| `kill` | Local channel address; request non-cooperative closure | +| `wallet-ton-balance` | Read the funding wallet's native balance | + +A locally active channel and a deployed on-chain contract are different states. Inspect `our_onchain` and `their_onchain`, not only whether `list` includes the channel. + +## Virtual-channel commands + +| Command | Inputs and behavior | +| ------- | ------------------------------------------------------------------------------------------------ | +| `send` | Ordered route keys, currency, amount, fee; request a self-closing virtual transfer | +| `open` | Route keys, currency, capacity, fee; return `private_key`, a base64-encoded 32-byte signing seed | +| `sign` | Signing seed, currency, cumulative amount; return the encrypted base64 `signed_state` | +| `close` | Recipient supplies the `signed_state` from `sign` to request virtual-channel settlement | + +`close` concerns a virtual channel. `destroy` and `kill` concern the underlying payment channel. Keep the virtual signing key private; transfer the signed state to the recipient instead. + +The amount passed to `sign` is cumulative for that virtual channel, not an additional payment. For example, signing `0.1` and later `0.2` represents a total of `0.2` in the selected asset. The signed amount must not decrease or exceed the channel capacity. + +## Closure settings + +The following fields are under `ChannelConfig`: + +| Field | Purpose | Unit | +| ----------------------------- | ------------------------------------------------ | ------- | +| `QuarantineDurationSec` | Period for challenging a submitted channel state | Seconds | +| `ConditionalCloseDurationSec` | Conditional-settlement period | Seconds | +| `ActionsDuration` | Action-execution period | Seconds | +| `BufferTimeToCommit` | Node scheduling margin for committing state | Seconds | + +`destroy` requires no pending on-chain transfers, no unexpired conditionals, and no actions that still require an on-chain commit. If these checks fail, the request is rejected before scheduling closure. + +An accepted request schedules cooperative closure and a non-cooperative fallback after five minutes. The fallback worker checks that the same channel remains active and both sides are active on-chain before proceeding. `kill` requests non-cooperative closure directly; settlement follows the contract's deadlines. + +## HTTP API + +The administration API exposes these core routes: + +POST inputs are JSON body fields; GET inputs are query parameters. + +| Method | Path | Inputs | Purpose | +| ------ | -------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------------------- | +| POST | `/api/v1/channel/onchain/open` | `with_node` | Initialize a channel; return its `address` | +| POST | `/api/v1/channel/onchain/topup` | `address`, `currency`, `amount_nano` | Fund a channel | +| POST | `/api/v1/channel/onchain/withdraw` | `address`, `to`, `currency`, `amount_nano` | Request a withdrawal | +| POST | `/api/v1/channel/onchain/close` | `address`, `force` | Request closure; `force: true` selects the non-cooperative path | +| GET | `/api/v1/channel/onchain/list` | Optional `status`, peer `key` | List channels | +| GET | `/api/v1/channel/onchain` | `address` | Read a local channel | +| POST | `/api/v1/channel/conditional/open` | `currency`, `capacity`, `ttl_seconds`, `nodes_chain` | Request a virtual channel; return its keys, status, and deadline | +| POST | `/api/v1/channel/conditional/transfer` | `currency`, `amount`, `ttl_seconds`, `nodes_chain` | Request a virtual transfer | +| POST | `/api/v1/channel/conditional/close` | `key`, `state` | Request virtual-channel settlement | +| GET | `/api/v1/channel/conditional/list` | `address` | List conditionals for a local channel | + +`nodes_chain` is an ordered array of payment nodes with `key`, `fee`, and `deadline_gap_seconds` fields. Amounts and fees use the formats in [Assets and amounts](#assets-and-amounts); `ttl_seconds` and `deadline_gap_seconds` are in seconds. + +The conditional-close API accepts a virtual-channel public `key` and a signed-state cell in `state`. It does not accept the encrypted `signed_state` string returned by the console's `sign` command. + +The node's API operates on its wallet and channel state. A successful request is not proof of completed on-chain settlement. Consult the versioned [channel handlers](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/tonpayments/api/channel.go#L39-L298) and [conditional handlers](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/tonpayments/api/virtual.go#L271-L497) for request and response fields. + +## Contract versions + +The node embeds supported contract bytecode in `pkg/payments/types.go`. Its first code entry matches the Universal contract compiled from `contracts/universal/payment-channel-contract.tolk` at the source revision below. The repository also contains a different `contracts/payment-channel-contract.tolk` variant; their layouts and wrappers are not interchangeable. + +## Sources + +- [Standalone node v1.3.2 and console commands](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/cmd/node/main.go#L461-L923) +- [Channel operations and first top-up deployment](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/tonpayments/api.go#L2170-L2320) +- [Node and asset configuration](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/tonpayments/config/config.go#L96-L242) +- [Embedded contract code](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/pkg/payments/types.go#L101-L115) +- [Universal contract](https://github.com/xssnick/payment-channel-contract/blob/9704af6a04b4dfedebb56f4261a07bd5578b667d/contracts/universal/payment-channel-contract.tolk#L32-L110) +- [Browser node](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/cmd/web/main.go#L878-L990) +- [Local payment-node tests](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/cmd/test-node/integration_test.go#L357-L506) +- [Virtual-channel state layout](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/pkg/payments/conditionals/channel.go#L569-L623) +- [Cooperative closure and five-minute fallback](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/tonpayments/api.go#L1054-L1096) +- [Fallback worker conditions](https://github.com/xssnick/ton-payment-network/blob/b5187d050c1cac581708c919e783e378b15a78c4/tonpayments/worker.go#L763-L795) diff --git a/content/foundations/web3/payment-network/run-node.mdx b/content/foundations/web3/payment-network/run-node.mdx new file mode 100644 index 000000000..5779d5601 --- /dev/null +++ b/content/foundations/web3/payment-network/run-node.mdx @@ -0,0 +1,89 @@ +--- +title: "How to run a TON Payment Network node" +sidebarTitle: "Run a payment node" +description: "Build and configure a mainnet payment node with manual balance management" +--- + +Run the standalone TON Payment Network v1.3.2 node. This guide uses mainnet and manual deposits and withdrawals. The commands require a POSIX shell. + +## Prerequisites + +- [Go 1.26 or later](https://go.dev/dl/) (tested with Go 1.26.1) +- UDP connectivity for communication with peers +- For an inbound node: a public IPv4 address and a reachable UDP listener + +## Build the node + +```bash +git clone --branch v1.3.2 https://github.com/xssnick/ton-payment-network +cd ton-payment-network +go build -ldflags "-w -s -X main.GitCommit=$(git describe --tags --always --dirty)" -o build/payment-node cmd/node/main.go +``` + +The executable is `build/payment-node`. Run subsequent commands from this repository directory. + +## Generate and review configuration + + + The configuration contains wallet and node private keys. Keep it private and backed up with the payment database. Generated balance-control settings can trigger transfers after channels become active; review them before funding the wallet. + + +Generate the configuration without starting the payment service using the [`-config` and `-web-conn-info` options](/foundations/web3/payment-network/reference#cli-options): + +```bash +umask 077 +./build/payment-node -config payment-network-config.json -web-conn-info +chmod 600 payment-network-config.json +``` + +[`-web-conn-info`](/foundations/web3/payment-network/reference#cli-options) prints public connection keys for browser clients and exits. The private keys remain in the configuration file. + +Open `payment-network-config.json`. Keep the generated mainnet [`NetworkConfigUrl`](/foundations/web3/payment-network/reference#configuration-fields). For manual funding in these guides, set [`ChannelConfig.SupportedCoins.Ton.BalanceControl`](/foundations/web3/payment-network/reference#configuration-fields) to `null`. Apply the same choice to any additional enabled asset. + +For an inbound node, set [`ExternalIP`](/foundations/web3/payment-network/reference#node-configuration) to the node's public IPv4 address and make the UDP port in `NodeListenAddr` reachable. With an empty `ExternalIP`, the node starts as an outbound ADNL client. + +## Start and verify + +```bash +./build/payment-node -config payment-network-config.json +``` + +Wait for “wallet initialized” and “payment node initialized”. They report different identifiers: the wallet address receives on-chain funds; the node public key identifies the payment peer. + +In the running node's console, enter: + +```text +list +``` + +A fresh node reports “no active channels”. The console accepts a command name and then asks for each argument separately. + +Use Ctrl+C to stop the process before changing configuration. Preserve the configured `DBPath` and private keys when restarting. + +## Enable the HTTP API (optional) + + + +To bind the HTTP API to localhost, use [`-api`](/foundations/web3/payment-network/reference#cli-options): + +```bash +./build/payment-node -config payment-network-config.json -api 127.0.0.1:8096 +``` + +The [HTTP API](/foundations/web3/payment-network/reference#http-api) can request fund movements. Keep it on a trusted local interface; configure both [`-api-login` and `-api-password`](/foundations/web3/payment-network/reference#cli-options) if authentication is needed. + +## Troubleshoot + +| Problem | Check | +| ---------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| Configuration upgrade message followed by exit | Review the updated file and restart. | +| Cannot connect to liteservers | Check `NetworkConfigUrl` and network reachability. | +| Peer cannot connect to the node | Check `ExternalIP`, UDP listener, and firewall rules. | +| API does not start | Enable `-api`; the `APIListenAddr` configuration field alone does not enable it in this version. | + +Continue with [Open and fund a channel](/foundations/web3/payment-network/use-channels#initialize-the-channel). diff --git a/content/foundations/web3/payment-network/use-channels.mdx b/content/foundations/web3/payment-network/use-channels.mdx new file mode 100644 index 000000000..83adf7663 --- /dev/null +++ b/content/foundations/web3/payment-network/use-channels.mdx @@ -0,0 +1,151 @@ +--- +title: "How to use payment channels" +sidebarTitle: "Use payment channels" +description: "Open, fund, use, and close channels with the Payment Network console" +--- + +Initialize and fund a channel, send payments, then withdraw funds or close the channel using the standalone v1.3.2 node. + +## Prerequisites + +- A running [payment node v1.3.2](/foundations/web3/payment-network/run-node) configured for mainnet and manual balance management, with its original private keys and database +- A reachable mainnet peer and its payment-node public key in base64 +- Funds in the node's wallet for the chosen asset and native-currency transaction fees + + + Funding, withdrawals, and closure can send on-chain transactions. Mainnet transfers cannot be rolled back. Check the peer, destination, asset, amount, and fees before submitting the final console response. Preserve the private keys and payment database, and keep the node running during settlement. + + +## Initialize the channel + +Enter [`init`](/foundations/web3/payment-network/reference#channel-console-commands) inside the node's console: + +```text +init +``` + +When prompted, enter the peer's base64 payment-node public key. This is not the peer's wallet address or ADNL transport key. + +Wait for “channel opened offchain”, then run [`list`](/foundations/web3/payment-network/reference#channel-console-commands) to find the local channel address. In this version, initialization exchanges signed configuration off-chain. It does not by itself prove that the channel contracts are deployed or funded. + +## Fund the local side + +Enter [`topup`](/foundations/web3/payment-network/reference#channel-console-commands): + +```text +topup +``` + +Answer the prompts in order: + +1. The local channel address from `list`. +1. The configured currency symbol, such as `TON` for the native currency. +1. The amount in whole-coin units, for example `1` rather than `1000000000` for one native coin. + +The first top-up can deploy and activate the channel contracts. Wait for “topup transaction completed”, then allow the node to process the on-chain update. + +For jettons or extra-currencies, enable the asset's configuration on the participating nodes first. [Symbols and decimals](/foundations/web3/payment-network/reference#assets-and-amounts) come from that configuration. + +## Verify channel capacity + +Enter [`show`](/foundations/web3/payment-network/reference#channel-console-commands), then the local channel address. Check the peer identity, on-chain activation flags, and balances for the chosen asset. + +The local available outgoing balance is separate from incoming capacity. To receive payments through the peer, its side must provide sufficient capacity. Funding the local node's wallet does not fund the peer's side. + +## Send a payment + +Before sending, obtain the ordered base64 payment-node keys ending with the recipient, agree on forwarding fees, and check capacity for the selected asset along the route. Record the relevant channel balances on the sender and recipient nodes. + +In the sender's node console, enter [`send`](/foundations/web3/payment-network/reference#virtual-channel-commands): + +```text +send +``` + +Answer the prompts in order: + +1. The next nodes in the route, including the recipient, separated by commas without spaces. Do not include the sender's node key. +1. The configured currency symbol, such as `TON`. +1. The amount the recipient should receive, in whole-coin units. +1. The forwarding fee per intermediate node, in the same asset's units. + +For a direct payment, the route contains only the recipient's key. For a routed payment, consecutive nodes must have suitable channels and capacity. + +The command reports “virtual transfer requested”. This confirms submission, not completion at the recipient. + +### Verify receipt + +On both sender and recipient nodes, use `show` followed by the relevant local channel address. Compare the selected asset's available balances before and after the payment has settled off-chain. Account for fees, locked capacity, and any concurrent channel activity. + +Do not treat a request log or the sender's wallet balance as proof of receipt. The recipient should confirm the resulting channel state. + +### Send repeated payments + + + +For a reusable virtual channel, [`open`](/foundations/web3/payment-network/reference#virtual-channel-commands) follows the same route and capacity prompts but returns a private signing key. The sender uses [`sign`](/foundations/web3/payment-network/reference#virtual-channel-commands) to produce a signed payment state. The recipient uses [`close`](/foundations/web3/payment-network/reference#virtual-channel-commands) with that state to settle it. Keep the private signing key with the sender, not the recipient. + +## Withdraw part of the balance + +Use a mainnet destination address and check the available balance before withdrawing. + +In the node's console, enter [`withdraw`](/foundations/web3/payment-network/reference#channel-console-commands): + +```text +withdraw +``` + +Provide the local channel address, destination wallet address, currency symbol, and amount in whole-coin units when prompted. + +The command requests a withdrawal through the channel. Verify the resulting transaction and destination balance; a submitted request is not a completed withdrawal. Withdrawing funds reduces capacity available for subsequent payments. + +## Close the channel + +Check pending obligations before requesting closure. Keep the node running and its state available during settlement. + +### Close cooperatively + +Check the [cooperative-closure conditions](/foundations/web3/payment-network/reference#closure-settings), then enter: + +```text +destroy +``` + +Provide the local channel address. The node reports “cooperative channel closure attempt has been started”. + +Wait for completion and verify the on-chain results. An accepted request also schedules the [non-cooperative fallback](/foundations/web3/payment-network/reference#closure-settings). + +### Close without cooperation + +To request non-cooperative closure directly, inspect the channel state and active obligations, then enter: + +```text +kill +``` + +Provide the local channel address. The node reports “uncooperative channel closure has been started”. + +This begins a settlement process governed by the channel's [quarantine, conditional-settlement, and action deadlines](/foundations/web3/payment-network/reference#closure-settings). Funds are not necessarily available immediately. Preserve the latest signed state and keep the node online to process the required steps. + +### Verify closure + +Use `list_all` to include closing and inactive channels, then `show` with the local address. Check the final state and resulting on-chain transfers. A channel disappearing from `list`, which shows active channels only, is not sufficient proof that settlement finished. + +## Troubleshoot + +| Problem | Check | +| ----------------------------------------- | ---------------------------------------------------------------------------- | +| Invalid key format or length | Use the peer's 32-byte payment-node public key encoded as base64. | +| Unknown currency | Check the enabled asset and symbol on each participating node. | +| Insufficient wallet funds | Check both the asset balance and native currency for transaction fees. | +| Channel listed but not active on-chain | Inspect the activation flags and the result of the first top-up. | +| Route cannot be opened | Check every peer key, channel, deadline policy, fee, and available capacity. | +| Request submitted but receipt unconfirmed | Inspect both endpoints' channel states and logs before retrying. | +| Withdrawal cannot proceed | Check available balance, fees, peer connectivity, and pending obligations. | +| Cooperative close remains pending | Check the peer's response and the scheduled fallback in the node logs. | +| Forced closure is not finished | Check the contract deadlines and the node's settlement progress. | diff --git a/content/foundations/web3/ton-dns.mdx b/content/foundations/web3/ton-dns.mdx deleted file mode 100644 index 9658acd6b..000000000 --- a/content/foundations/web3/ton-dns.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: "TON DNS" -description: "On-chain hierarchical domain name service for TON Network" ---- - -TON DNS is a service for translating human-readable domain names (such as `example.ton` or `mysite.temp.ton`) into TON smart contract addresses, ADNL addresses used by services on the TON Network, and other network entities. - -## What TON DNS resolves - -TON DNS records can point to several types of addresses: - -- **Wallet addresses**: on-chain smart contract addresses stored under the `wallet` category, allowing users to send cryptocurrency directly to a human-readable domain name instead of a raw address. -- **ADNL addresses**: used to locate TON Sites running on the TON Network. -- **TON Storage Bag IDs**: identifiers for files and data stored via TON Storage. -- **Next resolver references**: delegation of subdomains to another DNS smart contract. -- **Text records**: arbitrary UTF-8 text associated with a domain name. - -## Implementation - -TON DNS is built as a tree of DNS smart contracts. The root contract lives on the masterchain; its address is stored in blockchain configuration parameter #4. `.ton` is the only first-level domain. Each `.ton` domain is an NFT following the TEP-0081 standard: the resolver contract acts as an NFT collection and each registered domain is an NFT item, making domains transferable through any NFT-compatible wallet or marketplace. - -The `.t.me` namespace operates as a delegated sub-resolver on the same infrastructure, implementing the same `dnsresolve` interface and supporting the same record types as `.ton` domains. - -Every DNS smart contract exposes a `dnsresolve` get-method: - -```func -(int, cell) dnsresolve(slice subdomain, int category) -``` - -`subdomain` is the portion of the domain name remaining to be resolved. `category` is the SHA-256 hash of the record category name, or `0` to retrieve all records. The method returns the number of bits consumed and a cell containing the DNS record. If fewer bits were consumed than the full subdomain length, the returned cell is a `dns_next_resolver` pointing to the contract that handles the remainder. - -## DNS record types - -DNS record values are described by TL-B schemas. The following record types are defined: - -- `dns_adnl_address`: stores a 256-bit ADNL address for network services such as TON Sites. An optional protocol list describes supported protocols. - - ```tlb - dns_adnl_address#ad01 adnl_addr:bits256 flags:(## 8) { flags <= 1 } - proto_list:flags . 0?ProtoList = DNSRecord; - ``` - -- `dns_smc_address`: stores any smart contract address on the TON Blockchain, including wallets. An optional capability list describes the capabilities of the contract. Under the standard `wallet` category, this record enables sending funds to a domain name. - - ```tlb - dns_smc_address#9fd3 smc_addr:MsgAddressInt flags:(## 8) { flags <= 1 } - cap_list:flags . 0?SmcCapList = DNSRecord; - ``` - -- `dns_next_resolver`: delegates resolution of subdomains to another DNS smart contract at the specified address. - - ```tlb - dns_next_resolver#ba93 resolver:MsgAddressInt = DNSRecord; - ``` - -- `dns_storage_address`: stores a 256-bit TON Storage Bag ID, allowing domain names to be assigned to files stored via TON Storage. - - ```tlb - dns_storage_address#7473 bag_id:bits256 = DNSRecord; - ``` - -- `dns_text`: stores arbitrary UTF-8 text using the `Text` chunked encoding defined in the block layout specification. - - ```tlb - dns_text#1eda _:Text = DNSRecord; - ``` - -### Record categories - -When querying a DNS contract, the caller specifies a category to select which record type to retrieve. Categories are identified by the SHA-256 hash of a UTF-8 category name string. The standard categories defined by TEP-0081 are: - -| Category name | Purpose | -| ------------------- | ------------------------------------------ | -| `wallet` | Default wallet address (`dns_smc_address`) | -| `site` | TON Site ADNL address (`dns_adnl_address`) | -| `dns_next_resolver` | Subdomain delegation (`dns_next_resolver`) | -| `storage` | TON Storage Bag ID (`dns_storage_address`) | - -Passing category `0` retrieves all records stored for the domain. - -## Domain lifecycle - -Registered domains must be renewed annually by sending 0.015 GRAM to the domain contract. There is no grace period: once a domain has gone more than one year without renewal, anyone can trigger its release by calling `dns_balance_release` on the contract with a minimum payment. The domain then re-enters auction for one week, with the caller as the initial bidder. - -## Ecosystem integration - -TON domain names such as `.ton` domains are recognized by wallet applications and explorers in the TON ecosystem. Users can send cryptocurrency to a TON DNS domain name instead of copying a 256-bit account identifier. - -TON DNS also integrates with other TON services: - -- [TON Sites](/foundations/web3/ton-sites): a `dns_adnl_address` record pointing to an ADNL address gives a site a human-readable `.ton` domain. -- [TON Storage](/foundations/web3/ton-storage): a `dns_storage_address` record maps a domain name to a Bag ID, making stored files addressable by name. -- [TON Proxy](/foundations/web3/ton-proxy): resolves `.ton` domains to ADNL addresses before routing HTTP traffic to the target site. diff --git a/content/foundations/web3/ton-dns/domains.mdx b/content/foundations/web3/ton-dns/domains.mdx new file mode 100644 index 000000000..fbf49acbf --- /dev/null +++ b/content/foundations/web3/ton-dns/domains.mdx @@ -0,0 +1,61 @@ +--- +title: ".ton domains" +sidebarTitle: ".ton domains" +--- + +Names directly under `.ton` follow the registration, auction, and renewal rules of the official domain collection. These rules apply independently of the application used to manage the domain. Use [dns.ton.org](/foundations/web3/ton-dns/manage-domains) for registration and management through the website. + +## Registration rules + +The label before `.ton` must contain 4 to 126 characters: lowercase ASCII letters (`a-z`), digits (`0-9`), or hyphens. A hyphen cannot be the first or last character. For example, `example.ton` has the label `example`. + +These restrictions apply to registration in the `.ton` collection. The broader name format in [TEP-81](/foundations/web3/ton-dns/reference#name-encoding) also supports names served by other resolvers. Delegated subdomains follow their resolver's rules. + +## Minimum first bids + +The minimum opening bid depends on the label's length, excluding `.ton`: + +| Characters | Minimum first bid (GRAM) | +| ---------: | -----------------------: | +| 4 | 100 | +| 5 | 50 | +| 6 | 40 | +| 7 | 30 | +| 8 | 20 | +| 9 | 10 | +| 10 | 5 | +| 11–126 | 1 | + +Transaction fees are additional. The final price depends on competing bids. + +## Auctions + +Registration starts an auction for an unregistered name. New-domain auctions initially last one hour. Each competing bid must be at least 5% higher than the previous bid, with integer rounding in nanograms. A bid in the final hour extends the deadline to one hour after that bid. + +The collection deploys the domain contract and forwards the remaining message value after fees. The accepted first bid can therefore differ from the submitted value. + +After the deadline, the highest bidder can take ownership. Ownership is recorded when a further successful transaction finalizes the auction. The website displays the winner before that finalization; an owner record update can finalize it. See the [finalization interface](/foundations/web3/ton-dns/reference#auction-finalization) for contract behavior. + +## Ownership + +Each domain is a transferable [non-fungible token (NFT)](/foundations/glossary#non-fungible-token-nft). Its owner controls the DNS records and can transfer the domain to another account. + +Ownership and payment routing are separate: the `wallet` record can point to an account other than the owner. Transferring ownership keeps the existing DNS records, so a new owner must review payment and delegation destinations. + +## Renewal + +A domain's renewal period is 366 days from its last qualifying transaction. A successful owner record update, content replacement, ownership transfer, or balance top-up resets that period. An empty-body top-up qualifies after auction finalization. The [renewal interface](/foundations/web3/ton-dns/reference#renewal-interface) specifies the eligible messages. + +Renewal starts a new period from execution time. It does not add 366 days to the previous deadline. A payment to the domain's resolved wallet address does not necessarily reach or renew the domain contract. + +## Expiration + +Expiration does not automatically release the domain or remove its DNS records. After more than 366 days without renewal, anyone can start a new auction if none is active. Until that auction starts, the current owner can still renew. + +An expired-domain auction removes the previous owner's control and records the opening bidder. It initially lasts one week; subsequent bids follow the same extension rules as new-domain auctions. The domain address and DNS records remain unchanged. Ownership is assigned through finalization after the auction ends. + +## Sources + +- [Collection contract](https://github.com/ton-blockchain/dns-contract/blob/d08131031fb659d2826cccc417ddd9b98476f814/func/nft-collection.fc): registration and deployment. +- [Naming and pricing](https://github.com/ton-blockchain/dns-contract/blob/d08131031fb659d2826cccc417ddd9b98476f814/func/dns-utils.fc): label validation and minimum bids. +- [Domain contract](https://github.com/ton-blockchain/dns-contract/blob/d08131031fb659d2826cccc417ddd9b98476f814/func/nft-item.fc): auctions, ownership, renewal, and expiration. diff --git a/content/foundations/web3/ton-dns/index.mdx b/content/foundations/web3/ton-dns/index.mdx new file mode 100644 index 000000000..590068b35 --- /dev/null +++ b/content/foundations/web3/ton-dns/index.mdx @@ -0,0 +1,67 @@ +--- +title: "TON DNS overview" +sidebarTitle: "Overview" +description: "Human-readable names for addresses and services on TON" +--- + +TON DNS (Domain Name System) associates human-readable domain names with addresses and services on TON. Applications use names such as `example.ton` to find payment recipients, websites, and stored files. + +Smart contracts store domain records and expose a common interface for looking them up. + +## Domain registration and ownership + + + +Names directly under `.ton`, such as `example.ton`, are registered through auctions. Each registered domain is a [non-fungible token (NFT)](/foundations/glossary#non-fungible-token-nft). Its owner controls the domain’s DNS records and can transfer ownership. + +Domain ownership requires renewal. If a domain remains unrenewed beyond its renewal period, another participant can start a new auction. The [.ton domain rules](/foundations/web3/ton-dns/domains) cover registration, auctions, renewal, and expiration. + +Owning a domain and receiving payments through it are separate roles. The owner configures the payment address, which can belong to a different account. + +## DNS records + + + +TON DNS records associate a domain name with addresses, content identifiers, or another resolver. A domain can contain several records: + +- **Wallet addresses:** wallet or other smart contract addresses stored under the `wallet` category, allowing compatible applications to use a domain name as a payment recipient. +- **ADNL addresses:** [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl) addresses that identify network services such as TON Sites. +- **TON Storage BagIDs:** identifiers of files or directories shared through [TON Storage](/foundations/web3/ton-storage). +- **Next resolver references:** smart contract addresses that delegate subdomain resolution to another DNS resolver. +- **Text records:** UTF-8 text associated with a domain, using a category and encoding understood by the application. + +Applications request the category corresponding to their purpose. The [record reference](/foundations/web3/ton-dns/reference#dns-record-types) defines the record types and categories. + +## Subdomains and delegation + + + +A domain owner can delegate resolution of names such as `app.example.ton` to another smart contract, called a _resolver_. The parent domain stores a record pointing to that resolver. + +The delegated resolver defines how subdomains are created and managed. Subdomains do not automatically inherit the `.ton` collection’s NFT ownership, auction, or renewal rules. + +## Name resolution + + + +Resolution is the process of finding a domain’s requested record. Applications follow a hierarchy of resolver contracts, starting with the root resolver. + +For `example.ton`, the root resolver points to the `.ton` resolver, which points to the domain’s contract. The domain contract returns the requested record, if one exists. For a delegated subdomain, the application continues to the designated resolver. + +The official root resolver supports the `.ton` and `.t.me` namespaces. + +Applications read records through the [`dnsresolve` get-method](/foundations/web3/ton-dns/reference#dns-protocol). Reading requires no wallet signature or on-chain transaction. Registering a domain, changing its records, and transferring ownership require transactions. + +After resolution, the application uses the returned destination to send a payment, connect to a site, or retrieve files. + +## Next steps + +- [.ton domains](/foundations/web3/ton-dns/domains): names, minimum bids, auctions, and renewal rules. +- [Manage domains](/foundations/web3/ton-dns/manage-domains): register, configure, and renew `.ton` domains. +- [TON DNS reference](/foundations/web3/ton-dns/reference): resolver interfaces, record formats, getters, and contract messages. diff --git a/content/foundations/web3/ton-dns/manage-domains.mdx b/content/foundations/web3/ton-dns/manage-domains.mdx new file mode 100644 index 000000000..b89248011 --- /dev/null +++ b/content/foundations/web3/ton-dns/manage-domains.mdx @@ -0,0 +1,210 @@ +--- +title: "How to manage domains on dns.ton.org" +sidebarTitle: "Manage domains" +--- + +Register, configure, and renew `.ton` domains on [dns.ton.org](https://dns.ton.org/). + +## Prerequisites + +- A compatible non-custodial wallet on mainnet, with funds for bids and transaction fees. +- Ownership of the domain for record changes, subdomain delegation, or renewal. + + + Transactions on this site use mainnet and cannot be rolled back. Check the domain, amount, and values before confirming in the wallet. Changing a wallet record changes the payment recipient. + + +## Connect a wallet + +1. Open [dns.ton.org](https://dns.ton.org/). +1. Select Connect wallet and approve the connection in the wallet. +1. Search for the domain to manage. Check whether it is available, being auctioned, or already owned. + + + + + + + + + + + + + +## Register a domain + +1. Find an available name or an auction in progress. Check the [registration rules](/foundations/web3/ton-dns/domains#registration-rules) and [minimum first bid](/foundations/web3/ton-dns/domains#minimum-first-bids). +1. Select Place bid, enter at least the displayed minimum, and confirm the transaction in the wallet. +1. Wait for the page to display the accepted bid and bidder address. Follow the deadline and highest bidder. +1. After the auction ends, check that the winning address matches the connected wallet. If it matches, open Manage domain and save the intended wallet address to configure the domain and finalize ownership. +1. After the transaction succeeds, reload the page and check the owner and saved wallet address. + +When outbid, the contract returns the previous bid, subject to its available balance. + +Bids near the deadline can [extend the auction](/foundations/web3/ton-dns/domains#auctions). Saving the first record after winning also [finalizes ownership](/foundations/web3/ton-dns/domains#auctions). + + + + + + + + + +## Manage records + +| Field on dns.ton.org | Value | +| -------------------------------------------- | ------------------------------------------------------------------------------------------------------ | +| Wallet address | Wallet or smart contract address that should receive payments. | +| TON Site | The site's [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl) address in hexadecimal. | +| TON Site with Hosting in TON Storage enabled | The site's TON Storage Bag ID. | +| TON Storage | A Bag ID for stored files, separate from the site record. | +| Subdomains | The address of a DNS resolver contract. | + +1. Select Manage domain with the owner's wallet connected. +1. Enter the value in the corresponding field. For a site stored in TON Storage, enable Hosting in TON Storage and enter the Bag ID in TON Site. +1. Select Save for that field, check the transaction details, and confirm in the wallet. +1. Reload the page and check the saved value. + +To remove a record, clear its field and select Save, then confirm in the wallet. This does not delete the domain. The TON Site and TON Storage fields store separate records; changing one does not update the other. + + + + + + + + + +### Delegate subdomains + +Enter an existing [resolver contract's](/foundations/web3/ton-dns/reference#subdomain-resolvers) address in Subdomains, select Save, and confirm. The resolver must already contain the subdomain records; this field only delegates resolution. + +Test the full name, such as `app.example.ton`, in the application that uses it. Clear the field to remove delegation. + + + +The site has no text-record field. Text records require a [contract message](/foundations/web3/ton-dns/reference#record-updates). + + + + + + + + + +## Renew a domain + +1. Search for the domain with the owner's wallet connected and check its expiration date. The site shows the renewal button within 180 days of expiration or after expiration. +1. Select Renew this domain. Check the requested 0.015 GRAM payment and transaction fees before confirming in the wallet. +1. Reload the page and verify that the expiration date has advanced. + +Renewal starts a new 366-day period from the transaction time. Record updates also [renew the domain](/foundations/web3/ton-dns/domains#renewal). + + + + + + + + + +## Start an auction for an expired domain + +A release starts a new auction after more than 366 days without renewal, provided no auction is active. Expiration alone does not release the domain: the current owner can still renew until the auction starts. + +1. Search for the domain and check its expiration date and auction status. +1. Connect a wallet other than the current owner's. The site hides the release action from the owner. +1. Select Place a bid to start the auction. +1. Enter at least the displayed minimum and confirm the transaction in the wallet. The amount sent becomes the opening bid. +1. Reload the page and verify the accepted bid, bidder address, and auction deadline. + +Once the transaction succeeds: + +- The previous owner loses control of the domain. +- The sending wallet becomes the first bidder, not the new owner. +- A one-week auction begins. Bids in the final hour extend the deadline to one hour after that bid. +- The domain address and existing DNS records remain unchanged. + +The contract attempts to return its previous balance above a 1 GRAM reserve to the previous owner. This excludes the opening bid; fees affect the amount received. + +Follow the auction and finalize ownership after winning, as described in [Register a domain](#register-a-domain). + + + +## Verify the changes + +Each procedure ends with a check on the domain page. If the transaction fails or its result is unclear, inspect it in a block explorer before retrying. + + + +After changing a wallet record, enter the domain in a compatible wallet and compare the recipient without sending funds. For a site record, open the domain through a compatible TON Proxy. + + + +## Troubleshoot + +| Issue | Check | +| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | +| Bid is too small | Refresh the domain page and check the updated minimum. | +| Management controls are unavailable | Check that the connected wallet owns the domain and the auction has ended. | +| Invalid address or Bag ID | Check the field, value format, and Hosting in TON Storage setting. | +| Transaction or update fails | Check the wallet result and current domain state before retrying. | +| Renew this domain is absent | Check ownership and the [website's renewal window](#renew-a-domain). | +| Expired-domain auction is absent | Check expiration, connected ownership, and whether an auction has already started. The site hides this action from owners. | +| Subdomain does not resolve | Check the delegation address and the records configured in that resolver. | diff --git a/content/foundations/web3/ton-dns/meta.json b/content/foundations/web3/ton-dns/meta.json new file mode 100644 index 000000000..94825c921 --- /dev/null +++ b/content/foundations/web3/ton-dns/meta.json @@ -0,0 +1,10 @@ +{ + "$schema": "../../../../meta-schema.json", + "title": "TON DNS", + "pages": [ + "index", + "domains", + "manage-domains", + "reference" + ] +} diff --git a/content/foundations/web3/ton-dns/reference.mdx b/content/foundations/web3/ton-dns/reference.mdx new file mode 100644 index 000000000..69263aebd --- /dev/null +++ b/content/foundations/web3/ton-dns/reference.mdx @@ -0,0 +1,412 @@ +--- +title: "TON DNS reference" +sidebarTitle: "Reference" +--- + +Domain Name System (DNS) resolver interface, record schemas, and messages of the `.ton` domain contracts. For names, prices, auctions, and renewal periods, see [.ton domains](/foundations/web3/ton-dns/domains). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## DNS protocol + +TON DNS is built as a tree of DNS smart contracts. The [root resolver](https://github.com/ton-blockchain/dns-contract/blob/d08131031fb659d2826cccc417ddd9b98476f814/func/root-dns.fc) lives on the masterchain; its address is stored in blockchain configuration parameter #4. + +Every DNS smart contract exposes a `dnsresolve` get-method: + +```func +(int, cell) dnsresolve(slice subdomain, int category) +``` + +`subdomain` contains the remaining name in its internal encoding. `category` is an unsigned 256-bit key, usually the SHA-256 hash of a category name. Category `0` requests all records. + +### Name encoding + +TON Enhancement Proposal 81 (TEP-81) defines names as UTF-8 strings of at most 126 bytes, excluding byte values `0` through `32`. Applications normalize names to lowercase. Individual resolvers can impose additional registration restrictions. + +Reverse the dot-separated labels and terminate each with a zero byte: `app.example.ton` becomes `ton\0example\0app\0`. Each resolver returns the number of bits consumed; pass the remaining bytes to the next resolver. Do not strip a leading zero byte from that remainder. + +A single zero byte refers to the resolver itself. When starting a lookup directly on a non-root resolver, prefix the internal name with a zero byte. For a record on the domain contract itself, pass `\0`. + +### Resolution results + +| Result | Meaning | +| ----------------------------------- | ----------------------------------------------------------------------------------------- | +| Get-method failure | Resolution failed. | +| Zero bits consumed | No matching prefix was resolved. | +| Full name consumed, record returned | The requested record was found. | +| Full name consumed, null returned | No record exists for the requested category. | +| Partial name consumed | Continue through the returned `dns_next_resolver`. A missing delegation stops resolution. | +| Category `0`, full name consumed | The result is the category dictionary, which can be empty. | + + + + + +### DNS record types + +Record values use the following [TL-B](/foundations/tlb/overview) schemas: + +- `dns_adnl_address`: stores a 256-bit [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl) address for network services such as TON Sites. An optional protocol list describes supported protocols. + + ```tlb + dns_adnl_address#ad01 adnl_addr:bits256 flags:(## 8) { flags <= 1 } + proto_list:flags . 0?ProtoList = DNSRecord; + ``` + +- `dns_smc_address`: stores any smart contract address on the TON Blockchain, including wallets. An optional capability list describes the capabilities of the contract. Under the standard `wallet` category, this record enables sending funds to a domain name. + + ```tlb + dns_smc_address#9fd3 smc_addr:MsgAddressInt flags:(## 8) { flags <= 1 } + cap_list:flags . 0?SmcCapList = DNSRecord; + ``` + +- `dns_next_resolver`: delegates resolution of subdomains to another DNS smart contract at the specified address. + + ```tlb + dns_next_resolver#ba93 resolver:MsgAddressInt = DNSRecord; + ``` + +- `dns_storage_address`: stores a 256-bit TON Storage Bag ID, allowing domain names to be assigned to files stored via TON Storage. + + ```tlb + dns_storage_address#7473 bag_id:bits256 = DNSRecord; + ``` + +- `dns_text`: stores arbitrary UTF-8 text using the `Text` chunked encoding defined in the block layout specification. + + ```tlb + dns_text#1eda _:Text = DNSRecord; + ``` + + + +#### Record categories + +Categories select records independently of their TL-B type. Their keys are SHA-256 hashes of UTF-8 names. + +| Category | Record type | Definition or use | +| ------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| `wallet` | `dns_smc_address` | Defined by TEP-81. | +| `site` | `dns_adnl_address` or `dns_storage_address` | Site destination. | +| `dns_next_resolver` | `dns_next_resolver` | Defined by TEP-81. | +| `storage` | `dns_storage_address` | Used by the official DNS interface for a separate storage record; not a standard category listed in TEP-81. | + +TEP-81 defines the ADNL form. The [official proxy](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/rldp-http-proxy/DNSResolver.cpp#L69-L93) accepts both ADNL addresses and Bag IDs in the `site` category. The DNS interface also supports both. + +TEP-81 does not define a standard text category. Applications must agree on the category used for a `dns_text` value. + +#### Text encoding + +For `dns_text`, prefix the value with constructor `0x1eda` (16 bits), then encode `Text`: + +```tlb +chunk_ref$_ {n:#} ref:^(TextChunks (n + 1)) = TextChunkRef (n + 1); +chunk_ref_empty$_ = TextChunkRef 0; +text_chunk$_ {n:#} len:(## 8) data:(bits (len * 8)) next:(TextChunkRef n) = TextChunks (n + 1); +text_chunk_empty$_ = TextChunks 0; +text$_ chunks:(## 8) rest:(TextChunks chunks) = Text; +``` + +`chunks` counts the text chunks. Each chunk carries its byte length and data; a reference leads to the remaining chunks. Encode the text as UTF-8. This is not the same serialization as appending a string directly after `0x1eda`. + + + +### Subdomain resolvers + +The parent domain's `dns_next_resolver` category stores a record of the same type, containing the delegated contract's address. The `.ton` domain contract returns this record when resolving a subdomain. Updating or deleting it uses the [record update message](#record-updates). + +The delegated contract must implement `dnsresolve`. Subdomain creation, permissions, and payments depend on that contract; the `.ton` collection's registration rules do not automatically apply to it. + +Official implementations include [manual DNS](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/crypto/smartcont/dns-manual-code.fc), managed through signed requests, and [automatic DNS](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/crypto/smartcont/dns-auto-code.fc), which implements registration and expiration rules. + +## .ton contracts + + + +### Domain ownership + +Each `.ton` domain is a transferable non-fungible token (NFT) item following [TEP-62](https://github.com/ton-blockchain/TEPs/blob/fe8a154e4dad9f5c0bf7240df278cb50ec6cd908/text/0062-nft-standard.md). The collection and domain contracts implement DNS resolution following [TEP-81](https://github.com/ton-blockchain/TEPs/blob/fe8a154e4dad9f5c0bf7240df278cb50ec6cd908/text/0081-dns-standard.md). + + + + + +### Domain contract address + +The NFT index is `slice_hash` of the cell containing the label without `.ton`. The collection's `get_nft_address_by_index` returns the corresponding domain address, including before deployment. + +| Account state | Meaning | +| --------------- | ------------------------------------------------------------------------------ | +| `uninitialized` | No active domain contract at this address. | +| `active` | Read the NFT and auction state to determine ownership or bidding availability. | +| `frozen` | Stop the registration flow. | + + + + + + + +### Getters + +| Getter | Returns | +| --------------------------------- | --------------------------------------------------------------------------------------- | +| `get_nft_address_by_index(index)` | Domain address, queried on the collection. | +| `get_nft_data()` | Initialization flag, NFT index, collection address, owner address, and content cell. | +| `get_domain()` | Label as a slice, without `.ton`. | +| `get_auction_info()` | Highest bidder, accepted bid in nanograms, and deadline as a Unix timestamp in seconds. | +| `get_last_fill_up_time()` | Renewal timestamp in Unix seconds. | + + + + + + + +### Registration constraints + +The collection enforces the [label restrictions](/foundations/web3/ton-dns/domains#registration-rules) and [minimum opening bids](/foundations/web3/ton-dns/domains#minimum-first-bids). + + + + + + + + + + + +### Auction messages + +The destination and body distinguish new registrations from competing bids. Both follow the [auction deadlines and extension rules](/foundations/web3/ton-dns/domains#auctions). + +| Operation | Destination | Message body | +| --------------------- | --------------- | ----------------------------------------------------------- | +| Start an auction | Collection | Opcode `0` (32 bits), followed by the label without `.ton`. | +| Place a competing bid | Domain contract | Empty body. | + +The collection deploys the domain contract and forwards the remaining message value after fees. The accepted first bid can therefore differ from the value sent to the collection. + +The minimum competing bid is `previousBid * 105 / 100`, using integer division in nanograms. Another bid can change this threshold between reading the state and processing a transaction. + + + + + + + + + +### Auction finalization + +After the deadline, a successful internal `get_static_data` message finalizes the auction without changing DNS records. An empty message does not finalize ownership. A request before the deadline returns static data without finalizing the auction. + +| Message | Opcode | Fields after the opcode | +| -------------------- | ------------ | ---------------------------------------------------------------------- | +| `get_static_data` | `0x2fcb26a2` | `query_id:uint64` | +| `report_static_data` | `0x8b771735` | `query_id:uint64`, `index:uint256`, `collection_address:MsgAddressInt` | + +Opcodes occupy 32 bits. The response is sent to the request sender. Attach enough value for execution and outgoing-message fees; this payment is not another bid. + +An authorized record update after the deadline also finalizes ownership. A wallet record is not required to own the domain. + +After finalization, `get_nft_data` returns the winning wallet as owner. `get_auction_info` returns a null bidder, zero bid, and zero deadline. A wallet signature or broadcast confirmation alone does not establish these results. + + + + + +### Record updates + +Send `change_dns_record` to the domain contract from its owner's wallet: + +| Field | Encoding | +| ------------ | ------------------------------------------------------------------------------- | +| Opcode | `0x4eb1f0f9`, 32 bits. | +| Query ID | Unsigned 64-bit integer. | +| Category key | Unsigned 256-bit integer. | +| Value | Reference to the serialized DNS record, or no reference to delete the category. | + +The contract stores the referenced cell without validating its DNS record type. Encode the expected schema before sending. An absent reference deletes the category; a reference to an empty cell stores an empty cell instead. A successful update refreshes `last_fill_up_time`. + +For `dns_text` values, use the [Text encoding](#text-encoding). + + + +### Renewal interface + +The following successful owner operations reset `last_fill_up_time`: + +| Operation | Message | +| ----------------------------- | ----------------------------------------------------- | +| Update or remove a DNS record | `change_dns_record`. | +| Edit the domain content | `edit_content`. | +| Transfer ownership | NFT `transfer`. | +| Top up the domain contract | Empty body or opcode `0`, after auction finalization. | + +Each operation starts a new 366-day renewal period from its execution time. It does not add 366 days to the previous deadline. The contract does not enforce a fixed renewal payment; messages must fund their execution fees. + +Failed transactions and static-data requests do not reset the timestamp. A payment sent to a domain name's wallet record goes to that recipient, not necessarily to the domain contract. + + + +### Expired domain auctions + +Send `dns_balance_release` to the existing domain contract when `now() - last_fill_up_time > 31622400` (366 days) and no auction is active. Any sender can call it, including the owner. + +| Field | Encoding | +| -------- | ------------------------ | +| Opcode | `0x4ed14b65`, 32 bits. | +| Query ID | Unsigned 64-bit integer. | + +The attached message value is the opening bid and must meet the [minimum first bid](/foundations/web3/ton-dns/domains#minimum-first-bids) for the label's length. Query ID is an unsigned 64-bit value. + +On success, the contract: + +- Clears the owner address to `addr_none`. +- Records the sender as the highest bidder and the message value as the bid. +- Sets the auction deadline to `now() + 604800` (1 week) and resets the renewal timestamp. +- Keeps the domain address and DNS records unchanged. +- Attempts to return the existing balance above the 1 GRAM reserve to the previous owner. This excludes the opening bid; message fees affect the received amount. + +Subsequent bids follow the [auction rules](#auction-messages). Ownership is assigned through [auction finalization](#auction-finalization). + + + +### Contract errors + +| Contract | Exit code | Meaning | +| ---------- | --------- | ------------------------------------------------------------------- | +| Collection | `200` | Label shorter than four characters. | +| Collection | `201` | Label longer than 126 characters. | +| Collection | `202` | Invalid label byte alignment or comment continuation structure. | +| Collection | `203` | Invalid label characters. | +| Collection | `204` | First bid below the minimum. | +| Collection | `205` | Domain index present in the governance configuration. | +| Domain | `407` | Bid below the required minimum. | +| Domain | `414` | The renewal period has not elapsed or an auction is already active. | + +Check both compute and action results when investigating a failed transaction. + + + +## Sources + +- [Collection contract](https://github.com/ton-blockchain/dns-contract/blob/d08131031fb659d2826cccc417ddd9b98476f814/func/nft-collection.fc). +- [Domain contract](https://github.com/ton-blockchain/dns-contract/blob/d08131031fb659d2826cccc417ddd9b98476f814/func/nft-item.fc). +- [Naming and pricing](https://github.com/ton-blockchain/dns-contract/blob/d08131031fb659d2826cccc417ddd9b98476f814/func/dns-utils.fc). +- [TEP-81](https://github.com/ton-blockchain/TEPs/blob/fe8a154e4dad9f5c0bf7240df278cb50ec6cd908/text/0081-dns-standard.md). +- [DNS and Text schemas](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/crypto/block/block.tlb#L951-L975). +- [Official DNS interface](https://github.com/ton-blockchain/dns/blob/429f58774b05d8f3cfa05bd22f0e18df615daa01/src/index.js). +- [Release message payload](https://github.com/ton-blockchain/dns/blob/429f58774b05d8f3cfa05bd22f0e18df615daa01/src/utils.js#L515-L520). diff --git a/content/foundations/web3/ton-proxy.mdx b/content/foundations/web3/ton-proxy.mdx deleted file mode 100644 index 999f1c3d6..000000000 --- a/content/foundations/web3/ton-proxy.mdx +++ /dev/null @@ -1,136 +0,0 @@ ---- -title: "TON Proxy" -description: "HTTP-to-ADNL bridge for accessing and hosting TON Sites from a conventional browser" ---- - -TON Proxy is an HTTP-to-ADNL bridge that allows ordinary web browsers to access TON Sites. It is implemented by the `rldp-http-proxy` binary, which operates as a forward proxy for clients and as a reverse proxy for servers hosting TON Sites. - -## How TON Proxy works - -`rldp-http-proxy` runs locally and listens for HTTP requests from a web browser. When a request arrives for a `.ton` domain, the proxy resolves it via TON DNS to an ADNL address, then forwards the HTTP request over RLDP to the target TON Site. - -By default the forward proxy only intercepts requests for `.ton`, `.adnl`, and `.bag` hostnames; all other requests pass through unchanged. Setting `-P YES` makes the proxy intercept all HTTP requests regardless of suffix. - -### Forward proxy (client-side) - -To start a local forward proxy: - -```bash -rldp-http-proxy -p 8080 -c 3333 -C global.config.json -``` - -Configure the browser to use `127.0.0.1:8080` as an HTTP proxy. TON Sites are then reachable by their `.ton` domain names. - -| Flag | Long form | Description | -| -------------- | ------------------- | ------------------------------------------------------------------------ | -| `-p ` | `--port` | HTTP listening port for browser connections | -| `-c ` | `--client-port` | UDP port for client ADNL queries | -| `-C ` | `--global-config` | Path to the TON global network config file | -| `-P ` | `--proxy-all` | Proxy all HTTP requests, not only `.ton`, `.adnl`, `.bag` (default `NO`) | -| `-S ` | `--storage-gateway` | ADNL address of a TON Storage gateway for `.bag` resolution | -| `-D ` | `--db` | Database root path | -| `-d` | `--daemonize` | Daemonize the process | -| `-l ` | `--logname` | Log file path | - -## Reverse proxy mode - -`rldp-http-proxy` also operates as a reverse proxy for servers hosting TON Sites. In this mode it accepts inbound ADNL connections and forwards HTTP requests to a local or remote web server. Two implementations are available. - -### Use rldp-http-proxy - -`rldp-http-proxy` is the reverse proxy from the official TON monorepo. Key generation is manual. - -**Step 1.** Generate a persistent ADNL address: - -```bash -mkdir keyring -utils/generate-random-id -m adnlid -``` - -The command prints two values to stdout: the hex address and its user-friendly form: - -```text -45061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3 -``` - -It also writes the private key to a file named after the hex address. Move it into the keyring directory: - -```bash -mv 45061C1D* keyring/ -``` - -**Step 2.** Start the reverse proxy, using the user-friendly ADNL address from step 1: - -```bash -rldp-http-proxy -a :3333 -L '*' -C global.config.json -A -d -l tonsite.log -``` - -| Flag | Description | -| ------------------------------------- | ------------------------------------------------------------------------------ | -| `-a :` | Public IP and UDP port for inbound ADNL connections (published to the TON DHT) | -| `-A ` | ADNL address generated in step 1 | -| `-L [:]` | Forward requests for `` to `127.0.0.1` (default ports: 80, 443) | -| `-R [:]@:` | Forward requests for `` to a remote HTTP server at `:` | -| `-C ` | Path to the TON global network configuration file | -| `-D ` | Database root path | -| `-d` | Daemonize the process | -| `-l ` | Log file path | - -### Use `tonutils-reverse-proxy` - -`tonutils-reverse-proxy` is a Go implementation that handles key generation and domain linking automatically. - -**Install on Linux:** - -```bash -wget https://github.com/tonutils/reverse-proxy/releases/latest/download/tonutils-reverse-proxy-linux-amd64 -chmod +x tonutils-reverse-proxy-linux-amd64 -``` - -To build from source: - -```bash -git clone https://github.com/tonutils/reverse-proxy -cd reverse-proxy && make build -``` - -Run with the target `.ton` domain: - -```bash -./tonutils-reverse-proxy --domain .ton -``` - -On first run, the proxy generates a persistent ADNL key pair and displays a QR code. Scan it with a compatible TON wallet to confirm domain ownership and link the ADNL address to the domain. - -The web server must listen on `http://127.0.0.1:80`. The proxy adds two headers to each forwarded request: - -- `X-Adnl-Ip`: the IP address of the connecting client as seen by the ADNL network. -- `X-Adnl-Id`: the ADNL node ID of the connecting client. - -### Domain assignment - -To assign the ADNL address to a `.ton` domain, open the domain in the TON DNS management interface, paste the ADNL address into the "Site" field, and confirm the transaction with the domain owner's wallet. For record types and domain assignment context, see [TON DNS](/foundations/web3/ton-dns). - -## Security and privacy - -All traffic between the proxy and the TON Site is encrypted at the ADNL layer. The server is authenticated by its ADNL address, derived from its public key. - -The server IP is published to the TON DHT for ADNL routing but is not exposed at the HTTP layer. The proxy does not forward client network information to the upstream web server. - -## Response headers - -The proxy adds version headers to all responses. - -| Header | Added by | Value format | -| ------------------------- | --------------------------- | ----------------------------- | -| `Ton-Proxy-Site-Version` | Reverse proxy (server-side) | `Commit: , Date: ` | -| `Ton-Proxy-Entry-Version` | Forward proxy (client-side) | `Commit: , Date: ` | - -The proxy also supports the HTTP `CONNECT` method, which enables WebSocket connections and other TCP-based protocols to be tunneled over ADNL. - -## Related components - -- **ADNL**: the abstract datagram network layer used to reach TON Sites by their abstract address. -- **RLDP**: the reliable large datagram protocol over ADNL that carries HTTP requests and responses. -- [TON Sites](/foundations/web3/ton-sites): web services accessible through TON Proxy. -- [TON DNS](/foundations/web3/ton-dns): resolves `.ton` domain names to ADNL addresses for request routing. diff --git a/content/foundations/web3/ton-proxy/forward-proxy.mdx b/content/foundations/web3/ton-proxy/forward-proxy.mdx new file mode 100644 index 000000000..0f4122be5 --- /dev/null +++ b/content/foundations/web3/ton-proxy/forward-proxy.mdx @@ -0,0 +1,98 @@ +--- +title: "How to run a TON forward proxy" +sidebarTitle: "Run a forward proxy" +description: "Connect a browser to TON Sites and TON Storage files through a local proxy" +--- + +Run a local forward proxy to access TON Sites and TON Storage files from a browser. Choose either Tonutils-Proxy or the C++ `rldp-http-proxy`. + +## Prerequisites + +- For C++: extract `rldp-http-proxy` from the archive for the target platform in [TON v2026.08](https://github.com/ton-blockchain/ton/releases/tag/v2026.08) into the working directory. The separate `http-proxy` download is a different program. +- For C++: save the [mainnet global configuration](https://ton-blockchain.github.io/global.config.json) as `global.config.json` in the same directory. + +## Use Tonutils-Proxy + +[Tonutils-Proxy](https://github.com/xssnick/Tonutils-Proxy) is a community-developed open-source forward proxy. + + + Tonutils-Proxy creates `config.json` in its working directory and stores the [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl) private-key seed in [`ADNLKey`](/foundations/web3/ton-proxy/reference#tonutils-proxy-configuration). Keep this file confidential. + + +On Linux (x86-64), download and run version 1.8.3: + +```bash +wget https://github.com/xssnick/Tonutils-Proxy/releases/download/v1.8.3/tonutils-proxy-cli-linux-amd64 +chmod +x tonutils-proxy-cli-linux-amd64 +./tonutils-proxy-cli-linux-amd64 +``` + +For other platforms, use the corresponding CLI binary from the [same release](https://github.com/xssnick/Tonutils-Proxy/releases/tag/v1.8.3). + +The proxy listens on [`127.0.0.1:8080`](/foundations/web3/ton-proxy/reference#tonutils-proxy-options) and loads the mainnet configuration automatically. It also forwards ordinary HTTP requests. + +## Use rldp-http-proxy + + + The C++ proxy listens on all network interfaces. For local use, block inbound TCP connections to port `8080` on non-loopback interfaces with the host firewall. Configuring the browser to use localhost does not restrict the listener. + + +Run the extracted C++ binary: + +```bash +chmod +x rldp-http-proxy +./rldp-http-proxy -p 8080 -c 3333 -C global.config.json +``` + +The proxy uses UDP port [`3333`](/foundations/web3/ton-proxy/reference#forward-proxy-options) for ADNL traffic. + +## Connect the browser + +Keep the chosen proxy running and configure the browser's HTTP proxy to use `127.0.0.1` on port `8080`. Run only one of these proxies on that port at a time. + +## Verify + +Open `http://` in the configured browser, replacing `` with the full `.ton` name of a running TON Site. Confirm that the expected page loads. + +For direct access without DNS, open `http://.adnl`, replacing `` with the site's user-friendly ADNL address. + +## Access files over HTTP + +To access a file in a Storage bag, obtain its BagID and the path of the file within the bag. Keep the browser configured to use the forward proxy. + +With Tonutils-Proxy, continue to [Verify file access](#verify-file-access). For C++, [configure the gateway](#configure-the-gateway). + +### Configure the gateway + +For C++, obtain the user-friendly ADNL address of an existing TON Storage HTTP gateway. Stop the forward proxy and restart it with [`-S`](/foundations/web3/ton-proxy/reference#forward-proxy-options), replacing `` with that address: + +```bash +./rldp-http-proxy -p 8080 -c 3333 -C global.config.json -S +``` + +The [HTTP listener restrictions](#use-rldp-http-proxy) also apply to this command. + +### Verify file access + +Open `http://.bag/` in the configured browser. Replace `` with the bag's hexadecimal identifier and `` with the path within the bag. Confirm that the expected file is returned. + +Both implementations also accept a `.ton` domain whose [`site` record contains the BagID](/foundations/web3/ton-dns/reference#record-categories): open `http:///`, using the full domain name as ``. + +[Create and share a bag](/foundations/web3/ton-storage/get-started#create-and-share-a-bag) to publish files for HTTP access. + +## Troubleshoot + +| Problem | Check | +| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Browser cannot connect to the proxy | Check that the process is running and the browser uses port `8080`. | +| A `.ton` site cannot be reached | Check the domain's `site` record and whether its destination is online. | +| An ordinary Internet domain is rejected | The C++ proxy accepts only `.ton`, `.adnl`, and `.bag` destinations by default. With Tonutils-Proxy, check whether [`--no-http`](/foundations/web3/ton-proxy/reference#tonutils-proxy-options) is enabled. | +| “storage gateway is not set” | For the C++ proxy, [configure a Storage gateway](#configure-the-gateway) for a destination that resolves to a BagID. | +| File is unavailable | Check the BagID and file path. Peers must serve the bag; with C++, the gateway must also be reachable. | +| Domain routes to the wrong resource | Check the domain's `site` record. | diff --git a/content/foundations/web3/ton-proxy/index.mdx b/content/foundations/web3/ton-proxy/index.mdx new file mode 100644 index 000000000..7d73b513c --- /dev/null +++ b/content/foundations/web3/ton-proxy/index.mdx @@ -0,0 +1,64 @@ +--- +title: "TON Proxy overview" +sidebarTitle: "Overview" +description: "Access and host TON Sites through an HTTP proxy" +--- + +TON Proxy connects HTTP clients to [TON Sites](/foundations/web3/ton-sites). It carries HTTP requests and responses over the TON network, while the client and web server use their existing HTTP interfaces. + +## Forward and reverse proxies + +- A **forward proxy** accepts requests from an HTTP client, such as a browser or command-line tool, and sends them to the TON Site. +- A **reverse proxy** receives requests from the TON network and forwards them to the site's HTTP server. The server can run on the same machine or another host. + +The official C++ implementation, `rldp-http-proxy`, supports both roles. The community implementations [Tonutils-Proxy](/foundations/web3/ton-proxy/forward-proxy#use-tonutils-proxy) and [tonutils-reverse-proxy](/foundations/web3/ton-proxy/reverse-proxy#use-tonutils-reverse-proxy) provide the forward and reverse roles, respectively. + +## Request flow + + + +For a request to `http://example.ton/page`, where the domain points to a reverse proxy: + +1. The HTTP client sends the request to its configured forward proxy. +1. The forward proxy resolves the domain's `site` record through [TON DNS](/foundations/web3/ton-dns/reference#resolve-a-record). The record contains the reverse proxy's [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl) address. TON's [distributed hash table (DHT)](/foundations/network/dht) provides the corresponding IP address and UDP port for reaching that proxy. +1. The forward proxy sends the HTTP request over the [Reliable Large Datagram Protocol (RLDP)](/foundations/network/rldp), which runs over the [ADNL](/foundations/network/adnl). The reverse proxy forwards the request to its configured HTTP server. +1. The HTTP server processes the request. Its response returns through the reverse proxy and forward proxy to the client. + +The [HTTP over RLDP specification](/foundations/network/rldp#rldp-http) describes the request, response, and body transfers. + +## Name resolution + +A `.ton` domain gives a TON Site a readable name. Direct access through `.adnl` uses the reverse proxy's ADNL address without a DNS lookup. + +The `site` record can also contain a [TON Storage BagID](/foundations/web3/ton-storage#bag-contents-and-identity). In that case, the requested path identifies a file within the bag. The same files are [accessible directly through `.bag`](/foundations/web3/ton-proxy/forward-proxy#access-files-over-http), using the hexadecimal BagID. + +Storage access depends on the forward proxy implementation: + +- The C++ proxy forwards requests to a configured TON Storage HTTP gateway. +- Tonutils-Proxy includes a Storage client and retrieves files from the bag's peers. + +## Privacy and relays + + + +ADNL encrypts traffic between the forward and reverse proxies. This encryption does not cover the HTTP connection from the client to the forward proxy or from the reverse proxy to its HTTP server. + +A direct connection exposes the peers' network addresses to each other. [TON Tunnel](/foundations/web3/ton-tunnel) provides relays for ADNL traffic in compatible applications. + +## Next steps + +- [Run a forward proxy](/foundations/web3/ton-proxy/forward-proxy) to access TON Sites and Storage files. +- [Run a reverse proxy](/foundations/web3/ton-proxy/reverse-proxy) to connect an HTTP server to the TON network. +- [Reference](/foundations/web3/ton-proxy/reference) for implementation-specific options, routing, and headers. + +## Sources + +- [C++ HTTP request handling and reverse routing](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/rldp-http-proxy/rldp-http-proxy.cpp#L1061-L1212) +- [DNS site records](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/rldp-http-proxy/DNSResolver.cpp#L68-L94) +- [ADNL peer discovery](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/adnl/adnl-peer.cpp#L107-L149) +- [C++ destination resolution and request transport](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/rldp-http-proxy/rldp-http-proxy.cpp#L1354-L1443) +- [Tonutils-Proxy Storage retrieval](https://github.com/xssnick/Tonutils-Proxy/blob/526ece06e3c6e7398df09039a5ad0e3c144fc6ec/proxy/transport/client.go#L713-L737) diff --git a/content/foundations/web3/ton-proxy/meta.json b/content/foundations/web3/ton-proxy/meta.json new file mode 100644 index 000000000..19eaea95e --- /dev/null +++ b/content/foundations/web3/ton-proxy/meta.json @@ -0,0 +1,10 @@ +{ + "$schema": "../../../../meta-schema.json", + "title": "TON Proxy", + "pages": [ + "index", + "forward-proxy", + "reverse-proxy", + "reference" + ] +} diff --git a/content/foundations/web3/ton-proxy/reference.mdx b/content/foundations/web3/ton-proxy/reference.mdx new file mode 100644 index 000000000..f84c632fd --- /dev/null +++ b/content/foundations/web3/ton-proxy/reference.mdx @@ -0,0 +1,150 @@ +--- +title: "TON Proxy reference" +sidebarTitle: "Reference" +description: "Proxy options, routing, headers, and transport behavior" +--- + +The options and routing describe the C++ `rldp-http-proxy` and its [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl) transport, except where another implementation is named. + +## Forward proxy options + +| Flag | Long form | Description | +| ------------------- | ------------------- | ------------------------------------------------------------- | +| `-p ` | `--port` | HTTP listening port on all network interfaces | +| `-c ` | `--client-port` | UDP port for client ADNL queries | +| `-C ` | `--global-config` | Path to the TON global network config file | +| `-P ` | `--proxy-all` | Disable the TON hostname suffix filter (default `NO`) | +| `-S ` | `--storage-gateway` | ADNL address of a TON Storage gateway for `.bag` resolution | +| `-D ` | `--db` | Database root path | +| `-d` | `--daemonize` | Install the [SIGHUP handler](#data-directory-and-daemon-mode) | +| `-l ` | `--logname` | Log file path | + +## Tonutils-Proxy options + +These options apply to the Tonutils-Proxy v1.8.3 CLI, not to `rldp-http-proxy`. + +| Option | Default | Description | +| ----------------------- | ---------------------------------------------- | ---------------------------------------------------------------- | +| `-addr
` | `127.0.0.1:8080` | HTTP listener address and port | +| `-global-config ` | Mainnet configuration downloaded automatically | Use a local TON network configuration file | +| `-no-http` | Disabled | Block ordinary HTTP requests instead of forwarding them directly | + +## Reverse proxy options + +| Flag | Description | +| --------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| `-a :` | Public IP and UDP port for inbound ADNL connections (published to the TON DHT) | +| `-A ` | Server ADNL identity; see [key generation](/foundations/web3/ton-proxy/reverse-proxy#use-rldp-http-proxy) | +| `-L [:]` | Forward requests for `` to `127.0.0.1` (default ports: 80, 443) | +| `-R [:]@[:]` | Forward requests for `` to a remote HTTP server at `:` | +| `-C ` | Path to the TON global network configuration file | +| `-D ` | Database root path | +| `-d` | Install the [SIGHUP handler](#data-directory-and-daemon-mode) | +| `-l ` | Log file path | + +`` is a comma-separated list of incoming ports. + +## Go reverse proxy options + +These options apply to `tonutils-reverse-proxy` v0.6.0: + +| Option | Meaning | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| `--domain ` | Check the full TON domain's `site` record and prepare an update when it differs from the proxy's identity. Wallet confirmation is required. | +| `--tx-url` | Print the domain-update transaction URL instead of a QR code. | + +## Configuration + +### Data directory and daemon mode + +On Linux and macOS, `-d` installs a SIGHUP handler that closes standard input and starts a new session. It does not immediately launch the process in the background. + +The default database directory is `.`. Server private keys are read from its `keyring/` subdirectory. + +### Tonutils-Proxy configuration + +The v1.8.3 CLI reads `config.json` from its working directory and creates it on first launch. `ADNLKey` contains the base64-encoded ADNL private-key seed. HTTP listener and ordinary-HTTP forwarding settings are [CLI options](#tonutils-proxy-options), not fields in this file. + +### Go reverse proxy configuration + +Version 0.6.0 reads `config.json` from its working directory and creates it on first launch. Nonempty environment variables override the corresponding file values: + +| JSON field | Environment variable | Initial value | Meaning | +| -------------------- | -------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------- | +| `proxy_pass` | `PROXY_PASS` | `http://127.0.0.1:80/` | HTTP backend URL. | +| `external_ip` | `EXTERNAL_IP` | Detected public IP | Address advertised to TON peers in direct mode. | +| `listen_ip` | `LISTEN_IP` | `0.0.0.0` | Local UDP bind address. | +| `port` | `LISTEN_PORT` | Derived from the detected public IP | UDP listener and advertised port in direct mode. | +| `private_key` | `PRIVATE_KEY` | Generated on first launch | Base64-encoded 32-byte Ed25519 seed. Preserving it retains the ADNL identity. | +| `network_config_url` | `NETWORK_CONFIG_URL` | `https://ton-blockchain.github.io/global.config.json` | TON network configuration URL. | + +Environment overrides affect the running process; they are applied after the generated file is saved. Restart the proxy after changing configuration. + + + Both Go implementations store private-key seeds in `config.json`. Restrict access to these files and do not publish their contents. + + +## Routing + +For the C++ proxy, destinations must end in `.ton`, `.adnl`, or `.bag`; other hostnames are rejected with “bad server name”. `-P YES` disables this suffix check. It does not add ordinary Internet DNS forwarding. + +TON DNS resolution reads the `site` category and accepts an ADNL address or a Storage BagID. Bag requests require `-S` and are forwarded to `/gateway//` at that gateway. + +For C++ reverse routing, `-L` maps an incoming hostname and port to localhost; `-R` maps them to a specified backend. Both use ports `80` and `443` when the incoming port list is omitted. `*` is a fallback hostname when no exact hostname matches. A request must also match a configured port. With `-R`, omitting the backend port preserves the incoming port. + +Tonutils-Proxy v1.8.3 uses its TON transport when the HTTP `Host` field ends in `.ton`, `.adnl`, `.t.me`, or `.bag`. This suffix check does not remove an explicit port: `example.ton:80` does not match. Omit explicit ports in TON URLs with this version. Other HTTP requests use ordinary Internet transport unless `-no-http` is set. For a Storage BagID, it retrieves files from peers without the C++ `-S` option. + +## CONNECT + +The C++ proxy supports HTTP `CONNECT` to establish a TCP tunnel over RLDP. On the reverse proxy, the destination must match a configured host and port. This can carry TLS connections and protocols such as WebSocket inside the tunnel. + +## Client information headers + +`tonutils-reverse-proxy` adds the following headers to requests forwarded to its backend: + +- `X-Adnl-Ip`: the connecting client's address as reported by the ADNL connection. +- `X-Adnl-Id`: the connecting client's ADNL node ID. + +The Go forward proxy adds `X-Tonutils-Proxy` to outgoing HTTP requests. It also appends the connected HTTP client's IP address to `X-Forwarded-For`, preserving existing values. + +## Response headers + +The C++ proxy adds version headers when forwarding responses: + +| Header | Added by | Value format | +| ------------------------- | --------------------------- | ----------------------------- | +| `Ton-Proxy-Site-Version` | Reverse proxy (server-side) | `Commit: , Date: ` | +| `Ton-Proxy-Entry-Version` | Forward proxy (client-side) | `Commit: , Date: ` | + +The Go reverse proxy adds `Ton-Reverse-Proxy` to responses. Its value identifies the implementation and build. + +## Errors + +| Implementation | Error or response | Meaning | +| -------------- | ----------------------------- | ----------------------------------------------------------------------------- | +| C++ forward | “bad server name” | Hostname suffix is rejected by the forward-proxy filter. | +| C++ forward | “no DNS entries” | DNS resolution returned no supported destination. | +| C++ forward | “storage gateway is not set” | Bag routing requires a gateway configured with `-S`. | +| C++ forward | “peer does not support RLDP2” | Destination does not advertise the required transport capability. | +| C++ reverse | “502 Bad Gateway” | Hostname or port has no backend mapping, or forwarding to the backend failed. | +| Tonutils-Proxy | “HTTP Not allowed” (HTTP 400) | Ordinary HTTP forwarding is disabled by `-no-http`. | + +[Forward proxy troubleshooting](/foundations/web3/ton-proxy/forward-proxy#troubleshoot) and [reverse proxy troubleshooting](/foundations/web3/ton-proxy/reverse-proxy#troubleshoot) cover connectivity checks. + +## Sources + +- [C++ option parsing](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/rldp-http-proxy/rldp-http-proxy.cpp#L1519-L1650) +- [C++ HTTP request and reverse routing](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/rldp-http-proxy/rldp-http-proxy.cpp#L1061-L1212) +- [DNS resolution](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/rldp-http-proxy/DNSResolver.cpp#L68-L104) +- [ADNL key generation](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/utils/generate-random-id.cpp#L171-L176) +- [Go reverse proxy startup](https://github.com/tonutils/reverse-proxy/blob/300fc0ced8eab48ff5879ce822419d42b8e3a43e/cmd/proxy/main.go#L134-L368) +- [Tonutils-Proxy CLI options](https://github.com/xssnick/Tonutils-Proxy/blob/526ece06e3c6e7398df09039a5ad0e3c144fc6ec/cmd/proxy-cli/main.go#L18-L38) +- [Tonutils-Proxy HTTP routing and client headers](https://github.com/xssnick/Tonutils-Proxy/blob/526ece06e3c6e7398df09039a5ad0e3c144fc6ec/proxy/proxy.go#L61-L124) +- [C++ HTTP listener](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/http/http-server.cpp#L100-L104) +- [Go reverse proxy CLI, configuration, and domain linking](https://github.com/tonutils/reverse-proxy/blob/300fc0ced8eab48ff5879ce822419d42b8e3a43e/cmd/proxy/main.go#L415-L572) +- [Go reverse proxy client headers](https://github.com/tonutils/reverse-proxy/blob/300fc0ced8eab48ff5879ce822419d42b8e3a43e/rldphttp/server.go#L730-L731) +- [Tonutils-Proxy configuration file](https://github.com/xssnick/Tonutils-Proxy/blob/526ece06e3c6e7398df09039a5ad0e3c144fc6ec/cmd/proxy-cli/config/config.go#L23-L45) +- [Tonutils-Proxy Storage transport](https://github.com/xssnick/Tonutils-Proxy/blob/526ece06e3c6e7398df09039a5ad0e3c144fc6ec/proxy/transport/client.go#L713-L737) diff --git a/content/foundations/web3/ton-proxy/reverse-proxy.mdx b/content/foundations/web3/ton-proxy/reverse-proxy.mdx new file mode 100644 index 000000000..7f453ce95 --- /dev/null +++ b/content/foundations/web3/ton-proxy/reverse-proxy.mdx @@ -0,0 +1,203 @@ +--- +title: "How to run a TON reverse proxy" +sidebarTitle: "Run a reverse proxy" +description: "Forward requests from the TON network to an HTTP server" +--- + +Connect an HTTP server to the TON network using either `tonutils-reverse-proxy` or the official C++ `rldp-http-proxy`. This guide uses direct connections over the [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl) on mainnet. Verify access through the proxy before optionally linking a domain. + +## Prerequisites + +- A running HTTP server accessible from the reverse proxy host; the examples use `http://127.0.0.1:80/` +- A public IP address and an inbound UDP port reachable through the host firewall and any intervening NAT +- Outbound UDP access to TON peers and TCP access to the liteservers in the network configuration +- [Tonutils-Proxy v1.8.3](/foundations/web3/ton-proxy/forward-proxy#use-tonutils-proxy) or [C++ `rldp-http-proxy` from TON v2026.08](/foundations/web3/ton-proxy/forward-proxy#use-rldp-http-proxy) running at `127.0.0.1:8080` on the machine used for verification +- For domain linking only: a `.ton` domain controlled by the connected mainnet wallet and funds for the record-update transaction + +From the reverse proxy host, confirm that the HTTP server returns the expected page: + +```bash +curl --noproxy '*' --fail http://127.0.0.1/ +``` + +For another backend address, check that URL instead and configure the chosen proxy to match it. + + + Protect and back up generated private keys to preserve the site's ADNL identity. Linking a domain sends a mainnet transaction. Check the domain and record before confirming; confirmed transactions cannot be rolled back. + + +## Use tonutils-reverse-proxy + +Version 0.6.0 generates a persistent identity and configuration on first launch. + +### Install + +On Linux (x86-64), create a working directory and download the published binary: + +```bash +mkdir -p ton-reverse-proxy +cd ton-reverse-proxy +wget https://github.com/tonutils/reverse-proxy/releases/download/v0.6.0/tonutils-reverse-proxy-linux-amd64 +chmod +x tonutils-reverse-proxy-linux-amd64 +``` + +For another platform, use the corresponding binary from the [same release](https://github.com/tonutils/reverse-proxy/releases/tag/v0.6.0). + +
+ Build from source instead + + Building requires [Go 1.26.0](https://go.dev/dl/#go1.26.0) and Git: + + ```bash + git clone --branch v0.6.0 https://github.com/tonutils/reverse-proxy + cd reverse-proxy + go build -ldflags "-w -s -X main.GitCommit=$(git describe --tags --always --dirty)" -o build/tonutils-reverse-proxy cmd/proxy/main.go + ``` + + Use `./build/tonutils-reverse-proxy` in place of `./tonutils-reverse-proxy-linux-amd64` in the start commands. Keep using the repository directory as the working directory. +
+ +### Initialize the configuration + +Run the proxy without a domain: + +```bash +./tonutils-reverse-proxy-linux-amd64 +``` + +The first launch creates `config.json` in the working directory and attempts to start the proxy. + +Once `config.json` has been created, stop the process with Ctrl+C before editing it. Keep and back up this file; subsequent launches reuse its identity and settings. + +### Configure the backend and network + +Edit the generated `config.json`, preserving [`private_key`](/foundations/web3/ton-proxy/reference#go-reverse-proxy-configuration): + +- Set [`proxy_pass`](/foundations/web3/ton-proxy/reference#go-reverse-proxy-configuration) to the HTTP backend URL if it differs from `http://127.0.0.1:80/`. +- Check that [`external_ip`](/foundations/web3/ton-proxy/reference#go-reverse-proxy-configuration) is the public IP address through which peers can reach the proxy. +- Keep [`listen_ip`](/foundations/web3/ton-proxy/reference#go-reverse-proxy-configuration) as `0.0.0.0` to listen on all local interfaces, or select the local interface to bind. +- Read [`port`](/foundations/web3/ton-proxy/reference#go-reverse-proxy-configuration), the UDP port selected on first launch from the detected public IP address. Change it if necessary. + +Allow inbound UDP traffic on this port and outbound UDP traffic to TON peers. If behind NAT, forward the same UDP port to the proxy host. Update these rules whenever the port changes. + +Existing configuration values are reused on restart; an IP address change requires updating `external_ip`. + +### Start the proxy + +From the same working directory, start the proxy again: + +```bash +./tonutils-reverse-proxy-linux-amd64 +``` + +Record `ADNL_address` from the startup log as ``, the user-friendly identity used for direct access. Retain `hex_address`, its hexadecimal form, for manual domain linking. + +Keep the process running and continue to [Verify direct access](#verify-direct-access). + +## Use rldp-http-proxy + +The official C++ implementation uses a separately generated ADNL identity. + +### Prepare the binaries + +Extract `rldp-http-proxy` and `generate-random-id` from the archive for the target platform in [TON v2026.08](https://github.com/ton-blockchain/ton/releases/tag/v2026.08) into a working directory. Save the [mainnet configuration](https://ton-blockchain.github.io/global.config.json) there as `global.config.json`. + +Run the following commands from that directory. By default, the proxy reads private keys from its [database directory](/foundations/web3/ton-proxy/reference#data-directory-and-daemon-mode) under `keyring/`. + +### Generate an ADNL identity + +Generate a persistent ADNL address: + +```bash +chmod +x rldp-http-proxy generate-random-id +mkdir keyring +./generate-random-id -m adnlid +``` + +The command prints a hexadecimal key identifier followed by a user-friendly ADNL address. It writes the private key to a file named after the hexadecimal identifier. + +Record the user-friendly address as ``. Replace `` below with the hexadecimal identifier and move the private key into the keyring: + +```bash +mv "" keyring/ +``` + +Retain both address forms and back up the private key. On restart, reuse the same working directory, keyring, and ADNL address; do not generate a new identity. + +### Configure and start the proxy + + + +Allow inbound UDP traffic on port `3333` and outbound UDP traffic to TON peers. If behind NAT, forward UDP port `3333` to the proxy host. + +Replace `` with the reachable public IP address and `` with the generated user-friendly address: + +```bash +./rldp-http-proxy -a :3333 -L '*:80' -C global.config.json -A -l tonsite.log +``` + +[`-a`](/foundations/web3/ton-proxy/reference#reverse-proxy-options) sets the public endpoint and UDP port. [`-A`](/foundations/web3/ton-proxy/reference#reverse-proxy-options) selects the identity loaded from the keyring. [`-L '*:80'`](/foundations/web3/ton-proxy/reference#reverse-proxy-options) routes requests for any hostname on HTTP port `80` to `127.0.0.1:80`. + +For another backend, use [`-R`](/foundations/web3/ton-proxy/reference#routing) to configure its address and accepted hostnames and ports. + +The process stays in the foreground and writes logs to `tonsite.log`. Keep it running, then continue to [Verify direct access](#verify-direct-access). + +## Verify direct access + + + +On the machine running the forward proxy, replace `` with the user-friendly address recorded during setup: + +```bash +curl --noproxy '' --proxy http://127.0.0.1:8080 --fail "http://.adnl/" +``` + +Confirm that the response contains the same page returned by the backend check. If the application restricts allowed hostnames, allow `.adnl` for this request. + +## Link a domain (optional) + + + +Link the domain after direct access works, using one of the following methods. + +For `tonutils-reverse-proxy`, stop the process and restart it from the same directory with [`--domain`](/foundations/web3/ton-proxy/reference#go-reverse-proxy-options), using the full `.ton` name as ``: + +```bash +./tonutils-reverse-proxy-linux-amd64 --domain +``` + +If the domain's [`site` record](/foundations/web3/ton-dns/reference#record-categories) differs from the proxy's identity, a QR code appears. Scan it with a compatible TON wallet and confirm the update from the domain owner's wallet. The proxy waits for the record to update before starting its server. No transaction is requested if the record already matches. + +For either implementation, manual linking is also available through [Manage records](/foundations/web3/ton-dns/manage-domains#manage-records). Use the hexadecimal address from the C++ key-generation output or the Go `hex_address` log field as the domain's `site` record. + +Open `http:///` through the forward proxy and confirm that the same backend page loads. Allow that hostname in the application's configuration if required. Domain linking does not need to be repeated while the record points to the same ADNL identity. + +## Troubleshoot + +| Problem | Check | +| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| Backend check fails | Check the HTTP server's address, port, and process before investigating TON routing. | +| Go configuration is not created | Check the working directory's write permissions and outbound HTTPS access for public-IP detection. | +| Go startup fails while connecting to liteservers | Check outbound TCP access to the liteservers in the network configuration and inspect the startup error. | +| Go proxy waits for a domain update | Complete the wallet-confirmed update, or restart without `--domain` to verify direct access first. | +| Process starts but direct access fails | Check the advertised IP, UDP port, firewall, NAT forwarding, and proxy logs. | +| C++ proxy cannot load the ADNL key | Run it from the directory containing `keyring`, or set the [database path](/foundations/web3/ton-proxy/reference#reverse-proxy-options) accordingly. | +| Direct URL returns HTTP `502` | Check the backend's availability and the reverse proxy's hostname and port mapping. | +| Direct URL works but the domain fails | Check the domain's `site` record and the application's allowed hostnames. | + +## Sources + +- [Go version requirement](https://github.com/tonutils/reverse-proxy/blob/300fc0ced8eab48ff5879ce822419d42b8e3a43e/go.mod#L3) +- [Go build command](https://github.com/tonutils/reverse-proxy/blob/300fc0ced8eab48ff5879ce822419d42b8e3a43e/Makefile#L3-L6) +- [Go startup and domain setup](https://github.com/tonutils/reverse-proxy/blob/300fc0ced8eab48ff5879ce822419d42b8e3a43e/cmd/proxy/main.go#L134-L368) +- [Go configuration creation and loading](https://github.com/tonutils/reverse-proxy/blob/300fc0ced8eab48ff5879ce822419d42b8e3a43e/cmd/proxy/main.go#L415-L572) +- [C++ key generation](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/utils/generate-random-id.cpp#L171-L176) +- [C++ identity loading and network startup](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/rldp-http-proxy/rldp-http-proxy.cpp#L845-L982) +- [C++ routing options](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/rldp-http-proxy/rldp-http-proxy.cpp#L1519-L1632) diff --git a/content/foundations/web3/ton-sites.mdx b/content/foundations/web3/ton-sites.mdx deleted file mode 100644 index 3c9fda874..000000000 --- a/content/foundations/web3/ton-sites.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: "TON Sites" -description: "Web services accessible through TON Network via ADNL and RLDP" ---- - -TON Sites are web services that support an HTTP interface. They use RLDP datagrams over the ADNL protocol to transfer HTTP queries and responses, residing entirely within the TON Network. A TON Site is identified by its ADNL address rather than an IP address, so no IP address appears in the URL or at the HTTP layer. - -## How TON Sites work - -When a user visits a TON Site: - -1. The TON Proxy client accepts an HTTP request from an ordinary web browser. -1. The proxy resolves the target address, either through TON DNS (for human-readable `.ton` domains) or directly from a known ADNL address. -1. The HTTP request is encapsulated in RLDP datagrams and sent through the ADNL network to the TON Site's abstract address. -1. The TON Site processes the request and returns an HTTP response. - -## ADNL address as identity - -Every TON Site is identified by a 256-bit ADNL abstract address derived from its public key. Because the ADNL address is independent of the server's IP address, a site is not tied to any particular server location. - -## Host a TON Site - -A TON Site requires a reverse proxy that accepts inbound ADNL connections and forwards them to a local web server. Two implementations are available. - -### Use `rldp-http-proxy` - -`rldp-http-proxy` is the reverse proxy from the official TON monorepo. Key generation is manual. - -**Step 1.** Generate a persistent ADNL address: - -```bash -mkdir keyring -utils/generate-random-id -m adnlid -``` - -The command prints two values to stdout: the hex address and its user-friendly form: - -```text -45061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3 -``` - -It also writes the private key to a file named after the hex address. Move it into the keyring directory: - -```bash -mv 45061C1D* keyring/ -``` - -**Step 2.** Start the reverse proxy, using the user-friendly ADNL address from step 1: - -```bash -rldp-http-proxy -a :3333 -L '*' -C global.config.json -A -d -l tonsite.log -``` - -| Flag | Description | -| ------------------------------------- | ------------------------------------------------------------------------------ | -| `-a :` | Public IP and UDP port for inbound ADNL connections (published to the TON DHT) | -| `-A ` | ADNL address generated in step 1 | -| `-L [:]` | Forward requests for `` to `127.0.0.1` (default ports: 80, 443) | -| `-R [:]@:` | Forward requests for `` to a remote HTTP server at `:` | -| `-C ` | Path to the TON global network configuration file | -| `-D ` | Database root path | -| `-d` | Daemonize the process | -| `-l ` | Log file path | - -### Use `tonutils-reverse-proxy` - -`tonutils-reverse-proxy` is a Go implementation that handles key generation and domain linking automatically. - -**Install on Linux:** - -```bash -wget https://github.com/tonutils/reverse-proxy/releases/latest/download/tonutils-reverse-proxy-linux-amd64 -chmod +x tonutils-reverse-proxy-linux-amd64 -``` - -To build from source: - -```bash -git clone https://github.com/tonutils/reverse-proxy -cd reverse-proxy && make build -``` - -Run with the target `.ton` domain: - -```bash -./tonutils-reverse-proxy --domain .ton -``` - -On first run, the proxy generates a persistent ADNL key pair and displays a QR code. Scan it with a compatible TON wallet to confirm domain ownership and link the ADNL address to the domain. - -The web server must listen on `http://127.0.0.1:80`. The proxy adds two headers to each forwarded request: - -- `X-Adnl-Ip`: the IP address of the connecting client as seen by the ADNL network. -- `X-Adnl-Id`: the ADNL node ID of the connecting client. - -### Domain assignment - -To assign the ADNL address to a `.ton` domain, open the domain in the TON DNS management interface, paste the ADNL address into the "Site" field, and confirm the transaction with the domain owner's wallet. For record types and resolution details, see [TON DNS](/foundations/web3/ton-dns). - -## Domain name resolution - -### TON DNS - -A `dns_adnl_address` record in TON DNS maps a `.ton` domain name to the ADNL address of the TON Site. The proxy client resolves this record and connects to the correct ADNL address. See [TON DNS](/foundations/web3/ton-dns) for the full record type specification. - -### Direct access via ADNL address - -TON Sites can also be accessed directly by their ADNL address, without DNS resolution. - -## Related components - -- **ADNL**: the abstract datagram network layer providing transport for TON Sites. -- **RLDP**: the reliable large datagram protocol over ADNL for HTTP transfer. -- [TON Proxy](/foundations/web3/ton-proxy): bridges HTTP requests from a conventional browser to the ADNL network. -- [TON DNS](/foundations/web3/ton-dns): maps `.ton` domains to ADNL addresses. diff --git a/content/foundations/web3/ton-sites/index.mdx b/content/foundations/web3/ton-sites/index.mdx new file mode 100644 index 000000000..d3636090e --- /dev/null +++ b/content/foundations/web3/ton-sites/index.mdx @@ -0,0 +1,41 @@ +--- +title: "TON Sites overview" +sidebarTitle: "Overview" +description: "Publish websites on TON using an HTTP server or TON Storage" +--- + +TON Sites are websites and HTTP applications accessible through the TON network. A site can run on an HTTP server connected to TON, or its static files can be distributed through TON Storage. + +Visitors use a compatible TON client or a browser configured with a [forward proxy](/foundations/web3/ton-proxy/forward-proxy). The publication method determines how the site is hosted and updated. + +## Choose how to publish + +With a web server, a reverse proxy forwards requests from the TON network to the HTTP application. The server can process requests, access databases, and generate responses. The reverse proxy's [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl) address identifies it on the TON network. + +With TON Storage, the site's HTML, CSS, JavaScript, and other assets are shared as a [bag](/foundations/web3/ton-storage#bags-and-bagids), identified by its BagID. The BagID identifies a particular version of the bag, including its content and metadata. Changing the published files produces a new BagID. + +JavaScript delivered from a bag can run in the browser. Storage serves the files; it does not run server-side application code. + +| Property | Web server | TON Storage | +| ----------- | ------------------------------------------------ | ------------------------------------------------------------------- | +| Content | Static files and dynamically generated responses | An immutable bag of files | +| Backend | Runs on the server | Not executed by Storage | +| Destination | The reverse proxy's ADNL address | The bag's BagID | +| Updates | Update the files or application on the server | Create and share a new bag, then update the domain's record if used | + +## Domain names and access + + + +A TON DNS domain gives the site a readable name. Its `site` record points to the destination for the chosen publication method: the reverse proxy's ADNL address or the bag's BagID. + +The domain name can stay the same when its destination changes: [update its record](/foundations/web3/ton-dns/manage-domains#manage-records). + +Access without a domain is also possible through a `.adnl` address or a [`.bag` address](/foundations/web3/ton-proxy/forward-proxy#access-files-over-http), depending on the publication method and client. + +## Next steps + +- [Publish with a web server](/foundations/web3/ton-sites/web-server) to expose an HTTP application through the TON network. +- [Publish on TON Storage](/foundations/web3/ton-sites/storage) to distribute a versioned set of static files. diff --git a/content/foundations/web3/ton-sites/meta.json b/content/foundations/web3/ton-sites/meta.json new file mode 100644 index 000000000..d25e036ff --- /dev/null +++ b/content/foundations/web3/ton-sites/meta.json @@ -0,0 +1,9 @@ +{ + "$schema": "../../../../meta-schema.json", + "title": "TON Sites", + "pages": [ + "index", + "web-server", + "storage" + ] +} diff --git a/content/foundations/web3/ton-sites/storage.mdx b/content/foundations/web3/ton-sites/storage.mdx new file mode 100644 index 000000000..bbf67838c --- /dev/null +++ b/content/foundations/web3/ton-sites/storage.mdx @@ -0,0 +1,90 @@ +--- +title: "How to publish a TON Site on TON Storage" +sidebarTitle: "Publish on TON Storage" +description: "Publish static site files as an immutable bag and update the domain" +--- + +Publish static website files as a TON Storage bag, then optionally associate the bag with a `.ton` domain. + +## Prerequisites + +- A [TON Storage daemon and connected CLI](/foundations/web3/ton-storage/get-started#start-the-daemon) using TON v2026.08 +- [Tonutils-Proxy v1.8.3](/foundations/web3/ton-proxy/forward-proxy#use-tonutils-proxy) running at `127.0.0.1:8080` on the machine used to verify the site +- For a `.ton` domain: a domain controlled by the publishing wallet on mainnet and funds for its record-update transaction + +This guide uses Tonutils-Proxy's integrated Storage client for verification. For the C++ proxy, follow [Configure the gateway](/foundations/web3/ton-proxy/forward-proxy#configure-the-gateway). + +## Prepare the site files + +Use the application's static build output, not its source directory or backend code. For a minimal example, save the following as `index.html` in a new directory named `site`: + +```html + + + + + + TON Storage site + + +

Hello from TON Storage

+ + +``` + +Place `index.html` at the root of the directory to share. Include the HTML, CSS, JavaScript, images, and other assets needed by the site. Exclude private files and build-time credentials. + +Tonutils-Proxy serves `index.html` for the root URL. Other paths must match files in the bag; missing paths return `404`, without automatically falling back to `index.html`. Check direct links to nested pages when preparing a client-side application. + +## Create and share the bag + +Follow [Create and share a bag](/foundations/web3/ton-storage/get-started#create-and-share-a-bag), using the absolute path to the `site` directory as ``. Share the directory itself so `index.html` is at the bag's root. + +Record the returned BagID as ``. Check the bag's file list and keep the daemon online with uploads enabled. Creating a bag does not automatically replicate it to a paid provider. + +## Verify the site + +Through the running forward proxy, request the entry page: + +```bash +curl --noproxy '' --proxy http://127.0.0.1:8080 --fail "http://.bag/index.html" +``` + +For the sample site, the response contains `

Hello from TON Storage

`. Open `http://.bag/` in the proxy-configured browser and verify that the page and its assets load. + +## Link a domain + + + Linking a domain sends a mainnet transaction. Check the domain and BagID before confirming; confirmed transactions cannot be rolled back. + + +Follow [Manage records](/foundations/web3/ton-dns/manage-domains#manage-records) to set the domain's [`site` record](/foundations/web3/ton-dns/reference#record-categories) to the BagID with Hosting in TON Storage enabled. Use the site record, not the separate TON Storage field. + +Open `http:///`, replacing `` with the full `.ton` domain name, and confirm that the same site loads. + +## Publish a new version + +1. Update the static files and create a new bag using the same sharing procedure. +1. Verify the new bag through its `.bag` URL before changing the domain. +1. If using a domain, update its `site` record to the new BagID and verify the domain again. Otherwise, share the new `.bag` URL. + +Changing the source files does not modify the previous bag. Keep earlier bags available to preserve their direct URLs or point the domain back to an earlier version. + +[Store with a provider](/foundations/web3/ton-storage/store-with-provider) to keep another copy beyond the publishing daemon. + +## Troubleshoot + +| Problem | Check | +| ------------------------------ | --------------------------------------------------------------------------------------------- | +| Root page returns `404` | Check that `index.html` is at the bag's root. | +| A nested page returns `404` | Check the exact file path; Tonutils-Proxy does not provide an automatic application fallback. | +| Files cannot be downloaded | Keep a peer online with the complete bag and uploads enabled. | +| Domain shows the wrong version | Resolve its `site` record and compare the BagID with the published version. | + +## Sources + +- [Tonutils-Proxy file paths and root page](https://github.com/xssnick/Tonutils-Proxy/blob/526ece06e3c6e7398df09039a5ad0e3c144fc6ec/proxy/transport/client.go#L360) +- [Bag identity and metadata](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/TorrentInfo.cpp#L27) diff --git a/content/foundations/web3/ton-sites/web-server.mdx b/content/foundations/web3/ton-sites/web-server.mdx new file mode 100644 index 000000000..5a93b7a14 --- /dev/null +++ b/content/foundations/web3/ton-sites/web-server.mdx @@ -0,0 +1,71 @@ +--- +title: "How to publish a TON Site with a web server" +sidebarTitle: "Publish with a web server" +description: "Connect an HTTP application to TON and verify access" +--- + +Publish an existing HTTP application through a TON reverse proxy over the [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl). The application continues to run on its HTTP server. + +## Prerequisites + +- A running HTTP application accessible from the reverse proxy host +- The [tonutils-reverse-proxy v0.6.0 or C++ TON v2026.08 binaries and network configuration](/foundations/web3/ton-proxy/reverse-proxy) +- [Tonutils-Proxy v1.8.3](/foundations/web3/ton-proxy/forward-proxy#use-tonutils-proxy) or [C++ `rldp-http-proxy` from TON v2026.08](/foundations/web3/ton-proxy/forward-proxy#use-rldp-http-proxy) running at `127.0.0.1:8080` on the machine used to verify the site +- For a `.ton` domain: a domain controlled by the publishing wallet on mainnet and funds for its record-update transaction + + + Protect and back up the reverse proxy's private key to retain its ADNL identity. Linking a domain sends a mainnet transaction; check the domain and destination before confirming. Confirmed transactions cannot be rolled back. + + +## Check the application + +From the reverse proxy host, request a page from the application. Replace `` with its HTTP origin, including the port but no trailing slash. Use `` for the path to check, starting with `/` (for example, `/` or `/about.html`): + +```bash +curl --noproxy '*' --fail "" +``` + +Confirm that the response contains the expected page. Keep the application running throughout publication. + +## Connect the reverse proxy + +Follow [Run a reverse proxy](/foundations/web3/ton-proxy/reverse-proxy), choosing one implementation. Configure its backend to match the application URL. The guide's defaults use port `80`; for another address, use the C++ [`-R` option](/foundations/web3/ton-proxy/reference#reverse-proxy-options) or the Go implementation's [`proxy_pass` setting](/foundations/web3/ton-proxy/reference#go-reverse-proxy-configuration). + +For the initial direct-access check, start `tonutils-reverse-proxy` without [`--domain`](/foundations/web3/ton-proxy/reference#go-reverse-proxy-options). When supplied, that option can wait for a domain update before the server starts. Domain linking is an optional later step in this guide. + +Record the proxy's user-friendly ADNL address as `` for direct access, and retain its hexadecimal form for manual domain linking. The C++ key-generation command prints both forms; the Go proxy logs them as `ADNL_address` and `hex_address`. This identity is independent of the server's IP address. Preserve the private key to keep the same identity when moving the proxy to another host. + +## Verify direct access + +If the application restricts allowed hostnames, allow `.adnl` for this check and the `.ton` domain if one will be used. + +On the machine running the forward proxy, request the same ``: + +```bash +curl --noproxy '' --proxy http://127.0.0.1:8080 --fail "http://.adnl" +``` + +Confirm that the expected application page is returned. Then open the same URL in the proxy-configured browser and check its assets and application requests. + +## Link a domain + +To use a `.ton` name, follow [Manage records](/foundations/web3/ton-dns/manage-domains#manage-records) and set the domain's [`site` record](/foundations/web3/ton-dns/reference#record-categories) to the reverse proxy's ADNL address. For manual entry on dns.ton.org, use the recorded hexadecimal form. + +Open `http://` through the forward proxy, replacing `` with the full domain name. Confirm that the same application loads. + +## Publish updates + +Updating the website does not require changing its DNS record if the reverse proxy's ADNL address stays the same. + +## Troubleshoot + +| Problem | Check | +| ---------------------------------------- | ---------------------------------------------------------------------------------- | +| The backend check fails | Check the application address, port, and process before investigating TON routing. | +| The backend works but the ADNL URL fails | Check the reverse proxy logs, routing configuration, and ADNL connectivity. | +| The ADNL URL works but the domain fails | Check the domain's `site` record and the application's hostname configuration. | + +The [TON Proxy reference](/foundations/web3/ton-proxy/reference) lists proxy options and transport behavior. diff --git a/content/foundations/web3/ton-storage.mdx b/content/foundations/web3/ton-storage.mdx deleted file mode 100644 index d38409d08..000000000 --- a/content/foundations/web3/ton-storage.mdx +++ /dev/null @@ -1,314 +0,0 @@ ---- -title: "TON Storage" -description: "Distributed file storage for the TON Blockchain using torrent-like technology and on-chain payment contracts" ---- - -TON Storage is a distributed file storage system on the TON Network. Files are shared using a torrent-like protocol, with optional on-chain smart contracts for paid storage guarantees. The TON Blockchain uses TON Storage to distribute archive copies of blocks and state snapshots. - -The [storage provider guide](#run-a-storage-provider) below explains how to deploy, configure, and operate a TON Storage provider. - -## Bags - -Files are organized into _bags_, each identified by a unique 256-bit `BagID` (the hash of the torrent info cell). A bag can contain a single file or a directory. - -Files in a bag are split into **128 KiB chunks**. A Merkle tree built from SHA-256 hashes allows verification of individual chunks without downloading the full bag. Bag metadata can be exported as a metafile. - -## Peer discovery - -Nodes that store a bag register in the TON DHT under a key derived from the `BagID`. Clients query the DHT to find seeder addresses for a given bag. - -## Storage daemon - -`storage-daemon` is the official implementation, distributed as part of the TON software suite. To start: - -```bash -storage-daemon -v 3 -C global.config.json -I :3333 -p 5555 -D storage-db -``` - -There, - -- `-v` - log verbosity, where `3` = INFO -- `-C` - path to the global network config -- `-I` - ADNL listen IP and port, where `` is the public or reachable address of the host -- `-p` - TCP port for the console interface -- `-D` - path to the daemon database — CLI keys are generated inside the `cli-keys/` subdirectory on first start - -### Manage bags - -| Command | Description | -| ---------------------------------- | ---------------------------------------------------------- | -| `create -d "description"` | Create a new bag from a file or directory | -| `add-by-hash -d ` | Add a bag by its `BagID` | -| `add-by-meta -d ` | Add a bag from a metafile | -| `list` | List all bags | -| `list --hashes` | List bags with their `BagID`s | -| `get ` | Show full bag information | -| `get-peers ` | Show peers connected for a bag | -| `get-meta ` | Export the bag metafile | -| `download-pause ` | Pause a download | -| `download-resume ` | Resume a download | -| `priority-name ` | Set download priority for a file (0 = skip, 255 = highest) | - -To download only specific files from a bag, use the `--partial` flag when adding: - -```bash -add-by-hash --partial file1.txt file2.txt -``` - -Files not listed are assigned priority 0 and are not downloaded. - -## Storage providers - -A storage provider is a node that stores bags for a fee, backed by an on-chain smart contract. The provider system has two components: - -- Smart contract: deployed on the TON Blockchain, stores the Merkle tree hash of each bag, issues proof challenges, and manages client payments. -- `storage-daemon`: runs on the provider's machine, downloads bags, serves data to peers, and submits storage proofs to the contract. - -Provider workflow: - -1. The provider deploys a main smart contract and shares its address with clients. -1. A client creates a bag and sends a storage request to the provider contract. -1. The provider contract deploys a per-bag storage contract and notifies the client. -1. The provider downloads the bag and activates the per-bag contract. -1. The client transfers payment. The provider submits periodic Merkle proofs to prove data possession. -1. When the client balance reaches zero or either party closes the contract, remaining funds return to the client and the contract self-destructs. - -Storage pricing is expressed in **nanogram per megabyte per day**. - -## Integration with TON DNS - -A `.ton` domain can point to a bag using the `dns_storage_address` record: - -```tlb -dns_storage_address#7473 bag_id:bits256 = DNSRecord; -``` - -See [TON DNS](/foundations/web3/ton-dns#dns-record-types) for all record types. - -## Ecosystem use cases - -- NFT metadata: NFT collections can reference off-chain media and metadata stored as bags, using the `BagID` as a stable content identifier. Individual files within a bag are addressed using the `tonstorage:///path` URI scheme. -- [Static TON Sites](/foundations/web3/ton-sites): a bag containing HTML and static assets can be served as a TON Site by combining TON Storage, [TON DNS](/foundations/web3/ton-dns), and [TON Proxy](/foundations/web3/ton-proxy). - -## Run a storage provider - -Run the `storage-daemon` in provider mode, deploy its main contract, and manage paid storage contracts. - - - Provider commands deploy contracts, transfer funds, close storage contracts, and may delete local bag files. Test the complete workflow on testnet first. Mainnet transactions and contract closures cannot be rolled back. - - Keep independent backups of required files, verify every address and network, and use a small initialization transfer. - - -### Prerequisites - -- `storage-daemon` and `storage-daemon-cli` from the same [TON release](https://github.com/ton-blockchain/ton/releases/tag/v2026.08) -- A global configuration file for the target network: [mainnet](https://ton-blockchain.github.io/global.config.json) or [testnet](https://ton-blockchain.github.io/testnet-global.config.json) -- A funded wallet on the target network -- A public IP address and reachable [ADNL](/foundations/network/adnl) port - -### Start provider mode - -1. Start the `storage-daemon` with `-P`: - - ```bash - storage-daemon -v 3 -P \ - -C \ - -I : \ - -p \ - -D \ - ``` - - There, - - - `` is the target network's global configuration file. - - `` and `` identify the public ADNL endpoint. - - `` is the local CLI control port. - - `` is the daemon's persistent data directory. - - On its first launch, the daemon creates CLI keys under `/cli-keys`. - -1. Connect `storage-daemon-cli` to the control interface: - - ```bash - storage-daemon-cli \ - -I 127.0.0.1: \ - -k /cli-keys/client \ - -p /cli-keys/server.pub - ``` - -### Deploy the provider contract - -Run the deployment command inside `storage-daemon-cli`: - -```bash -deploy-provider -``` - - - Use testnet for the first deployment. The command prints an address that requires a non-bounceable initialization message containing 1 GRAM. Verify the network and address before sending funds. A transfer to the wrong network or address cannot be recovered. - - -Do not attach a large balance to the initialization message. Verify the deployed provider: - -```bash -get-provider-info -``` - -Fund the deployed provider contract separately to cover later transaction fees. Increase the balance only after verifying the deployment. - -### Configure capacity - -Set the maximum number and total size of managed storage contracts: - -```bash -set-provider-config \ - --max-contracts \ - --max-total-size -``` - -There, - -- `` is the maximum number of concurrent storage contracts. -- `` is the maximum combined bag size in bytes. - -### Configure contract terms - -Keep new requests disabled while configuring the on-chain terms: - -```bash -set-provider-params --accept 0 \ - --rate \ - --max-span \ - --min-file-size \ - --max-file-size -``` - -There, - -- `` is the price per megabyte per day in nanograms. -- `` is the maximum interval between storage proofs. -- `` and `` define the accepted bag-size range. - -Omitted flags retain their prior values. Wait for each on-chain update and verify it with `get-provider-info` before submitting another update. - -Enable requests after verifying every parameter: - -```bash -set-provider-params --accept 1 -``` - -The daemon then downloads accepted bags, distributes them to peers, and submits storage proofs. - -### Request storage from a provider - -1. Inspect a provider's on-chain terms by its contract address: - - ```bash - get-provider-params - ``` - - The result states whether the provider accepts contracts, its bag-size limits, its rate, and its maximum proof interval. - -1. Create a bag with the [storage daemon bag commands](/foundations/web3/ton-storage#manage-bags), record its `BagID`, and generate a request body: - - ```bash - new-contract-message \ - \ - --query-id \ - --provider - ``` - - There, - - - `` is the bag's 256-bit identifier. - - `` receives the internal message body, not a complete message. - - `` is an integer from `0` through `2^64 - 1`. - - Large bags can take longer to process. Review the rate and proof interval printed by the command before sending the body. The provider contract rejects the request if its parameters change before processing. - -1. Send the generated body in a bounceable internal message to the provider contract. A successful deployment returns [`0xbf7bd0c1`](https://github.com/ton-blockchain/ton/blob/v2026.08/storage/storage-daemon/smartcont/constants.fc#L4) with the original query ID. After the provider downloads the bag and activates the contract, it returns [`0xd4caedcd`](https://github.com/ton-blockchain/ton/blob/v2026.08/storage/storage-daemon/smartcont/constants.fc#L5). - -### Monitor the client balance - -The storage contract deducts provider earnings from the client balance according to the configured rate. The initial balance comes from the storage request message. Any wallet can top up the storage contract with a transfer. - -Call [`get_storage_contract_data`](https://github.com/ton-blockchain/ton/blob/v2026.08/storage/storage-daemon/smartcont/storage-contract.fc#L222) to inspect the contract. Its second return value, `balance`, is the unpaid client balance. - -A storage contract can close when: - -- The provider declines it before activation. -- Its client balance reaches `0`. -- The provider closes it. -- The client sends [`0x79f937ea`](https://github.com/ton-blockchain/ton/blob/v2026.08/storage/storage-daemon/smartcont/constants.fc#L3) with any 64-bit query ID from the client's wallet. - -### Operate active contracts - -List active contracts and their balances: - -```bash -get-provider-info --contracts --balances -``` - -`Client$` is the unpaid client balance. The difference between `Contract$` and `Client$` is available provider earnings. - -Withdraw earnings from one per-bag storage contract managed by the provider: - -```bash -withdraw -``` - -Withdraw from every contract with at least 1 GRAM available: - -```bash -withdraw-all -``` - -### Close a storage contract - - - Closing a contract may delete its local bag files when no other active contract uses the bag. Keep an independent copy before closing the contract. The on-chain closure cannot be rolled back. - - -Close one provider-managed contract: - -```bash -close-contract -``` - -Closing transfers available provider earnings to the main provider contract. - -### Transfer provider funds - - - Test transfers with a small amount on testnet. Verify the destination, amount, and network before sending. Mainnet transfers cannot be rolled back. - - -Transfer nanograms from the main provider contract: - -```bash -send-coins -send-coins --message "" -``` - -There, - -- `` is the receiving account. -- `` is the transferred amount in nanograms. -- `` is an optional text message. - -### Protect provider data - -The `list` command shows all bags managed by the daemon. Do not remove these bags or use the provider daemon to manage unrelated bags. Keep independent copies of data that must remain available after a storage contract closes. diff --git a/content/foundations/web3/ton-storage/get-started.mdx b/content/foundations/web3/ton-storage/get-started.mdx new file mode 100644 index 000000000..dfdb09032 --- /dev/null +++ b/content/foundations/web3/ton-storage/get-started.mdx @@ -0,0 +1,174 @@ +--- +title: "Get started with TON Storage" +sidebarTitle: "Get started" +description: "Start a storage daemon, share a bag, and download files" +--- + +Start the official TON Storage daemon, create and share a bag, and download files from another peer. + +## Prerequisites + +- `storage-daemon` and `storage-daemon-cli` from the same [TON release](https://github.com/ton-blockchain/ton/releases/tag/v2026.08) +- A global configuration file for the target network: [mainnet](https://ton-blockchain.github.io/global.config.json) or [testnet](https://ton-blockchain.github.io/testnet-global.config.json) +- A public IP address and reachable [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl) port +- A file or directory to share, and disk space for the copied and downloaded files +- A BagID supplied by another publisher, or a second daemon to download the bag created below + +## Start the daemon + +Start [`storage-daemon`](/foundations/web3/ton-storage/reference#daemon-and-cli-options): + +```bash +storage-daemon -v 3 \ + -C \ + -I : \ + -p \ + -D +``` + +There, + +- `` is the target network's global configuration file. +- `` and `` identify the public ADNL endpoint. +- `` is the local CLI control port. +- `` is the daemon's persistent data directory. + +On its first launch, the daemon creates CLI keys under `/cli-keys`. + + + `/cli-keys/client` is a private key that authorizes control of the daemon. Keep this file confidential and restrict access to it. + + +## Connect the CLI + +Connect [`storage-daemon-cli`](/foundations/web3/ton-storage/reference#daemon-and-cli-options) to the control interface: + +```bash +storage-daemon-cli \ + -I 127.0.0.1: \ + -k /cli-keys/client \ + -p /cli-keys/server.pub +``` + +Run the remaining commands inside `storage-daemon-cli` on the same host as the daemon. Run `list` to check the connection; a new database has no bags. + +## Create and share a bag + +Replace `` with the absolute path to the file or directory: + +```bash +create --copy "" +``` + +The CLI prints “Bag created” followed by the bag information, including `BagID =` and its 64-character hexadecimal identifier. Use this identifier as `` below. + +[`--copy`](/foundations/web3/ton-storage/reference#bag-command-options) copies the files into the daemon's storage directory. Allow enough disk space for this additional copy. Sharing is enabled by default. + +Keep the daemon running to serve the bag. Creating a bag does not automatically arrange paid storage with a provider. + +Inspect the bag: + +```bash +get +``` + +Check that the file list matches the source and that `Downloaded:` shows “(completed)”. An `Upload speed:` line indicates that sharing is enabled; a speed of zero can mean that no peer is requesting data. + +Share the BagID with a recipient. A successful download on another daemon verifies that the bag is reachable. To publish changed files, create a new bag from the updated source and distribute its new BagID. + +## Download a bag + +Use a BagID from another publisher, or connect to a second daemon configured for the same network to download the bag created above. Do not add a bag that the daemon already manages. + +Replace `` with the bag's 64-character hexadecimal identifier and `` with an absolute destination directory: + +```bash +add-by-hash -d "" +``` + +The CLI prints “Bag added” and the bag information; downloading starts in the background. + +Downloaded data is shared with other peers by default. + +## Verify + +Inspect download progress and the file list: + +```bash +get +``` + +Wait for `Downloaded:` to show “(completed)”. The `Dir name:` field identifies the bag's directory under ``; the file list shows paths within it. + +Inspect connected peers if the download is not progressing: + +```bash +get-peers +``` + +A BagID alone does not guarantee availability. Peers must be online and serving the required pieces. + +## Additional bag operations + +Run these commands inside the connected `storage-daemon-cli`. Importing a metafile or adding selected files requires a bag not already managed by that daemon. + +### Export a metafile + +Run `get-meta ` to export the bag metadata. `` is an absolute output file path on the CLI host. + +The CLI prints “Saved meta” with the number of bytes written. A metafile does not replace the peers serving the file contents. + +### Import a metafile + +`` is an absolute input file path on the CLI host: + +```bash +add-by-meta "" -d "" +``` + +The CLI prints “Bag added” and the BagID; downloading starts in the background. Use the returned BagID for subsequent commands. + +### Download selected files + +When adding a bag, use [`--partial`](/foundations/web3/ton-storage/reference#bag-command-options) followed by exact file names within the bag. Replace `` with a path supplied by the publisher: + +```bash +add-by-hash -d "" --partial "" +``` + +List multiple file paths after `--partial`. Put all other options before it: every following argument is treated as a file name. Unlisted files receive priority `0` and are excluded from the download. + +For a bag already added to the daemon, use the [file priority commands](/foundations/web3/ton-storage/reference#manage-bags). Do not add the same bag again to change its selection. + +Use `get ` to verify the selected files. “(completed)” refers to the selected download, not necessarily the entire bag. + +### Pause or resume sharing + +Run `upload-pause ` to stop sharing the bag, or `upload-resume ` to resume. + +Pausing uploads does not remove copies already downloaded by other peers. + +### Pause or resume downloads + +Run `download-pause ` to pause the download, or `download-resume ` to resume. + +These commands do not pause uploads. To stop sharing downloaded data, use [Pause or resume sharing](#pause-or-resume-sharing). + +## Troubleshoot + +| Problem | Check | +| -------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| “Invalid path” when creating a bag | Use an existing source path accessible to the CLI and daemon. | +| “Upload paused” in the bag information | Run `upload-resume `. | +| A recipient cannot download the bag | Keep the daemon online, check its ADNL connectivity, and confirm that uploads are enabled. | +| “Invalid BagID” | Copy the complete hexadecimal BagID without a URL prefix or file path. | +| “Download paused” | Run `download-resume `. | +| No peers or no progress | Check connectivity and ask the publisher to keep a complete copy online with sharing enabled. | +| “Failed to read meta” | Check the metafile path and read permissions on the CLI host. | +| “Failed to write meta” | Check that the output directory exists and the CLI can write to it. | +| A selected file does not download | Compare its name with the file list from `get ` once the header is available. Check its priority. | + +The [bag command reference](/foundations/web3/ton-storage/reference#bag-commands) lists syntax, options, and defaults. diff --git a/content/foundations/web3/ton-storage/index.mdx b/content/foundations/web3/ton-storage/index.mdx new file mode 100644 index 000000000..81bb7c32f --- /dev/null +++ b/content/foundations/web3/ton-storage/index.mdx @@ -0,0 +1,108 @@ +--- +title: "TON Storage overview" +sidebarTitle: "Overview" +description: "Distributed file sharing and paid storage on TON" +--- + +TON Storage distributes files between peers on the TON network. A publisher shares files from a storage daemon, and other peers download and share copies of those files. The files remain on the participating peers' disks. + +File sharing does not require an on-chain transaction. Optional storage contracts allow clients to pay providers to retain a copy of the data. + +## Bags and BagIDs + + + + + + + +A _bag_ is the unit of content shared through TON Storage. It contains a file or directory together with metadata describing the files and allowing their contents to be verified. + +Each bag has a _BagID_, a 256-bit identifier derived from its data and metadata. A publisher shares this identifier so that other peers can find and download the bag. The BagID identifies the content independently of which peer supplies it. + +The bag's header records the directory name, file paths, and positions of file data. Identical file contents alone do not guarantee identical BagIDs: the file paths, directory name, and bag description also contribute to the identifier. + +## File distribution + + + + + +The official implementation provides two tools: `storage-daemon` stores files and exchanges data with peers, while `storage-daemon-cli` controls the running daemon. + +When a daemon creates a bag, it makes the bag available to other peers if uploading is enabled. A receiving daemon uses the BagID to join the bag's overlay, a group of peers associated with that bag. Peer discovery uses the [distributed hash table (DHT)](/foundations/network/dht); the DHT stores discovery information rather than file contents. + +Peers exchange the bag's metadata and advertise which pieces they have. The receiving daemon requests missing pieces from those peers and verifies each piece before accepting it. Different pieces can come from different peers. When uploading is enabled, downloaded pieces can also be shared before the entire bag is complete. + +In the C++ implementation, peer queries use version 2 of the [Reliable Large Datagram Protocol (RLDP2)](/foundations/network/rldp) over the [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl). + +## Pieces and integrity + +The serialized header and file contents form a continuous data stream, divided into pieces. A piece can contain the end of one file and the beginning of another. Consequently, downloading a selected file can also transfer bytes from an adjacent, unselected file. The last piece can be shorter than the others. + +Each piece has a SHA-256 hash. These hashes form a [Merkle tree](/foundations/serialization/merkle) whose root is recorded in the `TorrentInfo` cell, together with the header hash and other [bag metadata](/foundations/web3/ton-storage/reference#bag-formats). The hash of that cell is the BagID. + +When starting from a BagID, the daemon checks that the received `TorrentInfo` cell hashes to that identifier. It then validates proofs of piece hashes against the Merkle root. For each received piece, it calculates the SHA-256 hash of the bytes and compares it with the expected hash. The header is also checked against its hash in `TorrentInfo`. + +These checks connect the file layout and downloaded bytes to the expected BagID, without a paid storage contract. + +## Metafiles and partial downloads + +A _metafile_ supplies bag metadata that a daemon would otherwise obtain from peers. It contains `TorrentInfo` and can optionally include the header and a Merkle proof. It does not contain the file contents or replace the peers serving them. + +A daemon can [download selected files](/foundations/web3/ton-storage/get-started#additional-bag-operations) from a bag. It uses the header to map file paths to the required pieces. Selecting files changes which pieces are requested, not the BagID or verification rules. + +## Availability and updates + + + +Integrity means that received data matches the expected BagID. Availability requires reachable peers that retain and serve every piece needed for the requested files. A valid BagID or metafile does not guarantee that those pieces are currently available. + +Updating files creates a new bag rather than changing an existing bag's identity. Copies already downloaded by other peers remain copies of the old bag. A [TON DNS record](/foundations/web3/ton-dns/manage-domains#manage-records) can point to the new BagID while keeping the same domain name. + +## Paid storage + +A [storage provider](/foundations/web3/ton-storage/provider-lifecycle) retains and serves bags in exchange for payment. The client funds an on-chain storage agreement, and the provider submits proofs of the stored data to earn payments. + +These proofs establish possession of the challenged data; the contract does not verify that the provider serves download requests. + +## Ecosystem integration + + + +- [TON DNS](/foundations/web3/ton-dns): associates a domain name with a BagID. +- [TON Sites](/foundations/web3/ton-sites): uses bags to store static website files, accessed through a Storage gateway. +- [Blockchain archives](/nodes/cpp/run-archive-liteserver): uses TON Storage to distribute historical blocks and state snapshots. +- Non-fungible token (NFT) collections can reference off-chain media and metadata stored as bags, using the BagID as a stable content identifier. + +## Next steps + +- [Get started](/foundations/web3/ton-storage/get-started) to run a daemon, share a bag, and download files. +- [Store with a provider](/foundations/web3/ton-storage/store-with-provider) to request paid storage. +- [Reference](/foundations/web3/ton-storage/reference) for formats, commands, and storage contracts. + +## Sources + +- [Header layout](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/TorrentHeader.h#L49) +- [Torrent info serialization and BagID](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/TorrentInfo.cpp#L27) +- [Stream construction and piece hashing](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/TorrentCreator.cpp#L117) +- [Torrent info, header, and piece verification](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/Torrent.cpp) +- [Merkle proof validation](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/MerkleTree.cpp#L104) +- [Bag overlay identifier](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/StorageManager.cpp#L27) +- [Peer discovery and query transport](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/PeerManager.h) +- [Peer information and piece exchange](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/PeerActor.cpp) +- [File priorities and piece selection](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/NodeActor.cpp#L334) +- [Metafile contents](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/TorrentMeta.cpp) +- [Paid storage contracts](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/smartcont/storage-contract.fc) diff --git a/content/foundations/web3/ton-storage/meta.json b/content/foundations/web3/ton-storage/meta.json new file mode 100644 index 000000000..c0a431c9c --- /dev/null +++ b/content/foundations/web3/ton-storage/meta.json @@ -0,0 +1,10 @@ +{ + "$schema": "../../../../meta-schema.json", + "title": "TON Storage", + "pages": [ + "index", + "get-started", + "providers", + "reference" + ] +} diff --git a/content/foundations/web3/ton-storage/provider-lifecycle.mdx b/content/foundations/web3/ton-storage/provider-lifecycle.mdx new file mode 100644 index 000000000..106b97172 --- /dev/null +++ b/content/foundations/web3/ton-storage/provider-lifecycle.mdx @@ -0,0 +1,68 @@ +--- +title: "Storage provider lifecycle" +sidebarTitle: "Provider lifecycle" +description: "Storage agreements, activation, proofs, payments, and closure" +--- + +A storage provider retains and serves a bag in exchange for payment. The client funds an on-chain agreement, while the provider daemon stores the files and submits proofs. The storage contract verifies those proofs and accounts for payments. + +## Participants and contracts + +The client supplies the bag and funds its storage. The provider operator runs the daemon and sets the storage terms. + +Two types of contract manage the agreement: + +- The main provider contract exposes the operator's terms, deploys storage contracts, and receives withdrawn provider earnings. +- A storage contract records one agreement between the client and provider, identifying the bag, agreed terms, and unpaid client balance. + +The provider daemon monitors these agreements, manages local files, and sends activation, proof, withdrawal, and closure messages through the main provider contract. + +The files remain off-chain. Their distribution and download verification are described in [TON Storage overview](/foundations/web3/ton-storage#bag-contents-and-identity). + +## Request and activation + +The client [requests storage](/foundations/web3/ton-storage/reference#contract-messages) for a published bag at the provider's advertised rate and proof interval. The provider contract checks whether requests are enabled, whether the bag size is within its limits, and whether the expected terms match its current terms. It then deploys an inactive storage contract funded by the request. + +The daemon separately applies its local limits on contract count and total bag size. If those limits are exceeded, it starts closing the new agreement. Deployment therefore does not guarantee acceptance by the daemon. + +For an accepted agreement, the daemon downloads the complete bag and verifies it against the storage-proof root supplied in the request. After this check, it enables uploads and requests activation. The storage contract accepts activation only from the provider address and only while inactive. + +The full-download and root checks belong to the daemon. The activation message itself does not prove to the contract that a complete download occurred. [Store with a provider](/foundations/web3/ton-storage/store-with-provider) covers the client procedure and activation checks. + +## Storage challenges and proofs + +Before activation, the daemon builds a Merkle tree from 64-byte microchunks of the bag's data stream, including its header. This tree is used for storage proofs and is distinct from the piece-hash tree used to verify downloads. + +The contract records a byte position to challenge. The daemon builds a Merkle proof revealing the corresponding microchunk and submits it through the provider contract. The storage contract checks that the agreement is active, that the sender is the provider, and that the proof matches its stored root and requested position. + +An accepted proof updates the client balance and proof timestamp and selects a new challenge position at random. + +A proof verifies the challenged data against the committed root. It does not verify that the provider answers peer download requests or achieves a particular download speed. + +## Payments and balances + +The unpaid client balance is an accounting value inside the storage contract, separate from the contract's actual coin balance. A valid proof reduces that accounting balance according to the bag size, agreed rate, and elapsed time, capped by `max_span`. The exact calculation and units are defined in [Payment accounting](/foundations/web3/ton-storage/reference#payment-accounting). + +A late proof can still be accepted, but time beyond `max_span` is not paid. + +Accepting a proof does not immediately transfer the earned amount to the provider. Earnings remain in the storage contract until withdrawn or distributed at closure. Withdrawals send the available earnings to the main provider contract. The operator can transfer funds from there to a wallet. The reserve calculation and the effect of a withdrawal with no remaining client balance are described in [Payment accounting](/foundations/web3/ton-storage/reference#payment-accounting). + +The client balance can be topped up to fund further storage. The contract's actual balance also covers transaction costs, so subtracting the client balance from it does not give the exact withdrawable earnings. For payment units and withdrawal commands, see the [Storage reference](/foundations/web3/ton-storage/reference#storage-providers) and [Run a storage provider](/foundations/web3/ton-storage/run-provider#operate-active-contracts). + +## Closure and data retention + +The [client](/foundations/web3/ton-storage/store-with-provider#close-the-agreement) or [provider](/foundations/web3/ton-storage/run-provider#close-a-storage-contract) can request closure. When the daemon observes a zero client balance on an active agreement, it starts the closure procedure; the contract does not close spontaneously when that balance reaches zero. + +For an inactive agreement, closure sends the remaining contract funds to the client. For an active agreement, the contract sends a refund message for the unpaid client balance and sends the remaining funds to the provider. These transfers incur blockchain fees; closure does not calculate an additional payment for time since the last accepted proof. + +After detecting that the storage contract has been deleted, the daemon removes it from its records. If no other tracked contract references the same BagID, it also requests removal of the local bag and its files. Other peers' copies are unaffected. + +## Sources + +- [Agreement creation and request validation](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/smartcont/storage-provider.fc#L20) +- [Client balance, activation, closure, withdrawals, and proof processing](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/smartcont/storage-contract.fc) +- [Request preparation from a complete bag](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/storage-daemon.cpp#L562) +- [Microchunk size](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/MicrochunkTree.h#L34) and [tree construction](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/MicrochunkTree.cpp#L200) +- [Daemon acceptance, download checks, and activation](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/StorageProvider.cpp#L315) +- [Daemon closure, file removal, and proof scheduling](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/StorageProvider.cpp#L543) +- [Provider withdrawals and wallet transfers](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/StorageProvider.cpp#L812) diff --git a/content/foundations/web3/ton-storage/providers/meta.json b/content/foundations/web3/ton-storage/providers/meta.json new file mode 100644 index 000000000..13340a53b --- /dev/null +++ b/content/foundations/web3/ton-storage/providers/meta.json @@ -0,0 +1,9 @@ +{ + "$schema": "../../../../../meta-schema.json", + "title": "Storage providers", + "pages": [ + "[Provider lifecycle](/foundations/web3/ton-storage/provider-lifecycle)", + "[Store with a provider](/foundations/web3/ton-storage/store-with-provider)", + "[Run a provider](/foundations/web3/ton-storage/run-provider)" + ] +} diff --git a/content/foundations/web3/ton-storage/reference.mdx b/content/foundations/web3/ton-storage/reference.mdx new file mode 100644 index 000000000..1b9f2a092 --- /dev/null +++ b/content/foundations/web3/ton-storage/reference.mdx @@ -0,0 +1,331 @@ +--- +title: "TON Storage reference" +sidebarTitle: "Reference" +description: "Bag formats, daemon commands, and storage provider behavior" +--- + +## Daemon and CLI options + + + +`storage-daemon` options used in the guides: + +| Option | Meaning | +| ---------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `-v ` | Log verbosity; `3` selects INFO. | +| `-C ` | Path to the target network's global configuration file. | +| `-I :` | Public [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl) address and UDP port. | +| `-p ` | TCP port for the CLI control interface. | +| `-D ` | Persistent daemon database directory. CLI keys are generated in its `cli-keys/` subdirectory on first start. | +| `-P` | Enable storage provider mode. | + +For `storage-daemon-cli`, `-I ` is the control endpoint, `-k ` is the client private key, and `-p ` is the server public key. The CLI `-p` option is a key path, not a port. [Connect the CLI](/foundations/web3/ton-storage/get-started#connect-the-cli) shows the connection command. + +## Bag commands + + + +Run these commands inside a connected `storage-daemon-cli`. `` is the bag's 64-character hexadecimal identifier; `` is an absolute destination directory. + +| Command | Description | +| ----------------------------------------------- | ----------------------------------------------------------- | +| `create ` | Create a new bag from a file or directory | +| `add-by-hash -d ` | Add a bag by its `BagID` | +| `add-by-meta -d ` | Add a bag from a metafile | +| `list` | List all bags | +| `list --hashes` | List bags with their `BagID`s | +| `get ` | Show full bag information | +| `get-peers ` | Show peers connected for a bag | +| `get-meta ` | Export the bag metafile | +| `download-pause ` | Pause a download | +| `download-resume ` | Resume a download | +| `priority-name ` | Set download priority for a file (0 = skip, 255 = highest) | +| `upload-pause ` | Pause sharing a bag with peers | +| `upload-resume ` | Resume sharing a bag with peers | +| `priority-all ` | Set the priority of every file (0 to 255; 0 excludes files) | + +### Bag command options + +| Option | Commands | Behavior | +| ----------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| `--copy` | `create` | Copy source files into the daemon's storage directory; without it, serve the original files in place. | +| `--no-upload` | `create`, `add-by-hash`, `add-by-meta` | Disable sharing when adding the bag. Sharing is enabled by default. | +| `-d ` | `create` | Store a description in the torrent info. | +| `-d ` | `add-by-hash`, `add-by-meta` | Set the download root directory; defaults to the daemon's internal storage. | +| `--paused` | `add-by-hash`, `add-by-meta` | Add the bag without starting its download. | +| `--partial ` | `add-by-hash`, `add-by-meta` | Download only the named files. All arguments after this flag are file names. | + +Paths passed to `create` must be accessible to both the CLI and daemon. The CLI reads and writes metafile data. When the CLI and daemon run on different hosts, download paths must also exist on the daemon host; the CLI creates and resolves the destination directory locally before sending the request. + +The [bag operations guide](/foundations/web3/ton-storage/get-started#additional-bag-operations) provides usage examples. + +## Bag formats + + + +The BagID is the 256-bit hash of the `TorrentInfo` cell. Its fields are serialized in this order: + +| Field | Encoding | Meaning | +| ------------- | ---------- | ------------------------------------------------------------- | +| `piece_size` | `uint32` | Piece size in bytes; `storage-daemon` creates 128 KiB pieces. | +| `file_size` | `uint64` | Total stream size in bytes, including the header. | +| `root_hash` | `bits256` | Root hash of the piece-hash Merkle tree. | +| `header_size` | `uint64` | Serialized header size in bytes. | +| `header_hash` | `bits256` | SHA-256 hash of the serialized header. | +| `description` | `CellText` | Bag description. | + +The [TON Storage overview](/foundations/web3/ton-storage#bag-contents-and-identity) explains stream layout and verification. + +### Metafiles + +A metafile serializes `TorrentInfo` as a [bag of cells (BoC)](/foundations/serialization/boc) and can include a root proof and the serialized header. It starts with a 32-bit flags field: bit `0` indicates a root proof, and bit `1` indicates a header. These are followed by the 32-bit size of the info BoC and, if present, the root-proof BoC size, then the info BoC, optional proof BoC, and optional header. File contents are not included. + +## Provider commands + + + +[Storage provider lifecycle](/foundations/web3/ton-storage/provider-lifecycle) explains contract roles, proofs, payments, and closure. + +Run these commands inside `storage-daemon-cli`. `` is the main provider contract; `` is a per-bag storage contract. + +The following entries cover the commands used in the provider guides. `get-provider-params` and `new-contract-message` are client commands. The remaining commands require provider mode (`-P`); except for `deploy-provider`, they also require an initialized provider. + +| Command | Purpose | +| --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| `get-provider-params ` | Read a provider's on-chain terms. | +| `new-contract-message --provider ` | Write a storage request body as a BoC file on the CLI host. | +| `deploy-provider` | Prepare the provider contract and print its [initialization address](/foundations/web3/ton-storage/run-provider#deploy-the-provider-contract). | +| `get-provider-info` | Show the local provider's address, contract count, and capacity. | +| `set-provider-config` | Update local capacity limits using the options below. | +| `set-provider-params` | Update on-chain terms using the options below. | +| `withdraw ` | Request withdrawal from one provider-managed storage contract. | +| `withdraw-all` | Request withdrawals from eligible active contracts. | +| `close-contract ` | Request closure of a provider-managed storage contract. | +| `send-coins ` | Transfer the specified nanogram amount from the main provider contract to the destination account. | + +`withdraw-all` selects active contracts where `Contract$ - Client$` is at least 1 GRAM. This threshold does not subtract reserves or transaction fees. + + + Provider updates, withdrawals, closures, and transfers send blockchain messages and incur fees. Verify the network and destination before sending; mainnet transactions cannot be rolled back. Keep independent backups because closure can also remove local bag files; see [Protect provider data](/foundations/web3/ton-storage/run-provider#protect-provider-data). + + +### Command options + +| Command | Option | Meaning | +| ------------------------------------------ | ----------------------- | --------------------------------------------------------------------------------- | +| `get-provider-params`, `get-provider-info` | `--json` | Return JSON output. | +| `get-provider-info` | `--contracts` | Include individual storage contracts and their states. | +| `get-provider-info` | `--balances` | Include the main contract balance and, with `--contracts`, per-contract balances. | +| `new-contract-message` | `--query-id ` | Unsigned 64-bit request identifier; defaults to `0`. | +| `send-coins` | `--message ""` | Attach the specified text comment to the transfer. | + +`Client$` is the unpaid client balance; `Contract$` is the storage contract's actual coin balance. Their difference is not the exact withdrawable earnings. + +`new-contract-message` reads the rate and proof interval from `--provider`. `` is an output file path, not a destination address. Generating the body does not send it; see [Send a storage request](#send-a-storage-request). + +### Provider parameters + +`set-provider-config` changes daemon limits. `set-provider-params` changes the main contract's terms for new agreements. Both commands require at least one option and retain omitted values. + +| Command | Option | Meaning | +| --------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------ | +| `set-provider-config` | `--max-contracts ` | Maximum number of tracked storage contracts. | +| `set-provider-config` | `--max-total-size ` | Maximum combined bag size in bytes. | +| `set-provider-params` | `--accept ` | Accept new requests when `` is `1`; reject them when it is `0`. | +| `set-provider-params` | `--rate ` | Price in nanograms per 1,048,576 bytes per day. | +| `set-provider-params` | `--max-span ` | Maximum elapsed time paid per accepted proof, in seconds. Later proofs remain valid. | +| `set-provider-params` | `--min-file-size ` | Minimum accepted bag stream size in bytes, including the header. | +| `set-provider-params` | `--max-file-size ` | Maximum accepted bag stream size in bytes, including the header. | + +## Storage contracts + +### Contract messages + +Operation codes occupy the first 32 bits of the message body. `uint64` and `bits256` below denote fixed-width fields; `Coins` uses TON coin serialization. + +| Message | Opcode | Fields after the opcode | Route | +| ----------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | +| Storage request | `0x107c49ef` | `query_id:uint64`, reference to `TorrentInfo`, microchunk root `bits256`, expected rate `Coins`, expected `max_span:uint32` | Client wallet to main provider contract. | +| Close agreement | `0x79f937ea` | `query_id:uint64` | Client or main provider contract to storage contract. | +| Deployment notification | `0xbf7bd0c1` | Original `query_id:uint64`, BagID `bits256` | Storage contract to client. | +| Activation notification | `0xd4caedcd` | Current logical time `uint64`, BagID `bits256` | Storage contract to client. | +| Closure notification | `0xb6236d63` | Current logical time `uint64`, BagID `bits256` | Storage contract to client and, when active, main provider contract. | + +A non-bounced transfer with an empty body or opcode `0` adds the received value to the storage contract's client balance, regardless of the sender. Opcode `0` permits a text-comment body and requires no query ID. + +### Storage contract data + +`get_storage_contract_data` returns these values in order: + +| Position | Field | Stored type | Meaning | +| -------: | ----------------- | ------------ | ----------------------------------------------------------------------------- | +| 1 | `active` | `int1` | Agreement active flag. | +| 2 | `balance` | `Coins` | Unpaid client balance in nanograms. | +| 3 | `provider` | `MsgAddress` | Main provider contract address. | +| 4 | `merkle_hash` | `uint256` | Storage-proof microchunk-tree root. | +| 5 | `file_size` | `uint64` | Bag stream size in bytes, including the header. | +| 6 | `next_proof` | `uint64` | Challenged byte position; initialized to zero. | +| 7 | `rate_per_mb_day` | `Coins` | Nanograms per 1,048,576 bytes per day. | +| 8 | `max_span` | `uint32` | Maximum elapsed time paid per proof, in seconds. | +| 9 | `last_proof_time` | `uint32` | Proof accounting timestamp in Unix seconds; initialized at contract creation. | +| 10 | `client` | `MsgAddress` | Client wallet address. | +| 11 | `torrent_hash` | `uint256` | BagID. | + +### Payment accounting + +At deployment, the storage contract credits the received value minus 2 notification allowances of 20,000,000 nanograms each. Blockchain fees reduce the amount forwarded by the main provider contract. + +For each accepted proof, the contract computes: + +```text +elapsed = min(now - last_proof_time, max_span) +bounty = floor(file_size * rate_per_mb_day * elapsed / (86400 * 1048576)) +balance = max(0, balance - bounty) +``` + +`file_size` is the bag stream size in bytes, `elapsed` is in seconds, and `bounty` and `balance` are in nanograms. The initial `last_proof_time` is set when the storage contract's initial state is built; activation does not reset it. Each accepted proof sets it to the current Unix time. + +A withdrawal while `balance` is positive requests a reserve of that balance plus 10,000,000 nanograms before forwarding the remaining funds to the main provider contract. The reserve uses the amount available if the requested amount exceeds it. [Payments and balances](/foundations/web3/ton-storage/provider-lifecycle#payments-and-balances) distinguishes accounting balance from earnings. + +When `balance` is zero, a successful withdrawal transfers the remaining funds to the main provider contract and deletes the storage contract. + +### Contract errors + +| Code | Meaning | +| ------ | ----------------------------------------------------------------------- | +| `401` | Sender is not authorized for the requested storage contract operation. | +| `1001` | Storage request attaches less than 60,000,000 nanograms. | +| `1002` | Storage proof does not match the committed root and challenge. | +| `1003` | Withdrawal or proof submission requires an active storage contract. | +| `1004` | Requested bag size is below the provider's minimum. | +| `1005` | Requested bag size exceeds the provider's maximum. | +| `1006` | Provider does not accept new storage contracts. | +| `1007` | Activation requested for an already active storage contract. | +| `1009` | Expected rate or `max_span` differs from the provider's on-chain terms. | + +## Integration examples + + + The request example transfers funds to a mainnet provider. The closure example deletes a storage agreement and distributes its remaining funds. Verify the network, destination, and amount before confirming; mainnet transactions cannot be rolled back. Keep an independent copy of required files before closing an agreement. + + +### Send a storage request + +The following helper uses `@ton/core` 0.63.1 with an existing [TON Connect application](/applications/ton-connect/how-to/connect). It builds a mainnet request with 1 GRAM attached. The provider contract requires at least 0.06 GRAM for a deployment request; fees and notification messages reduce the balance available for storage. + +```typescript +import { Address, Cell, toNano } from '@ton/core'; + +export function storageRequest(provider: Address, sender: Address, body: Cell) { + return { + validUntil: Math.floor(Date.now() / 1000) + 300, + network: '-239' as const, + from: sender.toRawString(), + messages: [{ + address: provider.toString({ bounceable: true }), + amount: toNano('1').toString(), + payload: body.toBoc().toString('base64'), + }], + }; +} +``` + +Integration excerpt, not a standalone application: `tonConnectUi` is the connected TON Connect UI instance, `provider` and `sender` are `Address` values, and `BODY_BASE64` is the base64-encoded contents of the BoC file generated by `new-contract-message`. + +```typescript +// Not runnable: requires storageRequest and a connected TON Connect application. +const body = Cell.fromBase64(BODY_BASE64); +const request = storageRequest(provider, sender, body); +await tonConnectUi.sendTransaction(request); +``` + +The response from TON Connect is not confirmation that the storage contract is deployed or active. Verify the on-chain result. + +### Read a storage contract + +This helper returns a subset of [the getter fields](#storage-contract-data), naming `client` as `owner`, `rate_per_mb_day` as `rate`, and `torrent_hash` as `bagId`. + +Use `@ton/ton` 16.3.0 with `@ton/core` 0.63.1. Supply a `TonClient` configured for mainnet using [TON Center API v2](/api/v2/rpc/json-rpc-endpoint) and the storage contract address obtained from the deployment notification. + +```typescript +import { Address } from '@ton/core'; +import { TonClient } from '@ton/ton'; + +export async function readStorageContract(client: TonClient, address: Address) { + const { stack } = await client.runMethod(address, 'get_storage_contract_data'); + const active = stack.readBoolean(); + const balance = stack.readBigNumber(); + const provider = stack.readAddress(); + stack.readBigNumber(); + stack.readBigNumber(); + stack.readBigNumber(); + const rate = stack.readBigNumber(); + const maxSpan = stack.readNumber(); + stack.readNumber(); + const owner = stack.readAddress(); + const bagId = stack.readBigNumber().toString(16).padStart(64, '0'); + return { active, balance, provider, rate, maxSpan, owner, bagId }; +} + +``` + +Call `readStorageContract(client, address)`. The returned `bagId` is a 64-character hexadecimal string; `active: false` means the provider has not activated the agreement. Units are listed in [Storage contract data](#storage-contract-data). + +### Close a storage contract + +Use `@ton/core` 0.63.1 with a connected mainnet TON Connect wallet. `contract` is the per-bag storage contract, `sender` is its client wallet, `amount` is the attached value in nanograms to cover transaction fees, and `queryId` is an unsigned 64-bit integer. + +```typescript +import { Address, beginCell } from '@ton/core'; + +export function storageCloseRequest( + contract: Address, + sender: Address, + amount: bigint, + queryId: bigint, +) { + const body = beginCell() + .storeUint(0x79f937ea, 32) + .storeUint(queryId, 64) + .endCell(); + return { + validUntil: Math.floor(Date.now() / 1000) + 300, + network: '-239' as const, + from: sender.toRawString(), + messages: [{ + address: contract.toString({ bounceable: true }), + amount: amount.toString(), + payload: body.toBoc().toString('base64'), + }], + }; +} +``` + +Pass the returned request to the connected `tonConnectUi.sendTransaction` instance. Verify that `sender` is the contract's client and review the attached amount before sending. Closure distributes the remaining funds and deletes the contract; see [Closure and data retention](/foundations/web3/ton-storage/provider-lifecycle#closure-and-data-retention). + +## Sources + +- [Daemon startup options](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/storage-daemon.cpp#L982) +- [Contract opcodes and error codes](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/smartcont/constants.fc) +- [CLI command parsing and options](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/storage-daemon-cli.cpp#L322) +- [CLI command execution and output](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/storage-daemon-cli.cpp#L995) +- [Bag completion and file selection](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/Torrent.cpp#L444) +- [Copying bag files](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/Torrent.cpp#L708) +- [Storage contract messages, payments, and getters](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/smartcont/storage-contract.fc) +- [Provider deployment and request validation](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/smartcont/storage-provider.fc) +- [Provider daemon lifecycle](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/storage-daemon/StorageProvider.cpp#L650) +- [Torrent info serialization and BagID](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/TorrentInfo.cpp#L27) +- [Merkle proof validation](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/MerkleTree.cpp#L104) +- [Metafile serialization](https://github.com/ton-blockchain/ton/blob/ed629c416f7a03cd3838697fcee9f8cd0097700b/storage/TorrentMeta.cpp#L56) diff --git a/content/foundations/web3/ton-storage/run-provider.mdx b/content/foundations/web3/ton-storage/run-provider.mdx new file mode 100644 index 000000000..eae2af8d4 --- /dev/null +++ b/content/foundations/web3/ton-storage/run-provider.mdx @@ -0,0 +1,169 @@ +--- +title: "How to run a TON Storage provider" +sidebarTitle: "Run a storage provider" +description: "Deploy and operate a paid storage provider" +--- + +Run the `storage-daemon` in provider mode, deploy its main contract, and manage paid storage contracts on mainnet. + + + Provider commands deploy contracts, transfer funds, close storage contracts, and may delete local bag files. Mainnet transactions and contract closures cannot be rolled back. + + Keep independent backups of required files, verify every address and network, and use a small initialization transfer. + + +## Prerequisites + +- `storage-daemon` and `storage-daemon-cli` from the same [TON release](https://github.com/ton-blockchain/ton/releases/tag/v2026.08) +- The [mainnet global configuration file](https://ton-blockchain.github.io/global.config.json) +- A funded mainnet wallet +- A public IP address and reachable [ADNL](/foundations/network/adnl) port + +## Start provider mode + + + +Follow [Start the daemon](/foundations/web3/ton-storage/get-started#start-the-daemon), adding `-P` to the daemon startup command. Use a dedicated database directory for the provider. + +The `list` command shows all bags managed by the daemon. Do not remove these bags or use the provider daemon to manage unrelated bags. Keep independent copies of data that must remain available after a storage contract closes. + +Run the commands below inside the connected `storage-daemon-cli`, one command per line. + +## Deploy the provider contract + +Run the [deployment command](/foundations/web3/ton-storage/reference#provider-commands) inside `storage-daemon-cli`: + +```bash +deploy-provider +``` + + + The command prints an address that requires a non-bounceable initialization message containing 1 GRAM. Verify the network and address before sending funds. A transfer to the wrong network or address cannot be recovered. + + +Do not attach a large balance to the initialization message. Verify the deployed provider: + +```bash +get-provider-info +``` + +Fund the deployed provider contract separately to cover later transaction fees. Increase the balance only after verifying the deployment. + +## Configure capacity + +Set the maximum number and total size of managed storage contracts: + +```bash +set-provider-config --max-contracts --max-total-size +``` + +`` is the contract-count limit; `` is the combined bag-size limit in bytes. These are daemon limits, separate from the [on-chain terms](/foundations/web3/ton-storage/reference#provider-parameters). + +## Configure contract terms + +Keep new requests disabled while configuring the on-chain terms: + +```bash +set-provider-params --accept 0 --rate --max-span --min-file-size --max-file-size +``` + +Set [``](/foundations/web3/ton-storage/reference#provider-parameters) to the price per 1,048,576 bytes per day. `` is the maximum paid interval between proofs. `` and `` bound the bag stream size, including its header. + +Omitted flags retain their prior values. After each on-chain update, read the terms with `get-provider-params ` before submitting another update. Use the main contract address printed during deployment as ``. + +## Enable and verify requests + +Enable requests after verifying every parameter: + +```bash +set-provider-params --accept 1 +``` + +Run `get-provider-params ` again and confirm that requests are enabled and all terms match the intended configuration. + +The daemon downloads accepted bags, distributes them to peers, and submits storage proofs. + +## Monitor agreements and withdraw earnings + + + +List tracked contracts, their states, and their balances: + +```bash +get-provider-info --contracts --balances +``` + +`Client$` is the unpaid client balance. The difference between `Contract$` and `Client$` includes provider earnings, storage reserves, and transaction funds; it is not the exact withdrawable amount. + +Withdraw earnings from one per-bag storage contract managed by the provider: + +```bash +withdraw +``` + +Request withdrawals from active contracts meeting the [CLI threshold](/foundations/web3/ton-storage/reference#provider-commands): + +```bash +withdraw-all +``` + +A withdrawal with a zero client balance can also delete the storage contract; see [Payment accounting](/foundations/web3/ton-storage/reference#payment-accounting). + +## Transfer provider funds + + + Start with a small transfer. Verify the destination, amount, and network before sending. Mainnet transfers cannot be rolled back. + + +Transfer nanograms from the main provider contract: + +```bash +send-coins +``` + +To include a text message, append `--message ""` to this command. + +There, + +- `` is the receiving account. +- `` is the transferred amount in nanograms. +- `` is an optional text message. + +## Close a storage contract + + + Closing a contract may delete its local bag files when no other tracked contract uses the bag. Keep an independent copy before closing the contract. The on-chain closure cannot be rolled back. + + +Close one provider-managed contract: + +```bash +close-contract +``` + +[Closing an active agreement](/foundations/web3/ton-storage/provider-lifecycle#closure-and-data-retention) transfers available provider earnings to the main provider contract. Before activation, the remaining funds return to the client. + +## Troubleshoot + +| Problem | Check | +| -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Provider commands fail because provider mode is disabled | Restart the daemon with `-P` and its existing database directory. | +| Contract is deployed but requests are rejected | Read the on-chain terms with `get-provider-params ` and check the [contract error](/foundations/web3/ton-storage/reference#contract-errors). | +| Agreement starts closing before activation | Check local capacity limits and daemon logs; deployment does not guarantee daemon acceptance. | +| `withdraw-all` prints “Nothing to withdraw” | Check contract states and the [withdrawal threshold](/foundations/web3/ton-storage/reference#provider-commands). | diff --git a/content/foundations/web3/ton-storage/store-with-provider.mdx b/content/foundations/web3/ton-storage/store-with-provider.mdx new file mode 100644 index 000000000..83ceec32e --- /dev/null +++ b/content/foundations/web3/ton-storage/store-with-provider.mdx @@ -0,0 +1,85 @@ +--- +title: "How to store a bag with a provider" +sidebarTitle: "Store with a provider" +description: "Request paid storage and monitor the client balance" +--- + +Request paid storage for a bag on mainnet and monitor its storage contract. + +## Prerequisites + +- A running TON v2026.08 [storage daemon](/foundations/web3/ton-storage/get-started#start-the-daemon) configured for mainnet and connected CLI +- A funded mainnet wallet +- The provider contract address on mainnet + + + Sending a storage request or topping up its contract transfers funds. Verify the mainnet provider address, amount, and terms before sending. Mainnet transfers cannot be rolled back. + + +Run the following [commands](/foundations/web3/ton-storage/reference#provider-commands) inside `storage-daemon-cli`, one command per line. + +## Prepare the bag + +[Create and share a bag](/foundations/web3/ton-storage/get-started#create-and-share-a-bag) and record its 64-character hexadecimal identifier as ``. Keep the bag available until the provider finishes downloading it. + +## Check provider terms + +Inspect the on-chain terms at ``, the main provider contract address: + +```bash +get-provider-params +``` + +The result states whether the provider accepts contracts, its bag-size limits, its rate, and the maximum paid interval between proofs. + +## Request storage from a provider + +1. Generate a request body for the bag: + + ```bash + new-contract-message --query-id --provider + ``` + + There, + + - `` receives the internal message body, not a complete message. + - `` is an integer from `0` through `2^64 - 1`. + + Large bags can take longer to process. Review the rate and proof interval printed by the command before sending the body. The provider contract rejects the request if its rate or proof interval changes before processing. + +1. Send the generated body to `` from the client wallet, using the [request example](/foundations/web3/ton-storage/reference#send-a-storage-request). The example attaches 1 GRAM to cover deployment and an initial storage balance. This is an example amount, not a fixed price or storage duration; review the provider's rate before sending. + +## Verify activation + + + +Find the incoming `0xbf7bd0c1` notification in the requesting wallet's transaction history. Its body contains the request query ID and BagID. The sender is the new storage contract; use that address as ``. + +Read the contract with the [verification helper](/foundations/web3/ton-storage/reference#read-a-storage-contract). Confirm that `owner`, `provider`, and `bagId` match the request, and that `balance` is positive. Wait for `active` to become `true` after the provider downloads the bag. Activation also sends a `0xd4caedcd` notification to the client. + +## Monitor and top up the balance + + + +Read `balance` with the [verification helper](/foundations/web3/ton-storage/reference#read-a-storage-contract). It is the [unpaid client balance](/foundations/web3/ton-storage/provider-lifecycle#payments-and-balances), not the contract's total coin balance. + +To top up, send a transfer to `` with an empty body or a text comment. Any wallet can add funds. Read the balance again after the transaction is included. + +## Close the agreement + +Send a closure request from the client wallet to ``, using the [closure example](/foundations/web3/ton-storage/reference#close-a-storage-contract). The provider's main contract address is not the destination for this request. + +Verify the closure notification and the contract's deletion on-chain. Refunds depend on whether the agreement was active; see [Closure and data retention](/foundations/web3/ton-storage/provider-lifecycle#closure-and-data-retention). A provider can also decline or close an agreement, including when its client balance reaches zero. + +## Troubleshoot + +| Problem | Check | +| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------- | +| Request rejected after the provider changes its rate or proof interval | Read the updated terms and regenerate the request body. | +| Contract remains inactive | Keep the bag shared and check with the provider that it can download the bag. | +| No deployment notification | Inspect the wallet transaction for a bounced request before retrying. | diff --git a/content/foundations/web3/ton-tunnel/architecture.mdx b/content/foundations/web3/ton-tunnel/architecture.mdx new file mode 100644 index 000000000..f08406a97 --- /dev/null +++ b/content/foundations/web3/ton-tunnel/architecture.mdx @@ -0,0 +1,90 @@ +--- +title: "TON Tunnel architecture" +sidebarTitle: "Architecture" +description: "Packet routes, encryption boundaries, and relay payments in ADNL Tunnel" +--- + +TON Tunnel gives an application a UDP endpoint on a remote gateway. The client builds routes through relays to carry outgoing packets and return responses. In ADNL Tunnel v0.2.2, relays can forward traffic for free or receive payments through TON Payment Network. + +## Components and responsibilities + +The tunnel client runs inside an application that integrates the library, such as a TON proxy. It selects relays from a configured pool and supplies the instructions needed to forward traffic. + +A routing relay forwards tunnel messages to the next participant. The outbound gateway is the relay at the end of the outgoing route: it allocates a UDP socket, sends packets to their destinations, and receives responses. A tunnel with one relay uses that relay as the gateway. + +Only packets passed to the [application's tunnel integration](/foundations/web3/ton-tunnel/use) use these routes. The tunnel does not redirect every connection made by the application or device. + +## Route establishment + +The client selects a gateway and, for a longer route, intermediate relays. It constructs outgoing and returning routes; their intermediate relays and order can differ. + +Each route consists of sections, with encryption keys and instructions for the participant processing each section. The client creates these keys and instructions to establish forwarding state and connect the gateway's UDP endpoint to a return route. + +The gateway reports its allocated address and port through that return route. During setup, relays cache forwarding instructions so traffic packets do not need to carry the full route setup each time. Separate control messages maintain the tunnel and carry payment updates. + +The pool determines which relays are eligible. Its format and route-length setting are described in [Client configuration and node pools](/foundations/web3/ton-tunnel/reference#client-configuration-and-node-pools). + +## Packet journey + +The following example uses the same intermediate relay in both directions. A shorter tunnel can connect the client directly to the gateway. + +```mermaid +sequenceDiagram + participant C as Tunnel client + participant R as Routing relay + participant G as Outbound gateway + participant D as Destination + C->>R: Encrypted tunnel payload + R->>G: Forward payload + G->>D: Original UDP packet + D->>G: UDP response + G->>R: Encrypted return payload + R->>C: Forward response +``` + +The client wraps the destination IP address, port, and packet bytes in an encrypted tunnel payload. Routing relays forward that payload. The gateway decrypts the tunnel envelope and sends the original packet from its allocated UDP socket. The destination therefore sees the gateway's network endpoint. + +For the return journey, the gateway wraps the response together with its source address, encrypts it, and forwards it through the configured return route. The client decrypts the envelope and delivers the packet to the application. + +This mechanism operates below HTTP. In a TON proxy integration, it transports packets from the application's [Abstract Datagram Network Layer (ADNL) connection](/foundations/network/adnl-udp). HTTP requests and responses travel over the [Reliable Large Datagram Protocol (RLDP)](/foundations/network/rldp#rldp-http). + +## Encryption and visibility + +Routing instructions are encrypted for each section. The packet envelope is encrypted between the tunnel client and the outbound gateway. These are separate from encryption applied by the application to the packet being transported. + +| Participant | Information available in its role | +| ---------------- | ----------------------------------------------------------------------------------------- | +| Tunnel client | The selected routes, destination, and original packets. | +| Routing relay | Its instructions, adjacent network peers, and the sizes and timing of forwarded messages. | +| Outbound gateway | The destination IP and port, original UDP packets, and their responses. | +| Destination | Packets arriving from the gateway's UDP endpoint. | + +Removing the tunnel envelope does not decrypt the transported ADNL packet. Conversely, the tunnel does not provide encryption between the gateway and destination for arbitrary unencrypted application data. + +The first relay communicates with the client, and the gateway communicates with the destination. Relaying changes which participants observe these connections; it does not by itself guarantee anonymity. + +## Traffic payments + +Traffic routes and payment routes serve different purposes. A packet can traverse several relays, while payment to each relay follows its own configured chain of Payment Network peers. Those payment intermediaries do not need to be the relays carrying the packet. + +```mermaid +flowchart LR + C[Client] -->|Traffic| R[Routing relay] + R -->|Traffic| G[Gateway] + C -. Payment .-> P[Payment intermediary] + P -. Payment .-> R + P -. Payment .-> G +``` + +For a paid section, the client opens a virtual channel and supplies signed payment states. Each state contains the total amount paid through that channel. The relay verifies and records the state, then converts the increase over the previously accepted amount into packet credit. Updating that state pays for another batch of packets without a blockchain transaction for every packet. + +Forwarding consumes packet credit. The client monitors consumption and sends further payment updates as credit runs low. The channel's capacity limits how much can be paid through it; unused channel capacity and prepaid traffic credit are different quantities. Free relays do not require these payments. + +Routing and gateway packet prices are separate from [Payment Network](/foundations/web3/payment-network) intermediary fees. [Payment routes](/foundations/web3/ton-tunnel/reference#payment-routes) define the advertised terms. Client funding and operator procedures belong in [Use a paid tunnel](/foundations/web3/ton-tunnel/use#enable-payments-optional) and [Accept traffic payments](/foundations/web3/ton-tunnel/run-relay#configure-prices). + +## Sources + +- [Relay selection and route establishment](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/setup.go#L244-L340) +- [Route construction](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/regularOutTunnel.go#L137-L253), [control messages](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/regularOutTunnel.go#L688-L906), and [client packet transport](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/regularOutTunnel.go#L1288-L1351) +- [Section keys and encrypted instructions](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/keys.go#L20-L74) +- [Relay forwarding](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/instructions.go#L415-L489), [gateway transport](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/instructions.go#L1113-L1203), and [payment acceptance](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/instructions.go#L501-L722) diff --git a/content/foundations/web3/ton-tunnel/index.mdx b/content/foundations/web3/ton-tunnel/index.mdx new file mode 100644 index 000000000..a3bd7f26a --- /dev/null +++ b/content/foundations/web3/ton-tunnel/index.mdx @@ -0,0 +1,35 @@ +--- +title: "TON Tunnel overview" +sidebarTitle: "Overview" +description: "Route ADNL traffic through relays with optional traffic payments" +--- + +TON Tunnel routes [Abstract Datagram Network Layer (ADNL) traffic](/foundations/network/adnl-udp) through intermediate nodes. The official implementation, ADNL Tunnel, provides the relay functionality described in TON Proxy announcements. + +Applications that integrate ADNL Tunnel can use a relay's network endpoint instead of communicating directly from their own endpoint. + +## Clients and relays + +A tunnel client selects relays from a configured pool and establishes routes for outgoing and returning traffic. Routes can contain one or more relays. + +A relay runs `tunnel-node` and forwards traffic according to encrypted routing instructions. Operators can share a public configuration containing their relay's public key and optional payment terms. + +TON Tunnel transports ADNL packets. Applications such as Tonutils-Proxy and tonutils-reverse-proxy integrate it with their existing networking. It does not replace the HTTP proxy described in [TON Proxy](/foundations/web3/ton-proxy). + +## Privacy and scope + +Only traffic sent through the application's [tunnel integration](/foundations/web3/ton-tunnel/architecture) uses these routes. A tunnel does not by itself guarantee anonymity. + +## Optional traffic payments + +Relays can forward traffic without charging or accept payments through TON Payment Network. + +Operators configure prices for forwarding traffic and for traffic entering or leaving the tunnel through a gateway. Clients use the payment terms associated with the relays in their pool. + +When payments are disabled on the client, it selects only pool entries without payment requirements. + +## Next steps + +- [Use a tunnel](/foundations/web3/ton-tunnel/use) to configure a compatible application. +- [Run a relay](/foundations/web3/ton-tunnel/run-relay) to forward traffic for tunnel clients. +- [Architecture](/foundations/web3/ton-tunnel/architecture) explains routes, encryption, and traffic payments. diff --git a/content/foundations/web3/ton-tunnel/meta.json b/content/foundations/web3/ton-tunnel/meta.json new file mode 100644 index 000000000..1c91d18f5 --- /dev/null +++ b/content/foundations/web3/ton-tunnel/meta.json @@ -0,0 +1,11 @@ +{ + "$schema": "../../../../meta-schema.json", + "title": "TON Tunnel", + "pages": [ + "index", + "architecture", + "use", + "run-relay", + "reference" + ] +} diff --git a/content/foundations/web3/ton-tunnel/reference.mdx b/content/foundations/web3/ton-tunnel/reference.mdx new file mode 100644 index 000000000..8bb33f12a --- /dev/null +++ b/content/foundations/web3/ton-tunnel/reference.mdx @@ -0,0 +1,131 @@ +--- +title: "TON Tunnel reference" +sidebarTitle: "Reference" +description: "Relay options, configuration, identifiers, and payment units" +--- + +This reference describes ADNL Tunnel v0.2.2. Client integrations may embed another library version, as listed below. + +## Client configuration and node pools + +| Field | Purpose | +| --------------------- | --------------------------------------------------------------------------- | +| `NodesPoolConfigPath` | Path to the public pool JSON file | +| `TunnelSectionsNum` | Number of sections used to construct a route; generated default `1` | +| `PaymentsEnabled` | With `false`, only entries whose `Payment` is absent or `null` are eligible | +| `TunnelServerKey` | Client's generated private tunnel key | +| `Payments` | Client payment configuration, including private keys | + +A [pool](/foundations/web3/ton-tunnel/use#configure-the-pool) contains a `NodesPool` array. Each entry has a `Key` and an optional `Payment` object. `Key` is an Ed25519 public key encoded as base64 in JSON. `Payment` contains a payment-node chain and packet prices. Export this file with `-gen-shared-config` rather than copying a private configuration. + +The pool must contain enough eligible entries for `TunnelSectionsNum`. Outgoing and returning routes can use different intermediate nodes. + +## Client integrations + +| Application | Embedded ADNL Tunnel | Configuration object | Activation | +| ----------------------------- | -------------------- | -------------------- | ---------------------------------------- | +| Tonutils-Proxy v1.8.3 | v0.1.8 | `TunnelConfig` | Nonempty `NodesPoolConfigPath` | +| tonutils-reverse-proxy v0.6.0 | v0.2.1 | `tunnel_config` | `--enable-tunnel` with a configured pool | + +These are application integration points, not flags of `tunnel-node`. Keep each application's generated configuration and private keys when changing tunnel settings. + +## Relay CLI + +| Option | Default | Purpose | +| -------------------------------- | ----------------------------------------- | ------------------------------------------------------------------- | +| `-config ` | `config.json` | Private relay configuration; generated if absent | +| `-gen-shared-config ` | Disabled | Export a public node pool and exit; output path must end in `.json` | +| `-payment-node ` | Automatic selection or interactive prompt | Select a payment peer by its 32-byte public key in hexadecimal | +| `-v ` | `2` | Logging verbosity | +| `-log-filename ` | `tunnel.log` | Log file path | +| `-log-disable-file` | `false` | Disable file logging | +| `-metrics-listen-addr
` | Disabled | HTTP address for Prometheus metrics | + +## Relay configuration + +| Field | Purpose | +| ------------------ | ---------------------------------------------------------------- | +| `TunnelServerKey` | Private Ed25519 seed identifying the relay; keep it secret | +| `TunnelListenAddr` | UDP listener, default `0.0.0.0:17330` | +| `ExternalIP` | Public IPv4 address advertised for the relay | +| `NetworkConfigUrl` | TON network configuration URL; mainnet by default | +| `TunnelThreads` | Listener worker count; `0` uses the CPU count | +| `PaymentsEnabled` | Whether to initialize the payment service; default `false` | +| `Payments` | Payment keys, database path, channel settings, and packet prices | + +## Network endpoints + +The fixed UDP listener accepts tunnel traffic. When acting as an outbound gateway, the relay also allocates a UDP socket on an operating-system-selected port. Return traffic uses this socket. Network rules must accommodate these gateway sockets as well as the configured listener. + +`ExternalIP` does not configure port forwarding or a firewall. + +## Payment settings + +| Field under `Payments` | Purpose | +| ------------------------ | --------------------------------------------------------------- | +| `MinPricePerPacketRoute` | Minimum price in nanograms per routed packet | +| `MinPricePerPacketInOut` | Minimum price in nanograms per gateway inbound/outbound packet | +| `PaymentsNodeKey` | Private seed for the Payment Network node | +| `ADNLServerKey` | Private seed for the payment transport | +| `WalletPrivateKey` | Private seed for the payment wallet | +| `DBPath` | Persistent payment database, generated default `./payments-db/` | +| `ChannelsConfig` | Payment Network channel policy | + +The shared configuration advertises payment terms when `PaymentsEnabled` is true and at least one price is positive. Private seeds are not included in the export. + +Without `-payment-node`, startup selects an active channel using the peer's Gram deposit, or prompts for a peer if none is available. The CLI option accepts hexadecimal; the prompt accepts base64. Both identify a 32-byte payment-node public key, distinct from the relay key and wallet address. + +### Payment routes + +Each paid pool entry contains a `Payment.Chain` array, ordered from the client's first payment peer to the relay's payment node. The client prepares a payment channel with the first peer. Intermediaries need outgoing channel capacity to the next payment peer. + +The relay's pool export starts with a single entry for its own payment-node key. Selecting a peer with `-payment-node` does not add that peer to the exported chain. For an indirect payment route, the pool must include the intermediary keys and their agreed terms. + +For native Gram payments, the fields under each `Payment.Chain` entry are: + +| Field | Meaning | +| ------------------------------ | -------------------------------------------------------------- | +| `NodeKey` | A 32-byte payment-node public key encoded as base64. | +| `MinFeePerVirtualChannel` | Minimum fee per virtual channel, as a decimal string in GRAM. | +| `PercentFeePerVirtualChannel` | Percentage fee applied when building the payment route. | +| `MaxCapacityPerVirtualChannel` | Maximum virtual-channel capacity, as a decimal string in GRAM. | + +`Payment.PricePerPacketRouteNano` and `Payment.PricePerPacketOutNano` specify the route and gateway prices in nanograms per packet. These packet prices are separate from virtual-channel fees. + +### Client funding + +A paid client runs an embedded Payment Network node with its own wallet and database, configured under `Payments`. Its startup log prints the wallet address to fund. The client wallet, the relay wallet, and payment-channel capacity are separate balances. + +The generated v0.2.2 client configuration enables automatic balance management under `Payments.ChannelsConfig.SupportedCoins.Ton.BalanceControl`: + +| Field | Generated value, GRAM | Meaning | +| --------------------------- | --------------------: | ----------------------------------------------------- | +| `DepositWhenAmountLessThan` | `1` | Threshold for requesting an automatic channel top-up. | +| `DepositUpToAmount` | `3` | Target channel balance after the top-up. | + +Review these settings before funding the client wallet. Wallet funds must also cover deployment and transaction fees. The target applies to each channel, not to total spending. These defaults are client policy, not a fixed cost for using a tunnel. + +## Console commands + +Enter these commands in the running relay's console, not in a shell. + +| Command | Result | +| --------------------- | ---------------------------------------------------------------------------------------- | +| `stats` | Cumulative packet and prepaid-credit counters per active section | +| `speed` | Toggle per-second packet statistics | +| `balance` | Summed available local Gram balance across active payment channels | +| `capacity` | Summed available peer-side Gram balance across active payment channels | +| `wallet-ton-balance` | Balance of the separate payment wallet | +| `wallet-ton-transfer` | Interactive transfer from the payment wallet; prompts for recipient, amount, and comment | + +Payment commands require paid mode. Channel balances and capacity are separate from the wallet's on-chain balance. + +## Sources + +- [Relay startup, payment setup, and console commands](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/cmd/node/main.go#L131-L411) +- [Configuration and public pool export](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/config/config.go#L221-L489) +- [Relay selection](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/setup.go#L78-L96) and [route construction](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/setup.go#L244-L340) +- [Forwarding](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/instructions.go#L415-L489), [gateway allocation](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/instructions.go#L741-L851), and [payment checks](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/tunnel/instructions.go#L501-L722) +- [Local single-route and multiple-relay integration tests](https://github.com/ton-blockchain/adnl-tunnel/blob/c00a15763f7a10f3b7426beea6b728834f2a86c9/cmd/test-tunnel/integration_test.go#L31-L136) +- [Tonutils-Proxy tunnel initialization](https://github.com/xssnick/Tonutils-Proxy/blob/526ece06e3c6e7398df09039a5ad0e3c144fc6ec/proxy/proxy.go#L225-L280) +- [Go reverse proxy tunnel initialization](https://github.com/tonutils/reverse-proxy/blob/300fc0ced8eab48ff5879ce822419d42b8e3a43e/cmd/proxy/main.go#L182-L230) diff --git a/content/foundations/web3/ton-tunnel/run-relay.mdx b/content/foundations/web3/ton-tunnel/run-relay.mdx new file mode 100644 index 000000000..30c402f4b --- /dev/null +++ b/content/foundations/web3/ton-tunnel/run-relay.mdx @@ -0,0 +1,172 @@ +--- +title: "How to run an ADNL tunnel relay" +sidebarTitle: "Run a relay" +description: "Build and configure a relay with optional traffic payments" +--- + +Run an [Abstract Datagram Network Layer (ADNL)](/foundations/network/adnl-udp) Tunnel v0.2.2 relay, optionally enable traffic payments, and share its public configuration with clients. The commands require a POSIX shell. + +## Prerequisites + +- [Go 1.26 or later](https://go.dev/dl/) (tested with Go 1.26.1) +- A public IPv4 address and UDP connectivity for the relay listener and [gateway ports](/foundations/web3/ton-tunnel/reference#network-endpoints) + +## Build the relay + +```bash +git clone --branch v0.2.2 https://github.com/ton-blockchain/adnl-tunnel +cd adnl-tunnel +go build -ldflags "-w -s -X main.GitCommit=$(git describe --tags --always --dirty)" -o build/tunnel-node cmd/node/main.go +``` + +The executable is `build/tunnel-node`. The examples below run from this repository directory. + +## Generate configuration + + + `relay.json` contains private keys, including a payment wallet key even when payments are disabled. Keep it private and backed up. Share only the exported `nodes.json` file. + + +Generate the private configuration and public pool with [`-config` and `-gen-shared-config`](/foundations/web3/ton-tunnel/reference#relay-cli): + +```bash +./build/tunnel-node -config relay.json -gen-shared-config nodes.json +``` + +On first use, this creates `relay.json` and exports `nodes.json`, then exits without starting the relay. The configuration generator also attempts to detect a reachable public IP address. + +Open `relay.json` and check these [relay configuration fields](/foundations/web3/ton-tunnel/reference#relay-configuration) without replacing the generated keys: + +- Set `ExternalIP` to the relay's public IPv4 address. +- Set `TunnelListenAddr` to the address and UDP port to listen on, for example `0.0.0.0:17330`. +- Keep `PaymentsEnabled` set to `false`. +- Keep `NetworkConfigUrl` set to the generated mainnet configuration URL. + +## Configure prices (optional) + + + +In `relay.json`, enable `PaymentsEnabled` and set the two prices under `Payments`. + +The following is a partial fragment to merge into the existing configuration. Preserve all generated keys and channel settings. The values are example prices, in nanograms per packet: + +```jsonc +// Not runnable: merge into relay.json, preserving its generated keys and settings. +{ + "PaymentsEnabled": true, + "Payments": { + "MinPricePerPacketRoute": 1, + "MinPricePerPacketInOut": 1 + } +} +``` + +The first [price](/foundations/web3/ton-tunnel/reference#payment-settings) applies to relay forwarding; the second applies to the gateway's inbound and outbound traffic. + + + Enabling payments can deploy an on-chain channel and spend funds from the wallet configured in `relay.json`. Verify the peer and network first. Preserve the private configuration and payment database; restarting with new keys does not restore the old channels. + + +Paid mode also requires a mainnet Payment Network peer, its payment-node public key, incoming channel capacity, and funds for deployment and transaction fees. + +## Start the relay + +For a free relay, run: + +```bash +./build/tunnel-node -config relay.json +``` + +For a paid relay, use the command below instead. In either mode, wait for “Tunnel started, listening on” followed by the listener address and relay public key. Keep the process running. Use Ctrl+C to stop it before editing its configuration. + +### Connect to the payment peer (paid mode) + + + +Start the relay with [`-payment-node`](/foundations/web3/ton-tunnel/reference#relay-cli), replacing `` with the peer's 32-byte payment-node public key encoded as 64 hexadecimal characters: + +```bash +./build/tunnel-node -config relay.json -payment-node +``` + +This is the payment-node key, not its wallet address or tunnel relay key. + +The startup logs include “wallet initialized” with the relay wallet address. If channel deployment fails because the wallet has insufficient funds, fund that address on mainnet and restart with the same configuration and database. There is no fixed funding amount in this guide; fees and required reserves depend on the channel settings. + +The relay reuses an active channel with the specified peer or attempts to open one. Wait for the message “prioritized channel for payments is active”. + +### Obtain incoming capacity + +Coordinate with the payment peer's operator to [fund its side of the channel](/foundations/web3/payment-network/use-channels#fund-the-local-side). Funding only the relay wallet does not provide incoming channel capacity. + +In the relay console, run: + +```text +capacity +``` + +“Capacity left” sums the available incoming capacity across all active channels, not the relay wallet balance. A positive total does not establish capacity for the published route. Ask the payment peer's operator to confirm that route's channel capacity. + +## Publish the pool + +Export an updated pool file from another terminal in the repository directory: + +```bash +./build/tunnel-node -config relay.json -gen-shared-config nodes.json +``` + +For paid mode, include any agreed [payment intermediaries and their terms](/foundations/web3/ton-tunnel/reference#payment-routes) before distributing the pool. The export contains only the relay's own payment-node key; `-payment-node` does not add the selected peer. + +Share the final `nodes.json` with clients. Paid entries require clients with payments enabled and funded Payment Network connectivity. + +## Connect a client and verify + +Follow [Use a tunnel](/foundations/web3/ton-tunnel/use). The exported pool contains one relay; clients need a larger pool for routes with more sections. + +After the client establishes a tunnel and sends traffic, enter this command in the relay's console: + +```text +stats +``` + +Check that the relevant `routed`, `sent`, or `received` counters increase. A newly started relay with no active sections may print no counters. + +To toggle continuous per-second statistics, enter: + +```text +speed +``` + +Run `speed` again to stop the continuous output. + +### Verify payments + + + +After a funded client sends traffic, check [`stats`, `balance`, and `capacity`](/foundations/web3/ton-tunnel/reference#console-commands) in the relay console. + +Record `balance` and `capacity` before and after a controlled traffic test. These values aggregate all active payment channels; they are not tunnel-specific revenue counters. Account for deposits, withdrawals, and other channel activity when interpreting changes. Packet counters alone do not prove that payment was received. + +## Troubleshoot + +| Problem | Check | +| -------------------------------------- | -------------------------------------------------------------------------------------------- | +| “Invalid external IP address” | Set `ExternalIP` to the public IPv4 address, without a port. | +| Client cannot establish a route | Check the relay's public reachability, UDP rules, and the public key in the shared pool. | +| Tunnel starts but return traffic fails | Check the dynamically allocated gateway UDP ports as well as the fixed listener. | +| “payments are not enabled” | `balance` and `capacity` require paid mode; use `stats` for a free relay. | +| Invalid payment-node key | The CLI option expects hexadecimal; the interactive prompt, if used instead, expects base64. | +| Channel deployment fails | Check wallet funds, peer reachability, and whether both nodes use mainnet. | +| “Capacity left” is zero | Ask the peer operator to provide incoming capacity. | +| Clients cannot select the relay | Distribute the updated pool and check client payment settings. | +| Payment database cannot be opened | Do not run multiple paid relay processes against the same database. | diff --git a/content/foundations/web3/ton-tunnel/use.mdx b/content/foundations/web3/ton-tunnel/use.mdx new file mode 100644 index 000000000..cf9e36fac --- /dev/null +++ b/content/foundations/web3/ton-tunnel/use.mdx @@ -0,0 +1,137 @@ +--- +title: "How to use an ADNL tunnel" +sidebarTitle: "Use a tunnel" +description: "Configure a relay pool in a compatible TON proxy application" +--- + +Route a compatible application's [Abstract Datagram Network Layer (ADNL) traffic](/foundations/network/adnl-udp) through relays. The commands require a POSIX shell. Use a free relay, or enable payments for relays that charge for traffic. + +## Prerequisites + +- One of these initialized applications, with its generated `config.json`: + - [Tonutils-Proxy v1.8.3](/foundations/web3/ton-proxy/forward-proxy#use-tonutils-proxy) + - [tonutils-reverse-proxy v0.6.0](/foundations/web3/ton-proxy/reverse-proxy#use-tonutils-reverse-proxy) +- A `nodes.json` file exported by a [relay operator](/foundations/web3/ton-tunnel/run-relay#generate-configuration), containing at least one reachable relay + +The two [client integrations](/foundations/web3/ton-tunnel/reference#client-integrations) use different tunnel-library versions and JSON field names. Follow the matching configuration below. + +## Configure the pool + +Stop the application before editing its `config.json`. + + + `config.json` contains private keys even when payments are disabled. Keep it private and backed up. Preserve the generated keys and other settings; share only the public pool file with the relay operator. + + +This is a partial configuration fragment, not a replacement file. Merge these [client configuration fields](/foundations/web3/ton-tunnel/reference#client-configuration-and-node-pools) into `TunnelConfig` for Tonutils-Proxy, or into `tunnel_config` for tonutils-reverse-proxy: + +```jsonc +// Not runnable: merge into the existing tunnel configuration object. +{ + "NodesPoolConfigPath": "", + "TunnelSectionsNum": 1, + "PaymentsEnabled": false +} +``` + +Replace `` with the absolute path to `nodes.json` on the application's host. + +One section is sufficient for the initial connection check. For multiple sections: + +1. Set `TunnelSectionsNum` to the desired number. +1. Copy the entries from the relays' exported `NodesPool` arrays into one `NodesPool` array in a single JSON file. +1. Preserve each entry's `Key` and `Payment` fields. Include each relay key only once, with at least `TunnelSectionsNum` eligible entries. + +## Enable payments (optional) + + + Tonutils-Proxy v1.8.3 is not compatible with paid ADNL Tunnel v0.2.2 relays. Select a compatible published client release before enabling payments. + + +Paid mode requires a compatible published client, a mainnet funding wallet, and a payment route with sufficient capacity supplied by the operator. + +### Review the pool + +Check the advertised packet prices and the [payment peers](/foundations/web3/ton-tunnel/reference#payment-routes) in `Payment.Chain`. + +The relay key identifies the traffic relay. The keys in `Payment.Chain` identify payment nodes; the first entry selects the client's payment peer. Ask the operator to confirm the route and terms before funding the client. + +Set `PaymentsEnabled` to `true` in the tunnel configuration above. Preserve the generated private keys and payment database path. + + + The client's payment service can deposit wallet funds into channels automatically. Review its balance-control settings and the relay's prices before funding the wallet. Mainnet transfers cannot be rolled back. Keep the private configuration and payment database backed up. + + +Review [`Payments.ChannelsConfig.SupportedCoins.Ton.BalanceControl`](/foundations/web3/ton-tunnel/reference#client-funding) inside the application's tunnel configuration. The deposit target applies to each channel, not to total spending. + +## Start Tonutils-Proxy + +Restart the same executable used in the [forward proxy guide](/foundations/web3/ton-proxy/forward-proxy#use-tonutils-proxy). A nonempty `TunnelConfig.NodesPoolConfigPath` enables tunnel mode; there is no `--enable-tunnel` flag for this application. + +Keep the browser configured to use the local forward proxy. + +## Start tonutils-reverse-proxy + +Alternatively, append [`--enable-tunnel`](/foundations/web3/ton-tunnel/reference#client-integrations) to the startup command from [Run a reverse proxy](/foundations/web3/ton-proxy/reverse-proxy#use-tonutils-reverse-proxy). Preserve the existing backend and domain settings. + +The application uses the tunnel's external endpoint for its ADNL address list. + +## Fund the client wallet (paid mode) + + + +For paid mode, find “wallet initialized with address:” in the startup log and record that address as ``. + +Transfer Gram from the funding wallet to ``, allowing for the configured deposit target and on-chain fees. Keep the client's configuration and database unchanged if startup must be retried. + +The embedded payment service prepares the channel with the pool's first payment peer and manages funding according to `BalanceControl`. + +## Wait for the tunnel + +Wait for “tunnel updated” in Tonutils-Proxy, or “Tunnel updated” in tonutils-reverse-proxy, then for the application's HTTP listener or server to start. + +Channel initialization alone does not establish that the tunnel is ready or that the payment route has sufficient capacity. + +If the client cannot obtain capacity, ask the operator to check the payment route through to the relay. Funding the client wallet does not provide an intermediary's outgoing capacity. + +## Verify + +Request a known TON Site through the forward proxy, or the hosted site through the reverse proxy. In paid mode, record the relay's traffic counters, prepaid credit, and channel balances with the operator before sending the request. + +Replace `` with the user-friendly address of a TON Site with known content. Through the local forward proxy, request that site: + +```bash +curl --noproxy '' --proxy http://127.0.0.1:8080 --fail "http://.adnl/" +``` + +Confirm the expected response and ask the relay operator to check its [traffic counters](/foundations/web3/ton-tunnel/run-relay#connect-a-client-and-verify). An ordinary Internet HTTP request through Tonutils-Proxy does not test the tunnel: it uses the regular HTTP client. + +### Verify traffic and payment + +For paid mode, compare the counters, prepaid credit, and channel balances recorded before the request with their values afterward using the [relay verification procedure](/foundations/web3/ton-tunnel/run-relay#verify). + +A successful HTTP response proves traffic forwarding. Packet counters alone do not establish that the relay received payment. Account for virtual-channel fees and prepaid credit when comparing balances. + +## Troubleshoot + +| Problem | Check | +| ----------------------------------------- | ------------------------------------------------------------------------------------------- | +| “failed to load tunnel nodes pool config” | Check the pool path and file permissions. | +| “no nodes pool provided” | With payments disabled, the pool must include an entry with no payment requirement. | +| “not enough nodes” | Reduce `TunnelSectionsNum` or add eligible relays to the pool. | +| No tunnel initialization message | Check the application's field name and whether its tunnel mode is enabled. | +| Tunnel is established but the site fails | Check the destination and its DNS record separately from relay connectivity. | +| The payment peer cannot be found | Confirm the first `Payment.Chain` key, its network, and its reachability with the operator. | +| Channel funding fails | Check the client's payment-wallet balance, deposit policy, and on-chain transaction result. | +| Insufficient route capacity | Ask the operator to check capacity on the payment hops leading to the relay. | diff --git a/content/from-ethereum.mdx b/content/from-ethereum.mdx index f6378ee36..863d20b0e 100644 --- a/content/from-ethereum.mdx +++ b/content/from-ethereum.mdx @@ -110,6 +110,6 @@ The table maps Ethereum standards and proposals, including ERC and EIP, to their | Non-fungible token standard | ERC-721 | [NFT standard (TEP-0062)](/contracts/standard/tokens/nft/overview) | | Token metadata | ERC-4955 (Not exactly, but close match) | [Token Data Standard (TEP-0064)](/contracts/standard/tokens/metadata) | | NFT royalty standard | EIP-2981 | [NFT Royalty Standard (TEP-0066)](/contracts/standard/tokens/nft/comparison) | -| DNS-like registry | ENS (EIP-137) | [DNS Standard (TEP-0081)](/foundations/web3/overview) | +| DNS-like registry | ENS (EIP-137) | [DNS Standard (TEP-0081)](/foundations/web3/ton-dns/reference#dns-protocol) | | Soulbound / account-bound token concept | EIP-4973 | [SBT Standard (TEP-0085)](/contracts/standard/tokens/nft/comparison#sbt) | | Wallet connection protocol | WalletConnect / EIP-1193 | [TonConnect (TEP-0115)](/applications/ton-connect/overview) | diff --git a/content/meta.json b/content/meta.json index f2e2e44a4..5c00f5ff6 100644 --- a/content/meta.json +++ b/content/meta.json @@ -22,6 +22,8 @@ "...tvm", "---[BrickWall]Blockchain foundations---", "...foundations", + "---[Globe]Web3 services---", + "...foundations/web3", "---[FileArchive]Legacy languages---", "...languages", "---[HeartHandshake]Contributing---", diff --git a/scripts/check-redirects.mjs b/scripts/check-redirects.mjs index b66e32276..8ad681c00 100644 --- a/scripts/check-redirects.mjs +++ b/scripts/check-redirects.mjs @@ -447,9 +447,11 @@ const checkUpstream = async (localConfig) => { }; const upstreamNavLinks = Object.freeze(new Set(findUnignoredMdxUpstream())); - const localNavLinks = getNavLinksSet(); + const localNavLinks = new Set([...getNavLinksSet()].map((it) => it.replace(/\/index$/, ''))); - const upstreamOnlyLinks = [...upstreamNavLinks].filter((it) => !localNavLinks.has(it)); + const upstreamOnlyLinks = [...upstreamNavLinks].filter( + (it) => !localNavLinks.has(it.replace(/\/index$/, '')), + ); if (upstreamOnlyLinks.length === 0) { return { ok: true }; } diff --git a/src/app/(docs)/layout.tsx b/src/app/(docs)/layout.tsx index 35a6deafc..523d3c0aa 100644 --- a/src/app/(docs)/layout.tsx +++ b/src/app/(docs)/layout.tsx @@ -22,7 +22,16 @@ const tabUrls: Record> = { Contracts: new Set(pagePaths.filter((it) => it.startsWith('/contracts/'))), Tolk: new Set(pagePaths.filter((it) => it.startsWith('/tolk/'))), TVM: new Set(pagePaths.filter((it) => it.startsWith('/tvm/'))), - Foundations: new Set(pagePaths.filter((it) => it.startsWith('/foundations/'))), + Foundations: new Set( + pagePaths.filter( + (it) => it.startsWith('/foundations/') && !it.startsWith('/foundations/web3/'), + ), + ), + Web3: new Set( + pagePaths + .filter((it) => it.startsWith('/foundations/web3/')) + .map((it) => it.replace(/\/index$/, '')), + ), }; export default function Layout({ children }: { children: ReactNode }) { @@ -93,6 +102,16 @@ export default function Layout({ children }: { children: ReactNode }) { url: '/foundations/overview', urls: tabUrls.Foundations, }, + { + title: ( + <> + Web3 + Web3 services + + ), + url: '/foundations/web3/overview', + urls: tabUrls.Web3, + }, ]} tabMode="top" // Fumadocs works with a named-area CSS grid: each layout part self-places via its own `grid-area`. diff --git a/src/dictionaries/custom.txt b/src/dictionaries/custom.txt index 899bf8081..4a2b7bd6e 100644 --- a/src/dictionaries/custom.txt +++ b/src/dictionaries/custom.txt @@ -459,9 +459,14 @@ Merkle Mersenne metafile Metafile +metafiles +Metafiles MetalLB Metaverse MEV +microchunk +Microchunk +microchunks micropayment micropayments Micropayments @@ -771,6 +776,7 @@ tonstatus tonutils toolchain toolset +topup TPS tracebacks TransactionDescr diff --git a/vercel.json b/vercel.json index c37d8ec5f..1dafa7dc8 100644 --- a/vercel.json +++ b/vercel.json @@ -585,7 +585,7 @@ }, { "source": "/v3/documentation/dapps/defi/ton-payments", - "destination": "/foundations/web3/overview", + "destination": "/foundations/web3/payment-network", "permanent": true }, { @@ -1620,7 +1620,7 @@ }, { "source": "/v3/guidelines/web3/ton-dns/subresolvers", - "destination": "/foundations/web3/ton-dns", + "destination": "/foundations/web3/ton-dns/reference", "permanent": true }, { @@ -1630,7 +1630,7 @@ }, { "source": "/v3/guidelines/web3/ton-proxy-sites/how-to-run-ton-site", - "destination": "/foundations/web3/ton-sites", + "destination": "/foundations/web3/ton-sites/web-server", "permanent": true }, { @@ -1640,12 +1640,12 @@ }, { "source": "/v3/guidelines/web3/ton-proxy-sites/connect-with-ton-proxy", - "destination": "/foundations/web3/ton-proxy", + "destination": "/foundations/web3/ton-proxy/forward-proxy", "permanent": true }, { "source": "/v3/guidelines/web3/ton-proxy-sites/how-to-open-any-ton-site", - "destination": "/foundations/web3/ton-proxy", + "destination": "/foundations/web3/ton-proxy/forward-proxy", "permanent": true }, { @@ -1665,12 +1665,12 @@ }, { "source": "/v3/guidelines/web3/ton-storage/storage-daemon", - "destination": "/foundations/web3/ton-storage", + "destination": "/foundations/web3/ton-storage/get-started", "permanent": true }, { "source": "/v3/guidelines/web3/ton-storage/storage-provider", - "destination": "/foundations/web3/ton-storage", + "destination": "/foundations/web3/ton-storage/provider-lifecycle", "permanent": true }, { @@ -1750,7 +1750,7 @@ }, { "source": "/develop/howto/subresolvers", - "destination": "/foundations/web3/ton-dns", + "destination": "/foundations/web3/ton-dns/reference", "permanent": true }, { @@ -2155,7 +2155,7 @@ }, { "source": "/develop/dapps/defi/ton-payments", - "destination": "/foundations/web3/overview", + "destination": "/foundations/web3/payment-network", "permanent": true }, { @@ -2485,7 +2485,7 @@ }, { "source": "/develop/dapps/tutorials/how-to-run-ton-site", - "destination": "/foundations/web3/ton-sites", + "destination": "/foundations/web3/ton-sites/web-server", "permanent": true }, {