├── .babelrc ├── .gitignore ├── .prettierignore ├── README.md ├── config-overrides.js ├── package.json ├── public ├── ConfigParam-HOWTO.txt ├── DNS-HOWTO.txt ├── FullNode-HOWTO.txt ├── HOWTO.txt ├── README.txt ├── TonSites-HOWTO.txt ├── Validator-HOWTO.txt ├── catchain.pdf ├── favicon.ico ├── fiftbase.pdf ├── fight.jpg ├── index.html ├── info.html ├── logo192.png ├── logo512.png ├── manifest.json ├── projects.html ├── robots.txt ├── smc-guidelines.txt ├── tblkch.pdf ├── test.png ├── test3.png ├── ton-global-lite-client.config.json ├── ton-global.config.json ├── ton-lite-client-test1.config.json ├── ton-lite-client-test3.config.json ├── ton.pdf ├── toncommunity-global.config.json ├── toncommunity-lite-client.config.json ├── toncommunity-testnet3-config.json └── tvm.pdf └── src ├── index.css ├── index.js ├── pages ├── App │ ├── App.js │ ├── App.test.js │ └── logo.svg ├── Faucet │ ├── Faucet.js │ ├── index.js │ └── logo2.png ├── Home │ ├── Home.js │ ├── index.js │ ├── logo.svg │ ├── logo2.png │ ├── telegram.svg │ └── twitter.svg └── useScrollTop.js ├── serviceWorker.js └── setupTests.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-react-pug", 4 | "@babel/transform-react-jsx" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | yarn.lock 8 | 9 | # testing 10 | /coverage 11 | 12 | # production 13 | /build 14 | 15 | # misc 16 | .DS_Store 17 | .env.local 18 | .env.development.local 19 | .env.test.local 20 | .env.production.local 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | /public 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | TON Community logo 4 | 5 |

6 | 7 | **TON Community Project - Official info for core projects** 8 | 9 | Community Blockchain, wallet applications, base-TON project and other package index. The source code for the TON Blockchain which operates a node on the TON Community Network is kept in here. 10 | 11 | 12 | 13 | [![Website toncommunity](https://img.shields.io/website-up-down-green-red/https/toncommunity.org.svg)](https://www.toncommunity.org) 14 | [![Twitter](https://img.shields.io/twitter/follow/toncommunity?style=social)](https://twitter.com/toncommunity) 15 | [![Telegram Channel](https://img.shields.io/badge/TONCommunity-Channel-blue)](https://t.me/ton_news) 16 | [![Telegram Group EN](https://img.shields.io/badge/TONCommunity-EN__Group-blue)](https://t.me/ton_en) 17 | [![Telegram Group CN](https://img.shields.io/badge/TONCommunity-CN__Group-blue)](https://t.me/ton_cn) 18 | 19 | 20 | Contents: 21 | 22 | 23 | 24 | - [TONCommunity.org's Mission - Bring Crypto Into Mainstream](#mission) 25 | - [TON Community Worldview](#worldview) 26 | - [TON Blockchain(Original Project)](#original) 27 | - [Roadmap](#roadmap) 28 | - [Token Distirution](#token) 29 | - [Ask Questions, Find Answers, Get in Touch](#ask) 30 | - [Marketing](#marketing) 31 | 32 | 33 | ## ✅ TONCommunity.org's Mission - Bring Crypto Into Mainstream 34 | 35 | TONCommunity.org from TON Blockchain old supporter. But must declare, all people come from the community, it has nothing to do with Telegram Official. We long telegram. And we think social network + crypto is the key to bringing crypto into mainstream. 36 | 37 | ## 💻 TON Community Worldview 38 | - We Long Crypto and Blockchain. 39 | - We Trust Socal Network Will bring crypto into mainstream. 40 | - Globalization will not stop(WE ARE CYBER KID), it will arrive in another way. We participate throughout. 41 | - Privacy, permissionless, hostingless, unstoppable. It will be building step by step. 42 | 43 |

44 | 45 | user-friendly 46 | 47 |

48 | 49 | ## 🗝 How to test & join TONCommunity.org Pre-main network 50 | ### You have 5 user-friendly ways: 51 | 1,Download Wallet App and create your wallet address: 52 | - :rocket:[iOS](https://testflight.apple.com/join/sYg7ibyW) 53 | - :rocket:[Winodws](https://ton.org/apps/wsetup.0.9.8.exe) 54 | - :rocket:[macOS](https://ton.org/apps/wsetup.0.9.8.dmg) 55 | - :rocket:[Android](https://ton.org/apps/wallet.apk) 56 | - :rocket:[Android(Google Play)](https://play.google.com/store/apps/details?id=org.tginfo.telegram.messenger.wallet) 57 | 58 | 2,Change the Waller server config: choice Testnetwork and Config source - Url, copy URL: 59 | ``` 60 | https://toncommunity.org/toncommunity-lite-client.config.json 61 | ``` 62 |

63 | 64 | user-friendly 65 | 66 |

67 | 68 | 3,Change Blockchain ID: TONCommunity. 69 | 70 | 4,Confirm, re-start the wallet/enter the mnemonic phrase. 71 | 72 | 5,Connected the TONCommunity.org network successfully. 73 | 74 |

75 | 76 | dev 77 | 78 |

79 | 80 | ### You have 3 dev way to join Blockchain Network. 81 | Configuration 82 | - [Global configuration](https://github.com/TONCommunity/Project/blob/master/public/toncommunity-global.config.json) 83 | - [Client Configuration](https://github.com/TONCommunity/Project/blob/master/public/toncommunity-lite-client.config.json) 84 | 85 | Check subdirectory and choice your way. 86 | - [Lite-client howto](https://github.com/TONCommunity/Project/blob/master/public/README.txt) 87 | - [Fullnode howto](https://github.com/TONCommunity/Project/blob/master/public/FullNode-HOWTO.txt) 88 | - [Validator howto](https://github.com/TONCommunity/Project/blob/master/public/Validator-HOWTO.txt) 89 | 90 | ## ❤ TON Blockchain(Original Project) 91 | - [TON Whitepaper](https://github.com/TONCommunity/Project/blob/master/public/ton.pdf) – a general description of TON Network and TON Blockchain 92 | - [TVM](https://github.com/TONCommunity/Project/blob/master/public/tvm.pdf) - TON Virtual Machine description 93 | - [TON Blockchain description (may include outdated information)](https://github.com/TONCommunity/Project/blob/master/public/tblkch.pdf) 94 | - [Fiftbase](https://github.com/TONCommunity/Project/blob/master/public/fiftbase.pdf) - A brief introduction to the Fift programming language 95 | - [🔗Catchain ](https://github.com/TONCommunity/Project/blob/master/public/catchain.pdf)– Description of BFT Consensus protocol employed by TON Blockchain while creating new blocks 96 | - [Smart Contracts Guidelines](https://github.com/TONCommunity/Project/blob/master/public/smc-guidelines.txt) - and best practices related to implementation of TON Blockchain smart contracts 97 | 98 | ## 🔨 Roadmap 99 | [Roadmap - TONCommunity.org](https://drive.google.com/file/d/1OQFa27yPbAnIZwrY793F-32fDuV6kjCJ/view?usp=sharing) 100 | 101 | ## 🏘 TON-based Projects 102 | About TON-based project and a list of projects on TON submitted for the Telegram blockchain competition. 103 | We support [TON-base's blockchain](https://toncommunity.org/projects.html) project. 104 | 105 | ## :gem: Token Distirution 106 | 107 | ## ✈ Marketing 108 | - 🎈[About Airdrop Round A](https://t.me/toncommunity_bot) 109 | - 🎈[2021新春活动: TON 中文社区&Bananatok(原币用APP)](https://t.me/TON_CN/16656) 110 | 111 | ## 🔈 Ask Questions, Find Answers, Get in Touch 112 | - 🚀[Telegram Channel](https://t.me/ton_news) 113 | - 🌕[Chat Group(EN)](https://t.me/ton_en) 114 | - 🌕[Chat Group(CN)](https://t.me/ton_cn) 115 | - :robot:[Testnet Wallet Bot](https://t.me/gram50bot) 116 | - 📌[Twitter](https://twitter.com/TONCommunity) 117 | -------------------------------------------------------------------------------- /config-overrides.js: -------------------------------------------------------------------------------- 1 | const { 2 | override, 3 | fixBabelImports, 4 | useBabelRc, 5 | disableEsLint, 6 | } = require("customize-cra"); 7 | 8 | module.exports = override( 9 | fixBabelImports("antd", { 10 | libraryDirectory: "es", 11 | style: "css", 12 | }), 13 | disableEsLint(), 14 | useBabelRc() 15 | ); 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@ant-design/icons": "^4.2.1", 7 | "@testing-library/jest-dom": "^5.7.0", 8 | "@testing-library/react": "^10.0.4", 9 | "@testing-library/user-event": "^10.3.0", 10 | "antd": "^4.2.3", 11 | "axios": "^0.19.2", 12 | "babel-plugin-import": "^1.13.0", 13 | "classnames": "^2.2.6", 14 | "dayjs": "^1.8.27", 15 | "history": "^5.0.0", 16 | "react": "^16.13.1", 17 | "react-app-rewired": "^2.1.6", 18 | "react-dom": "^16.13.1", 19 | "react-router": "6.0.0-beta.0", 20 | "react-router-dom": "6.0.0-beta.0", 21 | "react-scripts": "3.4.1" 22 | }, 23 | "scripts": { 24 | "start": "react-app-rewired start", 25 | "build": "react-app-rewired build", 26 | "test": "react-app-rewired test", 27 | "eject": "react-scripts eject" 28 | }, 29 | "eslintConfig": { 30 | "extends": "react-app" 31 | }, 32 | "browserslist": { 33 | "production": [ 34 | ">0.2%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "last 1 chrome version", 40 | "last 1 firefox version", 41 | "last 1 safari version" 42 | ] 43 | }, 44 | "devDependencies": { 45 | "babel-plugin-transform-react-pug": "^7.0.1", 46 | "customize-cra": "^0.9.1", 47 | "husky": "^4.2.5", 48 | "prettier": "2.0.5", 49 | "pretty-quick": "^2.0.1", 50 | "styled-components": "^5.1.0", 51 | "svgo": "^1.3.2" 52 | }, 53 | "husky": { 54 | "hooks": { 55 | "pre-commit": "pretty-quick --staged" 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /public/DNS-HOWTO.txt: -------------------------------------------------------------------------------- 1 | The aim of this document is to provide a very brief introduction to TON DNS, a service for translating human-readable domain names (such as `test.ton` or `mysite.temp.ton`) into TON smart contract addresses, ADNL addresses employed by services running in the TON Network (such as TON Sites), and so on. 2 | 3 | 1. Domain names 4 | ~~~~~~~~~~~~~~~ 5 | 6 | TON DNS employs familiarly-looking domain names, consisting of a UTF-8 encoded string up to 126 bytes, with different sections of the domain name separated by dots (`.`). Null characters (i.e. zero bytes) and, more generally, bytes in range 0..32 are not allowed in domain names. For instance, `test.ton` and `mysite.temp.ton` are valid TON DNS domains. A major difference from usual domain names is that TON DNS domains are case-sensitive; one could convert all domains to lowercase before performing a TON DNS lookup in order to obtain case-insensitivity if desired. 7 | 8 | Currently, only domains ending in `.ton` are recognized as valid TON DNS domains. This could change in the future. Notice, however, that it is a bad idea to define first-level domains coinciding with first-level domains already existing in the Internet, such as `.com` or `.to`, because one could then register a TON domain `google.com`, deploy a TON site there, create a hidden link to a page at this TON site from his other innocently-looking TON site, and steal `google.com` cookies from unsuspecting visitors. 9 | 10 | Internally, TON DNS transforms domain names as follows. First, a domain name is split into its components delimited by dot characters `.`. Then null characters are appended to each component, and all components are concatenated in reverse order. For example, `google.com` becomes `com\0google\0`. 11 | 12 | 2. Resolving TON DNS domains 13 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14 | 15 | A TON DNS domain is resolved as follows. First, the *root DNS smart contract* is located by inspecting the value of configuration parameter #4 in a recent masterchain state. This parameter contains the 256-bit address of the root DNS smart contract inside the masterchain. 16 | 17 | Then a special get-method `dnsresolve` (method id 123660) is invoked for the root DNS smart contract, with two parameters. The first parameter is a CellSlice with *8n* data bits containing the internal representation of the domain being resolved, where *n* is the length of the internal representation in bytes (at most 127). The second parameter is a signed 16-bit Integer containing the required *category*. If the category is zero, then all categories are requested. 18 | 19 | If this get-method fails, then the TON DNS lookup is unsuccessful. Otherwise the get-method returns two values. The first is *8m*, the length (in bits) of the prefix of the internal representation of the domain that has been resolved, 0 < m <= n. The second is a Cell with the TON DNS record for the required domain in the required category, or the root a Dictionary with 16-bit signed integer keys (categories) and values equal to the serializations of corresponding TON DNS records. If the domain cannot be resolved by the root DNS smart contract, i.e. if no non-empty prefix is a valid domain known to the smart contract, then (0, null) is returned. In other words, m = 0 means that the TON DNS lookup has found no data for the required domain. In that case, the TON DNS lookup is also unsuccessful. 20 | 21 | If m = n, then the second component of the result is either a Cell with a valid TON DNS record for the required domain and category, or a Null if there is no TON DNS record for this domain with this category. In either case, the resolution process stops, and the TON DNS record thus obtained is deserialized and the required information (such as the type of the record and its parameters, such as a smart contract address or a ADNL address). 22 | 23 | Finally, if m < n, then the lookup is successful so far, but only a partial result is available for the m-byte prefix of the original internal representation of the domain. The longest of all such prefixes known to the DNS smart contract is returned. For instance, an attempt to look up `mysite.test.ton` (i.e. `ton\0test\0mysite\0` in the internal representation) in the root DNS smart contract might return 8m=72, corresponding to prefix `ton\0test\0`, i.e. to subdomain "test.ton" in the usual domain representation. In that case, dnsresolve() returns the value for category -1 for this prefix regardless of the category originally requested by the client. By convention, category -1 usually contains a TON DNS Record of type *dns_next_resolver*, containing the address of next resolver smart contract (which can reside in any other workchain, such as the basechain). If that is indeed the case, the resolution process continues by running get-method `dnsresolve` for the next resolver, with the internal representation of the domain name containing only its part unresolved so far (if we were looking up `ton\0test\0mysite\0`, and prefix `ton\0test\0` was found by the root DNS smart contract, then the next `dnsresolve` will be invoked with `mysite\0` as its first argument). Then either the next resolver smart contract reports an error or the absence of any records for the required domain or any of its prefixes, or the final result is obtained, or another prefix and next resolver smart contract is returned. In the latter case, the process continues in the same fashion until all of the original domain is resolved. 24 | 25 | 3. Using LiteClient and TonLib to resolve TON DNS domains 26 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | 28 | The above process can be invoked automatically using the TON LiteClient or TONLib. For instance, one can invoke the command `dnsresolve test.ton 1` in the LiteClient to resolve "test.ton" with category 1 and obtain the following result: 29 | 30 | ================================================ 31 | > dnsresolve test.ton 32 | ... 33 | Result for domain 'test.ton' category 1 34 | raw data: x{AD011B3CBBE404F47FFEF92D0D7894C5C6F215F677732A49E544F16D1E75643D46AB00} 35 | 36 | category #1 : (dns_adnl_address adnl_addr:x1B3CBBE404F47FFEF92D0D7894C5C6F215F677732A49E544F16D1E75643D46AB flags:0) 37 | adnl address 1B3CBBE404F47FFEF92D0D7894C5C6F215F677732A49E544F16D1E75643D46AB = UNTZO7EAT2H77XZFUGXRFGFY3ZBL5TXOMVETZKE6FWR45LEHVDKXAUY 38 | ================================================ 39 | 40 | In this case, the TON DNS record for "test.ton" is a `dns_adnl_address` record containing ADNL address UNTZO7EAT2H77XZFUGXRFGFY3ZBL5TXOMVETZKE6FWR45LEHVDKXAUY 41 | 42 | Alternatively, one can invoke `tonlib-cli` and enter the following command: 43 | ================================================ 44 | > dns resolve root test.ton 1 45 | Redirect resolver 46 | ... 47 | Done 48 | test.ton 1 ADNL:untzo7eat2h77xzfugxrfgfy3zbl5txomvetzke6fwr45lehvdkxauy 49 | ================================================ 50 | 51 | This is a more compact representation of the same result. 52 | 53 | Finally, if one uses RLDP-HTTP Proxy in the client mode to access TON Sites from a browser as explained in `TONSites-HOWTO.txt`, the TONLib resolver is automatically invoked to resolve all domains entered by the end user, so that a HTTP query to `http://test.ton/testnet/last` is automatically forwarded to ADNL address `untzo7eat2h77xzfugxrfgfy3zbl5txomvetzke6fwr45lehvdkxauy` via RLDP. 54 | 55 | 4. Registering new domains 56 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 57 | 58 | Suppose that you have a new TON Site with a newly-generated ADNL address, such as `vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3`. Of course, the end user might type `http://vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3.adnl/` to visit your TON Site from a browser using a RLDP-HTTP Proxy in client mode, but this is not very convenient. Instead, you could register a new domain, say, `mysite.temp.ton` with a `dns_adnl_address` record in category 1 containing the ADNL address vcq...25f3 of your TON Site. Then the user would access your TON Site by simply typing `mysite.temp.ton` in a browser. 59 | 60 | In general, you would need to contact the owner of the higher-level domain and ask him to add a record for your subdomain in his DNS resolver smart contract. However, the TestNet of the TON Blockchain has a special resolver smart contract for `temp.ton` that allows anyone to automatically register any subdomains of `temp.ton` not registered yet, provided a small fee (in test Grams) is paid to that smart contract. In our case, we first need to find out the address of this smart contract, for example by using the Lite Client: 61 | 62 | ================================================ 63 | > dnsresolve temp.ton -1 64 | ... 65 | category #-1 : (dns_next_resolver 66 | resolver:(addr_std 67 | anycast:nothing workchain_id:0 address:x190BD756F6C0E7948DC26CB47968323177FB20344F8F9A50918CAF87ECB34B79)) 68 | next resolver 0:190BD756F6C0E7948DC26CB47968323177FB20344F8F9A50918CAF87ECB34B79 = EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN 69 | ================================================ 70 | 71 | We see that the address of this automatic DNS smart contract is EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN. We can run several get methods to compute the required price for registering a subdomain, and to learn the period for which the subdomain will be registered: 72 | 73 | ================================================ 74 | > runmethod EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN getstdperiod 75 | ... 76 | arguments: [ 67418 ] 77 | result: [ 700000 ] 78 | remote result (not to be trusted): [ 700000 ] 79 | > runmethod EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN getppr 80 | ... 81 | arguments: [ 109522 ] 82 | result: [ 100000000 ] 83 | remote result (not to be trusted): [ 100000000 ] 84 | ================================================ 85 | 86 | We see that subdomains are registered for 700000 seconds (about eight days), and that the registration price is 100000000ng = 0.1 test Grams per domain, plus a price for each bit and cell of stored data, which can be learned by running get-methods `getppb` and `getppc`. 87 | 88 | Now we want this smart contract to register our subdomain. In order to do this, we have to create a special message from our wallet to the automatic DNS smart contract. Let us assume that we have a wallet `my_new_wallet` with address kQABzslAMKOVwkSkkWfelS1pYSDOSyTcgn0yY_loQvyo_ZgI. Then we run the following Fift script (from the subdirectory `crypto/smartcont` of the source tree): 89 | 90 | fift -s auto-dns.fif add owner cat 1 adnl 91 | 92 | For example: 93 | 94 | =============================================== 95 | $ fift -s auto-dns.fif EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN add 'mysite' 700000 owner kQABzslAMKOVwkSkkWfelS1pYSDOSyTcgn0yY_loQvyo_ZgI cat 1 adnl vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3 96 | Automatic DNS smart contract address = 0:190bd756f6c0e7948dc26cb47968323177fb20344f8f9a50918caf87ecb34b79 97 | kQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLef5H 98 | Action: add mysite 1583865040 99 | Operation code: 0x72656764 100 | Value: x{2_} 101 | x{BC000C_} 102 | x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00} 103 | x{BFFFF4_} 104 | x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_} 105 | 106 | Internal message body is: x{726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_} 107 | x{2_} 108 | x{BC000C_} 109 | x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00} 110 | x{BFFFF4_} 111 | x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_} 112 | 113 | B5EE9C7241010601007800012F726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A10102012002030105BC000C040105BFFFF4050046AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD0000499FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01070E6337D 114 | Query_id is 6799642071046147647 = 0x5E5D2E700481CE3F 115 | (Saved to file dns-msg-body.boc) 116 | ================================================ 117 | 118 | We see that the internal message body for this query has been created and saved into file `dns-msg-body.boc`. Now you have to send a payment from your wallet kQAB..ZgI to the automatic DNS smart contract EQA..UXN, along with message body from file `dns-msg-body.boc`, so that the automatic DNS smart contract knows what you want it to do. If your wallet has been created by means of `new-wallet.fif`, you can simply use `-B` command-line argument to `wallet.fif` while performing this transfer: 119 | 120 | ================================================ 121 | $ fift -s wallet.fif my_new_wallet EQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLeUXN 1 1.7 -B dns-msg-body.boc 122 | Source wallet address = 0:01cec94030a395c244a49167de952d696120ce4b24dc827d3263f96842fca8fd 123 | kQABzslAMKOVwkSkkWfelS1pYSDOSyTcgn0yY_loQvyo_ZgI 124 | Loading private key from file my_new_wallet.pk 125 | Transferring GR$1.7 to account kQAZC9dW9sDnlI3CbLR5aDIxd_sgNE-PmlCRjK-H7LNLef5H = 0:190bd756f6c0e7948dc26cb47968323177fb20344f8f9a50918caf87ecb34b79 seqno=0x1 bounce=-1 126 | Body of transfer message is x{726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_} 127 | x{2_} 128 | x{BC000C_} 129 | x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00} 130 | x{BFFFF4_} 131 | x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_} 132 | 133 | signing message: x{0000000103} 134 | x{62000C85EBAB7B6073CA46E1365A3CB41918BBFD901A27C7CD2848C657C3F659A5BCA32A9F880000000000000000000000000000726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_} 135 | x{2_} 136 | x{BC000C_} 137 | x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00} 138 | x{BFFFF4_} 139 | x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_} 140 | 141 | resulting external message: x{8800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA050E3817FC01F564AECE810B8077D72E3EE15C81392E8B4AE9CDD0D6575821481C996AE8FFBABA0513F131E10E27C006C6544E99D71E0A6AACF7D02C677342B040000000081C_} 142 | x{62000C85EBAB7B6073CA46E1365A3CB41918BBFD901A27C7CD2848C657C3F659A5BCA32A9F880000000000000000000000000000726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A1_} 143 | x{2_} 144 | x{BC000C_} 145 | x{AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD00} 146 | x{BFFFF4_} 147 | x{9FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01_} 148 | 149 | B5EE9C72410207010001170001CF8800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA050E3817FC01F564AECE810B8077D72E3EE15C81392E8B4AE9CDD0D6575821481C996AE8FFBABA0513F131E10E27C006C6544E99D71E0A6AACF7D02C677342B040000000081C01019762000C85EBAB7B6073CA46E1365A3CB41918BBFD901A27C7CD2848C657C3F659A5BCA32A9F880000000000000000000000000000726567645E5D2E700481CE3F0EDAF2E6D2E8CA00BCCFB9A10202012003040105BC000C050105BFFFF4060046AD0145061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD0000499FD3800039D928061472B84894922CFBD2A5AD2C2419C9649B904FA64C7F2D085F951FA01031E3A74C 150 | (Saved to file wallet-query.boc) 151 | ===================================================== 152 | 153 | (You have to replace 1 with the correct sequence number for your wallet.) Once you obtain a signed external message in `wallet-query.boc`, addressed to your wallet and instructing it to transfer 1.7 test Grams to the automatic DNS smart contract along with the description of your new domain to be registered, you can upload this message using the LiteClient by typing 154 | 155 | ===================================================== 156 | > sendfile wallet-query.boc 157 | [ 1][t 1][!testnode] sending query from file wallet-query.boc 158 | [ 3][t 1][!query] external message status is 1 159 | ===================================================== 160 | 161 | If all works correctly, you'll obtain some change from the automatic DNS smart contract in a confirmation message (it will charge only the storage fees for your subdomain and processing fees for running the smart contract and sending messages, and return the rest), and your new domain will be registered: 162 | 163 | ===================================================== 164 | > last 165 | ... 166 | > dnsresolve mysite.temp.ton 1 167 | ... 168 | Result for domain 'mysite.temp.ton' category 1 169 | category #1 : (dns_adnl_address adnl_addr:x45061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD flags:0) 170 | adnl address 45061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD = vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3 171 | ===================================================== 172 | 173 | You can modify or prolong this domain in essentially the same manner, by first creating a request in file `dns-msg-body.boc` by means of `auto-dns.fif`, using such actions as `update` or `prolong`, and then embedding this request into a message from your wallet to the automatic DNS smart contract using `wallet.fif` or a similar script with command-line argument `-B dns-msg-body.boc`. 174 | -------------------------------------------------------------------------------- /public/FullNode-HOWTO.txt: -------------------------------------------------------------------------------- 1 | The aim of this document is to provide step-by-step instructions for setting up a full node for the TON Blockchain. We assume some familiarity with the TON Blockchain Lite Client, at least to the extent explained in the Lite Client HOWTO. 2 | 3 | Note that you need a machine with a public IP address and a high-bandwidth network connection to run a TON Blockchain Full Node. Typically you'll need a sufficiently powerful server in a datacenter with good network connectivity, using at least a 1 Gbit/s connection to reliably accommodate peak loads (the average load is expected to be approximately 100 Mbit/s). We recommend a dual-processor server with at least eight cores in each processor, at least 256 MiB RAM, at least 8 TB of conventional HDD storage and at least 512 GB of faster SSD storage. It is a bad idea to run a Full Node on your home computer; instead, you could run a Full Node on a remote server, and use the TON Blockchain Lite Client to connect to it from home. 4 | 5 | 0. Downloading and compiling 6 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 | 8 | The complete TON Blockchain Library and Validator software is downloaded and compiled similarly to the Lite Client. This process is outlined in the corresponding README file. The most important difference is that you have to download the complete sources from public GitHub repository https://github.com/ton-blockchain/ton (e.g., by running `git clone https://github.com/ton-blockchain/ton` and `git submodule update` afterwards) instead of downloading the smaller Lite Client source archive. You should also build all goals defined in CMakeLists.txt (e.g. by running `cmake ` and `make` in your build directory), not only those specifically related to the Lite Client (which is also included in the larger distribution; you don't have to download and build it separately). We strongly recommend building a "release" or a "release with debug information" version of the TON Blockchain Library and especially of the Validator/Full Node by passing `-DCMAKE_BUILD_TYPE=Release` or `-DCMAKE_BUILD_TYPE=RelWithDebInfo` as an extra argument to `cmake` during its first run (if you forgot to do this, you can later delete file `CMakeCache.txt` from your build directory and re-run `cmake` with the appropriate options). 9 | 10 | 1. Full Node binaries 11 | ~~~~~~~~~~~~~~~~~~~~~ 12 | 13 | After the sources have been compiled successfully, you should obtain executable files `validator-engine/validator-engine` and `validator-engine-console/validator-engine-console` in your build directory. These are the most important files you need to run a TON Blockchain Full Node (or even a Validator), and to control it. You might wish to install them into your /usr/bin or similar directory. You are also likely to need the `generate-random-id` utility during setup. 14 | 15 | 2. Working directory of the Full Node 16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 | 18 | The Full Node (also known as "validator-engine") stores its data in subdirectories of its working directory, e.g., `/var/ton-work/db`. It requires write access to this directory. If you want to use another directory as the working directory of the Full Node, you can use the command line option --db : 19 | 20 | $ validator-engine --db ${DB_ROOT} 21 | 22 | where ${DB_ROOT} is /var/ton-work/db or any other directory where validator-engine has write permissions. 23 | 24 | 3. Working directory layout 25 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26 | 27 | An approximate layout of the working directory of the TON Blockchain Full Node software is as follows: 28 | 29 | * ${DB_ROOT}/config.json -- Automatically generated configuration file. It is automatically regenerated by validator-engine on some occasions. When validator-engine is not running, you can edit this file in a text editor because it is a JSON file. 30 | * ${DB_ROOT}/static -- A directory with files that cannot be downloaded from the network, such as the "zerostate" (corresponding to the Genesis block of other blockchain architectures) of the masterchain and active workchains. Normally you don't have to initialize this directory unless you want to run your own instance of the TON Blockchain (for example, for testing or development purposes). Full nodes of existing instances of the TON Blockchain (such as the "testnet" and the "mainnet") will be able to download all required files from already running full nodes. 31 | * ${DB_ROOT}/keyring -- Stores public and private keys known to validator-engine. For example, if your full node runs as a validator for some of the TON Blockchain shardchains, the validator block signing key is kept here. You may wish to set more restrictive permissions for this directory, such as 0700 (in *nix systems), so that only the user under which validator-engine is running would have access to this directory. 32 | * ${DB_ROOT}/error -- A directory where validator-engine copies files related to severe error conditions (e.g., invalid block candidates) for further study. It is normally empty, and validator-engine never deletes files from this directory. 33 | * ${DB_ROOT}/archive -- A directory where old and rarely used blocks are kept until their storage period expires. You can mount a larger but slower disk partition at this directory, or make this directory a symlink to a directory in such a partition. We recommend locating the remainder of ${DB_ROOT} in a fast storage device such as an SSD. 34 | * ${DB_ROOT}/etc -- (Non-automatic) configuration files may be kept here, or in any other directory read-accessible to validator-engine. 35 | * Other subdirectories of ${DB_ROOT} are used to keep ADNL cache data, recent blocks and states, and so on. They are not relevant to the purposes of this document. 36 | 37 | 4. Global configuration of the TON Blockchain 38 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 39 | 40 | In order to set up your Full Node, you'll need a special JSON file called the "global configuration (file)". It is called this because it is the same for all full nodes, and even nodes participating in different instances of the TON Blockchain (e.g., "testnet" vs. "mainnet") share an almost identical global configuration. 41 | 42 | The "testnet" global configuration can be downloaded at https://toncommunity.org/toncommunity-global.config.json as follows: 43 | 44 | $ wget https://toncommunity.org/toncommunity-global.config.json 45 | 46 | You may wish to put this file into /var/ton-work/etc/toncommunity-global.config.json . 47 | 48 | We'll discuss the structure of this file later in more detail. For now, let us remark that the bulk of this file consists of a list of known TON DHT nodes required for the bootstrapping of the TON Network. A smaller section near the end of this file describes the particular instance of the TON Blockchain that we wish to connect to. 49 | 50 | All instances of the TON Blockchain use the same "global" TON Network (i.e., the TON Network is not fragmented into several instances for each blockchain instance). While the global network configuration is therefore independent of the particular TON Blockchain instance chosen, the Full Nodes belonging to different instances will later connect to different overlay subnetworks inside the TON Network. 51 | 52 | It is important to distinguish this "global configuration file", used for setting up a TON Blockchain Full Node, and the "local" or "automatic configuration file", automatically updated by validator-engine and usually stored in ${DB_ROOT}/config.json. The global configuration is used to generate the initial automatic configuration file, which is thereafter updated by validator-engine itself (e.g., by adding new DHT nodes or storing hashes of newer masterchain blocks). 53 | 54 | 5. Initializing the local configuration 55 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 56 | 57 | Once the global configuration file is downloaded, it can be used to create the initial local configuration in ${DB_ROOT}/config.json. To do this, execute validator-engine once: 58 | 59 | $ validator-engine -C /var/ton-work/etc/toncommunity-global.config.json --db /var/ton-work/db/ --ip : -l /var/ton-work/log 60 | 61 | Here `/var/ton-work/log` is the log directory of `validator-engine`, where it will create its log files. The argument to the `-C` command-line option is the global configuration file downloaded from test.ton.org as explained above, and `/var/ton-work/db/` is the working directory ${DB_ROOT}. Finally, : are the global IP address of this full node (you need to indicate a public IPv4 address here) and the UDP port used to run TON Network protocols such as ADNL and RLDP. Make sure that your firewall is configured to pass UDP packets with source or destination : at least for the `validator-engine` binary. 62 | 63 | When validator-engine is invoked as above, and ${DB_ROOT}/config.json does not exist, it creates a new local configuration file ${DB_ROOT}/config.json using the information from the global configuration file and from the command-line options such as --ip, and then exits. If ${DB_ROOT}/config.json already exists, it is not rewritten; instead validator-engine starts up as a daemon using both the local and the global configuration. 64 | 65 | If you need to change the local configuration afterwards, you'll need to either delete this file and regenerate it from the global configuration (potentially forgetting other important information accumulated in the local configuration), or edit the local configuration in a text editor (when validator-engine is not running). 66 | 67 | 6. Setting up remote control CLI 68 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 69 | 70 | You will almost surely want to enable validator-engine-console in the local configuration, to be able to control your Full Node (i.e., validator-engine daemon) when it is running. For this, you'll need to generate two keypairs, one for the server (validator-engine) and one for the client (validator-engine-console). In the examples below we assume that validator-engine-console runs on the same machine and connects to validator-engine through the loopback network interface. (This is not necessarily so; you can use validator-engine-console for remote control as well.) 71 | 72 | As a first step, use the `generate-random-id` executable to create two keypairs, one for the server (on the machine running `validator-engine`) and one for the client (on the machine running `validator-engine-console`): 73 | 74 | $ ./generate-random-id -m keys -n server 75 | 6E9FD109F76E08B5710445C72D2C5FEDE04A96357DAA4EC0DDAEA025ED3AC3F7 bp/RCfduCLVxBEXHLSxf7eBKljV9qk7A3a6gJe06w/c= 76 | 77 | This utility generates a new keypair and saves the private key into file `server` and the public key into `server.pub`. The hexadecimal (6E9F...F7) and the base64 ("bp/RC...6wc/=") representations of the public key are displayed in the standard output, and are used henceforth to identify this key. 78 | 79 | We have to install the private key `server` into the keyring of the Full Node (validator-engine): 80 | 81 | $ mv server /var/ton-work/db/keyring/6E9FD109F76E08B5710445C72D2C5FEDE04A96357DAA4EC0DDAEA025ED3AC3F7 82 | 83 | Notice that the file name to store this private key inside the keyring equals the hexadecimal identifier (which essentially is a hash of the public key) of this key. 84 | 85 | Next, we generate the client keypair: 86 | 87 | $ ./generate-random-id -m keys -n client 88 | 8BBA4F8FCD7CC4EF573B9FF48DC63B212A8E9292B81FC0359B5DBB8719C44656 i7pPj818xO9XO5/0jcY7ISqOkpK4H8A1m127hxnERlY= 89 | 90 | We obtain a client keypair, saved into files `client` and `client.pub`. This second operation should be run in the working directory of the client (validator-engine-console), possibly on another machine. 91 | 92 | Now we have to list the client's public key in the server's local configuration file ${DB_ROOT}/config.json. To do this, open the local configuration file in a text editor (after terminating validator-engine if it was running) and find the empty "control" section: 93 | 94 | "control": [ 95 | ] 96 | 97 | Replace it with the following: 98 | 99 | "control" : [ 100 | { "id" : "bp/RCfduCLVxBEXHLSxf7eBKljV9qk7A3a6gJe06w/c=", 101 | "port" : , 102 | "allowed" : [ 103 | { "id" : "i7pPj818xO9XO5/0jcY7ISqOkpK4H8A1m127hxnERlY=", 104 | "permissions" : 15 105 | } 106 | ] 107 | } 108 | ], 109 | 110 | `control.0.id` is set to the base64 identifier of the server's public key, and `control.0.allowed.0.id` is the base64 identifier of the client's public key. is the TCP port the server will listen to for console commands. 111 | 112 | 7. Running the Full Node 113 | ~~~~~~~~~~~~~~~~~~~~~~~~ 114 | 115 | To run the full node, simply run the validator-engine binary in a console: 116 | 117 | $ validator-engine --db ${DB_ROOT} -C /var/ton-work/etc/toncommunity-global.config.json -l /var/ton-work/log 118 | 119 | It will read the global configuration from /var/ton-work/etc/toncommunity-global.config.json, the local configuration from ${DB_ROOT}/config.json, and continue running silently. You should write suitable scripts for invoking validator-engine as a daemon (so that it does not terminate when the console is closed), but we'll skip these considerations for simplicity. (The command-line option `-d` of validator-engine should be sufficient for this on most *nix systems.) 120 | 121 | If the configuration is invalid, validator-engine will terminate immediately and, in most cases, output nothing. You'll have to study the log files under /var/ton-work/log to find out what went wrong. Otherwise, validator-engine will keep working silently. Again, you can understand what's going on by inspecting the log files, and by looking into subdirectories of the ${DB_ROOT} directory. 122 | 123 | If everything works as expected, validator-engine will locate other full nodes participating in the same instance of the TON Blockchain, and download recent blocks of the masterchain and all shardchains. (You can actually control the number of recent blocks to be downloaded, or even download them all starting from the zerostate---but this topic is outside the scope of this document; try running validator-engine with command-line option `-h` to find out the list of all available options with brief explanations). 124 | 125 | 8. Using the Console CLI 126 | ~~~~~~~~~~~~~~~~~~~~~~~~ 127 | 128 | If the validator-engine-console has been set up as explained in Section 6., you can use it to connect to the running validator-engine (i.e., your Full Node) and run simple status and key management queries: 129 | 130 | $ ./validator-engine-console -k client -p server.pub -a : 131 | 132 | connecting to [:] 133 | local key: 8BBA4F8FCD7CC4EF573B9FF48DC63B212A8E9292B81FC0359B5DBB8719C44656 134 | remote key: 6E9FD109F76E08B5710445C72D2C5FEDE04A96357DAA4EC0DDAEA025ED3AC3F7 135 | conn ready 136 | > gettime 137 | received validator time: time=1566568904 138 | 139 | The `gettime` command obtains the current Unix time at the validator. If everything has been configured properly, you'll see an output similar to the one above. Notice that you need both the client's private key ("client") and the server's public key ("server.pub") for the console to work. You might wish to move them (especially the client's private key) into a separate directory with suitable permissions. 140 | 141 | Other console commands are available in validator-engine-console. For instance, `help` displays a list of all console commands with short descriptions. In particular, they are used to set up the Full Node as a Validator for the TON Blockchain, as explained in the separate document Validator-HOWTO. 142 | 143 | 9. Setting up the Full Node as a Lite Server 144 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 145 | 146 | You can set up your Full Node to function as a Lite Server, so that you can use the Lite Client to connect to it from the same or a remote host. For instance, sending the command `last` in a Lite Client connected to your Full Node will display the identifier of the most recent masterchain block known to your Full Node, so that you can inspect the progress of block downloading. You can also inspect the state of all smart contracts, send external messages (e.g., wallet queries), and so on as explained in the Lite Client HOWTO. 147 | 148 | In order to set up your Full Node as a Lite Server, you have to generate another keypair and install the private key into the server's keyring, similarly to what we did to enable the remote console: 149 | 150 | $ utils/generate-random-id -m keys -n liteserver 151 | BDFEA84525ADB3B16D0192488837C04883C10FF1F4031BB6DEECDD17544F5347 vf6oRSWts7FtAZJIiDfASIPBD/H0Axu23uzdF1RPU0c= 152 | mv liteserver ${DB_ROOT}/keyring/BDFEA84525ADB3B16D0192488837C04883C10FF1F4031BB6DEECDD17544F5347 153 | 154 | After that, stop validator-engine if it is running and open the local configuration file ${TON_DB}/config.json in a text editor. Find the empty section 155 | 156 | "liteservers" : [ 157 | ] 158 | 159 | and replace it with a record containing the TCP port for listening to inbound Lite Client connections and the lite server's public key: 160 | 161 | "liteservers" : [ 162 | { 163 | "id" : "vf6oRSWts7FtAZJIiDfASIPBD/H0Axu23uzdF1RPU0c=", 164 | "port" : 165 | } 166 | ], 167 | 168 | Now start `validator-engine` again. If it does not terminate immediately, it is likely that you have re-configured it properly. Now you can use the lite-client binary (usually located as "lite-client/lite-client" with respect to the build directory) to connect to the Lite Server running as a part of your Full Node: 169 | 170 | $ lite-client -a : -p liteserver.pub 171 | 172 | Again, `help` lists all commands available in the Lite Client. The Lite Client HOWTO contains some examples of what can be done with the Lite Client. 173 | -------------------------------------------------------------------------------- /public/README.txt: -------------------------------------------------------------------------------- 1 | This archive is a distribution of a preliminary version of the TON Blockchain Lite Client along with the relevant portions of the TON Blockchain Library. It is not necessarily representative of the totality of the TON Blockchain code developed so far; rather it is a simplified stable version, containing only those files that are necessary for compiling the Lite Client, and sometimes outdated versions of these files sufficient for this purpose. 2 | 3 | Use this software at your own risk; consult the DISCLAIMER for more information. 4 | 5 | The software is licensed under GNU Lesser General Public License version 2 or later; consult LICENSE.LGPL and LGPL.v2 for more information. If you ever use any of these source files to develop your own versions of this or other software, you must attach a comment with the contents of LGPL.v2 to the beginning of each source file taken from this archive. 6 | 7 | The software is likely to compile and work properly on most Linux systems. It should work on macOS and even Windows; however, we do not guarantee this for this preliminary version. 8 | 9 | BASIC COMPILATION AND INSTALLATION INSTRUCTIONS 10 | 11 | 1) Download the newest version of the TON blockchain sources, available at GitHub repository https://github.com/ton-blockchain/ton/ : 12 | 13 | git clone https://github.com/ton-blockchain/ton.git 14 | git submodule update 15 | 16 | The TON Blockchain Test Network is updated quite often, so we cannot guarantee that older versions of the Lite Client will always work. Backward compatibility is not enforced at this development stage. 17 | 18 | 2) Install the newest versions of make, cmake (version 3.0.2 or later), OpenSSL (including C header files), and g++ or clang (or another C++14-compatible compiler as appropriate for your operating system). We strongly recommend installing OpenSSL version 1.1.1 or later for better performance, especially if you intend to run a Full Node or a Validator as well. 19 | 20 | 3) Suppose that you have fetched the source tree to directory ~/ton, where ~ is your home directory, and that you have created an empty directory ~/liteclient-build. Then run the following in a terminal on a Linux system: 21 | 22 | cd ~/liteclient-build 23 | cmake ~/ton 24 | cmake --build . --target lite-client 25 | 26 | You might also build some extra utilities useful for smart-contract development: 27 | 28 | cmake --build . --target fift 29 | cmake --build . --target func 30 | 31 | 4) Download the newest configuration file from https://test.ton.org/ton-lite-client-test1.config.json : 32 | 33 | wget https://toncommunity.org/ton-lite-client-test3.config.json 34 | 35 | 5) Run the Lite Client: 36 | 37 | ./lite-client/lite-client -C ton-lite-client-test3.config.json 38 | 39 | If everything was installed successfully, the Lite Client will connect to a special server (a full node for the TON Blockchain Test Network #1) and will send some queries to the server. 40 | If you indicate a writeable "database" directory as an extra argument to the client, it will download and save the block and the state corresponding to the newest masterchain block: 41 | 42 | ./lite-client/lite-client -C ton-lite-client-test3.config.json -D ~/ton-db-dir 43 | 44 | Basic help info can be obtained by typing "help" into the Lite Client. Type "quit" or press Ctrl-C to exit. 45 | 46 | 6) Now you can create new smart contracts, examine the state of existing smart contracts, send external messages to smart contracts and so on. You can also use Fift (if you have compiled it) to compile, execute, and debug your smart contracts locally. 47 | 48 | More details on these activities, including step-by-step instructions for creating a simple wallet smart contract (along with its source code), may be found in the HOWTO file included in this archive. 49 | 50 | 7) Some documentation on the TON Blockchain and TON Virtual Machine may be found at the download page https://test.ton.org/download . Be aware that this documentation may not be completely in sync with the version currently employed by the Test Network, because some minor implementation details are likely to be changed during the final development and testing phases. 51 | -------------------------------------------------------------------------------- /public/TonSites-HOWTO.txt: -------------------------------------------------------------------------------- 1 | The aim of this document is to provide a gentle introduction into TON Sites, which are (TON) Web sites accessed through the TON Network. TON Sites may be used as a convenient entry point for other TON Services. In particular, HTML pages downloaded from TON Sites may contain links to ton://... URIs representing payments that can be performed by the user by clicking to the link, provided a TON Wallet is installed on the user's device. 2 | 3 | From the technical perspective, TON Sites are very much like the usual Web sites, but they are accessed through the TON Network (which is an overlay network inside the Internet) instead of the Internet. More specifically, they have an ADNL address (instead of a more customary IPv4 or IPv6 address), and they accept HTTP queries via RLDP protocol (which is a higher-level RPC protocol built upon ADNL, the main protocol of TON Network) instead of the usual TCP/IP. All encryption is handled by ADNL, so there is no need to use HTTPS (i.e., TLS). 4 | 5 | In order to access existing and create new TON Sites one needs special gateways between the "ordinary" internet and the TON Network. Essentially, TON Sites are accessed with the aid of a HTTP->RLDP proxy running locally on the client's machine, and they are created by means of a reverse RLDP->HTTP proxy running on a remote web server. 6 | 7 | 1. Compiling RLDP-HTTP Proxy 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | 10 | The RLDP-HTTP Proxy is a special utility specially designed for accessing and creating TON Sites. Its current (alpha) version is a part of the general TON Blockchain source tree, available at GitHub repository ton-blockchain/ton. In order to compile the RLDP-HTTP Proxy, follow the instructions outlined in README and Validator-HOWTO. The Proxy binary will be located as 11 | 12 | rldp-http-proxy/rldp-http-proxy 13 | 14 | in the build directory. Alternatively, you may want to build just the Proxy instead of building all TON Blockchain projects. This can be done by invoking 15 | 16 | cmake --build . --target rldp-http-proxy 17 | 18 | in the build directory. 19 | 20 | 2. Running RLDP-HTTP Proxy to access TON Sites 21 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 | 23 | In order to access existing TON Sites, you need a running instance of RLDP-HTTP Proxy on your computer. It can be invoked as follows: 24 | 25 | rldp-http-proxy/rldp-http-proxy -p 8080 -c 3333 -C ton-global-lite-client.config.json 26 | 27 | or 28 | 29 | rldp-http-proxy/rldp-http-proxy -p 8080 -a :3333 -C ton-global-lite-client.config.json 30 | 31 | where is your public IPv4 address, provided you have one on your home computer. The TON Network global configuration file `ton-global-lite-client.config.json` can be downloaded at https://test.ton.org/ton-global-lite-client.config.json : 32 | 33 | wget https://test.ton.org/ton-global-lite-client.config.json 34 | 35 | In the above example, 8080 is the TCP port that will be listened to at localhost for incoming HTTP queries, and 3333 is the UDP port that will be used for all outbound and inbound RLDP and ADNL activity, i.e., for connecting to the TON Sites via the TON Network. 36 | 37 | If you have done everything correctly, the Proxy will not terminate, but it will continue running in the terminal. It can be used now for accessing TON Sites. When you don't need it anymore, you can terminate it by pressing Ctrl-C, or simply by closing the terminal window. 38 | 39 | 3. Accessing TON Sites 40 | ~~~~~~~~~~~~~~~~~~~~~~ 41 | 42 | Now suppose that you have a running instance of the RLDP-HTTP Proxy running on your computer and listening on localhost:8080 for inbound TCP connections, as explained above in Section 2. 43 | 44 | A simple test that everything is working property may be performed using programs such as Curl or WGet. For example, 45 | 46 | curl -x 127.0.0.1:8080 http://test.ton 47 | 48 | attempts to download the main page of (TON) Site `test.ton` using the proxy at `127.0.0.1:8080`. If the proxy is up and running, you'll see something like 49 | 50 | 51 |

TON Blockchain Test Network — files and resources

52 |

News

53 |
    54 | ... 55 | 56 | 57 | because TON Site `test.ton` is currently set up to be a mirror of Web Site https://test.ton.org. 58 | 59 | You can also access TON Sites by means of their ADNL addresses by using fake domain `.adnl`: 60 | 61 | curl -x 127.0.0.1:8080 http://untzo7eat2h77xzfugxrfgfy3zbl5txomvetzke6fwr45lehvdkxauy.adnl/ 62 | 63 | currently fetches the same TON Web page. 64 | 65 | Alternatively, you can set up `localhost:8080` as a HTTP proxy in your browser. For example, if you use Firefox, visit [Setup] -> General -> Network Settings -> Settings -> Configure Proxy Access -> Manual Proxy configuration, and type "127.0.0.1" into the field "HTTP Proxy", and "8080" into the field "Port". If you don't have Firefox yet, visit https://www.getfirefox.com first. 66 | 67 | Once you have set up `localhost:8080` as the HTTP proxy to be used in your browser, you can simply type the required URI, such as `http://test.ton` or `http://untzo7eat2h77xzfugxrfgfy3zbl5txomvetzke6fwr45lehvdkxauy.adnl/`, in the navigation bar of your browser, and interact with the TON Site in the same way as with the usual Web Sites. 68 | 69 | 4. Creating TON Sites 70 | ~~~~~~~~~~~~~~~~~~~~~ 71 | 72 | Most people will need just to access existing TON Sites, not to create new ones. However, if you want to create one, you'll need to run RLDP-HTTP Proxy on your server, along with the usual web server software such as Apache or Nginx. 73 | 74 | We suppose that you know already how to set up an ordinary web site, and that you have already configured one on your server, accepting incoming HTTP connections on TCP port :80, and defining the required TON Network domain name, say, `example.ton`, as the main domain name or an alias for your web site in the configuration of your web server. 75 | 76 | After that, you first need to generate a persistent ADNL address for your server: 77 | 78 | mkdir keyring 79 | 80 | util/generate-random-id -m adnlid 81 | 82 | You see something like 83 | 84 | 45061C1D4EC44A937D0318589E13C73D151D1CEF5D3C0E53AFBCF56A6C2FE2BD vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3 85 | 86 | This is your newly-generated persistent ADNL address, in hexadecimal and user-friendly form. The corresponding private key is saved into file 45061...2DB in the current directory. Move it into the keyring directory: 87 | 88 | mv 45061C1* keyring/ 89 | 90 | After that, you execute 91 | 92 | rldp-http-proxy -a :3333 -L '*' -C ton-global.config.json -A 93 | 94 | (with equal to 'vcqm...35f3' in this example) in the background (you can try this in a terminal at first, but if you want your TON Site to run permanently, you'll have to use options `-d` and `-l ` as well). 95 | 96 | If all works properly, the RLDP-HTTP proxy will accept incoming HTTP queries from the TON Network via RLDP/ADNL running on UDP port 3333 (of course, you can use any other UDP port if you want to) of IPv4 address (in particular, if you are using a firewall, don't forget to allow `rldp-http-proxy` to receive and send UDP packets from this port), and it will forward these HTTP queries addressed to all hosts (if you want to forward only specific hosts, change `-L '*'` to `-L `) to TCP port 80 at 127.0.0.1, i.e., to your ordinary Web server. 97 | 98 | You can visit TON Site `http://.adnl` (`http://vcqmha5j3ceve35ammfrhqty46rkhi455otydstv66pk2tmf7rl25f3.adnl` in this example) from a browser running on a client machine as explained in Sections 2 and 3 and check whether your TON Site is actually available to the public. 99 | 100 | If you want to, you can register a TON DNS domain, such as 'example.ton', and create a record for this domain pointing to the persistent ADNL address of your TON Site. Then the RLDP-HTTP proxies running in client mode would resolve 'http://example.ton' as pointing to your ADNL address and will access your TON Site. The process of registration of TON DNS domains is described in a separate document. 101 | 102 | -------------------------------------------------------------------------------- /public/Validator-HOWTO.txt: -------------------------------------------------------------------------------- 1 | The aim of this document is to provide step-by-step instructions for setting up a full node for the TON Blockchain as a validator. We assume that a TON Blockchain Full Node is already up and running as explained in FullNode-HOWTO. We also assume some familiarity with the TON Blockchain Lite Client. 2 | 3 | Note that a validator must be run on a dedicated high-performance server with high network bandwidth installed in a reliable datacenter, and that you'll need a large amount of Grams (test Grams, if you want to run a validator in the "testnet") as stakes for your validator. If your validator works incorrectly or is not available for prolonged periods of time, you may lose part or all of your stake, so it makes sense to use high-performance, reliable servers. We recommend a dual-processor server with at least eight cores in each processor, at least 256 MiB RAM, at least 8 TB of conventional HDD storage and at least 512 GB of faster SSD storage, with 1 Gbit/s network (and Internet) connectivity to reliably accomodate peak loads. 4 | 5 | 0. Downloading and compiling 6 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 | 8 | The basic instructions are the same as for a TON Blockchain Full Node, as explained in FullNode-HOWTO. In fact, any Full Node will automatically work as a validator if it discovers that the public key corresponding to its private key appears as a member of the current validator set for the currently selected TON Blockchain instance. In particular, the Full Node and the Validator use the same binary file `validator-engine`, and are controlled by means of the same `validator-engine-console`. 9 | 10 | 1. Controlling smart contract of a validator 11 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 | 13 | In order to run a Validator, you'll need a Full Node that is already up and running (and completely synchronized with the current blockchain state), and a wallet in the masterchain holding a large amount of Grams (or test Grams, if you want to run a validator in the "testnet" TON Blockchain instance). Typically you'll need at least 100,001 Grams in the production network, and at least 10,001 test Grams in the test network. The actual value (in nanograms) can be found as the value of `min_stake` in configuration parameter #17 (available by typing `getconfig 17` into the Lite Client), plus one Gram. 14 | 15 | Each validator is identified by its (Ed25519) public key. During the validator elections, the validator (or rather its public key) is also associated with a smart contract residing in the masterchain. For simplicity, we say that the validator is "controlled" by this smart contract (e.g., a wallet smart contract). Stakes are accepted on behalf of this validator only if they arrive from its associated smart contract, and only that associated smart contract is entitled to collect the validator's stake after it is unfrozen, along with the validator's share of bonuses (e.g., block mining fees, transaction and message forwarding fees collected from the users of the TON Blockchain by the validator pool). Typically the bonuses are distributed proportionally to the (effective) stakes of the validators. On the other hand, validators with higher stakes are assigned a larger amount of work to perform (i.e., they have to create and validate blocks for more shardchains), so it is important not to stake an amount that will yield more validation work than your node is capable of handling. 16 | 17 | Notice that each validator (identified by its public key) can be associated with at most one controlling smart contract (residing in the masterchain), but the same controlling smart contract may be associated with several validators. In this way you can run several validators (on different physical servers) and make stakes for them from the same smart contract. If one of these validators stops functioning and you lose its stake, the other validators should continue operating and will keep their stakes and potentially receive bonuses. 18 | 19 | 2. Creating the controlling smart contract 20 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21 | 22 | If you don't have a controlling smart contract, you can simply create a wallet in the masterchain. A simple wallet can be created with the aid of the script new-wallet.fif, located in the subdirectory crypto/smartcont of the source tree. In what follows, we assume that you have configured the environment variable FIFTPATH to include /crypto/fift/lib:/crypto/smartcont, and that your PATH includes a directory with the Fift binary (located as /crypto/fift). Then you can simply run 23 | 24 | $ fift -s new-wallet.fif -1 my_wallet_id 25 | 26 | where "my_wallet_id" is any identifier you want to assign to your new wallet, and -1 is the workchain identifier for the masterchain. If you have not set up FIFTPATH and PATH, then you'll have to run a longer version of this command in your build directory as follows: 27 | 28 | $ crypto/fift -I /crypto/fift/lib:/crypto/smartcont -s new-wallet.fif -1 my_wallet_id 29 | 30 | Once you run this script, the address of the new smart contract is displayed: 31 | ... 32 | new wallet address = -1:af17db43f40b6aa24e7203a9f8c8652310c88c125062d1129fe883eaa1bd6763 33 | (Saving address to file my_wallet_id.addr) 34 | Non-bounceable address (for init): 0f-vF9tD9Atqok5yA6n4yGUjEMiMElBi0RKf6IPqob1nYzqK 35 | Bounceable address (for later access): kf-vF9tD9Atqok5yA6n4yGUjEMiMElBi0RKf6IPqob1nY2dP 36 | ... 37 | (Saved wallet creating query to file my_wallet_id-query.boc) 38 | 39 | Now my_wallet_id.pk is a new file containing the private key for controlling this wallet (you must keep it secret), and my_wallet_id.addr is a (not so secret) file containing the address of this wallet. Once this is done, you have to transfer some (test) Grams to the non-bounceable address of your wallet, and run "sendfile my_wallet_id-query.boc" in the Lite Client to finish creating the new wallet. This process is explained in more detail in the LiteClient-HOWTO. 40 | 41 | If you are running a validator in the "mainnet", it is a good idea to use more sophisticated wallet smart contracts (e.g., a multi-signature wallet). For the "testnet", the simple wallet should be enough. 42 | 43 | 3. Elector smart contract 44 | ~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | 46 | The elector smart contract is a special smart contract residing in the masterchain. Its full address is -1:xxx..xxx, where -1 is the workchain identifier (-1 corresponds to the masterchain), and xxx..xxx is the hexadecimal representation of its 256-bit address inside the masterchain. In order to find out this address, you have to read the configuration parameter #1 from a recent state of the blockchain. This is easily done by means of the command `getconfig 1` in the Lite Client: 47 | 48 | > getconfig 1 49 | ConfigParam(1) = ( elector_addr:xA4C2C7C05B093D470DE2316DBA089FA0DD775FD9B1EBFC9DC9D04B498D3A2DDA) 50 | x{A4C2C7C05B093D470DE2316DBA089FA0DD775FD9B1EBFC9DC9D04B498D3A2DDA} 51 | 52 | In this case, the complete elector address is -1:A4C2C7C05B093D470DE2316DBA089FA0DD775FD9B1EBFC9DC9D04B498D3A2DDA 53 | 54 | We assume familiarity with the Lite Client and that you know how to run it and how to obtain a global configuration file for it. Notice that the above command can be run in batch mode by using the '-c' command-line option of the Lite Client: 55 | 56 | $ lite-client -C -c 'getconfig 1' 57 | ... 58 | ConfigParam(1) = ( elector_addr:xA4C2C7C05B093D470DE2316DBA089FA0DD775FD9B1EBFC9DC9D04B498D3A2DDA) 59 | x{A4C2C7C05B093D470DE2316DBA089FA0DD775FD9B1EBFC9DC9D04B498D3A2DDA} 60 | 61 | $ 62 | 63 | The elector smart contract has several uses. Most importantly, you can participate in validator elections or collect unfrozen stakes and bonuses by sending messages from the controlling smart contract of your validator to the elector smart contract. You can also learn about current validator elections and their participants by invoking the so-called "get-methods" of the elector smart contract. 64 | 65 | Namely, running 66 | 67 | > runmethod -1:A4C2C7C05B093D470DE2316DBA089FA0DD775FD9B1EBFC9DC9D04B498D3A2DDA active_election_id 68 | ... 69 | arguments: [ 86535 ] 70 | result: [ 1567633899 ] 71 | 72 | (or lite-client -C -c "runmethod -1: active_election_id" in batch mode) will return the identifier of the currently active elections (a non-zero integer, typically the Unix time of the start of the service term of the validator group being elected), or 0, if no elections are currently active. In this example, the identifier of the active elections is 1567633899. 73 | 74 | You can also recover the list of all active participants (pairs of 256-bit validator public keys and their corresponding stakes expressed in nanograms) by running the method "participant_list" instead of "active_election_id". 75 | 76 | 4. Creating a validator public key and ADNL address 77 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 78 | 79 | In order to participate in validator elections, you need to know the elections identifier (obtained by running get-method "active_elections_id" of the elector smart contract), and also the public key of your validator. The public key is created by running validator-engine-console (as explained in FullNode-HOWTO) and running the following commands: 80 | 81 | $ validator-engine-console ... 82 | ... 83 | conn ready 84 | > newkey 85 | created new key BCA335626726CF2E522D287B27E4FAFFF82D1D98615957DB8E224CB397B2EB67 86 | > exportpub BCA335626726CF2E522D287B27E4FAFFF82D1D98615957DB8E224CB397B2EB67 87 | got public key: xrQTSIQEsqZkWnoADMiBnyBFRUUweXTvzRQFqb5nHd5xmeE6 88 | > addpermkey BCA335626726CF2E522D287B27E4FAFFF82D1D98615957DB8E224CB397B2EB67 1567633899 1567733900 89 | success 90 | 91 | Now the full node (validator-engine) has generated a new keypair, exported the base64 representation of the public key (xrQT...E6), and registered it as a persistent key for signing blocks starting from Unix time 1567633899 (equal to the election identifier) until 1567733900 (equal to the previous number plus the term duration of the validator set to be elected, available in configuration parameter #15, which can be learned by typing "getconfig 15" in the Lite Client, plus a safety margin in case elections actually happen later than intended). 92 | 93 | You also need to define a temporary key to be used by the validator to participate in the network consensus protocol. The simplest way (sufficient for testing purposes) is to set this key equal to the persistent (block signing) key: 94 | 95 | > addtempkey BCA335626726CF2E522D287B27E4FAFFF82D1D98615957DB8E224CB397B2EB67 BCA335626726CF2E522D287B27E4FAFFF82D1D98615957DB8E224CB397B2EB67 1567733900 96 | success 97 | 98 | It is also a good idea to create a dedicated ADNL address to be used exclusively for validator purposes: 99 | 100 | > newkey 101 | created new key C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C 102 | > addadnl C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C 0 103 | success 104 | > addvalidatoraddr BCA335626726CF2E522D287B27E4FAFFF82D1D98615957DB8E224CB397B2EB67 C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C 1567733900 105 | success 106 | 107 | Now C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C is a new ADNL address, which will be used by the Full Node for running as a validator with the public key BCA...B67, with expiration time set to 1567733900. 108 | 109 | 5. Creating an election participation request 110 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 111 | 112 | The special script validator-elect-req.fif (located in /crypto/smartcont) is used to create a message that has to be signed by the validator in order to participate in the elections. It is run as follows: 113 | 114 | $ fift -s validator-elect-req.fif [] 115 | 116 | For example, 117 | 118 | $ fift -s validator-elect-req.fif kf-vF9tD9Atqok5yA6n4yGUjEMiMElBi0RKf6IPqob1nY2dP 1567633899 2.7 C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C 119 | 120 | or, if you have created the controlling wallet by means of new-wallet.fif, you can use @my_wallet_id.addr instead of copying the wallet address kf-vF...dP: 121 | 122 | --------------------------------------- 123 | $ fift -s validator-elect-req.fif @my_wallet_id.addr 1567633899 2.7 C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C 124 | 125 | Creating a request to participate in validator elections at time 1567633899 from smart contract Uf+vF9tD9Atqok5yA6n4yGUjEMiMElBi0RKf6IPqob1nY4EA = -1:af17db43f40b6aa24e7203a9f8c8652310c88c125062d1129fe883eaa1bd6763 with maximal stake factor with respect to the minimal stake 176947/65536 and validator ADNL address c5c2b94529405fb07d1ddfb4c42bfb07727e7ba07006b2db569fbf23060b9e5c 126 | 654C50745D7031EB0002B333AF17DB43F40B6AA24E7203A9F8C8652310C88C125062D1129FE883EAA1BD6763C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C 127 | ZUxQdF1wMesAArMzrxfbQ_QLaqJOcgOp-MhlIxDIjBJQYtESn-iD6qG9Z2PFwrlFKUBfsH0d37TEK_sHcn57oHAGsttWn78jBgueXA== 128 | --------------------------------------- 129 | 130 | Here = 2.7 is the maximum ratio allowed between your stake and the minimal validator stake in the elected validator group. In this way you can be sure that your stake will be no more than 2.7 times the smallest stake, so the workload of your validator is at most 2.7 times the lowest one. If your stake is too large compared to the stakes of other validators, then it will be clipped to this value (2.7 times the smallest stake), and the remainder will be returned to you (i.e., to the controlling smart contract of your validator) immediately after elections. 131 | 132 | Now you obtain a binary string in hexadecimal (654C...9E5C) and base64 form to be signed by the validator. This can be done in validator-engine-console: 133 | 134 | > sign BCA335626726CF2E522D287B27E4FAFFF82D1D98615957DB8E224CB397B2EB67 654C50745D7031EB0002B333AF17DB43F40B6AA24E7203A9F8C8652310C88C125062D1129FE883EAA1BD6763C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C 135 | got signature ovf9cmr2J/speJEtMU+tZm6zH/GBEyZCPpaukqL3mmNH9Wipyoys63VFh0yR386bARHKMPpfKAYBYslOjdSjCQ 136 | 137 | Here BCA...B67 is the identifier of the signing key of our validator, and 654...E5C is the message generated by validator-elect-req.fif. The signature is ovf9...jCQ (this is the base64 representation of 64-byte Ed25519 signature). 138 | 139 | Now you have to run another script validator-elect-signed.fif, which also requires the public key and the signature of the validator: 140 | 141 | ------------------------------------ 142 | $ fift -s validator-elect-signed.fif @my_wallet_id.addr 1567633899 2.7 C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C xrQTSIQEsqZkWnoADMiBnyBFRUUweXTvzRQFqb5nHd5xmeE6 ovf9cmr2J/speJEtMU+tZm6zH/GBEyZCPpaukqL3mmNH9Wipyoys63VFh0yR386bARHKMPpfKAYBYslOjdSjCQ== 143 | Creating a request to participate in validator elections at time 1567633899 from smart contract Uf+vF9tD9Atqok5yA6n4yGUjEMiMElBi0RKf6IPqob1nY4EA = -1:af17db43f40b6aa24e7203a9f8c8652310c88c125062d1129fe883eaa1bd6763 with maximal stake factor with respect to the minimal stake 176947/65536 and validator ADNL address c5c2b94529405fb07d1ddfb4c42bfb07727e7ba07006b2db569fbf23060b9e5c 144 | String to sign is: 654C50745D7031EB0002B333AF17DB43F40B6AA24E7203A9F8C8652310C88C125062D1129FE883EAA1BD6763C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C 145 | Provided a valid Ed25519 signature A2F7FD726AF627FB2978912D314FAD666EB31FF1811326423E96AE92A2F79A6347F568A9CA8CACEB7545874C91DFCE9B0111CA30FA5F28060162C94E8DD4A309 with validator public key 8404B2A6645A7A000CC8819F20454545307974EFCD1405A9BE671DDE7199E13A 146 | query_id set to 1567632790 147 | 148 | Message body is x{4E73744B000000005D702D968404B2A6645A7A000CC8819F20454545307974EFCD1405A9BE671DDE7199E13A5D7031EB0002B333C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C} 149 | x{A2F7FD726AF627FB2978912D314FAD666EB31FF1811326423E96AE92A2F79A6347F568A9CA8CACEB7545874C91DFCE9B0111CA30FA5F28060162C94E8DD4A309} 150 | 151 | Saved to file validator-query.boc 152 | ----------------------- 153 | 154 | Alternatively, if you are running validator-engine-console on the same machine as your wallet, you can skip the above steps and instead use the `createelectionbid` command in the Validator Console to directly create a file (e.g., "validator-query.boc") with the message body containing your signed elections participation request. For this command to work, you have to run validator-engine with the `-f ` command-line option, where is a directory containing copies of all required Fift source files (such as Fift.fif, TonUtil.fif, validator-elect-req.fif, and validator-elect-signed.fif), even though these files normally reside in different source directories (/crypto/fift/lib and /crypto/smartcont). 155 | 156 | Now you have a message body containing your elections participation request. You must send it from the controlling smart contract, carrying the stake as its value (plus one extra Gram for sending confirmation). If you use the simple wallet smart contract, this can be done by using the `-B` command-line argument to wallet.fif: 157 | 158 | -------------------------------------------- 159 | $ fift -s wallet.fif my_wallet_id -1:A4C2C7C05B093D470DE2316DBA089FA0DD775FD9B1EBFC9DC9D04B498D3A2DDA 1 100001. -B validator-query.boc 160 | Source wallet address = -1:af17db43f40b6aa24e7203a9f8c8652310c88c125062d1129fe883eaa1bd6763 161 | kf-vF9tD9Atqok5yA6n4yGUjEMiMElBi0RKf6IPqob1nY2dP 162 | Loading private key from file my_wallet_id.pk 163 | Transferring GR$100001. to account kf-kwsfAWwk9Rw3iMW26CJ-g3Xdf2bHr_J3J0EtJjTot2lHQ = -1:a4c2c7c05b093d470de2316dba089fa0dd775fd9b1ebfc9dc9d04b498d3a2dda seqno=0x1 bounce=-1 164 | Body of transfer message is x{4E73744B000000005D702D968404B2A6645A7A000CC8819F20454545307974EFCD1405A9BE671DDE7199E13A5D7031EB0002B333C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C} 165 | x{A2F7FD726AF627FB2978912D314FAD666EB31FF1811326423E96AE92A2F79A6347F568A9CA8CACEB7545874C91DFCE9B0111CA30FA5F28060162C94E8DD4A309} 166 | 167 | signing message: x{0000000101} 168 | x{627FD26163E02D849EA386F118B6DD044FD06EBBAFECD8F5FE4EE4E825A4C69D16ED32D79A60A8500000000000000000000000000001} 169 | x{4E73744B000000005D702D968404B2A6645A7A000CC8819F20454545307974EFCD1405A9BE671DDE7199E13A5D7031EB0002B333C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C} 170 | x{A2F7FD726AF627FB2978912D314FAD666EB31FF1811326423E96AE92A2F79A6347F568A9CA8CACEB7545874C91DFCE9B0111CA30FA5F28060162C94E8DD4A309} 171 | 172 | resulting external message: x{89FF5E2FB687E816D5449CE40753F190CA4621911824A0C5A2253FD107D5437ACEC6049CF8B8EA035B0446E232DB8C1DFEA97738076162B2E053513310D2A3A66A2A6C16294189F8D60A9E33D1E74518721B126A47DA3A813812959BD0BD607923B010000000080C_} 173 | x{627FD26163E02D849EA386F118B6DD044FD06EBBAFECD8F5FE4EE4E825A4C69D16ED32D79A60A8500000000000000000000000000001} 174 | x{4E73744B000000005D702D968404B2A6645A7A000CC8819F20454545307974EFCD1405A9BE671DDE7199E13A5D7031EB0002B333C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C} 175 | x{A2F7FD726AF627FB2978912D314FAD666EB31FF1811326423E96AE92A2F79A6347F568A9CA8CACEB7545874C91DFCE9B0111CA30FA5F28060162C94E8DD4A309} 176 | 177 | B5EE9C7241040401000000013D0001CF89FF5E2FB687E816D5449CE40753F190CA4621911824A0C5A2253FD107D5437ACEC6049CF8B8EA035B0446E232DB8C1DFEA97738076162B2E053513310D2A3A66A2A6C16294189F8D60A9E33D1E74518721B126A47DA3A813812959BD0BD607923B010000000080C01016C627FD26163E02D849EA386F118B6DD044FD06EBBAFECD8F5FE4EE4E825A4C69D16ED32D79A60A85000000000000000000000000000010201A84E73744B000000005D702D968404B2A6645A7A000CC8819F20454545307974EFCD1405A9BE671DDE7199E13A5D7031EB0002B333C5C2B94529405FB07D1DDFB4C42BFB07727E7BA07006B2DB569FBF23060B9E5C030080A2F7FD726AF627FB2978912D314FAD666EB31FF1811326423E96AE92A2F79A6347F568A9CA8CACEB7545874C91DFCE9B0111CA30FA5F28060162C94E8DD4A309062A7721 178 | (Saved to file wallet-query.boc) 179 | ---------------------------------- 180 | 181 | Now you just have to send wallet-query.boc from the Lite Client (not the Validator Console): 182 | 183 | > sendfile wallet-query.boc 184 | 185 | or you can use the Lite Client in batch mode: 186 | 187 | $ lite-client -C -c "sendfile wallet-query.boc" 188 | 189 | This is an external message signed by your private key (which controls your wallet); it instructs your wallet smart contract to send an internal message to the elector smart contract with the prescribed payload (containing the validator bid and signed by its key) and transfer the specified amount of Grams. When the elector smart contract receives this internal message, it registers your bid (with the stake equal to the specified amount of Grams minus one), and sends you (i.e., the wallet smart contract) a confirmation (carrying 1 Gram minus message forwarding fees back) or a rejection message with an error code (carrying back almost all of the original stake amount minus processing fees). 190 | 191 | You can check whether your stake has been accepted by running get-method "participant_list" of the elector smart contract. 192 | 193 | 6. Recovering stakes and bonuses 194 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 195 | 196 | If your stake is only partially accepted (because of ) during the elections, or after your stake is unfrozen (this happens some time after the expiration of the term of the validator group to which your validator has been elected), you may want to collect back all or part of your stake, along with whatever share of bonuses is due to your validator. The elector smart contract does not send the stake and bonuses to you (i.e., the controlling smart contract) in a message. Instead, it credits the amount to be returned to you inside a special table, which can be inspected with the aid of get-method "compute_returned_stake" (which expects the address of the controlling smart contract as an argument): 197 | 198 | $ lite-client -C ton-lite-client-test1.config.json -rc 'runmethod -1:A4C2C7C05B093D470DE2316DBA089FA0DD775FD9B1EBFC9DC9D04B498D3A2DDA compute_returned_stake 0xaf17db43f40b6aa24e7203a9f8c8652310c88c125062d1129fe883eaa1bd6763' 199 | arguments: [ 79196899299028790296381692623119733846152089453039582491866112477478757689187 130944 ] 200 | result: [ 0 ] 201 | 202 | If the result is zero, nothing is due to you. Otherwise, you'll see part or all of your stake, perhaps with some bonuses. In that case, you can create a stake recovery request by using recover-stake.fif: 203 | 204 | ----------------------------- 205 | $ fift -s recover-stake.fif 206 | query_id for stake recovery message is set to 1567634299 207 | 208 | Message body is x{47657424000000005D70337B} 209 | 210 | Saved to file recover-query.boc 211 | ----------------------------- 212 | 213 | Again, you have to send recover-query.boc as the payload of a message from the controlling smart contract (i.e., your wallet) to the elector smart contract: 214 | 215 | $ fift -s wallet.fif my_wallet_id -B recover-query.boc 216 | 217 | For example, 218 | 219 | $ fift -s wallet.fif my_wallet_id -1:A4C2C7C05B093D470DE2316DBA089FA0DD775FD9B1EBFC9DC9D04B498D3A2DDA 2 1. -B recover-query.boc 220 | ... 221 | (Saved to file wallet-query.boc) 222 | 223 | Notice that this message carries a small value (one Gram) just to pay the message forwarding and processing fees. If you indicate a value equal to zero, the message will not be processed by the election smart contract (a message with exactly zero value is almost useless in the TON Blockchain context). 224 | 225 | Once wallet-query.boc is ready, you can send it from the Lite Client: 226 | 227 | $ liteclient -C -c 'sendfile wallet-query.boc' 228 | 229 | If you have done everything correctly (in particular indicated the correct seqno of your wallet instead of "2" in the example above), you'll obtain a message from the elector smart contract containing the change from the small value you sent with your request (1. Gram in this example) plus the recovered portion of your stake and bonuses. 230 | 231 | 7. Participating in the next elections 232 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 233 | 234 | Notice that even before the term of the validator group containing your elected validator finishes, new elections for the next validator group will be announced. You'll probably want to participate in them as well. For this, you can use the same validator, but you must generate a new validator key and new ADNL address. You'll also have to make a new stake before your previous stake is returned (because your previous stake will be unfrozen and returned only some time after the next validator group becomes active), so if you want to participate in concurrent elections, it likely does not make sense to stake more than half of your Grams. 235 | -------------------------------------------------------------------------------- /public/catchain.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/public/catchain.pdf -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/public/favicon.ico -------------------------------------------------------------------------------- /public/fiftbase.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/public/fiftbase.pdf -------------------------------------------------------------------------------- /public/fight.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/public/fight.jpg -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 16 | 20 | 21 | 25 | 26 | 35 | TON Community Blockchain 36 | 37 | 38 | 39 |
    40 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /public/info.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | 14 | 15 |

    TONCommunity.org Project

    16 |

    $TON Token Overview

    17 | TON Community Blockchain support by TONCommunity.org. The testnet is already online. We add Defi project in Roadmap and release ERC20 Token. 18 |
    19 |
    Our Goal: Defi in Telegram 20 |
    21 | Lite Paper | Roadmap | Token Distribution 22 |
    23 |
    New Post: Defi and TON Synthetic Assets 24 |
    ================================ 25 |

    Available Token

    26 |
      27 |
    • ERC20 $TON Token
    • 28 |
    • Native $TON Coin
    • 29 |
        30 |
      • 02.2021 Main Network Launch
      • 31 | (Debug asset security) 32 |
      33 |
    34 |

    ERC20 $TON Distribution

    35 |
      Total Supply: 400 million
    36 |
    • 37 | 1,000,000 TON Token Auction(Active)
      Proof of Heart
    • 38 |
    • 15.14%, 60,572,831 (UPCOMING)
      Public Donation
    • 39 |
    • 47.11%, 188,424,576 (UPCOMING)
      Private Donation
    • 40 |
    • 12.5%, 50,000,000 (Lock)
      Earmarked, For Liquidity Pool
    • 41 |
    • 25.0%, 100,000,000 (Lock)
      Grant Lock, Strategic Reserve
    • 42 |
    =========================== 43 |
    44 |

    Active Auction - Proof of Heart

    45 |
      Auction 1 million TON, donate to ETH Foundation. Thank you ETH for bringing Defi world. Address:
    46 | 0xe315fc27f00eB6d1c35bF0d1CcBb3D72903fD53F 47 |
    48 |
    Please contrast with @TON_EN pinned message. 49 |
    50 |
    51 |

    Auction Rules

    52 |
      53 |
    1. Before ETH Network Block ID = 10694900 (including 10694900, estimated at 12:00 UTC August 20), all ETH received by this address will be donated to the ETH Foundation.
    2. 54 |
    3. According to the quantity, the top 20 will give a total of 1 million TON. Gift rules:
    4. 55 | 1th: 110,000 TON Token 56 |
      2th: 80,000 TON Token 57 |
      3th: 70,000 TON Token 58 |
      4-10th: 50,000 TON Token 59 |
      11-19th: 40,000 TON Token 60 |
      20th: 30,000 TON Token 61 |
      62 |
      63 |
    5. Important: This event is a charity donation, and all the ETH obtained will be donated to the Ethereum Foundation. More quantity in Private Donation and Public Donation, after this event. Relax and enjoy~
    6. 64 |
    7. The same address, the quantity can be accumulated.
    8. 65 |
    9. Valid Decimals are 2(ex. 1.123, valid quantity is 1.12), and the earlier donors are ranked higher when the amount is the same.
    10. 66 |
    11. Welcome small donations, after ranking 20th will be divided equally 50,000 TON according to receive valid ETH. This means that participation will earn TON Token. (Ex: After ranking 20th, we receive 5 ETH, Alice donate 0.2 ETH, then she will get 0.2*50000/5=2000 TON.)
    12. 67 |
    13. Discuss and publish in @ton_en
    14. 68 |
    ============================== 69 |

    Upcoming

    70 |
      71 |
    • 47.11%, Private Donation
    • 72 |
    • 15.14%, Public Donation
    • 73 |
    74 | 75 |

    Documentation

    76 | 83 | 84 |

    About

    85 | 92 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/projects.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 |

    Some TON-based Projects

    12 |
      13 |
    1. 14 | Grampay Commerce
      15 | https://grampay.org/
      16 | A marketplace for Sellers and Buyers with escrow payments and a dispute system. Use a Telegram bot to create your shop and start selling your products for Grams.
      17 | Bot: https://t.me/grampayorgbot
      18 |
    2. 19 |
    3. 20 | TON Goods
      21 | https://www.ton-goods.com/
      22 | An ecosystem for selling and buying goods using the TON Blockchain.
      23 |
    4. 24 |
    5. 25 | TON Decentralized Exchange
      26 | https://dexton.online/
      27 | Decentralized exchange that supports for Grams, built-in extra currencies, custom workchains and TRC20 tokens (like Ethereums ERC20 tokens).
      28 |
    6. 29 |
    7. 30 | TON Auction
      31 | http://ton-auction.com/
      32 | A platform for auctions and trade. Sell items or create auctions for everyone to participate. Supports three types of auctions: open English auction, first-price and second-price sealed-bid blind auctions.
      33 |
    8. 34 |
    9. 35 | TON Gambling
      36 | http://ton-gamble.com/
      37 | A platform for virtual games. Currently supports Lottery and Blackjack, but the code can be re-used to add more games.
      38 |
    10. 39 |
    11. 40 | OracleHub
      41 | http://oraclehub.online/
      42 | A platform allowing smartcontracts to interact with the outside world, a martketplace of data-providers.
      43 |
    12. 44 |
    13. 45 | Conditional Transfer Contract
      46 | https://skydev0h.github.io/ton-freestyle-2/ctsc.html
      47 | A decentralized smart contract that collects Grams and releases them when a specific condition is met. Can be used for escrow, crowdfunding, custody, splitting, etc.
      48 |
    14. 49 |
    15. 50 | Data Storage Proxy
      51 | https://skydev0h.github.io/ton-freestyle-2/dspsc.html
      52 | A data storage proxy contract that stores data and allows using it, respecting the data owner, access rights and other attributes.
      53 |
    16. 54 |
    17. 55 | TON American Roulette
      56 | https://ton-roulette.org/
      57 | A web client for an American-style roulette on the TON Blockchain.
      58 |
    18. 59 |
    19. 60 | TON Roulette Lottery
      61 | http://ton-roulette.fun/
      62 | Roulette-style lottery. Buy squares on the playing field and wait for the end of the round to get returns from 0 to 1259% on the price of your squares.
      63 |
    20. 64 |
    21. 65 | TokeTON
      66 | https://toketon.com/
      67 | Initial Coin Offering (ICO) fundraising for various projects using the Gram cryptocurrency.
      68 |
    22. 69 |
    23. 70 | TON Pool
      71 | https://ton.ms/
      72 | Pool funds in the TON blockchain network for a specified purpose – like creating a validator or buying a present for someone – and redistribute the returns proportionally, if any.
      73 | Bot: https://t.me/pool_ton_bot
      74 |
    24. 75 |
    25. 76 | The Chat Game
      77 | https://thechatgame.net/
      78 | A game based on various RPG mechanics, including collectible items. User inventories are implemented as an open registry on the TON Blockchain, allowing users to hoard, transfer and subject their items to arbitrary complex operations governed by smartcontracts.
      79 |
    26. 80 |
    27. 81 | TON Register
      82 | https://www.ton-register.com/
      83 | A system for teachers and students for keeping a register of school marks on the TON Blockchain.
      84 |
    28. 85 |
    29. 86 | ERC20 Tokens ported to TON
      87 | https://ton.adoriasoft.com/
      88 | Illustrates the capabilities of the TON blockchain through a smart contract for issuing fungible ERC20 tokens. The smart contract can be easily modified to support a token sale.
      89 |
    30. 90 |
    31. 91 | Crypto Sender
      92 | http://complex-soft.com/messenger.aspx
      93 | Experimental encrypted messenger for Android using the TON Blockchain. Allows exchanging on-chain messages with contacts as well sending cryptocurrency.
      94 |
    32. 95 |
    33. 96 | Nicegram wallet
      97 | https://testflight.apple.com/join/sYg7ibyW
      98 | an unofficial Gram Wallet app for iOS from the developer of Nicegram client.
      99 |
    34. 100 |
    35. 101 | TON Info
      102 | https://t.me/infoton
      103 | Post about TON Blockchain.
      104 |
    36. 105 |
    37. 106 | TONBUS
      107 | https://tonbus.com/
      108 | TON China Community.
      109 |
    38. 110 |
    111 | 112 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/smc-guidelines.txt: -------------------------------------------------------------------------------- 1 | This document collects some recommendations and best practices that could be followed when developing new smart contracts for TON Blockchain. 2 | 3 | 1. Internal messages 4 | ~~~~~~~~~~~~~~~~~~~~ 5 | 6 | Smart contracts interact with each other by sending the so-called *internal messages*. When an internal message reaches its intended destination, an ordinary transaction is created on behalf of the destination account, and the internal message is processed as specified by the code and the persistent data of this account (smart contract). In particular, the processing transaction can create one or several outbound internal messages, some of which could be addressed to the source address of the internal message being processed. This can be used to create simple "client-server applications", when a query is incapsulated in an internal message and sent to another smart contract, which processes the query and sends back a response, again as an internal message. 7 | 8 | This approach leads to the necessity of distinguishing whether an internal message is intended as a "query" or as a "response", or doesn't require any additional processing (like a "simple money transfer"). Furthermore, when a response is received, there must be a means to understand to which query it corresponds. 9 | 10 | In order to achieve this goal, the following recommended internal message layout can be used (notice that the TON Blockchain does not enforce any restrictions on the message body, so these are indeed just recommendations): 11 | 12 | 0) The body of the message can be embedded into the message itself, or be stored in a separate cell referred to from the message, as indicated by the TL-B scheme fragment 13 | 14 | message$_ {X:Type} ... body:(Either X ^X) = Message X; 15 | 16 | The receiving smart contract should accept at least internal messages with embedded message bodies (whenever they fit into the cell containing the message). If it accepts message bodies in separate cells (using the `right` constructor of `(Either X ^X)`), the processing of the inbound message should not depend on the specific embedding option chosen for the message body. On the other hand, it is perfectly valid not to support message bodies in separate cells at all for simpler queries and responses. 17 | 18 | 1) The message body typically begins with the following fields: 19 | 20 | * A 32-bit (big-endian) unsigned integer *op*, identifying the "operation" to be performed, or the "method" of the smart contract to be invoked. 21 | * A 64-bit (big-endian) unsigned integer *query_id*, used in all query-response internal messages to indicate that a response is related to a query (the *query_id* of a response must be equal to the *query_id* of the corresponding query). If *op* is not a query-response method (e.g., it invokes a method that is not expected to send an answer), then *query_id* may be omitted. 22 | * The remainder of the message body is specific for each supported value of *op*. 23 | 24 | 2) If *op* is zero, then the message is a "simple transfer message with comment". The comment is contained in the remainder of the message body (without any *query_id* field, i.e., starting from the fifth byte). If it does not begin with the byte 0xff, the comment is a text one; it can be displayed "as is" to the end user of a wallet (after filtering invalid and control characters and checking that it is a valid UTF-8 string). For instance, users may indicate the purpose of a simple transfer from their wallet to the wallet of another user in this text field. On the other hand, if the comment begins with the byte 0xff, the remainder is a "binary comment", which should not be displayed to the end user as text (only as hex dump if necessary). The intended use of "binary comments" is, e.g., to contain a purchase identifier for payments in a store, to be automatically generated and processed by the store's software. 25 | 26 | Most smart contracts should not perform non-trivial actions or reject the inbound message on receiving a "simple transfer message". In this way, once *op* is found to be zero, the smart contract function for processing inbound internal messages (usually called `recv_internal()`) should immediately terminate with a zero exit code indicating success (e.g., by throwing exception 0, if no custom exception handler has been installed by the smart contract). This will lead to the receiving account being credited with the value transferred by the message without any further effect. 27 | 28 | 3) A "simple transfer message without comment" has an empty body (without even an *op* field). The above considerations apply to such messages as well. Note that such messages should have their bodies embedded into the message cell. 29 | 30 | 4) We expect "query" messages to have an *op* with the high-order bit clear, i.e., in the range 1 .. 2^31-1, and "response" messages to have an *op* with the high-order bit set, i.e., in the range 2^31 .. 2^32-1. If a method is neither a query nor a response (so that the corresponding message body does not contain a *query_id* field), it should use an *op* in the "query" range 1 .. 2^31 - 1. 31 | 32 | 5) There are some "standard" response messages with the *op* equal to 0xffffffff and 0xfffffffe. In general, the values of *op* from 0xfffffff0 to 0xffffffff are reserved for such standard responses. 33 | 34 | * op = 0xffffffff means "operation not supported". It is followed by the 64-bit *query_id* extracted from the original query, and the 32-bit *op* of the original query. All but the simplest smart contracts should return this error when they receive a query with an unknown *op* in the range 1 .. 2^31-1. 35 | * op = 0xfffffffe means "operation not allowed". It is followed by the 64-bit *query_id* of the original query, followed by the 32-bit *op* extracted from the original query. 36 | 37 | Notice that unknown "responses" (with an *op* in the range 2^31 .. 2^32-1) should be ignored (in particular, no response with an *op* equal to 0xffffffff should be generated in response to them), just as unexpected bounced messages (with "bounced" flag set). 38 | 39 | 2. Paying for processing queries and sending responses 40 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 41 | 42 | In general, if a smart contract wants to send a query to another smart contract, it should pay for sending the internal message to the destination smart contract (message forwarding fees), for processing this message at the destination (gas fees), and for sending back the answer if required (message forwarding fees). 43 | 44 | In most cases, the sender will attach a small amount of Grams (e.g., one Gram) to the internal message (sufficient to pay for the processing of this message), and set its "bounce" flag (i.e., send a bounceable internal message); the receiver will return the unused portion of the received value with the answer (deducting message forwarding fees from it). This is normally accomplished by invoking SENDRAWMSG with mode=64 (cf. Appendix A of TON VM documentation). 45 | 46 | If the receiver is unable to parse the received message and terminates with a non-zero exit code (for example, because of an unhandled cell deserialization exception), the message will be automatically "bounced" back to its sender, with the "bounce" flag cleared and the "bounced" flag set. The body of the bounced message will be the same as that of the original message; therefore, it is important to check the "bounced" flag of incoming internal messages before parsing the *op* field in the smart contract and processing the corresponding query (otherwise there is a risk that the query contained in a bounced message will be processed by its original sender as a new separate query). If the "bounced" flag is set, special code could find out which query has failed (e.g., by deserializing *op* and *query_id* from the bounced message) and take appropriate action. A simpler smart contract might simply ignore all bounced messages (terminate with zero exit code if "bounced" flag is set). 47 | 48 | On the other hand, the receiver might parse the incoming query successfully and find out that the requested method *op* is not supported, or that another error condition is met. Then a response with *op* equal to 0xffffffff or another appropriate value should be sent back, using SENDRAWMSG with mode=64 as mentioned above. 49 | 50 | In some situations, the sender wants both to transfer some value to the sender and to receive either a confirmation or an error message. For instance, the validator elections smart contract receives an election participation request along with the stake as the attached value. In such cases, it makes sense to attach, say, one extra Gram to the intended value. If there is an error (e.g., the stake may not be accepted for any reason), the full received amount (minus the processing fees) should be returned to the sender along with an error message (e.g., by using SENDRAWMSG with mode=64 as explained before). In the case of success, the confirmation message is created and exactly one Gram is sent back (with the message transferring fees deducted from this value; this is mode=1 of SENDRAWMSG). 51 | 52 | 3. Using non-bounceable messages 53 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 54 | 55 | Almost all internal messages sent between smart contracts should be bounceable, i.e., should have their "bounce" bit set. Then, if the destination smart contract does not exist, or if it throws an unhandled exception while processing this message, the message will be "bounced" back carrying the remainder of the original value (minus all message transfer and gas fees). The bounced message will have the same body, but with the "bounce" flag cleared and the "bounced" flag set. Therefore, all smart contracts should check the "bounced" flag of all inbound messages and either silently accept them (by immediately terminating with a zero exit code) or perform some special processing to detect which outbound query has failed. The query contained in the body of a bounced message should never be executed. 56 | 57 | On some occasions, non-bounceable internal messages must be used. For instance, new accounts cannot be created without at least one non-bounceable internal message sent to them. Unless this message contains a StateInit with the code and data of the new smart contract, it does not make sense to have a non-empty body in a non-bounceable internal message. 58 | 59 | It is a good idea not to allow the end user (e.g., of a wallet) to send unbounceable messages carrying large value (e.g., more than five Grams), or at least to warn them if they try this. It is a better idea to send a small amount first, then initialize the new smart contract, and then send a larger amount. 60 | 61 | 4. External messages 62 | ~~~~~~~~~~~~~~~~~~~~ 63 | 64 | External messages are sent from the outside to the smart contracts residing in the TON Blockchain to make them perform certain actions. For instance, a wallet smart contract expects to receive external messages containing orders (e.g., internal messages to be sent from the wallet smart contract) signed by the wallet's owner; when such an external message is received by the wallet smart contract, it first checks the signature, then accepts the message (by running the TVM primitive ACCEPT), and then performs whatever actions are required. 65 | 66 | Notice that all external messages must be protected against replay attacks. The validators normally remove an external message from the pool of suggested external messages (received from network); however, in some situations another validator could process the same external message twice (thus creating a second transaction for the same external message, leading to the duplication of the original action). Even worse, a malicious actor could extract the external message from the block containing the processing transaction and re-send it later. This could force a wallet smart contract to repeat a payment, for example. 67 | 68 | The simplest way to protect smart contracts from replay attacks related to external messages is to store a 32-bit counter *cur-seqno* in the persistent data of the smart contract, and to expect a *req-seqno* value in (the signed part of) any inbound external messages. Then an external message is ACCEPTed only if both the signature is valid and *req-seqno* equals *cur-seqno*. After successful processing, the *cur-seqno* value in the persistent data is increased by one, so the same external message will never be accepted again. 69 | 70 | One could also include an *expire-at* field in the external message, and accept an external message only if the current Unix time is less than the value of this field. This approach can be used in conjuction with *seqno*; alternatively, the receiving smart contract could store the set of (the hashes of) all recent (not expired) accepted external messages in its persistent data, and reject a new external message if it is a duplicate of one of the stored messages. Some garbage collecting of expired messages in this set should also be performed to avoid bloating the persistent data. 71 | 72 | In general, an external message begins with a 256-bit signature (if needed), a 32-bit *req-seqno* (if needed), a 32-bit *expire-at* (if needed), and possibly a 32-bit *op* and other required parameters depending on *op*. The layout of external messages does not need to be as standardized as that of the internal messages because external messages are not used for interaction between different smart contracts (written by different developers and managed by different owners). 73 | 74 | 5. Get-methods 75 | ~~~~~~~~~~~~~~ 76 | 77 | Some smart contracts are expected to implement certain well-defined get-methods. For instance, any subdomain resolver smart contract for TON DNS is expected to implement the get-method "dnsresolve". Custom smart contracts may define their specific get-methods. Our only general recommendation at this point is to implement the get-method "seqno" (without parameters) that returns the current *seqno* of a smart contract that uses sequence numbers to prevent replay attacks related to inbound external methods, whenever such a method makes sense. 78 | -------------------------------------------------------------------------------- /public/tblkch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/public/tblkch.pdf -------------------------------------------------------------------------------- /public/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/public/test.png -------------------------------------------------------------------------------- /public/test3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/public/test3.png -------------------------------------------------------------------------------- /public/ton-global-lite-client.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "liteservers": [ 3 | { 4 | "ip": 1992173407, 5 | "id": { 6 | "@type": "pub.ed25519", 7 | "key": "5zJE1NWZilUVMhacngkix8AaAViqhQwO4zsVezxzSSU=" 8 | }, 9 | "port": "53762" 10 | } 11 | ], 12 | "dht": { 13 | "a": 3, 14 | "k": 3, 15 | "static_nodes": { 16 | "nodes": [ 17 | { 18 | "signature": "azO52OQ1MI1Kgav1JNQqrC/KDi1CIf6nVk0uGrXu/z9JG9zpFUYL4wIWGV+XdaxSabpCBmJG5Je5E1khF3J6AQ==", 19 | "version": -1, 20 | "addr_list": { 21 | "priority": 0, 22 | "version": 0, 23 | "addrs": [ 24 | { 25 | "ip": 1992173407, 26 | "@type": "adnl.address.udp", 27 | "port": 53761 28 | } 29 | ], 30 | "@type": "adnl.addressList", 31 | "expire_at": 0, 32 | "reinit_date": 0 33 | }, 34 | "@type": "dht.node", 35 | "id": { 36 | "@type": "pub.ed25519", 37 | "key": "dPThTSuHADkeklvOK3ZzSCZtWWBvYFvxB7/+hKqYHIk=" 38 | } 39 | }, 40 | { 41 | "signature": "WeHovczBvBvUYtmF2YQL0IM8qKnjSWoQAcPN287xuiHl43S4j0u1DQ//SJOQFIwjDwsZtC30nQM2rDL+ZdW0Bw==", 42 | "version": -1, 43 | "addr_list": { 44 | "priority": 0, 45 | "version": 0, 46 | "addrs": [ 47 | { 48 | "ip": 312892958, 49 | "@type": "adnl.address.udp", 50 | "port": 53761 51 | } 52 | ], 53 | "@type": "adnl.addressList", 54 | "expire_at": 0, 55 | "reinit_date": 0 56 | }, 57 | "@type": "dht.node", 58 | "id": { 59 | "@type": "pub.ed25519", 60 | "key": "5IiFc6e5LUo+/bIijkbtmV6Pxjq8b500bFD3X9xATps=" 61 | } 62 | }, 63 | { 64 | "signature": "7ndSDT38tjiQicfraZxwN2ZnHIdH34peVp9uXaHyux3YLeje3snQlvjTZCJlauzWc6JNxAqFKNa9rd3D+dUmBw==", 65 | "version": -1, 66 | "addr_list": { 67 | "priority": 0, 68 | "version": 0, 69 | "addrs": [ 70 | { 71 | "ip": 57771459, 72 | "@type": "adnl.address.udp", 73 | "port": 53761 74 | } 75 | ], 76 | "@type": "adnl.addressList", 77 | "expire_at": 0, 78 | "reinit_date": 0 79 | }, 80 | "@type": "dht.node", 81 | "id": { 82 | "@type": "pub.ed25519", 83 | "key": "ebf6bNCADREOPzs3b76HT6YBhBo3f3wbr+zFbvOPfmw=" 84 | } 85 | }, 86 | { 87 | "signature": "zBaj20ky3V+DWVfiSj3i1J+4SmB1E2SGdH+VDQtX6DJT8ixKy+kDiV7nHt1HFTyAAWzkw2IeDMStDXbFlFfHCQ==", 88 | "version": -1, 89 | "addr_list": { 90 | "priority": 0, 91 | "version": 0, 92 | "addrs": [ 93 | { 94 | "ip": 313663840, 95 | "@type": "adnl.address.udp", 96 | "port": 53761 97 | } 98 | ], 99 | "@type": "adnl.addressList", 100 | "expire_at": 0, 101 | "reinit_date": 0 102 | }, 103 | "@type": "dht.node", 104 | "id": { 105 | "@type": "pub.ed25519", 106 | "key": "F6M3Zcs+JUvl8n2s1Xv/mwFHYmDgamXeHoQgXxX09KM=" 107 | } 108 | }, 109 | { 110 | "signature": "blFQStN141XNg+WMA/LNY1BCMc8/tDSZhZHYrnLNeLLSZ7JWzBAR5oJ5xHG5DTCHb10wHBrRzNgEyPKe0j0EDw==", 111 | "version": -1, 112 | "addr_list": { 113 | "priority": 0, 114 | "version": 0, 115 | "addrs": [ 116 | { 117 | "ip": 313615677, 118 | "@type": "adnl.address.udp", 119 | "port": 53761 120 | } 121 | ], 122 | "@type": "adnl.addressList", 123 | "expire_at": 0, 124 | "reinit_date": 0 125 | }, 126 | "@type": "dht.node", 127 | "id": { 128 | "@type": "pub.ed25519", 129 | "key": "VekrRzSIrDX0M2mu6vT4Cv8GS0znipRRMs29IrFR7s8=" 130 | } 131 | } 132 | ], 133 | "@type": "dht.nodes" 134 | }, 135 | "@type": "dht.config.global" 136 | }, 137 | "@type": "config.global", 138 | "validator": { 139 | "zero_state": { 140 | "file_hash": "+fFJaMu6zsnwOwvFTtxOoOptHhiJtY3CcNiqRsKiH5w=", 141 | "seqno": 0, 142 | "root_hash": "0ofVQql2DyGCiZy23CLgguYHjT6PJMsFVw2MPCJo/Nc=", 143 | "workchain": -1, 144 | "shard": -9223372036854775808 145 | }, 146 | "@type": "validator.config.global" 147 | } 148 | } -------------------------------------------------------------------------------- /public/ton-global.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "@type": "config.global", 3 | "dht": { 4 | "@type": "dht.config.global", 5 | "k": 3, 6 | "a": 3, 7 | "static_nodes": { 8 | "@type": "dht.nodes", 9 | "nodes": [ 10 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"dPThTSuHADkeklvOK3ZzSCZtWWBvYFvxB7/+hKqYHIk="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":1992173407,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"azO52OQ1MI1Kgav1JNQqrC/KDi1CIf6nVk0uGrXu/z9JG9zpFUYL4wIWGV+XdaxSabpCBmJG5Je5E1khF3J6AQ=="}, 11 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"5IiFc6e5LUo+/bIijkbtmV6Pxjq8b500bFD3X9xATps="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":312892958,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"WeHovczBvBvUYtmF2YQL0IM8qKnjSWoQAcPN287xuiHl43S4j0u1DQ//SJOQFIwjDwsZtC30nQM2rDL+ZdW0Bw=="}, 12 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"ebf6bNCADREOPzs3b76HT6YBhBo3f3wbr+zFbvOPfmw="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":57771459,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"7ndSDT38tjiQicfraZxwN2ZnHIdH34peVp9uXaHyux3YLeje3snQlvjTZCJlauzWc6JNxAqFKNa9rd3D+dUmBw=="}, 13 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"F6M3Zcs+JUvl8n2s1Xv/mwFHYmDgamXeHoQgXxX09KM="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":313663840,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"zBaj20ky3V+DWVfiSj3i1J+4SmB1E2SGdH+VDQtX6DJT8ixKy+kDiV7nHt1HFTyAAWzkw2IeDMStDXbFlFfHCQ=="}, 14 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"VekrRzSIrDX0M2mu6vT4Cv8GS0znipRRMs29IrFR7s8="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":313615677,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"blFQStN141XNg+WMA/LNY1BCMc8/tDSZhZHYrnLNeLLSZ7JWzBAR5oJ5xHG5DTCHb10wHBrRzNgEyPKe0j0EDw=="} 15 | ] 16 | } 17 | }, 18 | "validator": { 19 | "@type": "validator.config.global", 20 | "zero_state": { 21 | "workchain": -1, 22 | "shard": -9223372036854775808, 23 | "seqno": 0, 24 | "root_hash": "0ofVQql2DyGCiZy23CLgguYHjT6PJMsFVw2MPCJo/Nc=", 25 | "file_hash": "+fFJaMu6zsnwOwvFTtxOoOptHhiJtY3CcNiqRsKiH5w=" 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /public/ton-lite-client-test1.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "liteservers": [ 3 | { 4 | "ip":1992173407, 5 | "id": { 6 | "@type": "pub.ed25519", 7 | "key": "5zJE1NWZilUVMhacngkix8AaAViqhQwO4zsVezxzSSU=" 8 | }, 9 | "port": "53762" 10 | } 11 | ], 12 | "validator": { 13 | "@type": "validator.config.global", 14 | "zero_state": { 15 | "workchain": -1, 16 | "shard": -9223372036854775808, 17 | "seqno": 0, 18 | "root_hash": "0ofVQql2DyGCiZy23CLgguYHjT6PJMsFVw2MPCJo/Nc=", 19 | "file_hash": "+fFJaMu6zsnwOwvFTtxOoOptHhiJtY3CcNiqRsKiH5w=" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /public/ton-lite-client-test3.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "liteservers": [ 3 | { 4 | "ip": 795459766, 5 | "id": { 6 | "@type": "pub.ed25519", 7 | "key": "5R0wv44h6lPWQP5VNn8urVG1yNGJ1AflJfvvwmUORyM=" 8 | }, 9 | "port": "53762" 10 | } 11 | ], 12 | "dht": { 13 | "a": 3, 14 | "k": 3, 15 | "static_nodes": { 16 | "nodes": [ 17 | { 18 | "signature": "Jck1tGIP4Qb/MMYmvVuetjyPBs2T9AsngrUnX9gHy3JZkbn/VI9zvWLjRIIEpSZzmOWwVSiiGOLimMAFwdZdBw==", 19 | "version": -1, 20 | "addr_list": { 21 | "priority": 0, 22 | "version": 0, 23 | "addrs": [ 24 | { 25 | "ip": -1407222339, 26 | "@type": "adnl.address.udp", 27 | "port": 53761 28 | } 29 | ], 30 | "@type": "adnl.addressList", 31 | "expire_at": 0, 32 | "reinit_date": 0 33 | }, 34 | "@type": "dht.node", 35 | "id": { 36 | "@type": "pub.ed25519", 37 | "key": "llGV7AyGXVBMBrYkhtNvzAatY007WV/53qZy3BgjUF0=" 38 | } 39 | }, 40 | { 41 | "signature": "wyJ1BrqBpNsL8PP5f+PtSuyUg/YcjWxo77xsJtODllkoD5TvWR4sT2etHc9vc/f8vfJVQpoYd99dFxg9sQDeDQ==", 42 | "version": -1, 43 | "addr_list": { 44 | "priority": 0, 45 | "version": 0, 46 | "addrs": [ 47 | { 48 | "ip": -1407222338, 49 | "@type": "adnl.address.udp", 50 | "port": 53761 51 | } 52 | ], 53 | "@type": "adnl.addressList", 54 | "expire_at": 0, 55 | "reinit_date": 0 56 | }, 57 | "@type": "dht.node", 58 | "id": { 59 | "@type": "pub.ed25519", 60 | "key": "ggdze9PmPS/HclbPYcmHiwKZwnSgGZkOQDrh5/449ew=" 61 | } 62 | }, 63 | { 64 | "signature": "mJwq1nKXJmbLJ0NFAMsKE5kFxuy+pMvyvfdbNf/XJhuo41BBcf0Z71xSd9MS1Hlgm0vhX6RQ9r39ws+tiV7WDQ==", 65 | "version": -1, 66 | "addr_list": { 67 | "priority": 0, 68 | "version": 0, 69 | "addrs": [ 70 | { 71 | "ip": -1407222341, 72 | "@type": "adnl.address.udp", 73 | "port": 53761 74 | } 75 | ], 76 | "@type": "adnl.addressList", 77 | "expire_at": 0, 78 | "reinit_date": 0 79 | }, 80 | "@type": "dht.node", 81 | "id": { 82 | "@type": "pub.ed25519", 83 | "key": "jp+n4XwTYTP1TDj/f2CAdJI8YEyqd+9DTb82e1Lfcs8=" 84 | } 85 | }, 86 | { 87 | "signature": "JDcPADL6vixgTtOsIrDm3rvAwcyVwIcJaFxItOJGVkPGROApF9N5sEFFJhlTOHBHXHn6DeWkwkwDrg/oUpmWDA==", 88 | "version": -1, 89 | "addr_list": { 90 | "priority": 0, 91 | "version": 0, 92 | "addrs": [ 93 | { 94 | "ip": -1407222340, 95 | "@type": "adnl.address.udp", 96 | "port": 53761 97 | } 98 | ], 99 | "@type": "adnl.addressList", 100 | "expire_at": 0, 101 | "reinit_date": 0 102 | }, 103 | "@type": "dht.node", 104 | "id": { 105 | "@type": "pub.ed25519", 106 | "key": "hUlLuyM63l3hPhAXWk+P2I5oJyMoZQq1fssJ5B4zdJo=" 107 | } 108 | } 109 | ], 110 | "@type": "dht.nodes" 111 | }, 112 | "@type": "dht.config.global" 113 | }, 114 | "@type": "config.global", 115 | "validator": { 116 | "zero_state": { 117 | "file_hash": "7iOWQX3cAFanWqEodieZaVBiTjiHfrVUMFg1We2H/LM=", 118 | "seqno": 0, 119 | "root_hash": "i9NJN0zCA8HviG/oTRCdNkiYf8v3DkBUw5LK0vKTvqU=", 120 | "workchain": -1, 121 | "shard": -9223372036854775808 122 | }, 123 | "@type": "validator.config.global", 124 | "init_block": { 125 | "file_hash": "7iOWQX3cAFanWqEodieZaVBiTjiHfrVUMFg1We2H/LM=", 126 | "seqno": 0, 127 | "root_hash": "i9NJN0zCA8HviG/oTRCdNkiYf8v3DkBUw5LK0vKTvqU=", 128 | "workchain": -1, 129 | "shard": -9223372036854775808 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /public/ton.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/public/ton.pdf -------------------------------------------------------------------------------- /public/toncommunity-global.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "@type": "config.global", 3 | "dht": { 4 | "@type": "dht.config.global", 5 | "k": 3, 6 | "a": 3, 7 | "static_nodes": { 8 | "@type": "dht.nodes", 9 | "nodes": [ 10 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"bOLBlkP3G8DXfPkHVmi/MopzWiVgqWtbvRBqFMTNmus="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":-1407222342,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"qq986z6mRjdCaOsqc6OEzWTIB8ZWXOcgGaDzZNy9iyCHyna0GPHAy/n0XU2UVyKJnqbh+YKBkOIfNFLheQ6JCQ=="}, 11 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"7B7rC6T4dDNd9VUZk+kJLj7hcydXuMZhafwP2wH7N1k="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":-1407222339,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"uqDZSk2hfrDOPeXS49aPA1z8RxGru6WRyHxpZArPN/ltmtUnJUUBVUvy7ZWHqts36XbCeLnCfrsxZ89hY8thAg=="}, 12 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"AwVsyHVpnuM1RRfNkbybhkDXLvzpcLRckWw0vzTkQEc="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":-1407222338,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"QaQGwLp1Id3D+1WuzfVUylfqmf4hAU7FpUWAhX+N66eizh1O55fqvvPIjuAenXpSb3XDMg1hf/6UXIkY6z9ZBw=="}, 13 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"THQghKgTTbYIv8pO1Fsc4BHp10rZ+NRTy2Vuj9QEDM4="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":-1407222341,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"VcTwZUtOiu9xCOHqFXeHSg5mNe2V2TSNYzVxJQSd/FnccZZs04MruabZnVtRNpqKYYR+Ey5LD55ifjXPVyG1Ag=="}, 14 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"7T4xaxmBs54DtIogVXXl6vsamWGjbItYSbsjKW2rqVM="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":-1407222340,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"IrgEvHvbTiYqpuBAYgEAVP4OsT0oe8gR6ID/GSP5lOVMS/qyqDzuHdJGFhsYJY9ysWSdNucTHsx73Uc9JXOmBw=="} 15 | ] 16 | } 17 | }, 18 | "validator": { 19 | "@type": "validator.config.global", 20 | "zero_state": { 21 | "workchain": -1, 22 | "shard": -9223372036854775808, 23 | "seqno": 0, 24 | "root_hash": "lxLzD15VznheLWS6zr7FrwEqvG0VB2HJ+IYxoPUKW0I=", 25 | "file_hash": "IJ26WnuFq+nc6yRbkNfNBN7N49ZAiOWzOloz2yV5Mys=" 26 | }, 27 | "init_block": { 28 | "workchain": -1, 29 | "shard": -9223372036854775808, 30 | "seqno": 0, 31 | "root_hash": "lxLzD15VznheLWS6zr7FrwEqvG0VB2HJ+IYxoPUKW0I=", 32 | "file_hash": "IJ26WnuFq+nc6yRbkNfNBN7N49ZAiOWzOloz2yV5Mys=" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /public/toncommunity-lite-client.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "liteservers": 3 | [ 4 | { 5 | "ip": 1992173407, 6 | "id": 7 | { 8 | "@type": "pub.ed25519", 9 | "key": "TiDUVLwIRoOTO6pKcSuo0rNsdWNM3kFl1/pLhwF+l4I=" 10 | }, 11 | "port": "53762" 12 | }, 13 | { 14 | "ip": 795459766, 15 | "id": 16 | { 17 | "@type": "pub.ed25519", 18 | "key": "8UGf+hpWQB+vzkjmDg0AM7hsck4ook6SFC4PB6Xzxzg=" 19 | }, 20 | "port": "53762" 21 | }, 22 | { 23 | "ip": 795367252, 24 | "id": 25 | { 26 | "@type": "pub.ed25519", 27 | "key": "juafEb7Jqrae7vl2Vjoi6ne6NbiEpjcY3VJxfMh+V6o=" 28 | }, 29 | "port": "53762" 30 | }, 31 | { 32 | "ip": 795407168, 33 | "id": 34 | { 35 | "@type": "pub.ed25519", 36 | "key": "4cNzVycXSl3vz603V0xKU6olSU/2Ls/ydTrZ3xLS/S0=" 37 | }, 38 | "port": "53762" 39 | }, 40 | { 41 | "ip": 795445272, 42 | "id": 43 | { 44 | "@type": "pub.ed25519", 45 | "key": "+JmuqzMFgV0Q3Eqe++B9QMTf3kc8wZOG1f6gTo1mGvo=" 46 | }, 47 | "port": "53762" 48 | } 49 | ], 50 | "validator": 51 | { 52 | "@type": "validator.config.global", 53 | "zero_state": 54 | { 55 | "workchain": -1, 56 | "shard": -9223372036854775808, 57 | "seqno": 0, 58 | "root_hash": "lxLzD15VznheLWS6zr7FrwEqvG0VB2HJ+IYxoPUKW0I=", 59 | "file_hash": "IJ26WnuFq+nc6yRbkNfNBN7N49ZAiOWzOloz2yV5Mys=" 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /public/toncommunity-testnet3-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "@type": "config.global", 3 | "dht": { 4 | "@type": "dht.config.global", 5 | "k": 3, 6 | "a": 3, 7 | "static_nodes": { 8 | "@type": "dht.nodes", 9 | "nodes": [ 10 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"0kvOs7DcR9OMBB5JzbsHOqJiESIQQh91xYWoGPmhku4="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":1992173407,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"fWDAo1O9sRwjvPXBICle16cIn8bGwlCc8MWIGUL6MIF/NGDFyFbArh+Bphf8Jwau02YG7FovjEd+Gn2ckuwGAQ=="}, 11 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"s9VInoYJv2p6rMaFHHn05IF9AAJN1s6S/hF7ZU9ap9A="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":312892958,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"lcIABDlfaYGRukoILOB5hZXomN2XwoGknpik6aXtLgWyGejMflQUlagjaZo2VoZu5x/5/UrMv0Cgpc9IotklDw=="}, 12 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"yu7wVoh8b/sQuyY9cbHgTwrOCP0Arq2BpMz39OAogUc="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":57771459,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"a1p9qzk2GTYEyhf5t1nvswMLgHLIS0yqIYtqjbZL5tohAQ/xh+oxOqIEpfmEjqPEJSgG4GQAW+k8biNvKAWZDw=="}, 13 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"S09kzVmAvWMSZVWnxZxluWQai/lEc+VpjQseaT0B9mQ="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":313663840,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"LiYOxas2DjjrVbFTZcTQPkgiukVeU5A+S4p/CV4KeaxCUr/r29RycEiWyrOcQ81WB69hcSDMxfZI8DwVPm0YAA=="}, 14 | {"@type":"dht.node","id":{"@type":"pub.ed25519","key":"HdLWEOimtQUCewTnzwrzk+kAsEwfwh9Nyo/ErRj//14="},"addr_list":{"@type":"adnl.addressList","addrs":[{"@type":"adnl.address.udp","ip":313615677,"port":53761}],"version":0,"reinit_date":0,"priority":0,"expire_at":0},"version":-1,"signature":"nnAXaZaa6F5xjGubbf7uPzInM4+MoLnAOQasCIMTfQLwTseY9OGBbemUvUXzRT0vSs95AISt8ATGWYOY0vmZAw=="} 15 | ] 16 | } 17 | }, 18 | "liteservers": [ 19 | { 20 | "ip":1992173407, 21 | "id": { 22 | "@type": "pub.ed25519", 23 | "key": "qaHEsnyxUqld4t1ez94ECSvVdbZ8FBnXcOd2OJoAn9U=" 24 | }, 25 | "port": "53762" 26 | } 27 | ], 28 | "validator": { 29 | "@type": "validator.config.global", 30 | "zero_state": { 31 | "workchain": -1, 32 | "shard": -9223372036854775808, 33 | "seqno": 0, 34 | "root_hash": "sKOoLuTF+1HU/eJ4zORsR9NehOrpInbn4j5XdpXwP5M=", 35 | "file_hash": "9P0TuVjDyDA8od6t5oJFGNx0fl7aaaRsVeVt1Nu3cc4=" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /public/tvm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/public/tvm.pdf -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 11 | monospace; 12 | } 13 | 14 | #root { 15 | width: 100%; 16 | height: 100%; 17 | } 18 | .ant-layout { 19 | background: #fff !important; 20 | } 21 | .ant-anchor-ink { 22 | display: none; 23 | } 24 | .ant-anchor-link-active > .ant-anchor-link-title { 25 | color: #28a5e7; 26 | } 27 | a:hover { 28 | color: #71bfff !important; 29 | } 30 | .ant-anchor-link-title { 31 | color: #28a5e7 !important; 32 | } 33 | .ant-anchor-link { 34 | padding: 7px 0 !important; 35 | } 36 | 37 | .ant-drawer-body .ant-anchor-link { 38 | line-height: 2; 39 | } 40 | 41 | .ant-drawer-body button { 42 | margin-top: 20px; 43 | } 44 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | import App from "./pages/App/App"; 5 | import * as serviceWorker from "./serviceWorker"; 6 | import { createBrowserHistory } from "history"; 7 | import { BrowserRouter as Router } from "react-router-dom"; 8 | 9 | const history = createBrowserHistory(); 10 | 11 | ReactDOM.render( 12 | 13 | 14 | , 15 | document.getElementById("root") 16 | ); 17 | 18 | // If you want your app to work offline and load faster, you can change 19 | // unregister() to register() below. Note this comes with some pitfalls. 20 | // Learn more about service workers: https://bit.ly/CRA-PWA 21 | serviceWorker.unregister(); 22 | -------------------------------------------------------------------------------- /src/pages/App/App.js: -------------------------------------------------------------------------------- 1 | import React, { Suspense, lazy, useState } from "react"; 2 | import logo from "./logo.svg"; 3 | import { Layout, Spin, Anchor, Button, Drawer } from "antd"; 4 | import { LoadingOutlined } from "@ant-design/icons"; 5 | import styled from "styled-components"; 6 | import useScroll from "../useScrollTop"; 7 | import cn from "classnames"; 8 | import { MenuOutlined } from "@ant-design/icons"; 9 | import { Route, Routes } from "react-router-dom"; 10 | 11 | const Faucet = lazy(() => import("../Faucet")); 12 | const Home = lazy(() => import("../Home")); 13 | 14 | const { Link: AnchorLink } = Anchor; 15 | const antIcon = ; 16 | 17 | const App = styled(({ className }) => { 18 | const scrollTop = useScroll(); 19 | const [clientWidth, setClientWidth] = useState(document.body.clientWidth); 20 | window.onresize = function () { 21 | setClientWidth(document.body.clientWidth); 22 | }; 23 | const [visible, setVisible] = useState(false); 24 | const showDrawer = () => { 25 | setVisible(true); 26 | }; 27 | const onClose = () => { 28 | setVisible(false); 29 | }; 30 | 31 | return ( 32 | 33 | 36 | 37 | 38 | } 39 | > 40 | 41 | 45 |
    60 })} 47 | > 48 |
    56 |
    window.scrollTo(0, 0)} 59 | > 60 | logo 61 |
    62 | {clientWidth > 768 ? ( 63 |
    64 | 65 | 66 | 67 | 68 | 72 | 73 |
    74 | ) : ( 75 |
    76 | 142 | 143 |
    144 | )} 145 |
    146 |
    147 | 148 | 149 | } 150 | /> 151 | } /> 152 |
    153 |
    154 |
    155 | ); 156 | })` 157 | .drawer-header { 158 | display: flex; 159 | } 160 | .header-wrapper { 161 | position: fixed; 162 | width: 100%; 163 | background: #fff; 164 | z-index: 999; 165 | .wrapper { 166 | display: flex; 167 | justify-content: space-between; 168 | align-items: center; 169 | width: 100%; 170 | margin: 0 auto; 171 | } 172 | .wrapper-mobile { 173 | display: flex; 174 | justify-content: flex-end; 175 | align-items: center; 176 | width: 100%; 177 | margin: 0 auto; 178 | } 179 | a { 180 | padding: 7px 3px 7px 16px; 181 | color: #28a5e7; 182 | } 183 | } 184 | .header { 185 | display: flex; 186 | justify-content: start; 187 | align-items: center; 188 | width: 100%; 189 | height: 60px; 190 | line-height: 60px; 191 | color: #fff; 192 | overflow: hidden; 193 | .ant-anchor { 194 | width: 100%; 195 | display: flex; 196 | align-items: center; 197 | .ant-anchor-link-active { 198 | color: #28a5e7; 199 | } 200 | } 201 | } 202 | a:hover { 203 | color: #71bfff !important; 204 | } 205 | .logo { 206 | height: 30px; 207 | margin: 16px 24px 16px 0; 208 | float: left; 209 | } 210 | .loading { 211 | display: flex; 212 | width: 100vw; 213 | height: 100vh; 214 | justify-content: center; 215 | align-items: center; 216 | } 217 | .top-jumper { 218 | cursor: pointer; 219 | } 220 | .shadow { 221 | box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1); 222 | } 223 | .ant-btn-primary { 224 | color: #fff; 225 | background-color: #28a5e7; 226 | border-color: #28a5e7; 227 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.12); 228 | -webkit-box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045); 229 | box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045); 230 | &:hover { 231 | color: #fff; 232 | background-color: #3997e4; 233 | border-color: #3997e4; 234 | } 235 | } 236 | .ant-btn-circle { 237 | color: #28a5e7; 238 | border: 0; 239 | } 240 | `; 241 | 242 | export default App; 243 | -------------------------------------------------------------------------------- /src/pages/App/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /src/pages/App/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 编组 2 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /src/pages/Faucet/Faucet.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { Layout, Row, Typography, Input, Button, notification } from "antd"; 3 | import styled from "styled-components"; 4 | import bannerIcon from "./logo2.png"; 5 | import axios from "axios"; 6 | 7 | const { Paragraph } = Typography; 8 | const { Content } = Layout; 9 | const FaucetComponent = ({ className }) => { 10 | const [value, setValue] = useState(""); 11 | 12 | const handleChange = (e) => { 13 | setValue(e.target.value); 14 | }; 15 | 16 | const handleClick = () => { 17 | try { 18 | axios.post(`https://toncommunity.org/address/${value}`).then((res) => { 19 | const result = res.data; 20 | const { state, message } = result; 21 | if (state === "Failed") { 22 | notification["error"]({ 23 | message: "Failed", 24 | description: message, 25 | }); 26 | } else { 27 | notification["success"]({ 28 | message: "Success", 29 | }); 30 | } 31 | }); 32 | } catch (err) { 33 | console.error(err); 34 | } 35 | }; 36 | return ( 37 | 38 | 39 | 40 |
    41 | bannerIcon 42 |
    43 |

    TON Community Blockchain

    44 |

    Test Network Faucet

    45 |
    46 |
    47 | 52 | 55 |
    56 | 57 | Make sure your config is correct. Each address is allowed to enter 58 | 3 times a day, each address can receive up to 300 test ntwork coins 59 | 60 | 61 | If you want running a validator, you need at least 10000+ test 62 | network coins.{" "} 63 | 68 | Contact here 69 | 70 | . 71 | 72 |
    73 |
    74 |
    75 |
    76 | ); 77 | }; 78 | 79 | export const Faucet = styled(FaucetComponent)` 80 | .banner { 81 | display: flex; 82 | justify-content: center; 83 | align-items: center; 84 | height: 100%; 85 | .bannerIcon { 86 | height: 160px; 87 | } 88 | .title-wrapper { 89 | max-width: 1120px; 90 | width: 100%; 91 | text-align: center; 92 | padding: 110px 20px 110px 20px; 93 | .title-wrapper-div { 94 | padding-top: 20px; 95 | padding-bottom: 10px; 96 | .title { 97 | font-size: 36px; 98 | color: #222222; 99 | font-family: PingFangSC-Semibold, PingFang SC; 100 | font-weight: 600; 101 | line-height: 50px; 102 | margin: 0; 103 | } 104 | } 105 | } 106 | .input-wrapper { 107 | display: flex; 108 | max-width: 500px; 109 | margin: 50px auto; 110 | } 111 | .input { 112 | margin: 8px; 113 | } 114 | .button { 115 | margin: 8px; 116 | background: #1677ff; 117 | } 118 | .details { 119 | max-width: 500px; 120 | margin: 20px auto; 121 | } 122 | } 123 | 124 | @media (max-width: 768px) { 125 | .banner { 126 | .title-wrapper { 127 | .title-wrapper-div { 128 | .title { 129 | font-size: 24px; 130 | } 131 | } 132 | } 133 | } 134 | .input-wrapper { 135 | flex-direction: column; 136 | } 137 | .input { 138 | margin: 8px 0 !important; 139 | } 140 | .button { 141 | margin: 8px 0 !important; 142 | } 143 | } 144 | `; 145 | -------------------------------------------------------------------------------- /src/pages/Faucet/index.js: -------------------------------------------------------------------------------- 1 | export * from "./Faucet"; 2 | export { Faucet as default } from "./Faucet"; 3 | -------------------------------------------------------------------------------- /src/pages/Faucet/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/src/pages/Faucet/logo2.png -------------------------------------------------------------------------------- /src/pages/Home/index.js: -------------------------------------------------------------------------------- 1 | export * from './Home'; 2 | export { Home as default } from './Home'; 3 | -------------------------------------------------------------------------------- /src/pages/Home/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 编组 2备份 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /src/pages/Home/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TONCommunity/Project/5970a1c9c403dac979d702632857c693522f40e3/src/pages/Home/logo2.png -------------------------------------------------------------------------------- /src/pages/Home/telegram.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | telegram 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/pages/Home/twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | twitter 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/pages/useScrollTop.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | 3 | const useScroll = () => { 4 | const [scroll, setScroll] = useState(0); 5 | 6 | useEffect(() => { 7 | window.addEventListener('scroll', scrollHandler); 8 | return () => { 9 | window.removeEventListener('scroll', scrollHandler); 10 | }; 11 | }); 12 | const scrollHandler = () => { 13 | setScroll(window.scrollY); 14 | }; 15 | return scroll; 16 | }; 17 | 18 | export default useScroll; 19 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' }, 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | --------------------------------------------------------------------------------