diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/how-it-works.md b/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/how-it-works.md new file mode 100644 index 0000000000..bfa7a87b82 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/how-it-works.md @@ -0,0 +1,152 @@ +# 작동 방식 + +![작동 방식](/img/localizationProgramGuideline/localization-program.png) + +**ownSquare Labs 현지화 프로그램**은 몇 가지 주요 요소로 구성됩니다. 이 장에서는 프로그램의 작동 방식을 개괄적으로 설명하여, 그 작동 원리와 효과적인 사용 방법을 이해할 수 있도록 도와줍니다. + +이 시스템 내에서는 여러 애플리케이션을 통합하여 하나의 통합된 프로그램으로 원활하게 작동하도록 합니다: + +- **GitHub**: 문서를 호스팅하고, 업스트림 리포지토리에서 문서를 동기화하고, 특정 브랜치에 번역을 동기화합니다. +- **Crowdin**: 번역, 교정, 언어 기본 설정 등 번역 프로세스를 관리합니다. +- **AI 시스템**: 번역자들을 지원하기 위해 고급 AI를 활용하여 원활한 워크플로우를 보장합니다. +- **맞춤형 용어집**: 번역자들을 안내하고 AI가 프로젝트의 맥락에 맞는 정확한 번역을 생성하도록 합니다. 사용자들은 필요에 따라 자신들의 용어집을 업로드할 수도 있습니다. + +:::info +이 가이드는 전체 과정을 자세히 다루지는 않지만, TownSquare Labs 현지화 프로그램의 독특한 주요 요소들을 강조할 것입니다. 프로그램을 더 자세히 탐색해 보세요. +::: + +## 문서 및 번역을 위한 GitHub 동기화 + +우리 리포지토리는 문서와 번역 관리를 위해 여러 브랜치를 활용합니다. 각 특수 브랜치의 목적과 기능에 대한 자세한 설명은 다음과 같습니다: + +### 브랜치 개요 + +#### 1. `dev` + +`dev` 브랜치는 동기화 작업을 처리하기 위해 GitHub Actions를 실행합니다. 워크플로우 설정은 [**`.github/workflows`**](https://github.com/TownSquareXYZ/ton-docs/tree/dev/.github/workflows) 디렉터리에서 찾을 수 있습니다: + +- **`sync-fork.yml`**: 이 워크플로우는 업스트림 리포지토리로부터 문서를 동기화합니다. 매일 00:00에 실행됩니다. +- **`sync-translations.yml`**: 이 워크플로우는 업데이트된 번역을 해당 언어 브랜치로 동기화하여 해당 언어 웹사이트에서 미리 볼 수 있도록 합니다. + +#### 2. '현지화' + +이 브랜치는 `dev` 브랜치에서 실행되는 GitHub Actions를 통해 업스트림 리포지토리와 동기화를 유지합니다. 또한 원래 리포지토리에 제안하고자 하는 특정 코드를 업데이트하는 데 사용됩니다. + +#### 3. `l10n_localization` + +이 브랜치는 `localization` 브랜치의 모든 변경 사항과 Crowdin의 번역을 포함합니다. 이 브랜치의 모든 수정 사항은 업스트림 리포지토리에 커밋됩니다. + +#### 4. `[lang]_localization` + +이 브랜치들은 `ko_localization` (한국어) 및 `ja_localization` (일본어)와 같이 특정 언어 미리보기를 위해 지정됩니다. 이를 통해 우리는 웹사이트를 다양한 언어로 미리 볼 수 있습니다. + +이 브랜치들을 유지하고 GitHub Actions를 사용함으로써, 우리는 문서와 번역 업데이트의 동기화를 효율적으로 관리하여 다국어 콘텐츠가 항상 최신 상태를 유지하도록 합니다. + +## Crowdin의 새 프로젝트를 설정하는 방법 + +1. [**Crowdin 계정**](https://accounts.crowdin.com/login) 에 로그인하세요. + +2. 메뉴에서 `새 프로젝트 만들기`를 클릭하세요. + ![새 프로젝트 만들기](/img/localizationProgramGuideline/howItWorked/create-new-project.png) + +3. 프로젝트 이름과 대상 언어를 설정하세요. 언어는 나중에 설정에서 변경할 수 있습니다. + ![프로젝트 설정 만들기](/img/localizationProgramGuideline/howItWorked/create-project-setting.png) + +4. 방금 만든 프로젝트로 이동하여, 통합 탭을 선택하고 `통합 추가` 버튼을 클릭한 다음, `GitHub`를 검색하여 설치하세요. + ![GitHub 통합 설치](/img/localizationProgramGuideline/howItWorked/install-github-integration.png) + +5. Crowdin에서 GitHub 통합을 구성하기 전에, 불필요한 파일 업로드를 방지하기 위해 Crowdin에 업로드할 파일을 지정하세요: + + 1. **GitHub 리포지토리 루트**에 **crowdin.yml** 파일을 기본 설정으로 만드세요: + + ```yml + project_id: + preserve_hierarchy: 1 + files: + - source: + translation: + ``` + + 2. 올바른 구성 값을 가져옵니다: + - **project_id**: Crowdin 프로젝트에서 도구 탭으로 이동하여 API를 선택하고, **project_id**를 찾으세요. + ![API 도구 선택](/img/localizationProgramGuideline/howItWorked/select-api-tool.png) + ![project\_id](/img/localizationProgramGuideline/howItWorked/projectId.png) + - **preserve_hierarchy**: Crowdin 서버에서 GitHub 디렉토리 구조를 유지합니다. + - **source**와 **translation**: Crowdin에 업로드할 파일 경로와 번역된 파일이 출력될 경로를 지정합니다. + + 예시는 [**공식 설정 파일**](https://github.com/TownSquareXYZ/ton-docs/blob/localization/crowdin.yml)을 참고하세요.\ + 자세한 내용은 [**Crowdin 구성 파일 문서**](https://developer.crowdin.com/configuration-file/)에서 확인할 수 있습니다. + +6. Crowdin을 구성하여 GitHub 리포지토리에 연결합니다: + 1. `리포지토리 추가`를 클릭하고 `소스 및 번역 파일 모드`를 선택합니다. + ![통합 모드 선택](/img/localizationProgramGuideline/howItWorked/select-integration-mode.png) + 2. GitHub 계정을 연결하고 번역할 리포지토리를 검색하세요. + ![리포지토리 검색](/img/localizationProgramGuideline/howItWorked/search-repo.png) + 3. 왼쪽에서 브랜치를 선택하면 Crowdin이 번역을 게시할 새 브랜치가 생성됩니다. + ![브랜치 설정](/img/localizationProgramGuideline/howItWorked/setting-branch.png) + 4. GitHub 브랜치로 번역을 업데이트할 빈도를 선택하세요. 다른 설정은 기본 설정을 유지한 후 저장을 클릭하여 통합을 활성화하세요. + ![빈도 설정 후 저장](/img/localizationProgramGuideline/howItWorked/frequency-save.png) + +자세한 내용은 [**GitHub 연동 문서**](https://support.crowdin.com/github-integration/)를 참조하세요. + +7. 마지막으로, 필요할 때마다 `지금 동기화` 버튼을 클릭하여 리포지토리와 번역을 동기화할 수 있습니다. + +## 용어집 + +### 용어집이란 무엇인가요? + +때로는 AI 번역기가 번역해서는 안 되는 특정 용어를 인식하지 못할 수 있습니다. 예를 들어, 프로그래밍 언어를 나타내는 "Rust"는 번역하지 않아야 합니다. 이러한 실수를 방지하기 위해 번역 지침으로 용어집을 사용합니다. + +**용어집**은 프로젝트별 용어를 한 곳에 생성, 저장 및 관리하여 용어가 올바르고 일관되게 번역되도록 합니다. + +참고용으로 [**ton-i18n-glossary**](https://github.com/TownSquareXYZ/ton-i18n-glossary)를 확인할 수 있습니다. +![ton-i18n-glossary](/img/localizationProgramGuideline/howItWorked/ton-i18n-glossary.png) + +### 새 언어에 대한 용어집을 설정하는 방법은 무엇인가요? + +대부분의 번역 플랫폼은 용어집을 지원합니다. Crowdin에서는 용어집을 설정한 후, 각 용어가 편집기에서 밑줄이 그어진 단어로 나타납니다. 용어 위에 마우스를 올리면 번역, 품사, 정의(제공된 경우)를 볼 수 있습니다. +![github-glossary](/img/localizationProgramGuideline/howItWorked/github-glossary.png) +![crowdin-glossary](/img/localizationProgramGuideline/howItWorked/crowdin-glossary.png) + +DeepL에서는 용어집을 업로드하면 AI 번역 중 자동으로 사용됩니다. + +우리는 업데이트를 자동으로 업로드하는 [**용어집 프로그램**](https://github.com/TownSquareXYZ/ton-i18n-glossary)을 만들었습니다. + +용어집에 용어를 추가하려면: + +1. 영어 용어가 이미 용어집에 있는 경우, 해당 언어의 번역을 입력하고 업로드합니다. +2. 새 용어집을 업로드하려면, 프로젝트를 클론하고 다음을 실행합니다: + + - `npm i` + - `npm run generate -- ` + +새 용어를 추가하려면 1단계를 반복합니다. + +**간단하고 효율적이지 않나요?** + +## AI 번역 Copilot을 활용하는 방법은 무엇인가요? + +AI 번역 코파일럿은 여러 가지 이점으로 언어 장벽을 허물어줍니다: + +- **향상된 일관성**: AI 번역은 최신 정보를 기반으로 하여 가장 정확하고 최신의 번역을 제공합니다. +- **속도와 효율성**: AI 번역은 실시간으로 대량의 콘텐츠를 즉시 처리합니다. +- **강력한 확장성**: AI 시스템은 지속적으로 학습하고 개선되어 번역 품질이 시간이 지남에 따라 향상됩니다. 제공된 용어집을 통해 AI 번역은 다양한 저장소의 특정 요구에 맞춰 조정될 수 있습니다. + +Crowdin에서 AI 번역을 사용하려면(저희 프로젝트에서는 DeepL 사용): + +1. Crowdin 메뉴에서 기계 번역을 선택하고 DeepL 라인에서 편집을 클릭하세요. + ![select-deepl](/img/localizationProgramGuideline/howItWorked/select-deepl.png) +2. DeepL 지원을 활성화하고 DeepL 번역기 API 키를 입력하세요. + > [DeepL 번역기 API 키 받기 방법](https://www.deepl.com/pro-api?cta=header-pro-api) + +![config-crowdin-deepl](/img/localizationProgramGuideline/howItWorked/config-crowdin-deepl.png) + +3. 우리의 DeepL 설정은 맞춤형 용어집을 사용합니다. 용어집 업로드에 대한 자세한 내용은 [**ton-i18n-glossary**](https://github.com/TownSquareXYZ/ton-i18n-glossary)를 확인하세요. + +4. 리포지토리에서 사전 번역을 클릭하고 기계 번역을 통해 선택하세요. + ![pre-translation](/img/localizationProgramGuideline/howItWorked/pre-translation.png) + +5. DeepL을 번역 엔진으로 선택하고, 대상 언어를 선택한 다음 번역할 파일을 선택하세요. + ![pre-translate-config](/img/localizationProgramGuideline/howItWorked/pre-translate-config.png) + +끝났습니다! 이제 사전 번역이 완료될 때까지 잠시 휴식을 취하면 됩니다. diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/how-to-contribute.md b/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/how-to-contribute.md new file mode 100644 index 0000000000..c8ae69c481 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/how-to-contribute.md @@ -0,0 +1,124 @@ +# 기여 방법 + +**TON을 가장 성공적인 블록체인으로 만드는** 우리의 목표를 이루기 위해, TON 문서가 전 세계 사람들에게 이해될 수 있도록 하는 것이 중요합니다. 현지화가 핵심이며, 이 노력에 당신이 함께 해주신다면 **정말 기쁠 것**입니다. + +## 사전 준비 사항 + +**TownSquare Labs Localization Program**은 누구에게나 열려 있습니다! 기여를 시작하기 전에 다음 단계를 따라주세요: + +1. [**Crowdin**](https://crowdin.com) 계정에 로그인하거나 가입하세요. +2. 기여하고 싶은 언어를 선택하세요. +3. [**Crowdin 사용 방법**](/contribute/localization-program/how-to-contribute) 가이드와 [**번역 스타일 가이드**](/contribute/localization-program/translation-style-guide)를 읽고 팁과 모범 사례를 익히세요. +4. 기계 번역을 사용하여 작업을 보조하지만, 단독으로 의존하지 마세요. +5. 모든 번역 결과는 교정이 완료된 후 1시간 내에 웹사이트에서 미리 볼 수 있습니다. + +## 역할 + +시스템에서 맡을 수 있는 **역할**은 다음과 같습니다: + +- **언어 코디네이터** – 할당된 언어 내 프로젝트 기능을 관리합니다. +- **개발자** – 파일 업로드, 번역 가능한 텍스트 편집, 통합 연결 및 API 사용을 담당합니다. +- **교정자** – 문자열을 번역하고 승인합니다. +- **번역가** (내부 또는 커뮤니티) – 문자열을 번역하고 다른 사람이 추가한 번역에 투표합니다. + +우리의 현지화 프로젝트는 [Crowdin](https://crowdin.com/project/ton-docs)에서 호스팅됩니다. + +:::info +Before you start contributing, **read the guidelines below** to ensure standardization and quality, making the review process much faster. + +## 나란히 보기 모드 + +모든 작업은 Crowdin Editor의 **나란히 보기** 모드에서 수행됩니다. 이를 활성화하려면 작업할 파일을 클릭하세요. 페이지 오른쪽 상단의 **편집기 보기** 버튼을 클릭하고 더 명확한 편집기 보기를 위해 **나란히 보기** 모드를 선택하세요. +![나란히 보기 모드](/img/localizationProgramGuideline/side-by-side.png) +::: + +### 언어 코디네이터 + +- **문자열 번역 및 승인** +- **프로젝트 콘텐츠 사전 번역** +- **프로젝트 멤버 및 가입 요청 관리** + ![멤버 관리](/img/localizationProgramGuideline/manage-members.png) +- **프로젝트 보고서 생성** + ![보고서 생성](/img/localizationProgramGuideline/generate-reports.png) +- **작업 생성** + ![작업 생성](/img/localizationProgramGuideline/create-tasks.png) + +### 개발자 + +- **파일 업로드** +- **번역 가능한 텍스트 편집** +- **통합 연결** (예: GitHub 통합 추가) + ![GitHub 통합 설치](/img/localizationProgramGuideline/howItWorked/install-github-integration.png) +- **[Crowdin API](https://developer.crowdin.com/api/v2/) 사용** + +### 교정자 + +**교정자**로서, **파란색 진행 막대**가 있는 파일에서 작업하게 됩니다. +![교정 단계1](/img/localizationProgramGuideline/proofread-step1.png) +파일을 클릭하여 편집 인터페이스로 들어가세요. + +#### 기여 시작 + +1. [**나란히 보기 모드**](#side-by-side-mode)에 있는지 확인하세요. **승인되지 않음** 번역으로 필터링하여 교정이 필요한 문자열을 확인하세요. + ![교정 필터](/img/localizationProgramGuideline/proofread-filter.png) + +2. 다음 규칙을 따르세요: + - **파란색 큐브 아이콘**이 있는 문자열을 선택하세요. 각 번역을 확인하세요: + - **올바르면**, ☑️ 버튼을 클릭하세요. + - **잘못되면**, 다음 줄로 이동하세요. + +![교정 승인됨](/img/localizationProgramGuideline/proofread-approved.png) + +:::info +You can also review approved lines: + +1. **승인됨**으로 필터링하세요. + +2. 승인된 줄에 문제가 있으면, ☑️ 버튼을 클릭하여 교정이 필요하도록 되돌리세요. + ::: + +3. 다음 파일로 이동하려면 상단의 파일 이름을 클릭하고, 팝업 창에서 새 파일을 선택하여 교정을 계속하세요. + ![다음으로 이동](/img/localizationProgramGuideline/redirect-to-next.png) + +#### 작업 미리보기 + +모든 승인된 콘텐츠는 1시간 내에 미리보기 웹사이트에 배포됩니다. 최신 PR의 **미리보기** 링크는 [**우리의 레포지토리**](https://github.com/TownSquareXYZ/ton-docs/pulls)에서 확인하세요. +![미리보기 링크](/img/localizationProgramGuideline/preview-link.png) + +### 번역가 + +**번역가**로서, 당신의 목표는 번역이 원문과 가깝고 표현이 풍부하여 이해하기 쉽게 만드는 것입니다. **파란색 진행 막대**를 100%로 만드는 것이 당신의 임무입니다. + +#### 번역 시작 + +성공적인 번역 과정을 위해 다음 단계를 따르세요: + +1. 번역이 100%에 도달하지 않은 파일을 선택하세요. + ![번역가 선택](/img/localizationProgramGuideline/translator-select.png) + +2. [**나란히 보기 모드**](#side-by-side-mode)에 있는지 확인하세요. **번역되지 않음** 문자열로 필터링하세요. + ![번역가 필터](/img/localizationProgramGuideline/translator-filter.png) + +3. 작업 공간은 네 부분으로 구성됩니다: + - **왼쪽 상단:** 소스 문자열을 기반으로 번역을 입력하세요. + - **왼쪽 하단:** 번역된 파일을 미리보기 합니다. 원본 형식을 유지하세요. + - **오른쪽 하단:** Crowdin의 번역 제안. 클릭하여 사용할 수 있지만, 특히 링크의 정확성을 확인하세요. + +4. 상단의 **저장** 버튼을 클릭하여 번역을 저장하세요. + ![번역가 저장](/img/localizationProgramGuideline/translator-save.png) + +5. 다음 파일로 이동하려면 상단의 파일 이름을 클릭하고 팝업 창에서 새 파일을 선택하세요. + ![다음으로 이동](/img/localizationProgramGuideline/redirect-to-next.png) + +## 새 언어 지원 추가 방법 + +현재, Crowdin에는 원하는 모든 언어가 있습니다. 커뮤니티 매니저인 경우, 다음 단계를 따르세요: + +1. [TownSquareXYZ/ton-docs](https://github.com/TownSquareXYZ/ton-docs)에 `[lang]_localization` (예: 한국어의 경우 `ko_localization`)이라는 새 브랜치를 추가하세요. +2. 이 저장소의 Vercel 소유자에게 연락하여 메뉴에 새 언어를 추가하도록 요청하세요. +3. dev 브랜치에 PR 요청을 생성하세요. **dev로 병합하지 마세요**; 이는 미리보기 용도입니다. + +이 단계가 완료되면 PR 요청에서 언어의 미리보기를 볼 수 있습니다. +![ko 미리보기](/img/localizationProgramGuideline/ko_preview.png) + +언어가 TON 문서에 준비되면, 문제를 생성하고, 우리가 프로덕션 환경에 언어를 설정하도록 요청하세요. diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md b/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md new file mode 100644 index 0000000000..1cf9362d71 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md @@ -0,0 +1,39 @@ +# 현지화 프로그램 + +번역 프로그램은 TON 관련 다양한 문서를 여러 언어로 번역하여 전 세계 수십억 명의 비영어권 사용자에게 웹사이트 접근성을 높이는 협업 노력입니다. + +## 시스템 설계 철학 + +![how it works](/img/localizationProgramGuideline/localization-program.png) + +현지화 프로그램은 **TON**의 가장 가까운 파트너 중 하나인 [**TownSquare Labs**](https://github.com/TownSquareXYZ)에 의해 **시작**되고 **적극적으로 유지 관리**됩니다. + +우리는 다국어 커뮤니티 협업을 위한 개방형 인프라를 구축하여 **TON을 더 나은 단계로 발전**시키는 것을 목표로 하고 있으며, 이를 위해 다음을 포함합니다: + +1. **다국어 커뮤니티에 적합** + 이 프로그램은 여러 언어를 지원하여 다양한 언어적 배경을 가진 사용자가 접근하기 쉽고 포괄적입니다. + +2. **개발, 통합 및 배포 자동화** + 자동화 도구를 활용하여 개발, 통합 및 배포 과정을 간소화하고 수작업을 줄이며 모든 현지화 작업에서 효율성과 일관성을 높입니다. + +3. **개발자, 번역가 및 검증자의 역할 분리** + 우리의 접근 방식은 개발자, 번역가 및 검증자의 책임을 분리하여 각 역할이 자신의 특정 작업에 집중할 수 있도록 합니다. 이를 통해 높은 품질의 번역과 원활한 협업이 보장되며, 업무 중복이나 충돌을 방지합니다. + +4. **커뮤니티 기여 인센티브** + 현지화 과정에 기여하는 커뮤니티 구성원에게 인센티브를 제공합니다. 이를 통해 적극적인 참여를 유도하고 프로그램을 개선하는 데 도움을 준 사람들을 보상하여 소속감과 커뮤니티 정신을 함양합니다. + +5. **고급 AI 시스템 통합** + 고급 AI 시스템은 지능형 제안 제공 및 반복 작업 자동화를 통해 번역 정확도와 효율성을 높여 적은 노력으로 높은 품질의 결과를 보장합니다. + +이 프로젝트는 특정 언어 사용자만을 위한 것이 아니라, **전 세계 개발자 생태계를 위한 서비스 제공**을 목표로 합니다. + +## 감사의 글 + +번역 프로그램의 핵심 구성원인 수천 명의 커뮤니티 멤버들에게 깊은 감사를 드립니다. 우리는 번역가들을 인정하고 그들의 경력 경로를 지원하고자 합니다. 가까운 미래에 리더보드와 번역 프로그램의 모든 기여자의 목록을 작성하여 최고의 번역가들을 인정할 것입니다. + +## 가이드 및 자료 + +번역 프로그램에 기여하거나 참여를 고려하고 있다면, 아래의 번역 가이드를 확인하세요: + +- [**번역 스타일 가이드**](/contribute/localization-program/translation-style-guide) – 번역가를 위한 지침 및 팁. +- [**Crowdin 온라인 편집기 가이드**](https://support.crowdin.com/online-editor/) – Crowdin 온라인 편집기와 일부 고급 기능 사용에 대한 심층 가이드. diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/translation-style-guide.md b/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/translation-style-guide.md new file mode 100644 index 0000000000..732b5918f8 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/contribute/localization-program/translation-style-guide.md @@ -0,0 +1,198 @@ +# 번역 스타일 가이드 + +이 번역 스타일 가이드는 웹사이트 로컬라이제이션을 돕기 위한 가장 중요한 지침, 지시사항, 팁을 포함하고 있습니다. + +이 문서는 일반적인 가이드이며 특정 언어에 국한되지 않습니다. + +## 메시지의 핵심 포착 + +TON 문서를 번역할 때, 문자 그대로의 번역을 피하십시오. + +번역이 메시지의 핵심을 포착하는 것이 중요합니다. 이는 특정 문구를 재구성하거나 내용의 단어 대 단어 번역 대신 설명적인 번역을 사용하는 것을 의미할 수 있습니다. + +각 언어는 서로 다른 문법 규칙, 관습 및 단어 순서를 가지고 있습니다. 번역할 때는 대상 언어의 문장 구조에 유의하고, 영어 소스를 문자 그대로 번역하는 것을 피하십시오. 이는 문장 구조와 가독성을 떨어뜨릴 수 있습니다. + +원문을 단어 대 단어로 번역하는 대신 전체 문장을 읽고 대상 언어의 관습에 맞게 조정하는 것이 좋습니다. + +## 격식 vs. 비격식 + +우리는 방문자 모두에게 항상 정중하고 적절한 격식적인 대화 방식을 사용합니다. + +격식적인 대화 방식을 사용하면 비공식적이거나 공격적으로 들리지 않으며 방문자의 나이와 성별에 관계없이 사용할 수 있습니다. + +대부분의 인도유럽어 및 아프라시아어는 남성과 여성을 구별하는 성별에 따른 2인칭 대명사를 사용합니다. 사용자에게 말할 때나 소유 대명사를 사용할 때 방문자의 성별을 가정하지 않을 수 있습니다. 격식적인 대화 방식은 일반적으로 적용 가능하며 일관성 있습니다. + +## 간단하고 명확한 어휘와 의미 + +우리의 목표는 웹사이트의 내용을 가능한 한 많은 사람들이 이해할 수 있도록 하는 것입니다. + +대부분의 경우, 짧고 간단한 단어를 사용하여 쉽게 이해할 수 있습니다. 동일한 의미를 가진 여러 가지 번역 가능한 단어가 있는 경우, 가장 짧고 의미를 명확하게 반영하는 단어를 사용하는 것이 가장 좋습니다. + +## 문자 체계 + +모든 콘텐츠는 대상 언어에 맞는 올바른 문자 체계를 사용하여 번역되어야 하며, 라틴 문자를 사용한 단어를 포함해서는 안 됩니다. + +번역할 때는 번역이 일관되고 라틴 문자를 포함하지 않도록 해야 합니다. + +**위 내용은 고유 명사는 번역하지 않는 것이 원칙인 언어에는 적용되지 않습니다.** + +## 페이지 메타데이터 번역 + +일부 페이지에는 'title', 'lang', 'description', 'sidebar' 등과 같은 메타데이터가 포함되어 있습니다. + +새 페이지를 Crowdin에 업로드할 때 번역자가 번역해서는 안 되는 내용을 숨기기 때문에 Crowdin에서 번역자가 볼 수 있는 모든 메타데이터는 번역해야 합니다. + +'source text'가 'en'인 문자열을 번역할 때 특히 주의해야 합니다. 이는 페이지가 제공되는 언어를 나타내며 [ISO 언어 코드](https://www.andiamo.co.uk/resources/iso-language-codes/)로 번역해야 합니다. 이러한 문자열은 대상 언어의 고유 문자 대신 라틴 문자를 사용하여 번역해야 합니다. + +어떤 언어 코드를 사용해야 할지 확신이 서지 않으면, Crowdin에서 번역 메모리를 확인하거나 Crowdin 온라인 편집기의 페이지 URL에서 해당 언어 코드를 찾을 수 있습니다. + +가장 많이 사용되는 언어의 언어 코드 예시: + +- 영어 - en +- 중국어 간체 - zh-CN +- 러시아어 - ru +- 한국어 - ko +- 폴란드어 - pl +- 우크라이나어 - uk + +## 외부 기사 제목 + +일부 문자열에는 외부 기사 제목이 포함되어 있습니다. 대부분의 개발자 문서 페이지에는 추가 읽기 자료를 위한 외부 기사 링크가 포함되어 있습니다. 기사 제목이 포함된 문자열은 일관된 사용자 경험을 위해 기사 언어에 관계없이 번역되어야 합니다. + +## Crowdin 경고 + +Crowdin에는 번역가가 실수를 할 때 경고하는 내장 기능이 있습니다. 태그를 포함하지 않거나, 번역해서는 안 되는 요소를 번역하거나, 여러 개의 연속적인 공백을 추가하거나, 종결 구두점을 잊는 경우 Crowdin은 저장하기 전에 자동으로 경고합니다. 이러한 경고가 표시되면 제안된 번역을 다시 확인하십시오. + +:::warning +이러한 경고를 무시하지 마십시오. 보통 무언가가 잘못되었거나 번역에서 소스 텍스트의 중요한 부분이 누락된 것을 의미합니다. +::: + +## 단축형 vs. 전체형/약어 + +웹사이트에는 dapps, NFT, DAO, DeFi 등 많은 약어가 사용됩니다. 이러한 약어는 영어로 널리 사용되며 대부분의 웹사이트 방문자가 익숙합니다. + +이러한 약어는 다른 언어로 정립된 번역이 없는 경우가 많으므로 이러한 용어와 유사한 용어에 접근하는 가장 좋은 방법은 전체 형태의 설명적인 번역을 제공하고 영어 약어를 괄호 안에 추가하는 것입니다. + +이러한 약어를 번역하지 마십시오. 대부분의 사람들이 익숙하지 않으며, 현지화된 버전은 대부분의 방문자에게 의미가 없을 것입니다. + +dapps 번역 예시: + +- Decentralized applications (dapps) → 번역된 전체형 (영어 약어 괄호 안에) + +## 정립된 번역이 없는 용어 + +일부 용어는 다른 언어로 정립된 번역이 없으며, 원래 영어 용어로 널리 알려져 있습니다. 이러한 용어는 주로 새로운 개념을 포함하며, 예를 들어 proof-of-work, proof-of-stake, Beacon Chain, staking 등이 있습니다. + +이러한 용어를 번역하면 부자연스러울 수 있지만, 영어 버전은 다른 언어에서도 일반적으로 사용되므로 번역하는 것이 좋습니다. + +번역할 때 창의적으로 설명적인 번역을 사용하거나 단순히 문자 그대로 번역해도 좋습니다. + +대부분의 용어를 영어로 남기기보다는 번역해야 하는 이유는 새로운 용어가 더 널리 퍼질 것이기 때문입니다. 더 많은 사람들이 TON 및 관련 기술을 사용하기 시작하면서, 더 많은 사람들이 쉽게 이해할 수 있는 용어를 다양한 언어로 제공해야 합니다. + +## 버튼 및 CTA + +웹사이트에는 여러 버튼이 있으며, 다른 콘텐츠와는 다르게 번역되어야 합니다. + +버튼 텍스트는 대부분의 문자열과 연결된 컨텍스트 스크린샷을 보거나 편집기에서 컨텍스트를 확인하여 식별할 수 있습니다. 여기에는 'button'이라는 구문이 포함됩니다. + +버튼 번역은 형식 불일치를 방지하기 위해 가능한 한 짧게 해야 합니다. 또한, 버튼 번역은 명령형, 즉 명령이나 요청을 제시해야 합니다. + +## 포용성을 위한 번역 + +TON 문서 방문자는 전 세계에서 다양한 배경을 가지고 있습니다. 웹사이트의 언어는 따라서 중립적이고 모두를 환영하며 배타적이지 않아야 합니다. + +중요한 측면 중 하나는 성 중립성입니다. 이는 공식적인 대화 방식을 사용하고 번역에서 성별에 특정한 단어를 피함으로써 쉽게 달성할 수 있습니다. + +또 다른 형태의 포용성은 특정 국가, 인종 또는 지역에 국한되지 않고 글로벌 관객을 대상으로 번역하는 것입니다. + +마지막으로, 언어는 모든 연령대와 청중에게 적합해야 합니다. + +## 언어별 번역 + +번역할 때는 소스를 복사하는 대신, 해당 언어에서 사용되는 문법 규칙, 관습 및 형식을 따르는 것이 중요합니다. 소스 텍스트는 영어 문법 규칙과 관습을 따르며, 이는 많은 다른 언어에 적용되지 않습니다. + +자신의 언어에 대한 규칙을 알고 이에 따라 번역해야 합니다. 도움이 필요하면 저희에게 연락 주시면 해당 언어에서 이러한 요소가 어떻게 사용되어야 하는지에 대한 리소스를 찾는 데 도움을 드리겠습니다. + +특히 주의해야 할 몇 가지 예시: + +### 구두점, 형식 + +#### 대문자 사용 + +- 다른 언어에서는 대문자 사용에 큰 차이가 있습니다. +- 영어에서는 제목 및 이름, 월 및 요일, 언어 이름, 휴일 등을 모두 대문자로 쓰는 것이 일반적입니다. 그러나 많은 다른 언어에서는 이러한 대문자 사용이 문법적으로 틀립니다. +- 일부 언어는 영어에서 대문자로 쓰지 않는 개인 대명사, 명사 및 특정 형용사를 대문자로 쓰는 규칙이 있습니다. + +#### 공백 + +- 철자 규칙은 각 언어의 공백 사용을 정의합니다. 공백은 어디에나 사용되기 때문에 이러한 규칙은 가장 두드러지며, 공백은 가장 오역된 요소 중 하나입니다. +- 영어와 다른 언어 간의 공백 사용의 일반적인 차이점: + - 단위와 통화 앞의 공백 (예: USD, EUR, kB, MB) + - 온도 기호 앞의 공백 (예: °C, ℉) + - 일부 구두점, 특히 줄임표 (…) 앞의 공백 + - 슬래시 (/) 전후의 공백 + +#### 목록 + +- 각 언어에는 다양한 목록 작성 규칙이 있으며, 이는 영어와 크게 다를 수 있습니다. +- 일부 언어에서는 각 새로운 줄의 첫 단어를 대문자로 써야 하고, 다른 언어에서는 소문자로 시작해야 합니다. 많은 언어는 각 줄의 길이에 따라 목록에서 대문자 사용에 대한 다른 규칙을 가지고 있습니다. +- 동일한 규칙이 항목의 끝 구두점에도 적용됩니다. 목록의 끝 구두점은 언어에 따라 마침표 (.), 쉼표 (,) 또는 세미콜론 (;)이 될 수 있습니다. + +#### 인용 부호 + +- 언어는 다양한 인용 부호를 사용합니다. 소스에서 영어 인용 부호를 복사하는 것은 종종 잘못된 것입니다. +- 가장 일반적인 인용 부호 유형: + - „예문“ + - ‚예문’ + - »예문« + - “예문” + - ‘예문’ + - «예문» + +#### 하이픈과 대시 + +- 영어에서는 하이픈 (-)을 사용하여 단어를 연결하거나 단어의 다른 부분을 연결하며, 대시 (–)는 범위 또는 일시 중지를 나타내는 데 사용됩니다. +- 많은 언어는 하이픈과 대시 사용에 대한 다른 규칙을 가지고 있습니다. + +### 형식 + +#### 숫자 + +- 각 언어의 숫자 작성에서 주요 차이점은 소수점 및 천 단위 구분 기호입니다. 천 단위의 경우, 이는 마침표, 쉼표 또는 공백이 될 수 있습니다. 비슷하게, 일부 언어는 소수점으로 마침표를, 다른 언어는 소수점으로 쉼표를 사용합니다. + - 큰 숫자의 예시: + - 영어 – **1,000.50** + - 스페인어 – **1.000,50** + - 프랑스어 – **1 000,50** +- 숫자 번역 시 중요한 고려 사항은 퍼센트 기호입니다. 이는 다양한 방식으로 작성될 수 있습니다: **100%**, **100 %** 또는 **%100**. +- 마지막으로, 음수는 언어에 따라 다르게 표시될 수 있습니다: -100, 100-, (100) 또는 [100]. + +#### 날짜 + +- 날짜를 번역할 때는 날짜 형식, 구분 기호, 대문자 사용 및 선행 0과 같은 여러 가지 고려 사항이 있습니다. 전체 길이 날짜와 숫자 날짜 간에도 차이가 있습니다. + - 다양한 날짜 형식 예시: + - 영국 영어 (dd/mm/yyyy) – 2022년 1월 1일 + - 미국 영어 (mm/dd/yyyy) – 2022년 1월 1일 + - 중국어 (yyyy-mm-dd) – 2022 年 1 月 1 日 + - 프랑스어 (dd/mm/yyyy) – 1er janvier 2022 + - 이탈리아어 (dd/mm/yyyy) – 1º gennaio 2022 + - 독일어 (dd/mm/yyyy) – 1. Januar 2022 + +#### 통화 + +- 통화를 번역하는 것은 형식, 관습 및 변환의 차이로 인해 어려울 수 있습니다. 일반적으로 통화는 소스와 동일하게 유지하십시오. 독자를 위해 괄호 안에 현지 통화와 변환을 추가할 수 있습니다. +- 다양한 언어에서 통화를 작성하는 주요 차이점은 기호 위치, 소수점과 소수점의 사용, 공백 및 약어 대 기호입니다. + - 기호 위치: $100 또는 100$ + - 소수점 대 소수점: 100,50$ 또는 100.50$ + - 공백: 100$ 또는 100 $ + - 약어 대 기호: 100 $ 또는 100 USD + +#### 단위 + +- 일반적으로, 단위는 소스와 동일하게 유지하십시오. 귀하의 국가가 다른 시스템을 사용하는 경우, 독자를 위해 괄호 안에 변환을 추가할 수 있습니다. +- 단위의 현지화 외에도 언어가 이러한 단위에 접근하는 방식의 차이점에 유의해야 합니다. 주요 차이점은 언어에 따라 숫자와 단위 사이의 공백입니다. 예시로는 100kB 대 100 kB 또는 50ºF 대 50 ºF가 있습니다. + +## 결론 + +번역할 때 서두르지 마십시오. 천천히 하며 즐기십시오! + +번역 프로그램에 참여해 주셔서 감사합니다. TON 커뮤니티는 글로벌하며, 여러분이 그 일원이 되어 기쁩니다! diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/blockchain/shards.mdx b/i18n/ko/docusaurus-plugin-content-docs/current/develop/blockchain/shards.mdx index c30c633d4a..96fd3c5432 100644 --- a/i18n/ko/docusaurus-plugin-content-docs/current/develop/blockchain/shards.mdx +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/blockchain/shards.mdx @@ -1,9 +1,5 @@ # 샤드 -:::warning -페이지가 개발 중입니다. -::: - 샤딩은 [데이터베이스 설계](https://en.wikipedia.org/wiki/Shard_(database_architecture))에서 기원한 성숙한 개념입니다. 이는 하나의 논리적 데이터 세트를 여러 데이터베이스에 나누어 분산시키는 것으로, 이 데이터베이스들은 서로 독립적이며 여러 서버에 배포될 수 있습니다. 간단히 말해, 샤딩은 수평적 확장성을 가능하게 합니다 - 데이터를 독립적인 여러 조각으로 나누어 병렬로 처리할 수 있게 하는 것입니다. 이는 데이터에서 [빅 데이터](https://en.wikipedia.org/wiki/Big_data)로의 전환에서 중요한 개념입니다. 데이터 세트가 전통적인 방법으로 처리하기에는 너무 커질 때, 더 작게 분할하지 않으면 확장할 다른 방법이 없습니다. diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/apis/README.md b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/apis/README.md new file mode 100644 index 0000000000..880c604ff2 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/apis/README.md @@ -0,0 +1,82 @@ +# API 유형 + +**고가용성 블록체인 API는 TON에서 유용한 애플리케이션을 안전하고 편리하며 빠르게 개발하는 핵심 요소입니다.** + +- [TON HTTP API](/develop/dapps/apis/toncenter) — _인덱싱된 블록체인 정보_를 다룰 수 있는 API. +- [TON ADNL API](/develop/dapps/apis/adnl) — ADNL 프로토콜을 기반으로 TON과 통신하는 안전한 API. + +## Toncenter APIs + +- [TON Index](https://toncenter.com/api/v3/) - TON Index는 전체 노드에서 데이터를 수집하여 PostgreSQL 데이터베이스에 저장하고 인덱싱된 블록체인에 대한 편리한 API를 제공합니다. +- [toncenter/v2](https://toncenter.com/) - 이 API는 TON 블록체인에 대한 HTTP 액세스를 가능하게 하며, 계정 및 지갑 정보 조회, 블록 및 트랜잭션 조회, 블록체인으로 메시지 전송, 스마트 계약의 get 메서드 호출 등을 지원합니다. + +## 타사 API + +- [tonapi.io](https://docs.tonconsole.com/tonapi/api-v2) - 계정, 트랜잭션, 블록에 대한 기본 데이터를 제공하는 빠른 인덱스 API로, NFT, 경매, Jettons, TON DNS, 구독과 같은 애플리케이션별 데이터도 제공합니다. 또한 트랜잭션 체인에 대한 주석 데이터를 제공합니다. +- [dton.io](https://dton.io/graphql/) - 계정, 트랜잭션, 블록에 대한 데이터를 제공하는 GraphQL API로, NFT, 경매, Jettons, TON DNS와 같은 애플리케이션별 데이터도 제공합니다. +- [ton-api-v4](https://mainnet-v4.tonhubapi.com) - CDN에서 공격적인 캐싱을 통해 속도에 중점을 둔 또 다른 라이트 API입니다. +- [docs.nftscan.com](https://docs.nftscan.com/reference/ton/model/asset-model) - TON 블록체인을 위한 NFT API. +- [evercloud.dev](https://ton-mainnet.evercloud.dev/graphql) - TON에서 기본 쿼리를 위한 GraphQL API. +- [everspace.center](https://everspace.center/toncoin) - TON 블록체인에 액세스하기 위한 간단한 RPC API. + +## 추가 API + +### Toncoin 환율 APIs + +- https://tonapi.io/v2/rates?tokens=ton¤cies=ton%2Cusd%2Crub +- https://coinmarketcap.com/api/documentation/v1/ +- https://apiguide.coingecko.com/getting-started + +### 주소 변환 API + +:::info +로컬 알고리즘을 통해 주소를 변환하는 것이 좋습니다. 자세한 내용은 문서의 [Addresses](/learn/overviews/addresses) 섹션을 참조하세요. +::: + +#### 친숙한 주소에서 원시 형태로 변환 + +/api/v2/unpackAddress + +Curl + +```curl +curl -X 'GET' \ +'https://toncenter.com/api/v2/unpackAddress?address=EQApAj3rEnJJSxEjEHVKrH3QZgto_MQMOmk8l72azaXlY1zB' \ +-H 'accept: application/json' +``` + +응답 본문 + +```curl +{ +"ok": true, +"result": "0:29023deb1272494b112310754aac7dd0660b68fcc40c3a693c97bd9acda5e563" +} +``` + +#### 친숙한 주소에서 원시 형태로 변환 + +/api/v2/packAddress + +Curl + +```curl +curl -X 'GET' \ +'https://toncenter.com/api/v2/packAddress?address=0%3A29023deb1272494b112310754aac7dd0660b68fcc40c3a693c97bd9acda5e563' \ +-H 'accept: application/json' +``` + +응답 본문 + +```json +{ + "ok": true, + "result": "EQApAj3rEnJJSxEjEHVKrH3QZgto/MQMOmk8l72azaXlY1zB" +} +``` + +## 참고 항목 + +- [TON HTTP API](/develop/dapps/apis/toncenter) +- [SDK 목록](/develop/dapps/apis/sdk) +- [TON 지침서](/develop/dapps/cookbook) diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/apis/sdk.mdx b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/apis/sdk.mdx new file mode 100644 index 0000000000..76a08eebf1 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/apis/sdk.mdx @@ -0,0 +1,79 @@ +# SDKs + +선호하는 언어로 빠르게 탐색하려면 오른쪽 사이드바를 사용하세요. + +## 개요 + +블록체인에 연결하는 방법에는 여러 가지가 있습니다: + +1. RPC 데이터 제공자 또는 기타 API: 대부분의 경우, 안정성과 보안에 _의존_해야 합니다. +2. ADNL 연결: [라이트서버](/participate/run-nodes/liteserver)에 연결합니다. 접근할 수 없는 경우도 있지만, 라이브러리에 구현된 특정 수준의 검증을 통해 거짓 정보를 제공할 수 없습니다. +3. Tonlib 바이너리: 라이트서버에 연결하여 모든 장점과 단점을 갖지만, 애플리케이션에 외부에서 컴파일된 동적 로드 라이브러리가 포함됩니다. +4. 오프체인 전용: 이러한 SDK는 셀을 생성하고 직렬화할 수 있으며, 이후 API로 전송할 수 있습니다. + +### TypeScript / JavaScript + +| 라이브러리 | 블록체인 연결 | 설명 | +| ----------------------------------------------- | --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | +| [ton](https://github.com/ton-org/ton) | RPC ([Orbs](https://www.orbs.com/ton-access/) / [Toncenter](https://toncenter.com/api/v2/) 등) | TON 블록체인에서 dApp 개발을 위한 지갑 래퍼가 있는 편리한 클라이언트 라이브러리 | +| [tonweb](https://github.com/toncenter/tonweb) | RPC ([Orbs](https://www.orbs.com/ton-access/) / [Toncenter](https://toncenter.com/api/v2/) 등) | 최소한의 외부 종속성이 있으며, 프로덕션에서 광범위하게 테스트된 구형 TON JS SDK | +| [tonkite/adnl](https://github.com/tonkite/adnl) | [ADNL](/develop/network/adnl-tcp) 네이티브 / WebSocket | ADNL TypeScript 구현체 | +| [tonutils](https://github.com/thekiba/tonutils) | 네이티브 [ADNL](/develop/network/adnl-tcp) | TON 생태계에서 애플리케이션을 구축하고 상호 작용하기 위한 TypeScript 기반 인터페이스. 네이티브 ADNL 종속성으로 인해 브라우저에서 블록체인 상호 작용에 사용할 수 없습니다. | +| [foton](https://foton.sh/) | RPC ([Orbs](https://www.orbs.com/ton-access/) / [Toncenter](https://toncenter.com/api/v2/) 등) | TON 지갑 및 블록체인과 상호 작용하기 위한 TypeScript 툴킷으로, 기존 솔루션(블루프린트 및 TON Connect)을 하나의 편리한 API | + +### Java + +| 라이브러리 | 블록체인 연결 | 설명 | +| ------------------------------------------ | ----------- | ----------------------------------- | +| [ton4j](https://github.com/neodix42/ton4j) | Tonlib 바이너리 | The Open Network (TON)를 위한 Java SDK | + +### Python + + + +| 라이브러리 | 블록체인 연결 | 설명 | +| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ---------------------------------------------------- | +| [pytoniq](https://github.com/yungwine/pytoniq) | 네이티브 ADNL | 네이티브 LiteClient 및 기타 ADNL 기반 프로토콜 구현이 포함된 Python SDK | +| [pytoniq-core](https://github.com/yungwine/pytoniq-core) | _오프체인 전용_ | 강력한 무료 전송 Python SDK | +| [pytonlib](https://github.com/toncenter/pytonlib) | Tonlib 바이너리 | TON 모노레포에서 가져온 바이너리 종속성을 사용하는 독립형 Python 라이브러리 | +| [mytonlib](https://github.com/igroman787/mytonlib) | 네이티브 ADNL | The Open Network를 다루기 위한 네이티브 Python SDK 라이브러리 | +| [TonTools](https://github.com/yungwine/TonTools) | RPC ([Orbs](https://www.orbs.com/ton-access/) / [Toncenter](https://toncenter.com/api/v2/) 등) | TON 블록체인과 상호 작용할 수 있는 고수준의 OOP 라이브러리 | +| [tonpy](https://github.com/disintar/tonpy) | 네이티브 ADNL | TON 블록체인과 상호 작용할 수 있는 데이터 구조 및 API를 제공하는 Python 패키지 | +| [tvm_valuetypes](https://github.com/toncenter/tvm_valuetypes) | _오프체인 전용_ | TVM 타입을 다루기 위한 유틸리티 모음 | +| [pytvm](https://github.com/yungwine/pytvm) | _오프체인_ | C++ 표준 에뮬레이터 바인딩을 사용하는 Python TVM 에뮬레이터 | + +### C# + +| 라이브러리 | 블록체인 연결 | 설명 | +| ----------------------------------------------------------------- | ---------------- | -------------------------------------- | +| [TonSdk.NET](https://github.com/continuation-team/TonSdk.NET) | 네이티브 ADNL 또는 RPC | The Open Network를 위한 네이티브 C# SDK | +| [justdmitry/TonLib.NET](https://github.com/justdmitry/TonLib.NET) | Tonlib 바이너리 | TON 모노레포에서 가져온 바이너리 종속성을 사용하는 .NET SDK | + +### Rust + +| 라이브러리 | 블록체인 연결 | 설명 | +| ------------------------------------------------------------- | ------------- | ------------------------------------------------------------------ | +| [tonlib-rs](https://github.com/ston-fi/tonlib-rs) | Tonlib 바이너리 | TON 모노레포에서 가져온 바이너리 종속성을 사용하는 Rust SDK | +| [getgems-io/ton-grpc](https://github.com/getgems-io/ton-grpc) | Tonlib binary | tonlibjson에 대한 Rust 바인딩(따라서 TON 모노레포의 바이너리에 종속됨) 및 이를 기반으로 구축된 서비스 | + +### Go + +| 라이브러리 | 블록체인 연결 | 설명 | +| -------------------------------------------------------- | ----------- | --------------------------------- | +| [tonutils-go](https://github.com/xssnick/tonutils-go) | 네이티브 ADNL | TON 블록체인과 상호 작용하기 위한 Golang 라이브러리 | +| [tongo](https://github.com/tonkeeper/tongo) | Native ADNL | TON 블록체인을 위한 Go 구현 라이브러리 | +| [tonlib-go](https://github.com/ton-blockchain/tonlib-go) | Tonlib 바이너리 | libtonlibjson에 대한 공식 바인딩 | + +### 기타 언어용 SDK + +| 라이브러리 | 언어 | 블록체인 연결 | 설명 | | +| --------------------------------------------------------------------------- | ------ | --------------------------------------------------------------------------------------------- | ------------------------------------------------ | - | +| [ton-kotlin](https://github.com/ton-community/ton-kotlin) | Kotlin | 네이티브 ADNL | The Open Network를 위한 Kotlin/Multiplatform SDK | | +| [tonlib-java](https://github.com/ton-blockchain/tonlib-java) | Java | Tonlib 바이너리 | Java/Scala/Kotlin 등에서 사용할 수 있는 TonLib에 대한 JVM 래퍼 | | +| [ayrat555/ton](https://github.com/ayrat555/ton) | Elixir | _오프체인 전용_ | Elixir용 TON SDK | | +| [C++ Tonlib](https://github.com/ton-blockchain/ton/tree/master/example/cpp) | C++ | Tonlib 바이너리 | TON 모노레포에서 제공하는 스마트 계약 상호 작용에 대한 공식 예제 | . | +| [Java Tonlib](https://github.com/ton-blockchain/tonlib-java) | Java | Tonlib 바이너리 | TON 모노레포에서 제공하는 스마트 계약 상호 작용에 대한 공식 예제 | | +| [labraburn/SwiftyTON](https://github.com/labraburn/SwiftyTON) | Swift | Tonlib 바이너리 | 비동기/대기를 사용하는 tonlib에 대한 네이티브 Swift 래퍼 | | +| [tonlib-xcframework](https://github.com/labraburn/tonlib-xcframework) | Swift | Tonlib 바이너리 | iOS의 모든 아키텍처용 Tonlib 빌드 도우미 | | +| [labraburn/node-tonlib](https://github.com/labraburn/node-tonlib) | NodeJS | Tonlib 바이너리 | tonlibjson을 사용하기 위한 NodeJS용 C++ 애드온 | | +| [olifanton/ton](https://github.com/olifanton/ton) | PHP | RPC ([Orbs](https://www.orbs.com/ton-access/) / [Toncenter](https://toncenter.com/api/v2/) 등) | 표준 프리미티브 및 계약 세트가 포함된 PHP SDK | | diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md new file mode 100644 index 0000000000..a7b575e742 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md @@ -0,0 +1,586 @@ +import Button from '@site/src/components/button' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# 결제 처리 + +이 페이지는 TON 블록체인에서 `디지털 자산`을 처리하는 방법을 **설명**합니다 (전송 및 수신). 주로 `TON 코인`과 관련된 내용을 다루지만, **이론적인 부분**은 `jettons`만 처리하고자 할 때에도 **중요**합니다. + +## 지갑 스마트 컨트랙트 + +지갑 스마트 계약은 TON 네트워크에서 블록체인 외부의 사용자들이 블록체인 내의 엔티티와 상호작용할 수 있도록 하는 계약입니다. 일반적으로 다음 세 가지 문제를 해결합니다: + +- 소유자 인증: 소유자가 아닌 사용자의 요청은 처리 및 수수료 지불을 거부합니다. +- 재생 보호: 동일한 요청을 반복적으로 실행하는 것을 금지합니다. 예를 들어, 자산을 다른 스마트 계약으로 전송하는 경우. +- 다른 스마트 계약과의 임의 상호작용을 시작합니다. + +첫 번째 문제에 대한 표준 해결책은 공개 키 암호화입니다. `지갑`은 공개 키를 저장하고, 요청이 소유자만 알고 있는 개인 키로 서명되었는지 확인합니다. + +세 번째 문제에 대한 해결책은 일반적으로 요청에 네트워크에 보낼 내부 메시지가 포함된다는 점에서 동일합니다. 하지만 재생 보호를 위해서는 몇 가지 다른 접근 방식이 있습니다. + +### Seqno 기반 지갑 + +Seqno 기반 지갑은 메시지를 순차적으로 처리하는 가장 단순한 접근 방식을 따릅니다. 각 메시지에는 `seqno`라는 정수가 포함되어 있으며, 이는 `지갑` 스마트 계약에 저장된 카운터와 일치해야 합니다. `지갑`은 각 요청에서 카운터를 업데이트하여 동일한 요청이 두 번 처리되지 않도록 합니다. Seqno 기반 지갑은 공개적으로 사용 가능한 메서드에 따라 몇 가지 버전이 있습니다: 요청을 만료 시간으로 제한하는 기능, 동일한 공개 키로 여러 지갑을 사용하는 기능 등. 하지만 이 접근 방식은 요청을 하나씩 전송해야 한다는 본질적인 요구 사항이 있으며, seqno 순서에 공백이 생기면 이후의 모든 요청을 처리할 수 없게 됩니다. + +### 고부하 지갑 + +이 지갑 유형은 스마트 계약 저장소에 만료되지 않은 요청 식별자를 저장하는 방식에 기반한 접근 방식을 따릅니다. 이 방식에서는 모든 요청이 이미 처리된 요청과 중복 여부를 확인하고, 중복이 감지되면 요청을 삭제합니다. 만료로 인해 스마트 계약은 모든 요청을 영구적으로 저장하지 않으며, 만료 제한으로 인해 처리할 수 없는 요청은 제거됩니다. 이 지갑에 대한 요청은 서로 간섭하지 않고 병렬로 전송될 수 있습니다. 하지만 이 접근 방식은 요청 처리에 대한 더 정교한 모니터링이 필요합니다. + +### 지갑 배포 + +TonLib를 통해 지갑을 배포하려면: + +1. [createNewKey](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L244) 또는 그 래퍼 함수를 통해 개인/공개 키 쌍을 생성합니다 (예시: [tonlib-go](https://github.com/mercuryoio/tonlib-go/tree/master/v2#create-new-private-key)). 개인 키는 로컬에서 생성되며, 호스트 머신을 벗어나지 않습니다. +2. 하나의 `지갑` 활성화에 해당하는 [InitialAccountWallet](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L62) 구조를 형성합니다. 현재는 `wallet.v3`, `wallet.v4`, `wallet.highload.v1`, `wallet.highload.v2`가 사용 가능합니다. +3. [getAccountAddress](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L283) 메서드를 통해 새 `지갑` 스마트 계약의 주소를 계산합니다. 기본 개정 `0`을 사용하는 것을 권장하며, 처리 및 저장 비용을 낮추기 위해 `basechain workchain=0`에 지갑을 배포하는 것이 좋습니다. +4. 계산된 주소로 약간의 Toncoin을 전송합니다. 이 주소는 아직 코드가 없기 때문에 수신 메시지를 처리할 수 없으므로 `non-bounce` 모드로 전송해야 합니다. `non-bounce` 플래그는 처리 실패 시에도 돈이 반송되지 않아야 함을 나타냅니다. 특히 큰 금액을 포함하는 거래에서는 `non-bounce` 플래그 사용을 권장하지 않으며, 반송 메커니즘은 실수로부터 어느 정도 보호를 제공합니다. +5. 원하는 [action](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L154)을 형성합니다. 예를 들어 배포만을 위한 `actionNoop`을 사용할 수 있습니다. 그런 다음 [createQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L292) 및 [sendQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L300)로 블록체인과 상호작용을 시작합니다. +6. 몇 초 후 [getAccountState](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L288) 메서드를 사용하여 계약을 확인합니다. + +:::tip +[지갑 튜토리얼](/develop/smart-contracts/tutorials/wallet#-deploying-a-wallet)에서 자세히 읽어보세요. +::: + +### 지갑 주소 유효성 확인 + +대부분의 SDK는 주소를 확인하도록 되어 있으며, 보통 지갑 생성 또는 거래 준비 과정에서 이를 확인합니다. 따라서 별도의 복잡한 단계를 수행할 필요는 거의 없습니다. + + + + + +```js + const TonWeb = require("tonweb") + TonWeb.utils.Address.isValid('...') +``` + + + + +```python +package main + +import ( + "fmt" + "github.com/xssnick/tonutils-go/address" +) + +if _, err := address.ParseAddr("EQCD39VS5j...HUn4bpAOg8xqB2N"); err != nil { + return errors.New("invalid address") +} +``` + + + + +```javascript +try { + Address.of("..."); + } catch (e) { + // not valid address +} +``` + + + + +```javascript + try { + AddrStd("...") + } catch(e: IllegalArgumentException) { + // not valid address + } +``` + + + + +:::tip +[스마트 계약 주소](/learn/overviews/addresses) 페이지에서 전체 주소 설명을 확인하세요. +::: + +## 송금 작업 + +### 컨트랙트의 거래 확인 + +컨트랙트의 거래는 [getTransactions](https://toncenter.com/api/v2/#/accounts/get_transactions_getTransactions_get) 메서드를 통해 얻을 수 있습니다. 이 메서드는 `last_transaction_id`와 그 이전의 10개의 거래를 가져옵니다. 모든 수신 거래를 처리하려면 다음 단계를 따르세요: + +1. 최신 `last_transaction_id`는 [getAddressInformation](https://toncenter.com/api/v2/#/accounts/get_address_information_getAddressInformation_get)에서 얻을 수 있습니다. +2. `getTransactions` 메서드를 사용하여 10개의 거래 목록을 로드합니다. +3. 수신 메시지에 빈 소스가 없는 거래를 처리하고, 목적지가 계정 주소와 일치하는지 확인합니다. +4. 다음 10개의 거래를 로드하고, 2, 3, 4 단계를 반복하여 모든 수신 거래를 처리합니다. + +### 수신/발신 거래 확인 + +거래 처리 중 메시지 흐름을 추적할 수 있습니다. 메시지 흐름은 DAG이므로, 현재 거래를 [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) 메서드를 사용하여 가져오고, [tryLocateResultTx](https://testnet.toncenter.com/api/v2/#/transactions/get_try_locate_result_tx_tryLocateResultTx_get)에서 `out_msg`로 수신 거래를 찾거나 [tryLocateSourceTx](https://testnet.toncenter.com/api/v2/#/transactions/get_try_locate_source_tx_tryLocateSourceTx_get)에서 `in_msg`로 발신 거래를 찾을 수 있습니다. + + + + +```ts +import { TonClient, Transaction } from '@ton/ton'; +import { getHttpEndpoint } from '@orbs-network/ton-access'; +import { CommonMessageInfoInternal } from '@ton/core'; + +async function findIncomingTransaction(client: TonClient, transaction: Transaction): Promise { + const inMessage = transaction.inMessage?.info; + if (inMessage?.type !== 'internal') return null; + return client.tryLocateSourceTx(inMessage.src, inMessage.dest, inMessage.createdLt.toString()); +} + +async function findOutgoingTransactions(client: TonClient, transaction: Transaction): Promise { + const outMessagesInfos = transaction.outMessages.values() + .map(message => message.info) + .filter((info): info is CommonMessageInfoInternal => info.type === 'internal'); + + return Promise.all( + outMessagesInfos.map((info) => client.tryLocateResultTx(info.src, info.dest, info.createdLt.toString())), + ); +} + +async function traverseIncomingTransactions(client: TonClient, transaction: Transaction): Promise { + const inTx = await findIncomingTransaction(client, transaction); + // now you can traverse this transaction graph backwards + if (!inTx) return; + await traverseIncomingTransactions(client, inTx); +} + +async function traverseOutgoingTransactions(client: TonClient, transaction: Transaction): Promise { + const outTxs = await findOutgoingTransactions(client, transaction); + // do smth with out txs + for (const out of outTxs) { + await traverseOutgoingTransactions(client, out); + } +} + +async function main() { + const endpoint = await getHttpEndpoint({ network: 'testnet' }); + const client = new TonClient({ + endpoint, + apiKey: '[API-KEY]', + }); + + const transaction: Transaction = ...; // Obtain first transaction to start traversing + await traverseIncomingTransactions(client, transaction); + await traverseOutgoingTransactions(client, transaction); +} + +main(); +``` + + + + +### 결제 전송 + +1. 서비스는 `지갑`을 배포하고, 스토리지 비용으로 인한 계약 파괴를 방지하기 위해 이를 자금으로 유지해야 합니다. 스토리지 비용은 일반적으로 연간 1 Toncoin 미만입니다. +2. 서비스는 사용자로부터 `destination_address`와 선택적 `comment`를 받아야 합니다. 같은 (`destination_address`, `value`, `comment`) 집합을 가진 미완료 발신 결제를 금지하거나, 결제가 확인된 후에만 다음 결제를 시작하도록 적절히 예약할 것을 권장합니다. +3. `comment`를 텍스트로 작성한 [msg.dataText](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L103)를 형성합니다. +4. `destination_address`, 빈 `public_key`, 금액, `msg.dataText`를 포함한 [msg.message](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L113)를 형성합니다. +5. 발신 메시지 세트를 포함한 [Action](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L154)을 형성합니다. +6. 발신 결제를 전송하려면 [createQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L292) 및 [sendQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L300) 쿼리를 사용합니다. +7. 서비스는 `wallet` 계약에 대해 [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) 메서드를 정기적으로 폴링해야 합니다. (`destination_address`, `value`, `comment`)와 일치하는 확인된 거래를 통해 결제가 완료되었음을 표시할 수 있으며, 사용자에게 해당 거래 해시와 lt(논리 시간)를 표시할 수 있습니다. +8. `v3`의 `high-load` 지갑에 대한 요청의 만료 시간은 기본적으로 60초입니다. 이 시간이 지나면 처리되지 않은 요청은 네트워크에 안전하게 다시 보낼 수 있습니다(3~6단계 참조). + +### 트랜잭션 ID 가져오기 + +트랜잭션에 대한 더 많은 정보를 얻으려면 사용자가 [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) 기능을 통해 블록체인을 스캔해야 한다는 것이 명확하지 않을 수 있습니다. +메시지를 보낸 직후에 트랜잭션 ID를 즉시 가져오는 것은 불가능합니다. 트랜잭션이 먼저 블록체인 네트워크에 의해 확인되어야 합니다. +필요한 파이프라인을 이해하려면 [Send payments](https://docs.ton.org/develop/dapps/asset-processing/#send-payments)를 주의 깊게 읽고, 특히 7번째 포인트를 확인하세요. + +## 송장 기반 접근 방식 + +첨부된 댓글을 기반으로 결제를 수락하려면 서비스는 다음을 수행해야 합니다. + +1. `wallet` 컨트랙트를 배포합니다. +2. 각 사용자에게 고유한 `invoice`를 생성합니다. uuid32의 문자열 표현이면 충분합니다. +3. 사용자는 `invoice`를 댓글로 첨부하여 Toncoin을 서비스의 `wallet` 컨트랙트로 전송하도록 지시받아야 합니다. +4. 서비스는 `wallet` 컨트랙트에 대해 [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) 메서드를 정기적으로 폴링해야 합니다. +5. 새로운 트랜잭션에 대해, 들어오는 메시지를 추출하고, `comment`를 데이터베이스와 일치시킨 후 **들어오는 메시지 값**을 사용자의 계정에 입금합니다. + +메시지가 컨트랙트에 도달할 때 거래를 구문 분석하여 **들어오는 메시지 값**을 계산해야 합니다. 거래는 [getTransactions](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L268)으로 얻을 수 있습니다. 들어오는 지갑 거래의 경우 하나의 들어오는 메시지와 0개의 나가는 메시지로 구성된 데이터가 정확합니다. 그렇지 않으면 지갑에 외부 메시지가 전송되어 소유자가 Toncoin을 소비하거나, 지갑이 배포되지 않아 들어오는 트랜잭션이 반송됩니다. + +어쨌든 일반적으로 메시지가 컨트랙트에 가져오는 금액은 들어오는 메시지의 값에서 나가는 메시지들의 값의 합계와 수수료를 뺀 값입니다: `value_{in_msg} - SUM(value_{out_msg}) - fee`. 기술적으로 거래 표현에는 `fee`라는 이름을 가진 세 가지 다른 필드가 있습니다: `fee`, `storage_fee`, 및 `other_fee`, 즉 총 수수료, 저장 비용과 관련된 수수료, 트랜잭션 처리와 관련된 수수료입니다. 첫 번째 것만 사용해야 합니다. + +### TON Connect를 사용한 송장 + +여러 결제/트랜잭션을 세션 내에서 서명해야 하거나 지갑과의 연결을 일정 시간 유지해야 하는 dApp에 적합합니다. + +- ✅ 지갑과의 영구적인 통신 채널, 사용자 주소 정보가 제공됩니다. + +- ✅ 사용자는 QR 코드를 한 번만 스캔하면 됩니다. + +- ✅ 사용자가 지갑에서 거래를 확인했는지 여부를 확인할 수 있으며, 반환된 BOC로 트랜잭션을 추적할 수 있습니다. + +- ✅ 다양한 플랫폼용 SDK 및 UI 키트가 제공됩니다. + +- ❌ 한 번의 결제만 필요하다면 사용자는 두 가지 작업을 해야 합니다: 지갑을 연결하고 트랜잭션을 확인합니다. + +- ❌ 통합이 ton:// 링크보다 더 복잡합니다. + +```mdx-code-block + +``` + +### ton:// 링크를 이용한 송장 + +:::warning +Ton 링크는 더 이상 사용되지 않으며, 사용을 피하는 것이 좋습니다. +::: + +단순한 사용자 흐름을 위한 쉬운 통합이 필요할 경우, ton:// 링크를 사용하는 것이 적합합니다. +일회성 결제 및 송장에 가장 적합합니다. + +```bash +ton://transfer/? + [nft=&] + [fee-amount=&] + [forward-amount=] +``` + +- ✅ 쉬운 통합 + +- ✅ 지갑을 연결할 필요가 없습니다. + +- ❌ 각 결제마다 새로운 QR 코드를 스캔해야 합니다. + +- ❌ 사용자가 트랜잭션을 서명했는지 여부를 추적할 수 없습니다. + +- ❌ 사용자의 주소 정보가 없습니다. + +- ❌ 그러한 링크를 클릭할 수 없는 플랫폼(예: Telegram 데스크톱 클라이언트에서 봇의 메시지)의 경우 우회 방법이 필요합니다. + +[ton 링크에 대해 더 알아보기](https://github.com/tonkeeper/wallet-api#payment-urls) + +## 탐색기 + +블록체인 탐색기는 https://tonscan.org입니다. + +탐색기에서 트랜잭션 링크를 생성하려면, 서비스는 lt(논리 시간), 트랜잭션 해시, 계정 주소(계정 주소는 [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) 메서드를 통해 얻은 lt와 txhash로 검색)를 얻어야 합니다. https://tonscan.org 및 https://explorer.toncoin.org는 다음 형식으로 해당 tx 페이지를 보여줄 수 있습니다: + +`https://tonviewer.com/transaction/{txhash as base64url}` + +`https://tonscan.org/tx/{lt as int}:{txhash as base64url}:{account address}` + +`https://explorer.toncoin.org/transaction?account={account address}<={lt as int}&hash={txhash as base64url}` + +## 모범 사례 + +### 지갑 생성 + + + + +- **toncenter:** + - [지갑 생성 + 지갑 주소 가져오기](https://github.com/toncenter/examples/blob/main/common.js) + +- **ton-community/ton:** + - [지갑 생성 + 잔액 확인](https://github.com/ton-community/ton#usage) + + + + + +- **xssnick/tonutils-go:** + - [지갑 생성 + 잔액 확인](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#wallet) + + + + + +- **psylopunk/pythonlib:** + - [지갑 생성 + 지갑 주소 가져오기](https://github.com/psylopunk/pytonlib/blob/main/examples/generate_wallet.py) +- **yungwine/pytoniq:** + +```py +import asyncio + +from pytoniq.contract.wallets.wallet import WalletV4R2 +from pytoniq.liteclient.balancer import LiteBalancer + + +async def main(): + provider = LiteBalancer.from_mainnet_config(2) + await provider.start_up() + + mnemonics, wallet = await WalletV4R2.create(provider) + print(f"{wallet.address=} and {mnemonics=}") + + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + + + + +### Toncoin 입금 (Toncoins 받기) + + + + +- **toncenter:** + - [토큰 입금 처리](https://github.com/toncenter/examples/blob/main/deposits.js) + - [다중 지갑의 토큰 입금 처리](https://github.com/toncenter/examples/blob/main/deposits-multi-wallets.js) + + + + + +- **xssnick/tonutils-go:** + +
+입금 확인 + +```go +package main + +import ( + "context" + "encoding/base64" + "log" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/liteclient" + "github.com/xssnick/tonutils-go/ton" +) + +const ( + num = 10 +) + +func main() { + client := liteclient.NewConnectionPool() + err := client.AddConnectionsFromConfigUrl(context.Background(), "https://ton.org/global.config.json") + if err != nil { + panic(err) + } + + api := ton.NewAPIClient(client, ton.ProofCheckPolicyFast).WithRetry() + + accountAddr := address.MustParseAddr("0QA__NJI1SLHyIaG7lQ6OFpAe9kp85fwPr66YwZwFc0p5wIu") + + // we need fresh block info to run get methods + b, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + log.Fatal(err) + } + + // we use WaitForBlock to make sure block is ready, + // it is optional but escapes us from liteserver block not ready errors + res, err := api.WaitForBlock(b.SeqNo).GetAccount(context.Background(), b, accountAddr) + if err != nil { + log.Fatal(err) + } + + lastTransactionId := res.LastTxHash + lastTransactionLT := res.LastTxLT + + headSeen := false + + for { + trxs, err := api.ListTransactions(context.Background(), accountAddr, num, lastTransactionLT, lastTransactionId) + if err != nil { + log.Fatal(err) + } + + for i, tx := range trxs { + // should include only first time lastTransactionLT + if !headSeen { + headSeen = true + } else if i == 0 { + continue + } + + if tx.IO.In == nil || tx.IO.In.Msg.SenderAddr().IsAddrNone() { + // external message should be omitted + continue + } + + if tx.IO.Out != nil { + // no outgoing messages - this is incoming Toncoins + continue + } + + // process trx + log.Printf("found in transaction hash %s", base64.StdEncoding.EncodeToString(tx.Hash)) + } + + if len(trxs) == 0 || (headSeen && len(trxs) == 1) { + break + } + + lastTransactionId = trxs[0].Hash + lastTransactionLT = trxs[0].LT + } +} +``` + +
+
+ + + +- **yungwine/pytoniq:** + +입금 확인 + +```python +import asyncio + +from pytoniq_core import Transaction + +from pytoniq import LiteClient, Address + +MY_ADDRESS = Address("kf8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM_BP") + + +async def main(): + client = LiteClient.from_mainnet_config(ls_i=0, trust_level=2) + + await client.connect() + + last_block = await client.get_trusted_last_mc_block() + + _account, shard_account = await client.raw_get_account_state(MY_ADDRESS, last_block) + assert shard_account + + last_trans_lt, last_trans_hash = ( + shard_account.last_trans_lt, + shard_account.last_trans_hash, + ) + + while True: + print(f"Waiting for{last_block=}") + + transactions = await client.get_transactions( + MY_ADDRESS, 1024, last_trans_lt, last_trans_hash + ) + toncoin_deposits = [tx for tx in transactions if filter_toncoin_deposit(tx)] + print(f"Got {len(transactions)=} with {len(toncoin_deposits)=}") + + for deposit_tx in toncoin_deposits: + # Process toncoin deposit transaction + print(deposit_tx.cell.hash.hex()) + + last_trans_lt = transactions[0].lt + last_trans_hash = transactions[0].cell.hash + + +def filter_toncoin_deposit(tx: Transaction): + if tx.out_msgs: + return False + + if tx.in_msg: + return False + + return True + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + +
+ +### Toncoin 출금 (Toncoins 보내기) + + + + +- **toncenter:** + - [지갑에서 Toncoins를 일괄 인출하기](https://github.com/toncenter/examples/blob/main/withdrawals-highload-batch.js) + - [지갑에서 Toncoins 인출하기](https://github.com/toncenter/examples/blob/main/withdrawals-highload.js) + +- **ton-community/ton:** + - [지갑에서 Toncoins 인출하기](https://github.com/ton-community/ton#usage) + + + + + +- **xssnick/tonutils-go:** + - [지갑에서 Toncoins 인출하기](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#wallet) + + + + + +- **psylopunk/pythonlib:** + - [지갑에서 Toncoins 인출하기](https://github.com/psylopunk/pytonlib/blob/main/examples/transactions.py) + +- **yungwine/pytoniq:** + +```python +import asyncio + +from pytoniq_core import Address +from pytoniq.contract.wallets.wallet import WalletV4R2 +from pytoniq.liteclient.balancer import LiteBalancer + + +MY_MNEMONICS = "one two tree ..." +DESTINATION_WALLET = Address("Destination wallet address") + + +async def main(): + provider = LiteBalancer.from_mainnet_config() + await provider.start_up() + + wallet = await WalletV4R2.from_mnemonic(provider, MY_MNEMONICS) + + await wallet.transfer(DESTINATION_WALLET, 5) + + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + + + + +### 컨트랙트의 트랜잭션 가져오기 + + + + +- **ton-community/ton:** + - [getTransaction 메소드가 있는 클라이언트](https://github.com/ton-community/ton/blob/master/src/client/TonClient.ts) + + + + + +- **xssnick/tonutils-go:** + - [트랜잭션 가져오기](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#account-info-and-transactions) + + + + + +- **psylopunk/pythonlib:** + - [트랜잭션 가져오기](https://github.com/psylopunk/pytonlib/blob/main/examples/transactions.py) +- **yungwine/pytoniq:** + - [트랜잭션 가져오기](https://github.com/yungwine/pytoniq/blob/master/examples/transactions.py) + + + + + +## SDKs + +다양한 언어(JS, Python, Golang, C#, Rust 등)에 대한 SDK 목록은 [여기](/develop/dapps/apis/sdk)에서 확인할 수 있습니다. diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md new file mode 100644 index 0000000000..e2306d9008 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md @@ -0,0 +1,1141 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Button from '@site/src/components/button'; + +# TON Jetton 처리 + +:::info +독자가 이 문서를 명확하게 이해하기 위해서는 [자산 처리 섹션](/develop/dapps/asset-processing/)에 설명된 자산 처리의 기본 원칙을 숙지하고 있어야 합니다. +::: + +Jetton은 TON 블록체인에서 사용되는 토큰으로, 이더리움의 ERC-20 토큰과 유사하게 생각할 수 있습니다. + +이 분석에서는 Jetton의 [동작](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) 및 [메타데이터](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md)에 대한 공식 표준을 자세히 살펴봅니다. +샤딩 중심의 비공식적인 Jetton 아키텍처 개요는 [Jetton 해부 블로그 게시물](https://blog.ton.org/how-to-shard-your-ton-smart-contract-and-why-studying-the-anatomy-of-tons-jettons)에서 확인할 수 있습니다. + +또한, Jetton 인출을 처리하는 두 가지 접근 방식이 있다는 점을 염두에 두어야 합니다: + +- [메모 입금](https://github.com/toncenter/examples/blob/main/deposits-jettons.js) - 하나의 입금 지갑을 유지하고, 사용자가 메모를 추가하여 시스템에서 식별될 수 있습니다. 이를 통해 블록체인 전체를 스캔할 필요는 없지만, 사용자에게는 다소 불편할 수 있습니다. +- [메모 없는 입금](https://github.com/gobicycle/bicycle) - 이 솔루션도 존재하지만 통합이 더 어렵습니다. 그러나 이 경로를 선택하고자 한다면 저희가 도움을 드릴 수 있습니다. 이 방법을 구현하기로 결정하기 전에 저희에게 알려주시기 바랍니다. + +## Jetton 아키텍처 + +TON의 표준화된 토큰은 다음 스마트 계약 세트를 사용하여 구현됩니다: + +- [Jetton 마스터](https://github.com/ton-blockchain/token-contract/blob/main/ft/jetton-minter.fc) 스마트 컨트랙트 +- [Jetton 지갑](https://github.com/ton-blockchain/token-contract/blob/main/ft/jetton-wallet.fc) 스마트 컨트랙트 + +

+
+ contracts scheme +

+ +## Jetton 마스터 스마트 계약 + +Jetton 마스터 스마트 계약은 Jetton에 대한 일반 정보를 저장합니다 (총 공급량, 메타데이터 링크 또는 메타데이터 자체 포함). + +:::warning Jetton 사기에 주의 + +어떤 사용자가 가치 있는 Jetton의 **복제본**을 임의의 이름, 티커, 이미지 등을 사용하여 **원본과 거의 동일하게** 만들 수 있습니다. 다행히도, 복제된 Jetton은 **주소로 구별**할 수 있으며 쉽게 식별할 수 있습니다. +`TON`이라는 `심볼`을 가진 Jetton 또는 `ERROR`, `SYSTEM` 등 시스템 알림 메시지를 포함하는 Jetton에 주의하십시오. Jetton이 TON 전송, 시스템 알림 등과 혼동되지 않도록 인터페이스에 표시되도록 하십시오. 때로는 `심볼`, `이름`, `이미지`조차도 사용자를 혼동시키기 위해 원본과 거의 동일하게 만들어질 수 있습니다. + +TON 사용자의 사기 가능성을 없애기 위해 특정 Jetton 유형에 대한 **원본 Jetton 주소**(Jetton 마스터 계약)를 조회하거나 **프로젝트의 공식 소셜 미디어** 채널 또는 웹사이트를 통해 **정확한 정보**를 확인하십시오. [Tonkeeper ton-assets 리스트](https://github.com/tonkeeper/ton-assets)로 자산을 확인하여 사기 가능성을 제거하십시오. +::: + +### Jetton 데이터 조회 + +구체적인 Jetton 데이터를 조회하려면 계약의 *get* 메서드인 `get_jetton_data()`를 사용하십시오. + +이 메서드는 다음 데이터를 반환합니다: + +| 이름 | 유형 | 설명 | +| -------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `total_supply` | `int` | 발행된 Jetton의 총 수량을 불가분 단위로 측정한 값. | +| `mintable` | `int` | 새로운 Jetton을 발행할 수 있는지 여부를 나타냅니다. 이 값은 -1 (발행 가능) 또는 0 (발행 불가)입니다. | +| `admin_address` | `slice` | | +| `jetton_content` | `cell` | [TEP-64](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md)에 따라 데이터가 포함되어 있으며, 자세한 내용은 [Jetton 메타데이터 분석 페이지](/develop/dapps/asset-processing/metadata)를 참조하십시오. | +| `jetton_wallet_code` | `cell` | | + +이를 [Toncenter API](https://toncenter.com/api/v3/#/default/get_jetton_masters_api_v3_jetton_masters_get) 또는 [SDK](https://docs.ton.org/develop/dapps/apis/sdk) 중 하나를 통해 호출할 수 있습니다. + + + + +> [Toncenter API](https://toncenter.com/api/v3/#/default/get_jetton_masters_api_v3_jetton_masters_get)에서 `jetton/masters` 메서드를 실행하십시오. + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: ""}); +const data = await jettonMinter.getJettonData(); +console.log('Total supply:', data.totalSupply.toString()); +console.log('URI to off-chain metadata:', data.jettonContentUri); +``` + + + + +### Jetton 민터 + +앞서 언급했듯이, Jetton은 `발행 가능` 또는 `발행 불가`일 수 있습니다. + +발행 불가인 경우, 추가 토큰을 발행할 수 없습니다. 첫 Jetton을 발행하려면 [첫 Jetton 발행](/develop/dapps/tutorials/jetton-minter) 페이지를 참조하십시오. + +발행 가능인 경우, 추가 Jetton을 발행할 수 있는 [민터 컨트랙트](https://github.com/ton-blockchain/minter-contract/blob/main/contracts/jetton-minter.fc)에 특별한 함수가 있습니다. 이 함수는 관리 주소에서 지정된 opcode로 `내부 메시지`를 보내 호출할 수 있습니다. + +Jetton 관리자가 Jetton 생성 제한을 원할 경우, 세 가지 방법이 있습니다: + +1. 컨트랙트 코드를 업데이트할 수 없거나 원하지 않는 경우, 관리자가 현재 관리 주소를 영 주소로 전송해야 합니다. 이렇게 하면 유효한 관리자가 없게 되어 누구도 Jetton을 발행할 수 없습니다. 그러나 Jetton 메타데이터 변경도 불가능해집니다. +2. 소스 코드에 접근하여 변경할 수 있는 경우, 호출 후 모든 발행 프로세스를 중단하는 플래그를 설정하는 메서드를 계약에 생성하고, 발행 함수에서 이 플래그를 확인하는 문을 추가할 수 있습니다. +3. 컨트랙트 코드를 업데이트할 수 있는 경우, 이미 배포된 컨트랙트의 코드를 업데이트하여 제한을 추가할 수 있습니다. + +## Jetton 지갑 스마트 컨트랙트 + +`Jetton 지갑` 컨트랙트는 **전송**, **수신** 및 **소각**에 사용됩니다. 각 *Jetton 지갑 컨트랙트* 는 특정 사용자의 지갑 잔액 정보를 저장합니다. +특정 경우, Jetton 지갑은 각 Jetton 유형의 개별 Jetton 보유자에게 사용됩니다. + +`Jetton 지갑`은 TON코인 자산만을 저장하고 블록체인과 상호작용하기 위한 지갑 (예: v3R2 지갑, 하이로드 지갑 등)과 **혼동해서는 안됩니다**. +이들은 **특정 Jetton 유형**만을 지원하고 관리하는 역할을 합니다. + +### Jetton Wallet 배포 + +지갑 간에 `jetton 전송`을 할 때, 트랜잭션(메시지)은 네트워크 **가스 요금** 및 Jetton 지갑 컨트랙트 코드에 따른 작업 실행을 위해 일정량의 TON을 필요로 합니다. 이는 **수신자가 jetton을 받기 전에 jetton 지갑을 배포할 필요가 없다는 것**을 의미합니다. 송신자가 필요한 가스 요금을 지불할 만큼 충분한 TON을 지갑에 보유하고 있는 한, 수신자의 jetton 지갑은 자동으로 배포됩니다. + +### 특정 사용자의 Jetton 지갑 주소 조회 + +`소유자 주소`(TON 지갑 주소)를 사용하여 `jetton 지갑` `주소`를 조회하려면, `Jetton 마스터 계약`의 `get_wallet_address(slice owner_address)` 메서드를 사용합니다. + + + + +> [Toncenter API](https://toncenter.com/api/v3/#/default/run_get_method_api_v3_runGetMethod_post)의 `/runGetMethod` 메서드를 통해 `get_wallet_address(slice owner_address)`를 실행하십시오. + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: ""}); +const address = await jettonMinter.getJettonWalletAddress(new TonWeb.utils.Address("")); +// It is important to always check that wallet indeed is attributed to desired Jetton Master: +const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider, { + address: jettonWalletAddress +}); +const jettonData = await jettonWallet.getData(); +if (jettonData.jettonMinterAddress.toString(false) !== new TonWeb.utils.Address(info.address).toString(false)) { + throw new Error('jetton minter address from jetton wallet doesnt match config'); +} + +console.log('Jetton wallet address:', address.toString(true, true, true)); +``` + + + + +### 특정 Jetton 지갑의 데이터 조회 + +지갑의 계좌 잔액, 소유자 식별 정보 및 특정 jetton 지갑 계약과 관련된 기타 정보를 조회하려면 jetton 지갑 계약 내의 `get_wallet_data()` get 메서드를 사용하십시오. + +이 메서드는 다음 데이터를 반환합니다: + +| 이름 | 유형 | +| -------------------- | --------- | +| `balance` | int | +| `owner` | 슬라이스slice | +| `jetton` | slice | +| `jetton_wallet_code` | cell | + + + + +> [Toncenter API](https://toncenter.com/api/v3/#/default/get_jetton_wallets_api_v3_jetton_wallets_get)의 `/jetton/wallets` get 메서드를 사용하여 이전에 디코딩된 jetton 지갑 데이터를 조회하십시오. + + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const walletAddress = "EQBYc3DSi36qur7-DLDYd-AmRRb4-zk6VkzX0etv5Pa-Bq4Y"; +const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider,{address: walletAddress}); +const data = await jettonWallet.getData(); +console.log('Jetton balance:', data.balance.toString()); +console.log('Jetton owner address:', data.ownerAddress.toString(true, true, true)); +// It is important to always check that Jetton Master indeed recognize wallet +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: data.jettonMinterAddress.toString(false)}); +const expectedJettonWalletAddress = await jettonMinter.getJettonWalletAddress(data.ownerAddress.toString(false)); +if (expectedJettonWalletAddress.toString(false) !== new TonWeb.utils.Address(walletAddress).toString(false)) { + throw new Error('jetton minter does not recognize the wallet'); +} + +console.log('Jetton master address:', data.jettonMinterAddress.toString(true, true, true)); +``` + + + + +## Jetton 지갑 간의 통신 개요 + +Jetton 지갑과 TON 지갑 간의 통신은 다음 통신 순서를 통해 이루어집니다: + +![](/img/docs/asset-processing/jetton_transfer.svg) + +#### 메시지 0 + +`발신자 -> 발신자의 jetton 지갑`. *전송* 메시지에는 다음 데이터가 포함됩니다: + +| 이름 | 유형 | 설명 | +| ---------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| `query_id` | uint64 | 애플리케이션이 `전송`, `전송 알림`, `과잉` 메시지 유형을 서로 연결할 수 있게 합니다. 이 프로세스가 올바르게 수행되도록 하려면 **항상 고유한 query id를 사용하는 것이 좋습니다**. | +| `amount` | coins | 메시지와 함께 전송될 총 `ton 코인` 금액. | +| `destination` | address | Jetton의 새로운 소유자의 주소. | +| `response_destination` | address | 과잉 메시지로 남은 ton 코인을 반환할 지갑 주소. | +| `custom_payload` | maybe cell | 항상 크기가 >= 1 비트. (보낸 사람 또는 받는 사람의 jetton 지갑의 내부 논리에서 사용되는) 사용자 정의 데이터. | +| `forward_ton_amount` | coins | 0이어야 합니다. 이는 **`amount` 값의 일부**이며 **`amount`보다 작아야 합니다**. | +| `forward_payload` | maybe cell | 항상 크기가 >= 1 비트. 처음 32비트가 0x0이면 단순한 메시지입니다. | + +#### 메시지 2' + +`수취인의 jetton 지갑 -> 수취인`. 전송 알림 메시지. **단,** `forward_ton_amount`가 0이 아닌 경우에만 전송됩니다. 다음 데이터를 포함합니다: + +| 이름 | 유형 | +| ----------------- | ------- | +| `query_id` | uint64 | +| `amount` | coins | +| `sender` | address | +| `forward_payload` | cell | + +여기서 `sender` 주소는 Alice의 `Jetton 지갑`의 주소입니다. + +#### 메시지 2'' + +`수취인의 jetton 지갑 -> 발신자`. 과잉 메시지 본문. **요금을 지불한 후 남은 ton 코인이 있는 경우에만 전송됩니다.** 다음 데이터를 포함합니다: + +| 이름 | 유형 | +| ---------- | ------ | +| `query_id` | uint64 | + +:::tip Jettons 표준 +Jetton 지갑 계약 필드에 대한 자세한 설명은 [TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) `Jetton 표준` 인터페이스 설명에서 찾을 수 있습니다. +::: + +## 주석을 포함한 Jetton 전송 + +Jetton을 전송할 때는 **수수료**와 선택적으로 **전송 알림 메시지**(forward amount 필드를 확인하세요)를 위해 TON 코인이 필요합니다. + +주석을 포함하려면 `forward payload`를 설정해야 합니다. 첫 32비트를 `0x0`으로 설정하고 텍스트를 추가합니다. + +`forward payload`는 `전송 알림` 내부 메시지로 전송됩니다. 이는 `forward amount`가 0보다 큰 경우에만 생성됩니다. + +`Excess` 메시지를 수신하려면 `response destination`을 설정해야 합니다. + +:::tip +"주석과 함께 Jetton 전송" 예제를 보려면 [best practices](/develop/dapps/asset-processing/jettons#best-practices)를 확인하세요. +::: + +## Jetton 오프체인 처리 + +:::info 거래 확인 +TON 거래는 한 번 확인되면 되돌릴 수 없습니다. 최고의 사용자 경험을 위해, TON 블록체인에서 거래가 완료되면 추가 블록을 기다리지 않는 것이 좋습니다. 자세한 내용은 [Catchain.pdf](https://docs.ton.org/catchain.pdf#page=3)에서 확인하세요. +::: + +Jetton을 수락하는 두 가지 방법이 있습니다: + +- **중앙화된 핫 월렛** 내에서. +- 각 사용자를 위한 **개별 주소**를 사용하여. + +보안상의 이유로, 별도의 Jetton에 대해 별도의 핫 월렛을 보유하는 것이 좋습니다(각 자산 유형에 대해 여러 월렛을 보유). + +자금을 처리할 때는 자동 입출금 과정에 참여하지 않는 초과 자금을 저장하기 위한 콜드 월렛을 제공하는 것이 좋습니다. + +### 자산 처리 및 초기 확인을 위한 새로운 Jetton 추가 + +1. 올바른 [스마트 컨트랙트 주소](/develop/dapps/asset-processing/jettons#jetton-master-smart-contract)를 찾습니다. +2. [메타데이터](/develop/dapps/asset-processing/jettons#retrieving-jetton-data)를 가져옵니다. +3. [사기](/develop/dapps/asset-processing/jettons#jetton-master-smart-contract) 여부를 확인합니다. + +### 전송 알림 메시지를 수신할 때 알려지지 않은 Jetton 식별 + +지갑 내에서 알려지지 않은 Jetton에 대한 전송 알림 메시지를 수신한 경우, 해당 Jetton을 보유하도록 지갑이 생성된 것입니다. + +`전송 알림` 본문을 포함하는 내부 메시지의 발신자 주소는 새로운 Jetton 지갑의 주소입니다. 이는 `전송 알림` [본문](/develop/dapps/asset-processing/jettons#jetton-wallets-communication-overview)의 `발신자` 필드와 혼동해서는 안 됩니다. + +1. [지갑 데이터 가져오기](/develop/dapps/asset-processing/jettons#retrieving-data-for-a-specific-jetton-wallet)를 통해 새로운 Jetton 지갑의 Jetton 마스터 주소를 가져옵니다. +2. Jetton 마스터 컨트랙트 사용하여 [사용자에 대한 Jetton 지갑 주소를 가져오는 방법](#retrieving-jetton-wallet-addresses-for-a-given-user)을 사용하여 지갑 주소의 Jetton 지갑 주소를 가져옵니다. +3. 마스터 컨트래트에서 반환된 주소와 실제 지갑 토큰의 주소를 비교합니다. + 일치하면 이상적입니다. 그렇지 않으면 가짜 토큰을 받은 것일 수 있습니다. +4. Jetton 메타데이터를 가져옵니다: [Jetton 메타데이터 수신 방법](#retrieving-jetton-data). +5. `심볼` 및 `이름` 필드를 사기 여부를 확인합니다. 필요시 사용자에게 경고합니다. [자산 처리 및 초기 확인을 위한 새로운 Jetton 추가](#adding-new-jettons-for-asset-processing-and-initial-verification)를 참조하세요. + +### 중앙화된 지갑을 통한 사용자로부터의 Jetton 수락 + +:::info +단일 지갑으로 들어오는 거래의 병목 현상을 방지하기 위해, 여러 지갑에 걸쳐 입금을 수락하고 필요에 따라 지갑의 수를 늘리는 것이 좋습니다. +::: + +이 시나리오에서는 결제 서비스가 발신자에게 중앙화된 지갑의 주소와 보낼 금액을 공개하는 고유 메모 식별자를 생성합니다. 발신자는 중앙화된 주소로 토큰을 지정된 메모와 함께 전송합니다. + +**이 방법의 장점:** 이 방법은 추가 수수료가 없으며 토큰이 직접 핫 월렛에 수신되기 때문에 매우 간단합니다. + +**이 방법의 단점:** 이 방법은 모든 사용자가 전송 시 주석을 첨부해야 하기 때문에 더 많은 입금 실수(메모 누락, 잘못된 메모 등)가 발생할 수 있으며, 이는 지원 직원의 작업 부담을 증가시킵니다. + +Tonweb 예제: + +1. [주석(메모)을 포함한 개별 HOT 월렛으로의 Jetton 입금 수락](https://github.com/toncenter/examples/blob/main/deposits-jettons.js) +2. [Jetton 출금 예제](https://github.com/toncenter/examples/blob/main/withdrawals-jettons.js) + +#### 준비 사항 + +1. [허용된 Jetton 목록 준비](/develop/dapps/asset-processing/jettons#adding-new-jettons-for-asset-processing-and-initial-verification) (Jetton 마스터 주소). +2. 핫 월렛 배포 (Jetton 출금이 예상되지 않는 경우 v3R2 사용; Jetton 출금이 예상되는 경우 고부하 v3 사용). [지갑 배포](/develop/dapps/asset-processing/#wallet-deployment). +3. 핫 월렛 주소를 사용하여 테스트 Jetton 전송을 수행하여 지갑을 초기화합니다. + +#### 수신되는 Jetton 처리 + +1. 허용된 Jetton 목록을 로드합니다. +2. 배포된 핫 월렛에 대한 [Jetton 지갑 주소 가져오기](#retrieving-jetton-wallet-addresses-for-a-given-user). +3. [지갑 데이터 가져오기](/develop/dapps/asset-processing/jettons#retrieving-data-for-a-specific-jetton-wallet)를 사용하여 각 Jetton 지갑의 Jetton 마스터 주소를 가져옵니다. +4. 1단계와 바로 위의 3단계의 Jetton 마스터 컨트랙트의 주소를 비교합니다. + 주소가 일치하지 않으면 Jetton 주소 확인 오류를 보고해야 합니다. +5. 핫 월렛 계정을 사용하여 가장 최근에 처리되지 않은 거래 목록을 가져오고 + 이를 반복합니다 (각 거래를 하나씩 확인). [계약의 거래 확인](https://docs.ton.org/develop/dapps/asset-processing/#checking-contracts-transactions)을 참조하세요. +6. 거래의 입력 메시지(in_msg)를 확인하고 입력 메시지에서 소스 주소를 가져옵니다. [Tonweb 예제](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L84) +7. 소스 주소가 Jetton 지갑 내의 주소와 일치하면 거래를 계속 처리해야 합니다. + 일치하지 않으면 거래 처리를 건너뛰고 다음 거래를 확인합니다. +8. 메시지 본문이 비어 있지 않고 메시지의 첫 32비트가 `전송 알림` 연산 코드 `0x7362d09c`와 일치하는지 확인합니다. + [Tonweb 예제](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L91) + 메시지 본문이 비어 있거나 연산 코드가 잘못된 경우 - 거래를 건너뜁니다. +9. 메시지 본문의 다른 데이터를 읽습니다. 여기에는 `query_id`, `amount`, `sender`, `forward_payload`가 포함됩니다. + [Jetton 컨트랙트 메시지 레이아웃](#jetton-contract-message-layouts), [Tonweb 예제](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L105) +10. `forward_payload` 데이터에서 텍스트 주석을 가져오려고 합니다. 첫 32비트는 + 텍스트 주석 연산 코드 `0x00000000`과 일치해야 하며, 나머지는 UTF-8로 인코딩된 텍스트입니다. + [Tonweb 예제](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L110) +11. `forward_payload` 데이터가 비어 있거나 연산 코드가 잘못된 경우 - 거래를 건너뜁니다. +12. 수신된 주석과 저장된 메모를 비교합니다. 일치하는 경우 (사용자 식별이 항상 가능) - 전송을 입금합니다. +13. 5단계부터 시작하여 전체 거래 목록을 순회할 때까지 과정을 반복합니다. + +### 사용자 입금 주소에서 Jetton 수락 + +사용자 입금 주소에서 Jetton을 수락하려면, 결제 서비스가 자금을 송금하는 각 참가자를 위한 개별 주소(입금 주소)를 생성해야 합니다. 이 경우 서비스 제공에는 새로운 입금 생성, 거래 블록 스캔, 입금에서 핫 월렛으로 자금 인출 등의 여러 병렬 프로세스가 포함됩니다. + +핫 월렛은 각 Jetton 유형에 대해 하나의 Jetton 지갑을 사용할 수 있기 때문에 여러 지갑을 만들어 입금을 시작해야 합니다. 많은 수의 지갑을 생성하면서도 하나의 시드 문구(또는 개인 키)로 이를 관리하려면, 지갑 생성 시 다른 `subwallet_id`를 지정해야 합니다. TON에서는 버전 v3 지갑 이상에서 서브월렛 생성을 지원합니다. + +#### Tonweb에서 서브월렛 생성 + +```js +const WalletClass = tonweb.wallet.all['v3R2']; +const wallet = new WalletClass(tonweb.provider, { + publicKey: keyPair.publicKey, + wc: 0, + walletId: , +}); +``` + +#### 준비 사항 + +1. [허용된 Jetton 목록 준비](#adding-new-jettons-for-asset-processing-and-initial-verification). +2. 핫 월렛 배포 (Jetton 출금이 예상되지 않는 경우 v3R2 사용; Jetton 출금이 예상되는 경우 고부하 v3 사용). [지갑 배포](/develop/dapps/asset-processing/#wallet-deployment). + +#### 입금 생성 + +1. 사용자의 새로운 입금 요청을 수락합니다. +2. 핫 월렛 시드를 기반으로 새 서브월렛(v3R2) 주소를 생성합니다. [Tonweb에서 서브월렛 생성](#creating-a-subwallet-in-tonweb) +3. 수신 주소는 사용자에게 Jetton 입금에 사용할 주소로 제공될 수 있습니다 (이는 입금 Jetton 지갑 소유자의 주소입니다). 지갑 초기화는 필요하지 않으며, 입금에서 Jetton을 인출할 때 수행할 수 있습니다. +4. 이 주소에 대해 Jetton 마스터 계약을 통해 Jetton 지갑 주소를 계산해야 합니다. + [주어진 사용자에 대한 Jetton 지갑 주소를 가져오는 방법](#retrieving-jetton-wallet-addresses-for-a-given-user). +5. 거래 모니터링을 위한 주소 풀에 Jetton 지갑 주소를 추가하고 서브월렛 주소를 저장합니다. + +#### 거래 처리 + +:::info 거래 확인 +TON 거래는 한 번 확인되면 되돌릴 수 없습니다. 최고의 사용자 경험을 위해, TON 블록체인에서 거래가 완료되면 추가 블록을 기다리지 않는 것이 좋습니다. 자세한 내용은 [Catchain.pdf](https://docs.ton.org/catchain.pdf#page=3)에서 확인하세요. +::: + +메시지에서 받은 Jetton의 정확한 양을 항상 확인할 수 있는 것은 아닙니다. Jetton 지갑이 `전송 알림`, `초과`, 및 `내부 전송` 메시지를 보내지 않을 수 있기 때문입니다. 이들은 표준화되지 않았습니다. 이는 `내부 전송` 메시지를 디코딩할 수 있다는 보장이 없음을 의미합니다. + +따라서, 지갑에서 받은 양을 확인하기 위해서는 잔액을 get 메서드를 사용하여 요청해야 합니다. 잔액을 요청할 때 필요한 주요 데이터를 가져오기 위해 블록이 사용됩니다. 특정 블록 온체인의 계정 상태에 따라 블록을 준비합니다. [Tonweb을 사용한 블록 수락 준비](https://github.com/toncenter/tonweb/blob/master/src/test-block-subscribe.js). + +이 과정은 다음과 같이 진행됩니다: + +1. 블록 수락 준비 (새 블록을 수락할 수 있도록 시스템을 준비). +2. 새 블록을 가져와 이전 블록 ID를 저장합니다. +3. 블록에서 거래를 수신합니다. +4. 입금 Jetton 지갑 풀의 주소로만 사용된 거래를 필터링합니다. +5. 메시지를 `전송 알림` 본문을 사용하여 디코딩하여 자세한 데이터를 수신합니다. 여기에는 `발신자` 주소, Jetton `양` 및 주석이 포함됩니다. (참조: [들어오는 Jetton 처리](#processing-incoming-jettons)) +6. 디코딩할 수 없는 출력 메시지가 포함된 거래가 하나라도 있는 경우 (메시지 본문에 `전송 알림` 연산 코드와 `초과` 연산 코드가 포함되지 않은 경우) 또는 계정 내 출력 메시지가 없는 경우, 현재 블록에 대해 Jetton 잔액을 get 메서드를 사용하여 요청해야 하며, 이전 블록을 사용하여 잔액 변화를 계산합니다. 이제 블록 내에서 수행된 거래로 인한 총 잔액 입금 변화를 드러낼 수 있습니다. +7. 식별되지 않은 Jetton 전송(`전송 알림`이 없는 경우)에 대한 식별자로서, 거래 데이터가 하나만 있는 경우 해당 거래 데이터를 사용할 수 있습니다. +8. 이제 입금 잔액이 정확한지 확인해야 합니다. 입금 잔액이 핫 월렛과 기존 Jetton 지갑 간의 전송을 시작할 만큼 충분한 경우, Jetton을 인출하여 지갑 잔액이 감소했는지 확인해야 합니다. +9. 2단계부터 다시 시작하여 전체 과정을 반복합니다. + +#### 예금에서 출금 + +각 예금 보충 시 예금에서 핫 월렛으로의 전송이 이루어지지 않도록 해야 합니다. 이는 전송 작업에 대한 TON 수수료(네트워크 가스 요금으로 지불)가 발생하기 때문입니다. 전송이 가치 있도록 하기 위해 필요한 최소한의 Jetton 양을 결정하는 것이 중요합니다. + +기본적으로, Jetton 예금 지갑의 지갑 소유자는 초기화되지 않습니다. 이는 저장 수수료를 사전에 지불할 필요가 없기 때문입니다. Jetton 예금 지갑은 `transfer` 본문이 포함된 메시지를 보낼 때 배포되며, 이후 즉시 파괴될 수 있습니다. 이를 위해 엔지니어는 메시지를 보내는 특별한 메커니즘을 사용해야 합니다: [128 + 32](/develop/smart-contracts/messages#message-modes). + +1. 핫 월렛으로 인출을 표시한 예금 목록을 가져옵니다. +2. 각 예금에 대한 소유자 주소를 저장된 정보를 바탕으로 가져옵니다. +3. 메시지는 각 소유자 주소로 전송되며, 이러한 메시지 여러 개를 묶어서 배치(batch) 형태로 고성능(highload) 지갑에서 전송합니다. 이때 첨부되는 TON Jetton 양은 v3R2 지갑 초기화에 필요한 수수료 + `transfer` 메시지 본문을 전송하는 데 필요한 수수료 + `forward_ton_amount`와 관련된 임의의 TON 양(필요한 경우)을 더하여 결정됩니다. 첨부된 TON 양은 v3R2 지갑 초기화에 필요한 수수료(값) + `transfer` 메시지 본문을 전송하는 데 필요한 수수료(값) + `forward_ton_amount`를 위한 임의의 TON 양(값)(필요한 경우)을 더하여 결정됩니다. +4. 주소의 잔액이 0이 아닌 경우 계정 상태가 변경됩니다. 몇 초 기다린 후 계정 상태를 확인하여 `nonexists` 상태에서 `uninit` 상태로 변경되는지 확인합니다. +5. 각 소유자 주소(`uninit` 상태)에 v3R2 지갑 초기화 및 Jetton 지갑에 예금을 위한 `transfer` 메시지를 포함한 외부 메시지를 보내야 합니다. `transfer`의 경우 핫 월렛 주소를 `destination` 및 `response destination`으로 지정해야 합니다. 전송을 식별하기 쉽게 하기 위해 텍스트 코멘트를 추가할 수 있습니다. +6. Jetton 지갑 주소에서 핫 월렛 주소로 Jetton이 전달되는지 확인할 수 있습니다. 자세한 내용은 [여기](#processing-incoming-jettons)에서 확인할 수 있습니다. + +### Jetton 인출 + +:::info 중요 + +이 섹션을 읽기 전에 [jetton 전송 작동 방식](#jetton-wallets-communication-overview) 및 [코멘트와 함께 jetton 보내기](#jetton-off-chain-processing) 기사들을 읽고 이해하는 것이 **권장**됩니다. + +Jetton을 인출하려면 지갑이 해당 Jetton 지갑으로 `transfer` 본문이 포함된 메시지를 보냅니다. Jetton 지갑은 수신자에게 Jetton을 보냅니다. 신뢰성을 위해 `forward_ton_amount` (선택적으로 `forward_payload`에 코멘트 추가)와 함께 일부 TON을 첨부하는 것이 중요합니다. 자세한 내용은 [Jetton 계약 메시지 레이아웃](#jetton-contract-message-layouts)을 참조하십시오. + +#### 준비 사항 + +1. 인출할 Jetton 목록을 준비합니다: [자산 처리 및 초기 검증을 위한 새로운 Jetton 추가](#adding-new-jettons-for-asset-processing-and-initial-verification) +2. 핫 월렛 배포를 시작합니다. 고부하 v3을 권장합니다. [지갑 배포](#wallet-deployment) +3. Jetton 지갑을 초기화하고 잔액을 보충하기 위해 핫 월렛 주소를 사용하여 Jetton 전송을 수행합니다. + +#### 출금 처리 + +1. 처리된 Jetton 목록을 불러옵니다. +2. 배포된 핫 월렛에 대한 Jetton 지갑 주소를 가져옵니다: [사용자에 대한 Jetton 지갑 주소를 가져오는 방법](#retrieving-jetton-wallet-addresses-for-a-given-user) +3. 각 Jetton 지갑의 Jetton 마스터 주소를 가져옵니다: [특정 Jetton 지갑의 데이터 가져오기](#retrieving-data-for-a-specific-jetton-wallet). `jetton` 매개변수가 필요합니다 (실제로 Jetton 마스터 계약의 주소입니다). +4. 1단계와 3단계에서 얻은 Jetton 마스터 계약의 주소를 비교합니다. 주소가 일치하지 않으면 Jetton 주소 검증 오류를 보고해야 합니다. +5. 인출 요청을 받아 실제로 전송되는 Jetton의 종류, 금액 및 수신자 지갑 주소를 나타냅니다. +6. 인출을 수행하기에 충분한 자금이 있는지 확인하기 위해 Jetton 지갑 잔액을 확인합니다. +7. [메시지 생성](#message-0). +8. 고부하 지갑을 사용할 때는 수수료 최적화를 위해 메시지를 일괄 처리하여 한 번에 한 배치씩 보내는 것이 좋습니다. +9. 외부 메시지의 만료 시간을 저장합니다 (이 시간 동안 지갑이 메시지를 성공적으로 처리한 후 지갑은 더 이상 메시지를 수락하지 않습니다). +10. 단일 메시지 또는 여러 메시지(배치 메시지)를 보냅니다. +11. 핫 월렛 계정 내 처리되지 않은 최신 거래 목록을 검색하고 이를 반복합니다. 자세한 내용은 [계약의 거래 확인](#checking-contracts-transactions), [Tonweb 예제](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-single-wallet.js#L43)를 참조하거나 Toncenter API `/getTransactions` 메서드를 사용합니다. +12. 계정에서 나가는 메시지를 확인합니다. +13. `transfer` 연산 코드가 포함된 메시지가 있으면 이를 디코딩하여 `query_id` 값을 가져옵니다. 가져온 `query_id`는 성공적으로 전송된 것으로 표시해야 합니다. +14. 현재 스캔된 거래를 처리하는 데 걸리는 시간이 만료 시간보다 길고 해당 `query_id`가 있는 나가는 메시지가 발견되지 않으면 요청이 만료된 것으로 표시하고 안전하게 다시 전송해야 합니다 (선택 사항). +15. 계정에서 들어오는 메시지를 확인합니다. +16. `excesses` 연산 코드를 사용하는 메시지가 있으면 메시지를 디코딩하여 `query_id` 값을 가져옵니다. 발견된 `query_id`는 성공적으로 전달된 것으로 표시해야 합니다. +17. 5단계로 돌아갑니다. 성공적으로 전송되지 않은 만료된 요청은 인출 목록으로 다시 푸시해야 합니다. + +## Jetton 온체인 처리 + +일반적으로, jetton을 수락하고 처리하기 위해 내부 메시지에 대한 메시지 핸들러는 `op=0x7362d09c` 연산 코드를 사용합니다. + +:::info 거래 확인 +TON 거래는 한 번의 확인 후에는 되돌릴 수 없습니다. 최고의 사용자 경험을 위해, TON 블록체인에서 거래가 완료된 후 추가 블록을 기다리지 않는 것이 좋습니다. 자세한 내용은 [Catchain.pdf](https://docs.ton.org/catchain.pdf#page=3)를 참조하십시오. +::: + +### 온체인 처리 권장 사항 + +아래는 **온체인 jetton 처리**를 수행할 때 고려해야 할 `권장 사항 목록`입니다: + +1. Jetton 마스터 계약이 아닌, 지갑 유형을 사용하여 **들어오는 Jetton을 식별**합니다. 다시 말해, 귀하의 계약은 특정 Jetton 지갑과 상호 작용해야 하며(메시지 수신 및 전송) 특정 Jetton 마스터 계약을 사용하는 알 수 없는 지갑과 상호 작용해서는 안 됩니다. +2. Jetton 지갑과 Jetton 마스터를 연결할 때, **이 연결이 양방향인지 확인**하십시오. 지갑이 마스터 계약을 인식하고 그 반대도 마찬가지여야 합니다. 예를 들어, 귀하의 계약 시스템이 Jetton 지갑으로부터 알림을 받을 경우(해당 지갑이 MySuperJetton을 마스터 계약으로 간주하는 경우), 그 이전에 `심볼`, `이름` 및 `이미지`를 표시하기 전에 MySuperJetton 지갑이 올바른 계약 시스템을 사용하는지 확인해야 합니다. 또한, 귀하의 계약 시스템이 MySuperJetton 또는 MySuperJetton 마스터 계약을 사용하여 Jetton을 전송해야 하는 경우, 지갑 X가 동일한 계약 매개변수를 사용하는지 확인하십시오. X에 `전송` 요청을 보내기 전에, 해당 지갑이 MySuperJetton을 마스터로 인식하는지 확인하십시오. +3. 탈중앙화 금융(DeFi)의 **진정한 힘**은 레고 블록처럼 프로토콜을 쌓을 수 있는 능력에 기반합니다. 예를 들어, Jetton A가 Jetton B로 교환되고, 이 Jetton B가 대출 프로토콜 내에서 레버리지로 사용되며(사용자가 유동성을 공급할 때) 그 후 NFT를 구매하는 데 사용됩니다. 따라서, 계약이 온체인 사용자뿐만 아니라 오프체인 사용자도 지원할 수 있도록 고려해야 하며, 전송 알림에 토큰화된 가치를 첨부하거나 전송 알림과 함께 전송될 수 있는 맞춤형 페이로드를 추가해야 합니다. +4. **모든 계약이 동일한 표준을 따르는 것은 아니라는 점**을 인지하십시오. 불행히도, 일부 Jetton은 공격 벡터를 사용하여 순진한 사용자를 공격하기 위해 생성된 악의적인 계약일 수 있습니다. 보안상의 이유로, 프로토콜이 여러 계약으로 구성된 경우 동일한 유형의 Jetton 지갑을 대량으로 생성하지 마십시오. 특히, 프로토콜 내에서 입금 계약, 금고 계약 또는 사용자 계정 계약 간에 Jetton을 전송하지 마십시오. 공격자는 전송 알림, Jetton 양 또는 페이로드 매개변수를 위조하여 계약 논리를 의도적으로 방해할 수 있습니다. 시스템 내에서 Jetton당 하나의 지갑만 사용하여 공격 가능성을 줄이십시오(모든 입출금을 위한). +5. 주소 스푸핑의 가능성을 줄이기 위해 각 개별 Jetton에 대한 하위 계약을 생성하는 것이 **종종 좋은 방법**입니다(예: Jetton A용으로 의도된 계약을 사용하여 Jetton B에 전송 메시지를 보낼 때). +6. 계약 수준에서 불가분의 Jetton 단위를 사용하는 것이 **강력히 권장**됩니다. 소수점 관련 로직은 일반적으로 사용자 인터페이스(UI)를 개선하기 위해 사용되며, 온체인 기록 유지와는 관련이 없습니다. + +**자세히 알아보고자** 한다면 [CertiK의 FunC에서 안전한 스마트 계약 프로그래밍](https://blog.ton.org/secure-smart-contract-programming-in-func)을 읽어보세요. 개발자들이 **모든 스마트 계약 예외를 처리**하도록 권장하며, 이는 애플리케이션 개발 중에 절대 건너뛰어서는 안 됩니다. + +## Jetton 지갑 처리 권장사항 + +일반적으로, 오프체인 Jetton 처리에 사용되는 모든 검증 절차는 지갑에도 적합합니다. Jetton 지갑 처리에 있어 가장 중요한 권장 사항은 다음과 같습니다: + +1. 지갑이 알 수 없는 Jetton 지갑으로부터 전송 알림을 받을 때, 해당 Jetton 지갑과 그 마스터 주소를 신뢰하는 것이 **매우 중요**합니다. 악의적인 위조일 수 있기 때문입니다. 스스로를 보호하기 위해, 제공된 주소를 사용하여 Jetton 마스터(마스터 계약)를 확인하고, 귀하의 검증 절차가 해당 Jetton 지갑을 정당한 것으로 인식하는지 확인하십시오. 지갑을 신뢰하고 정당한 것으로 확인된 후에만 계좌 잔액 및 기타 지갑 내 데이터를 접근할 수 있도록 허용하십시오. Jetton 마스터가 해당 지갑을 인식하지 못하면, Jetton 전송을 전혀 시작하거나 공개하지 않는 것이 좋으며, 전송 알림에 첨부된 Toncoin의 TON 전송만 표시하십시오. +2. 실제로, 사용자가 Jetton 지갑이 아닌 Jetton과 상호작용하기를 원할 때가 있습니다. 다시 말해, 사용자는 `EQAjN...`/`EQBLE...` 등이 아닌 wTON/oUSDT/jUSDT, jUSDC, jDAI 등을 전송합니다. 이는 종종 사용자가 Jetton 전송을 시작할 때, 지갑이 해당 Jetton 마스터에게(사용자가 소유한) 어떤 Jetton 지갑이 전송 요청을 시작해야 하는지를 묻는다는 것을 의미합니다. 이때 **마스터(마스터 계약)로부터 받은 데이터**를 무작정 신뢰해서는 안 됩니다. Jetton 지갑에 전송 요청을 보내기 전에, 해당 Jetton 지갑이 실제로 자신이 속해 있다고 주장하는 Jetton 마스터에 속하는지 확인하십시오. +3. **적대적인 Jetton 마스터/Jetton 지갑이** 시간이 지남에 따라 **지갑/마스터를 변경할 수 있다**는 점을 인지하십시오. 따라서 사용자는 각 사용 전에 상호작용하는 지갑의 정당성을 철저히 확인하는 것이 필수적입니다. +4. 인터페이스에 Jetton을 표시할 때 **TON 전송** 및 시스템 알림 등과 **혼동되지 않도록** 항상 주의하십시오. 심지어 `심볼`, `이름` 및 `이미지` 매개변수도 사용자를 오도하도록 조작될 수 있으며, 그 결과 피해자는 잠재적인 사기 피해자가 될 수 있습니다. 악의적인 Jetton이 TON 전송, 알림 오류, 보상 수익, 자산 동결 발표를 사칭하는 데 사용된 사례가 여러 번 있었습니다. +5. **악의적인 행위자들이** 위조된 Jetton을 생성할 가능성에 **항상 주의하십시오**. 사용자가 주요 사용자 인터페이스에서 원하지 않는 Jetton을 제거할 수 있는 기능을 제공하는 것이 좋습니다. + +작가: [kosrk](https://github.com/kosrk), [krigga](https://github.com/krigga), [EmelyanenkoK](https://github.com/EmelyanenkoK/), [tolya-yanot](https://github.com/tolya-yanot/) + +## 모범 사례 + +테스트 가능한 예제를 원한다면 [SDKs](/develop/dapps/asset-processing/jettons#sdks)에서 확인하고 실행해보세요. 아래는 코드 예제를 통해 Jetton 처리를 이해하는 데 도움이 될 코드 스니펫입니다. + +### 주석과 함께 Jetton 전송하기 + + + + +
+ +소스 코드 + + +```js +// first 4 bytes are tag of text comment +const comment = new Uint8Array([... new Uint8Array(4), ... new TextEncoder().encode('text comment')]); + +await wallet.methods.transfer({ + secretKey: keyPair.secretKey, + toAddress: JETTON_WALLET_ADDRESS, // address of Jetton wallet of Jetton sender + amount: TonWeb.utils.toNano('0.05'), // total amount of TONs attached to the transfer message + seqno: seqno, + payload: await jettonWallet.createTransferBody({ + jettonAmount: TonWeb.utils.toNano('500'), // Jetton amount (in basic indivisible units) + toAddress: new TonWeb.utils.Address(WALLET2_ADDRESS), // recepient user's wallet address (not Jetton wallet) + forwardAmount: TonWeb.utils.toNano('0.01'), // some amount of TONs to invoke Transfer notification message + forwardPayload: comment, // text comment for Transfer notification message + responseAddress: walletAddress // return the TONs after deducting commissions back to the sender's wallet address + }), + sendMode: 3, +}).send() +``` + +
+ +
+ + +
+ +소스 코드 + + +```go +client := liteclient.NewConnectionPool() + +// connect to testnet lite server +err := client.AddConnectionsFromConfigUrl(context.Background(), "https://ton.org/global.config.json") +if err != nil { + panic(err) +} + +ctx := client.StickyContext(context.Background()) + +// initialize ton api lite connection wrapper +api := ton.NewAPIClient(client) + +// seed words of account, you can generate them with any wallet or using wallet.NewSeed() method +words := strings.Split("birth pattern then forest walnut then phrase walnut fan pumpkin pattern then cluster blossom verify then forest velvet pond fiction pattern collect then then", " ") + +w, err := wallet.FromSeed(api, words, wallet.V3R2) +if err != nil { + log.Fatalln("FromSeed err:", err.Error()) + return +} + +token := jetton.NewJettonMasterClient(api, address.MustParseAddr("EQD0vdSA_NedR9uvbgN9EikRX-suesDxGeFg69XQMavfLqIw")) + +// find our jetton wallet +tokenWallet, err := token.GetJettonWallet(ctx, w.WalletAddress()) +if err != nil { + log.Fatal(err) +} + +amountTokens := tlb.MustFromDecimal("0.1", 9) + +comment, err := wallet.CreateCommentCell("Hello from tonutils-go!") +if err != nil { + log.Fatal(err) +} + +// address of receiver's wallet (not token wallet, just usual) +to := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N") +transferPayload, err := tokenWallet.BuildTransferPayload(to, amountTokens, tlb.ZeroCoins, comment) +if err != nil { + log.Fatal(err) +} + +// your TON balance must be > 0.05 to send +msg := wallet.SimpleMessage(tokenWallet.Address(), tlb.MustFromTON("0.05"), transferPayload) + +log.Println("sending transaction...") +tx, _, err := w.SendWaitTransaction(ctx, msg) +if err != nil { + panic(err) +} +log.Println("transaction confirmed, hash:", base64.StdEncoding.EncodeToString(tx.Hash)) +``` + +
+ +
+ + +
+ +소스 코드 + + +```py +my_wallet = Wallet(provider=client, mnemonics=my_wallet_mnemonics, version='v4r2') + +# for TonCenterClient and LsClient +await my_wallet.transfer_jetton(destination_address='address', jetton_master_address=jetton.address, jettons_amount=1000, fee=0.15) + +# for all clients +await my_wallet.transfer_jetton_by_jetton_wallet(destination_address='address', jetton_wallet='your jetton wallet address', jettons_amount=1000, fee=0.1) +``` + +
+ +
+ + + +
+ +소스 코드 + + +```py +from pytoniq import LiteBalancer, WalletV4R2, begin_cell +import asyncio + +mnemonics = ["your", "mnemonics", "here"] + +async def main(): + provider = LiteBalancer.from_mainnet_config(1) + await provider.start_up() + + wallet = await WalletV4R2.from_mnemonic(provider=provider, mnemonics=mnemonics) + USER_ADDRESS = wallet.address + JETTON_MASTER_ADDRESS = "EQBlqsm144Dq6SjbPI4jjZvA1hqTIP3CvHovbIfW_t-SCALE" + DESTINATION_ADDRESS = "EQAsl59qOy9C2XL5452lGbHU9bI3l4lhRaopeNZ82NRK8nlA" + + USER_JETTON_WALLET = (await provider.run_get_method(address=JETTON_MASTER_ADDRESS, + method="get_wallet_address", + stack=[begin_cell().store_address(USER_ADDRESS).end_cell().begin_parse()]))[0].load_address() + forward_payload = (begin_cell() + .store_uint(0, 32) # TextComment op-code + .store_snake_string("Comment") + .end_cell()) + transfer_cell = (begin_cell() + .store_uint(0xf8a7ea5, 32) # Jetton Transfer op-code + .store_uint(0, 64) # query_id + .store_coins(1 * 10**9) # Jetton amount to transfer in nanojetton + .store_address(DESTINATION_ADDRESS) # Destination address + .store_address(USER_ADDRESS) # Response address + .store_bit(0) # Custom payload is None + .store_coins(1) # Ton forward amount in nanoton + .store_bit(1) # Store forward_payload as a reference + .store_ref(forward_payload) # Forward payload + .end_cell()) + + await wallet.transfer(destination=USER_JETTON_WALLET, amount=int(0.05*1e9), body=transfer_cell) + await provider.close_all() + +asyncio.run(main()) +``` + +
+ +
+
+ +### 주석을 해석하여 Jetton 전송 수락하기 + + + + +
+ +소스 코드 + + +```ts +import { + Address, + TonClient, + Cell, + beginCell, + storeMessage, + JettonMaster, + OpenedContract, + JettonWallet, + Transaction +} from '@ton/ton'; + + +export async function retry(fn: () => Promise, options: { retries: number, delay: number }): Promise { + let lastError: Error | undefined; + for (let i = 0; i < options.retries; i++) { + try { + return await fn(); + } catch (e) { + if (e instanceof Error) { + lastError = e; + } + await new Promise(resolve => setTimeout(resolve, options.delay)); + } + } + throw lastError; +} + +export async function tryProcessJetton(orderId: string) : Promise { + + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + apiKey: 'TONCENTER-API-KEY', // https://t.me/tonapibot + }); + + interface JettonInfo { + address: string; + decimals: number; + } + + interface Jettons { + jettonMinter : OpenedContract, + jettonWalletAddress: Address, + jettonWallet: OpenedContract + } + + const MY_WALLET_ADDRESS = 'INSERT-YOUR-HOT-WALLET-ADDRESS'; // your HOT wallet + + const JETTONS_INFO : Record = { + 'jUSDC': { + address: 'EQB-MPwrd1G6WKNkLz_VnV6WqBDd142KMQv-g1O-8QUA3728', // + decimals: 6 + }, + 'jUSDT': { + address: 'EQBynBO23ywHy_CgarY9NK9FTz0yDsG82PtcbSTQgGoXwiuA', + decimals: 6 + }, + } + const jettons: Record = {}; + + const prepare = async () => { + for (const name in JETTONS_INFO) { + const info = JETTONS_INFO[name]; + const jettonMaster = client.open(JettonMaster.create(Address.parse(info.address))); + const userAddress = Address.parse(MY_WALLET_ADDRESS); + + const jettonUserAddress = await jettonMaster.getWalletAddress(userAddress); + + console.log('My jetton wallet for ' + name + ' is ' + jettonUserAddress.toString()); + + const jettonWallet = client.open(JettonWallet.create(jettonUserAddress)); + + //const jettonData = await jettonWallet; + const jettonData = await client.runMethod(jettonUserAddress, "get_wallet_data") + + jettonData.stack.pop(); //skip balance + jettonData.stack.pop(); //skip owneer address + const adminAddress = jettonData.stack.readAddress(); + + + if (adminAddress.toString() !== (Address.parse(info.address)).toString()) { + throw new Error('jetton minter address from jetton wallet doesnt match config'); + } + + jettons[name] = { + jettonMinter: jettonMaster, + jettonWalletAddress: jettonUserAddress, + jettonWallet: jettonWallet + }; + } + } + + const jettonWalletAddressToJettonName = (jettonWalletAddress : Address) => { + const jettonWalletAddressString = jettonWalletAddress.toString(); + for (const name in jettons) { + const jetton = jettons[name]; + + if (jetton.jettonWallet.address.toString() === jettonWalletAddressString) { + return name; + } + } + return null; + } + + // Subscribe + const Subscription = async ():Promise =>{ + + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + apiKey: 'TONCENTER-API-KEY', // https://t.me/tonapibot + }); + + const myAddress = Address.parse('INSERT-YOUR-HOT-WALLET'); // Address of receiver TON wallet + const transactions = await client.getTransactions(myAddress, { + limit: 5, + }); + return transactions; + } + + return retry(async () => { + + await prepare(); + const Transactions = await Subscription(); + + for (const tx of Transactions) { + + const sourceAddress = tx.inMessage?.info.src; + if (!sourceAddress) { + // external message - not related to jettons + continue; + } + + if (!(sourceAddress instanceof Address)) { + continue; + } + + const in_msg = tx.inMessage; + + if (in_msg?.info.type !== 'internal') { + // external message - not related to jettons + continue; + } + + // jetton master contract address check + const jettonName = jettonWalletAddressToJettonName(sourceAddress); + if (!jettonName) { + // unknown or fake jetton transfer + continue; + } + + if (tx.inMessage === undefined || tx.inMessage?.body.hash().equals(new Cell().hash())) { + // no in_msg or in_msg body + continue; + } + + const msgBody = tx.inMessage; + const sender = tx.inMessage?.info.src; + const originalBody = tx.inMessage?.body.beginParse(); + let body = originalBody?.clone(); + const op = body?.loadUint(32); + if (!(op == 0x7362d09c)) { + continue; // op != transfer_notification + } + + console.log('op code check passed', tx.hash().toString('hex')); + + const queryId = body?.loadUint(64); + const amount = body?.loadCoins(); + const from = body?.loadAddress(); + const maybeRef = body?.loadBit(); + const payload = maybeRef ? body?.loadRef().beginParse() : body; + const payloadOp = payload?.loadUint(32); + if (!(payloadOp == 0)) { + console.log('no text comment in transfer_notification'); + continue; + } + + const comment = payload?.loadStringTail(); + if (!(comment == orderId)) { + continue; + } + + console.log('Got ' + jettonName + ' jetton deposit ' + amount?.toString() + ' units with text comment "' + comment + '"'); + const txHash = tx.hash().toString('hex'); + return (txHash); + } + throw new Error('Transaction not found'); + }, {retries: 30, delay: 1000}); +} +``` + +
+ +
+ + +
+ +소스 코드 + + +```go +import ( + "context" + "fmt" + "log" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/liteclient" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/ton/jetton" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +const ( + MainnetConfig = "https://ton.org/global.config.json" + TestnetConfig = "https://ton.org/global.config.json" + MyWalletAddress = "INSERT-YOUR-HOT-WALLET-ADDRESS" +) + +type JettonInfo struct { + address string + decimals int +} + +type Jettons struct { + jettonMinter *jetton.Client + jettonWalletAddress string + jettonWallet *jetton.WalletClient +} + +func prepare(api ton.APIClientWrapped, jettonsInfo map[string]JettonInfo) (map[string]Jettons, error) { + userAddress := address.MustParseAddr(MyWalletAddress) + block, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + return nil, err + } + + jettons := make(map[string]Jettons) + + for name, info := range jettonsInfo { + jettonMaster := jetton.NewJettonMasterClient(api, address.MustParseAddr(info.address)) + jettonWallet, err := jettonMaster.GetJettonWallet(context.Background(), userAddress) + if err != nil { + return nil, err + } + + jettonUserAddress := jettonWallet.Address() + + jettonData, err := api.RunGetMethod(context.Background(), block, jettonUserAddress, "get_wallet_data") + if err != nil { + return nil, err + } + + slice := jettonData.MustCell(0).BeginParse() + slice.MustLoadCoins() // skip balance + slice.MustLoadAddr() // skip owneer address + adminAddress := slice.MustLoadAddr() + + if adminAddress.String() != info.address { + return nil, fmt.Errorf("jetton minter address from jetton wallet doesnt match config") + } + + jettons[name] = Jettons{ + jettonMinter: jettonMaster, + jettonWalletAddress: jettonUserAddress.String(), + jettonWallet: jettonWallet, + } + } + + return jettons, nil +} + +func jettonWalletAddressToJettonName(jettons map[string]Jettons, jettonWalletAddress string) string { + for name, info := range jettons { + if info.jettonWallet.Address().String() == jettonWalletAddress { + return name + } + } + return "" +} + +func GetTransferTransactions(orderId string, foundTransfer chan<- *tlb.Transaction) { + jettonsInfo := map[string]JettonInfo{ + "jUSDC": {address: "EQB-MPwrd1G6WKNkLz_VnV6WqBDd142KMQv-g1O-8QUA3728", decimals: 6}, + "jUSDT": {address: "EQBynBO23ywHy_CgarY9NK9FTz0yDsG82PtcbSTQgGoXwiuA", decimals: 6}, + } + + client := liteclient.NewConnectionPool() + + cfg, err := liteclient.GetConfigFromUrl(context.Background(), MainnetConfig) + if err != nil { + log.Fatalln("get config err: ", err.Error()) + } + + // connect to lite servers + err = client.AddConnectionsFromConfig(context.Background(), cfg) + if err != nil { + log.Fatalln("connection err: ", err.Error()) + } + + // initialize ton api lite connection wrapper + api := ton.NewAPIClient(client, ton.ProofCheckPolicySecure).WithRetry() + master, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + log.Fatalln("get masterchain info err: ", err.Error()) + } + + // address on which we are accepting payments + treasuryAddress := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N") + + acc, err := api.GetAccount(context.Background(), master, treasuryAddress) + if err != nil { + log.Fatalln("get masterchain info err: ", err.Error()) + } + + jettons, err := prepare(api, jettonsInfo) + if err != nil { + log.Fatalln("can't prepare jettons data: ", err.Error()) + } + + lastProcessedLT := acc.LastTxLT + + transactions := make(chan *tlb.Transaction) + + go api.SubscribeOnTransactions(context.Background(), treasuryAddress, lastProcessedLT, transactions) + + log.Println("waiting for transfers...") + + // listen for new transactions from channel + for tx := range transactions { + if tx.IO.In == nil || tx.IO.In.MsgType != tlb.MsgTypeInternal { + // external message - not related to jettons + continue + } + + msg := tx.IO.In.Msg + sourceAddress := msg.SenderAddr() + + // jetton master contract address check + jettonName := jettonWalletAddressToJettonName(jettons, sourceAddress.String()) + if len(jettonName) == 0 { + // unknown or fake jetton transfer + continue + } + + if msg.Payload() == nil || msg.Payload() == cell.BeginCell().EndCell() { + // no in_msg body + continue + } + + msgBodySlice := msg.Payload().BeginParse() + + op := msgBodySlice.MustLoadUInt(32) + if op != 0x7362d09c { + continue // op != transfer_notification + } + + // just skip bits + msgBodySlice.MustLoadUInt(64) + amount := msgBodySlice.MustLoadCoins() + msgBodySlice.MustLoadAddr() + + payload := msgBodySlice.MustLoadMaybeRef() + payloadOp := payload.MustLoadUInt(32) + if payloadOp == 0 { + log.Println("no text comment in transfer_notification") + continue + } + + comment := payload.MustLoadStringSnake() + if comment != orderId { + continue + } + + // process transaction + log.Printf("Got %s jetton deposit %d units with text comment %s\n", jettonName, amount, comment) + foundTransfer <- tx + } +} +``` + +
+
+ + + +
+ +소스 코드 + + +```py +import asyncio + +from pytoniq import LiteBalancer, begin_cell + +MY_WALLET_ADDRESS = "EQAsl59qOy9C2XL5452lGbHU9bI3l4lhRaopeNZ82NRK8nlA" + + +async def parse_transactions(provider: LiteBalancer, transactions): + for transaction in transactions: + if not transaction.in_msg.is_internal: + continue + if transaction.in_msg.info.dest.to_str(1, 1, 1) != MY_WALLET_ADDRESS: + continue + + sender = transaction.in_msg.info.src.to_str(1, 1, 1) + value = transaction.in_msg.info.value_coins + if value != 0: + value = value / 1e9 + + if len(transaction.in_msg.body.bits) < 32: + print(f"TON transfer from {sender} with value {value} TON") + continue + + body_slice = transaction.in_msg.body.begin_parse() + op_code = body_slice.load_uint(32) + if op_code != 0x7362D09C: + continue + + body_slice.load_bits(64) # skip query_id + jetton_amount = body_slice.load_coins() / 1e9 + jetton_sender = body_slice.load_address().to_str(1, 1, 1) + if body_slice.load_bit(): + forward_payload = body_slice.load_ref().begin_parse() + else: + forward_payload = body_slice + + jetton_master = ( + await provider.run_get_method( + address=sender, method="get_wallet_data", stack=[] + ) + )[2].load_address() + jetton_wallet = ( + ( + await provider.run_get_method( + address=jetton_master, + method="get_wallet_address", + stack=[ + begin_cell() + .store_address(MY_WALLET_ADDRESS) + .end_cell() + .begin_parse() + ], + ) + )[0] + .load_address() + .to_str(1, 1, 1) + ) + + if jetton_wallet != sender: + print("FAKE Jetton Transfer") + continue + + if len(forward_payload.bits) < 32: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton" + ) + else: + forward_payload_op_code = forward_payload.load_uint(32) + if forward_payload_op_code == 0: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton and comment: {forward_payload.load_snake_string()}" + ) + else: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton and unknown payload: {forward_payload} " + ) + + print(f"Transaction hash: {transaction.cell.hash.hex()}") + print(f"Transaction lt: {transaction.lt}") + + +async def main(): + provider = LiteBalancer.from_mainnet_config(1) + await provider.start_up() + transactions = await provider.get_transactions(address=MY_WALLET_ADDRESS, count=5) + await parse_transactions(provider, transactions) + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +
+
+
+ +## SDKs + +여기에서 다양한 언어(js, python, golang, C#, Rust 등)를 위한 SDK 목록을 확인할 수 있습니다: [여기](/develop/dapps/apis/sdk). + +## 참고 항목 + +- [결제 처리](/develop/dapps/asset-processing/) +- [TON에서 NFT 처리](/develop/dapps/asset-processing/nfts) +- [TON에서 메타데이터 파싱](/develop/dapps/asset-processing/metadata) diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md new file mode 100644 index 0000000000..817f9336ee --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md @@ -0,0 +1,62 @@ +import Button from '@site/src/components/button' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# 자산 처리 개요 + +여기서 TON 전송이 어떻게 작동하는지에 대한 **간단한 개요**를 찾을 수 있습니다. TON에서 찾을 수 있는 [자산 유형](/develop/dapps/asset-processing/overview#digital-asset-types-on-ton)은 무엇인지, 다음에 읽을 [내용](/develop/dapps/asset-processing/overview#read-next)은 무엇인지, 그리고 [프로그래밍 언어를 사용하여 TON과 상호작용](/develop/dapps/asset-processing/overview#interaction-with-ton-blockchain)하는 방법도 있습니다. 다음 페이지로 넘어가기 전에 아래에 설명된 모든 정보를 이해하는 것이 좋습니다. + +## 메시지와 트랜잭션 개요 + +전적으로 비동기적 접근 방식을 구현한 TON 블록체인은 전통적인 블록체인과는 다른 몇 가지 개념을 포함하고 있습니다. 특히, 블록체인과의 모든 참여자의 상호작용은 스마트 계약 및/또는 외부 세계 간에 비동기적으로 전송되는 [메시지](/develop/smart-contracts/guidelines/message-delivery-guarantees)의 그래프로 구성됩니다. 각 트랜잭션은 하나의 수신 메시지와 최대 512개의 발신 메시지로 이루어집니다. + +메시지는 3가지 유형이 있으며, 각각의 설명은 [여기](/develop/smart-contracts/messages#types-of-messages)에서 확인할 수 있습니다. 간단히 설명하면: + +- [외부 메시지](/develop/smart-contracts/guidelines/external-messages): + - `external in message`(때로는 `external message`라고도 함)는 블록체인 외부에서 블록체인 내부의 스마트 계약으로 보내진 메시지입니다. + - `external out message`(보통 `logs message`라고 불림)는 블록체인 엔터티에서 외부 세계로 보내지는 메시지입니다. +- [내부 메시지](/develop/smart-contracts/guidelines/internal-messages)는 한 블록체인 엔터티에서 다른 엔터티로 보내지며, 디지털 자산과 임의의 데이터 일부를 포함할 수 있습니다. + +일반적인 상호작용 경로는 `wallet` 스마트 계약으로 외부 메시지를 보내는 것으로 시작됩니다. 이 계약은 공개 키 암호화를 사용하여 메시지 발신자를 인증하고, 수수료 지불을 담당하며, 내부 블록체인 메시지를 보냅니다. 이 메시지 큐는 방향성 비순환 그래프 또는 트리를 형성합니다. + +예를 들어: + +![](/img/docs/asset-processing/alicemsgDAG.svg) + +- `Alice`는 예를 들어 [Tonkeeper](https://tonkeeper.com/)를 사용하여 `external message`를 자신의 지갑으로 보냅니다. +- `external message`는 소스가 비어 있는 (예: [Tonkeeper](https://tonkeeper.com/)처럼 어디서부터 온 메시지) `wallet A v4` 계약에 대한 입력 메시지입니다. +- `outgoing message`는 `wallet A v4` 계약의 출력 메시지이자 `wallet B v4` 계약의 입력 메시지입니다. 이때 소스는 `wallet A v4`이고, 목적지는 `wallet B v4`입니다. + +결과적으로 입력 및 출력 메시지 세트를 가진 두 개의 트랜잭션이 발생합니다. + +각 동작은 계약이 메시지를 입력으로 받아들이고(이에 의해 트리거됨), 이를 처리하여 출력 메시지를 생성하거나 생성하지 않는 형태로 이루어지며, 이를 `트랜잭션`이라고 합니다. 트랜잭션에 대한 자세한 내용은 [여기](/develop/smart-contracts/guidelines/message-delivery-guarantees#what-is-a-transaction)에서 확인할 수 있습니다. + +이러한 `트랜잭션`은 **오랜 시간** 동안 지속될 수 있습니다. 기술적으로, 메시지 큐가 있는 트랜잭션은 블록으로 집계되어 검증자에 의해 처리됩니다. TON 블록체인의 비동기적 특성으로 인해 메시지 전송 단계에서 트랜잭션의 해시와 논리적 시간(lt)을 예측할 수 없습니다. + +블록에 수락된 `트랜잭션`은 최종적이며 수정할 수 없습니다. + +:::info 트랜잭션 확인 +TON 트랜잭션은 한 번의 확인만으로도 되돌릴 수 없습니다. 최상의 사용자 경험을 위해서는 TON 블록체인에서 트랜잭션이 완료된 후 추가적인 블록을 기다리는 것을 피하는 것이 좋습니다. 자세한 내용은 [Catchain.pdf](https://docs.ton.org/catchain.pdf#page=3)에서 확인할 수 있습니다. +::: + +스마트 계약은 트랜잭션에 대해 여러 유형의 [수수료](/develop/smart-contracts/fees)를 지불합니다(보통은 들어오는 메시지의 잔액에서 지불되며, 이는 [메시지 모드](/develop/smart-contracts/messages#message-modes)에 따라 다릅니다). 수수료의 양은 워크체인 구성에 따라 달라지며, `masterchain`에서는 최대 수수료가 부과되고, `basechain`에서는 훨씬 낮은 수수료가 부과됩니다. + +## TON의 디지털 자산 유형 + +TON에는 세 가지 유형의 디지털 자산이 있습니다. + +- Toncoin, 네트워크의 주요 토큰입니다. 블록체인에서 모든 기본 작업에 사용되며, 예를 들어 가스 수수료를 지불하거나 검증을 위한 스테이킹에 사용됩니다. +- 계약 자산은 ERC-20/ERC-721 표준과 유사한 토큰 및 NFT와 같은 자산으로, 임의의 계약에 의해 관리되며 처리에 대한 사용자 정의 규칙이 필요할 수 있습니다. 이 처리에 대한 자세한 내용은 [NFT 처리](/develop/dapps/asset-processing/nfts) 및 [Jetton 처리](/develop/dapps/asset-processing/jettons) 문서에서 확인할 수 있습니다. +- 네이티브 토큰은 네트워크의 모든 메시지에 첨부할 수 있는 특수 자산입니다. 그러나 현재 네이티브 토큰을 발행하는 기능이 비활성화되어 사용되지 않고 있습니다. + +## TON 블록체인과의 상호작용 + +TON 블록체인에서의 기본 작업은 TonLib을 통해 수행할 수 있습니다. TonLib은 TON 노드와 함께 컴파일할 수 있는 공유 라이브러리로, 경량 클라이언트를 위한 서버(lite servers)를 통해 블록체인과 상호작용할 수 있는 API를 제공합니다. TonLib은 모든 수신 데이터를 증명으로 확인하는 신뢰 없는(trustless) 방식을 따르므로, 신뢰할 수 있는 데이터 제공자가 필요하지 않습니다. TonLib에서 사용할 수 있는 메서드는 [TL scheme](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L234)에 나와 있습니다. 이 메서드는 공유 라이브러리로 사용할 수 있으며, [wrappers](/develop/dapps/asset-processing/#repositories)를 통해 사용할 수 있습니다. + +## 다음 읽기 + +이 문서를 읽은 후에는 다음을 확인할 수 있습니다: + +1. [결제 처리](/develop/dapps/asset-processing/)에서 `TON 코인`으로 작업하는 방법을 확인하세요. +2. [Jetton 처리](/develop/dapps/asset-processing/jettons)에서 `jetton`(때때로 `토큰`이라고도 함)으로 작업하는 방법을 확인하세요. +3. [NFT 처리](/develop/dapps/asset-processing/nfts)에서 `NFT`(특별한 유형의 `jetton`)로 작업하는 방법을 확인하세요. diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/usdt.md b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/usdt.md new file mode 100644 index 0000000000..35a778151b --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/usdt.md @@ -0,0 +1,52 @@ +import Button from '@site/src/components/button' + +# USDT 처리 + +## Tether + +스테이블코인은 가격을 안정적으로 유지하기 위해 법정 화폐나 금과 같은 자산에 1:1로 고정된 암호화폐의 일종입니다. 최근까지 jUSDT 토큰이 있었는데, 이는 [bridge.ton.org](bridge.ton.org)를 통해 이더리움 토큰을 브릿지한 ERC-20 기반의 래핑된 토큰입니다. 하지만 [2023년 4월 18일](https://t.me/toncoin/824), [Tether](https://tether.to/en/)사가 발행한 **네이티브** USD₮ 토큰의 공개 출시가 있었습니다. USD₮가 출시된 후 jUSDT는 우선순위가 두 번째로 밀렸지만 여전히 USD₮의 대안 또는 추가 수단으로 서비스에서 사용되고 있습니다. + +TON 블록체인에서는 USD₮가 [Jetton 자산](/develop/dapps/asset-processing/jettons)으로 지원됩니다. + +:::info +TON 블록체인에서 Tether의 USD₮ 토큰을 통합하려면 아래의 계약 주소를 사용하세요: +[EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs](https://tonviewer.com/EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs?section=jetton) +::: + + + + + +## TON에서의 USD₮ 장점 + +### 텔레그램과의 매끄러운 통합 + +[TON에서의 USD₮](https://ton.org/borderless)은 텔레그램과 원활하게 통합되어, TON을 USD₮ 거래에 가장 편리한 블록체인으로 만드는 사용자 친화적인 경험을 제공합니다. 이 통합을 통해 텔레그램 사용자가 DeFi를 더 쉽게 접근하고 이해할 수 있게 됩니다. + +### 낮은 트랜잭션 수수료 + +이더리움에서의 USD₮ 전송에 소비되는 수수료는 네트워크 부하에 따라 동적으로 계산됩니다. 이 때문에 트랜잭션 수수료가 높아질 수 있습니다. + +```cpp +transaction_fee = gas_used * gas_price +``` + +- 'gas_used'는 거래 실행 중에 사용된 가스 양입니다. +- `gas_price`는 Gwei 단위로 계산된 1단위 가스의 가격이며, 동적으로 계산됩니다. + +반면, TON 블록체인에서 USD₮를 전송하는 데 드는 평균 수수료는 현재 약 0.0145 TON입니다. TON의 가격이 100배 상승하더라도 거래는 여전히 [초저가](/develop/smart-contracts/fees#average-transaction-cost)로 유지될 것입니다. TON의 핵심 개발 팀은 Tether의 스마트 계약을 최적화하여 다른 Jetton보다 세 배 더 저렴하게 만들었습니다. + +### 속도와 확장성 + +TON의 높은 처리량과 빠른 확인 시간 덕분에 USD₮ 거래가 그 어느 때보다 빠르게 처리될 수 있습니다. + +## 고급 세부 정보 + +:::caution 중요 + +중요 [권장 사항](/개발/앱/자산 처리/제톤#제톤-지갑 처리)을 참조하세요. +::: + +## 참고 항목 + +- [결제 처리](/develop/dapps/asset-processing/) diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/developers.md b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/developers.md new file mode 100644 index 0000000000..3b85cf71e4 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/developers.md @@ -0,0 +1,162 @@ +# TON Connect SDKs + +## SDK List + +:::info +If possible, it is recommended to use the [@tonconnect/ui-react](/develop/dapps/ton-connect/developers#ton-connect-ui-react) kit for your dApps. Only switch to lower levels of the SDK or reimplement your version of the protocol if it is really necessary for your product. +::: + +This page contents the list of useful libraries for TON Connect. + +- [TON Connect React](/develop/dapps/ton-connect/developers#ton-connect-react) +- [TON Connect JS SDK](/develop/dapps/ton-connect/developers#ton-connect-js-sdk) +- [TON Connect Python SDK](/develop/dapps/ton-connect/developers#ton-connect-python) +- [TON Connect Dart](/develop/dapps/ton-connect/developers#ton-connect-dart) +- [TON Connect C#](/develop/dapps/ton-connect/developers#ton-connect-c) +- [TON Connect Unity](/develop/dapps/ton-connect/developers#ton-connect-unity) +- [TON Connect Go](/develop/dapps/ton-connect/developers#ton-connect-go) + +## TON Connect React + +- [@tonconnect/ui-react](/develop/dapps/ton-connect/developers#ton-connect-ui-react) - TON Connect User Interface (UI) for React applications + +TonConnect UI React is a React UI kit for TonConnect SDK. Use it to connect your app to TON wallets via TonConnect protocol in React apps. + +- `@tonconnect/ui-react`를 사용한 DApp의 예시: [GitHub](https://github.com/ton-connect/demo-dapp-with-react-ui) +- Example of deployed `demo-dapp-with-react-ui`: [GitHub](https://ton-connect.github.io/demo-dapp-with-react-ui/) + +```bash +npm i @tonconnect/ui-react +``` + +- [GitHub](https://github.com/ton-connect/sdk/tree/main/packages/ui-react) +- [NPM](https://www.npmjs.com/package/@tonconnect/ui-react) +- [API Documentation](https://ton-connect.github.io/sdk/modules/_tonconnect_ui_react.html) + +## TON Connect JS SDK + +The TON Connect repository contains following main packages: + +- [@tonconnect/ui](/develop/dapps/ton-connect/developers#ton-connect-ui) - TON Connect User Interface (UI) +- [@tonconnect/sdk](/develop/dapps/ton-connect/developers#ton-connect-sdk) - TON Connect SDK +- [@tonconnect/protocol](/develop/dapps/ton-connect/developers#ton-connect-protocol-models) - TON Connect protocol specifications + +### TON Connect UI + +TonConnect UI is a UI kit for TonConnect SDK. Use it to connect your app to TON wallets via TonConnect protocol. It allows you to integrate TonConnect to your app easier using our UI elements such as "connect wallet button", "select wallet dialog" and confirmation modals. + +```bash +npm i @tonconnect/ui +``` + +- [GitHub](https://github.com/ton-connect/sdk/tree/main/packages/ui) +- [NPM](https://www.npmjs.com/package/@tonconnect/ui) +- [API Documentation](https://ton-connect.github.io/sdk/modules/_tonconnect_ui.html) + +The TON Connect User Interface (UI) is a framework that allows developers to improve the user experience (UX) for application users. + +TON Connect can easily be integrated with apps using simple UI elements such as the "connect wallet button", "select wallet dialog" and confirmation modals. Here are three main examples of how TON Connect improves UX in apps: + +- Example of app functionality in the DAppbrowser: [GitHub](https://ton-connect.github.io/demo-dapp/) +- Example of a backend partition of the DAppabove: [GitHub](https://github.com/ton-connect/demo-dapp-backend) +- Bridge server using Go: [GitHub](https://github.com/ton-connect/bridge) + +This kit will simplify the implementation of TON Connect in apps built for TON Blockchain. Standard frontend frameworks are supported, as well as applications that don’t use predetermined frameworks. + +### TON Connect SDK + +The most low-level of the three frameworks that helps developers integrate TON Connect into their applications is the TON Connect SDK. It is primarily used to connect apps to TON Wallets via the TON Connect protocol. + +- [GitHub](https://github.com/ton-connect/sdk/tree/main/packages/sdk) +- [NPM](https://www.npmjs.com/package/@tonconnect/sdk) + +### TON Connect protocol models + +This package contains protocol requests, protocol responses, event models and encoding and decoding functions. It can be used to integrate TON Connect to wallet apps written in TypeScript. In order to integrate TON Connect into a DAppthe [@tonconnect/sdk](https://www.npmjs.com/package/@tonconnect/sdk) should be used. + +- [GitHub](https://github.com/ton-connect/sdk/tree/main/packages/protocol) +- [NPM](https://www.npmjs.com/package/@tonconnect/protocol) + +## TON Connect Python + +### pytonconnect + +Python SDK for TON Connect 2.0. Analogue of the `@tonconnect/sdk` library. + +Use it to connect your app to TON wallets via TonConnect protocol. + +```bash +pip3 install pytonconnect +``` + +- [GitHub](https://github.com/XaBbl4/pytonconnect) + +### ClickoTON-Foundation tonconnect + +Library for connecting TON Connect to Python apps + +```bash +git clone https://github.com/ClickoTON-Foundation/tonconnect.git +pip install -e tonconnect +``` + +[GitHub](https://github.com/ClickoTON-Foundation/tonconnect) + +## TON Connect Dart + +Dart SDK for TON Connect 2.0. Analogue of the `@tonconnect/sdk` library. + +Use it to connect your app to TON wallets via TonConnect protocol. + +```bash + $ dart pub add darttonconnect +``` + +- [GitHub](https://github.com/romanovichim/dartTonconnect) + +## TON Connect C\# + +C# SDK for TON Connect 2.0. Analogue of the `@tonconnect/sdk` library. + +Use it to connect your app to TON wallets via TonConnect protocol. + +```bash + $ dotnet add package TonSdk.Connect +``` + +- [GitHub](https://github.com/continuation-team/TonSdk.NET/tree/main/TonSDK.Connect) + +## TON Connect Go + +Go SDK for TON Connect 2.0. + +Use it to connect your app to TON wallets via TonConnect protocol. + +```bash + go get github.com/cameo-engineering/tonconnect +``` + +- [GitHub](https://github.com/cameo-engineering/tonconnect) + +## General Questions and Concerns + +If any of our developers or community members encounter any additional issues during the implementation of TON Connect 2.0, please contact the [Tonkeeper developer](https://t.me/tonkeeperdev) channel. + +If you experience any additional issues, or would like to present a proposal on how to improve TON Connect 2.0, please contact us directly through the appropriate [GitHub directory](https://github.com/ton-connect/). + +## TON Connect Unity + +Unity asset for TON Connect 2.0. Uses `continuation-team/TonSdk.NET/tree/main/TonSDK.Connect`. + +Use it to integrate TonConnect protocol with your game. + +- [GitHub](https://github.com/continuation-team/unity-ton-connect) +- [Docs](https://docs.tonsdk.net/user-manual/unity-tonconnect-2.0/getting-started) + +## See Also + +- [Step by step guide for building your first web client](https://ton-community.github.io/tutorials/03-client/) +- [[YouTube] TON Smart Contracts | 10 | Telegram DApp[EN]](https://www.youtube.com/watch?v=D6t3eZPdgAU\&t=254s\&ab_channel=AlefmanVladimir%5BEN%5D) +- [Ton Connect Getting started](https://github.com/ton-connect/sdk/tree/main/packages/sdk) +- [Integration Manual](/develop/dapps/ton-connect/integration) +- [[YouTube] TON Dev Study TON Connect Protocol [RU]](https://www.youtube.com/playlist?list=PLyDBPwv9EPsCJ226xS5_dKmXXxWx1CKz_) diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/integration.md b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/integration.md new file mode 100644 index 0000000000..5f9ee299ff --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/integration.md @@ -0,0 +1,506 @@ +# Integration manual with the JavaScript SDK + +In this tutorial, we’ll create a sample web app that supports TON Connect 2.0 authentication. It will allow for signature verification to eliminate the possibility of fraudulent identity impersonation without agreement establishment between parties. + +## Documentation links + +1. [@tonconnect/sdk documentation](https://www.npmjs.com/package/@tonconnect/sdk) +2. [Wallet-application message exchange protocol](https://github.com/ton-connect/docs/blob/main/requests-responses.md) +3. [Tonkeeper implementation of wallet side](https://github.com/tonkeeper/wallet/tree/main/src/tonconnect) + +## Prerequisites + +In order for connectivity to be fluent between apps and wallets, the web app must make use of manifest that is accessible via wallet applications. The prerequisite to accomplish this is typically a host for static files. For example, say if a developer wants to make use of GitHub pages, or deploy their website using TON Sites hosted on their computer. This would therefore mean their web app site is publicly accessible. + +## Getting wallets support list + +To increase the overall adoption of TON Blockchain, it is necessary that TON Connect 2.0 is able to facilitate a vast number of application and wallet connectivity integrations. Of late and of significant importance, the ongoing development of TON Connect 2.0 has allowed for the connection of the Tonkeeper, TonHub, MyTonWallet and other wallets with various TON Ecosystem Apps. It is our mission to eventually allow for the exchange of data between applications and all wallet types built on TON via the TON Connect protocol. For now, this is realized by providing the ability for TON Connect to load an extensive list of available wallets currently operating within the TON Ecosystem. + +At the moment our sample web app enables the following: + +1. loads the TON Connect SDK (library meant to simplify integration), +2. creates a connector (currently without an application manifest), +3. loads a list of supported wallets (from [wallets.json on GitHub](https://raw.githubusercontent.com/ton-connect/wallets-list/main/wallets.json)). + +For learning purposes, let's take a looks at the HTML page described by the following code: + +```html + + + + + + + + + + +``` + +If you load this page in browser and look into console, you may get something like that: + +```bash +> Array [ {…}, {…} ] + +0: Object { name: "Tonkeeper", imageUrl: "https://tonkeeper.com/assets/tonconnect-icon.png", aboutUrl: "https://tonkeeper.com", … } + aboutUrl: "https://tonkeeper.com" + bridgeUrl: "https://bridge.tonapi.io/bridge" + deepLink: undefined + embedded: false + imageUrl: "https://tonkeeper.com/assets/tonconnect-icon.png" + injected: false + jsBridgeKey: "tonkeeper" + name: "Tonkeeper" + tondns: "tonkeeper.ton" + universalLink: "https://app.tonkeeper.com/ton-connect" +``` + +According to TON Connect 2.0 specifications, wallet app information always makes use of the following format: + +```js +{ + name: string; + imageUrl: string; + tondns?: string; + aboutUrl: string; + universalLink?: string; + deepLink?: string; + bridgeUrl?: string; + jsBridgeKey?: string; + injected?: boolean; // true if this wallet is injected to the webpage + embedded?: boolean; // true if the DAppis opened inside this wallet's browser +} +``` + +## Button display for various wallet apps + +Buttons may vary according to your web application design. +The current page produces the following result: + +```html + + + + + + + // highlight-start + + // highlight-end + + + // highlight-start +
+
+ // highlight-end + + + + +``` + +Please note the following: + +1. If the web page is displayed through a wallet application, it sets the property `embedded` option to `true`. This means it is important to highlight this login option because it's most commonly used. +2. If a specific wallet is built using only JavaScript (it has no `bridgeUrl`) and it hasn't set property `injected` (or `embedded`, for safety), then it is clearly inaccessible and the button should be disabled. + +## Connection without the app manifest + +In the instance the connection is made without the app manifest, the script should be changed as follows: + +```js + const $ = document.querySelector.bind(document); + + window.onload = async () => { + const connector = new TonConnectSDK.TonConnect(); + const walletsList = await connector.getWallets(); + + const unsubscribe = connector.onStatusChange( + walletInfo => { + console.log('Connection status:', walletInfo); + } + ); + + let buttonsContainer = $('#tonconnect-buttons'); + + for (let wallet of walletsList) { + let connectButton = document.createElement('button'); + connectButton.innerText = 'Connect with ' + wallet.name; + + if (wallet.embedded) { + // `embedded` means we are browsing the app from wallet application + // we need to mark this sign-in option somehow + connectButton.classList.add('featured'); + } + + // highlight-start + if (wallet.embedded || wallet.injected) { + connectButton.onclick = () => { + connectButton.disabled = true; + connector.connect({jsBridgeKey: wallet.jsBridgeKey}); + }; + } else if (wallet.bridgeUrl) { + connectButton.onclick = () => { + connectButton.disabled = true; + console.log('Connection link:', connector.connect({ + universalLink: wallet.universalLink, + bridgeUrl: wallet.bridgeUrl + })); + }; + } else { + // wallet app does not provide any auth method + connectButton.disabled = true; + } + // highlight-end + + buttonsContainer.appendChild(connectButton); + } + }; +``` + +Now that the above process has been carried out, status changes are being logged (to see whether TON Connect works or not). Showing the modals with QR codes for connectivity is out of the scope of this manual. For testing purposes, it is possible to use a browser extension or send a connection request link to the user’s phone by any means necessary (for example, using Telegram). +Note: we haven't created an app manifest yet. At this time, the best approach is to analyze the end result if this requirement is not fulfilled. + +### Logging in with Tonkeeper + +In order to log into Tonkeeper, the following link is created for authentication (provided below for reference): + +``` +https://app.tonkeeper.com/ton-connect?v=2&id=3c12f5311be7e305094ffbf5c9b830e53a4579b40485137f29b0ca0c893c4f31&r=%7B%22manifestUrl%22%3A%22null%2Ftonconnect-manifest.json%22%2C%22items%22%3A%5B%7B%22name%22%3A%22ton_addr%22%7D%5D%7D +``` + +When decoded, the `r` parameter produces the following JSON format: + +```js +{"manifestUrl":"null/tonconnect-manifest.json","items":[{"name":"ton_addr"}]} +``` + +Upon clicking the mobile phone link, Tonkeeper automatically opens and then closes, dismissing the request. Additionally, the following error appears in the web app page console: +`Error: [TON_CONNECT_SDK_ERROR] Can't get null/tonconnect-manifest.json`. + +This means the application manifest must be available for download. + +## Connection with using app manifest + +Starting from this point forward, it is necessary to host user files (mostly tonconnect-manifest.json) somewhere. In this instance we’ll use the manifest from another web application. This however is not recommended for production environments, but allowed for testing purposes. + +The following code snippet: + +```js + window.onload = async () => { + const connector = new TonConnectSDK.TonConnect(); + + const walletsList = await connector.getWallets(); + + const unsubscribe = connector.onStatusChange( + walletInfo => { + console.log('Connection status:', walletInfo); + } + ); +``` + +Must be replaced with this version: + +```js + window.onload = async () => { + const connector = new TonConnectSDK.TonConnect({manifestUrl: 'https://ratingers.pythonanywhere.com/ratelance/tonconnect-manifest.json'}); + // highlight-next-line + window.connector = connector; // for experimenting in browser console + + const walletsList = await connector.getWallets(); + + const unsubscribe = connector.onStatusChange( + walletInfo => { + console.log('Connection status:', walletInfo); + } + ); + // highlight-next-line + connector.restoreConnection(); +``` + +In the newer version above, the storing `connector` variable in the `window` was added so it is accessible in the browser console. Additionally, the `restoreConnection` so users don’t have to log in on each web application page. + +### Logging in with Tonkeeper + +If we decline our request from wallet, The result that appeared in the console will `Error: [TON_CONNECT_SDK_ERROR] Wallet declined the request`. + +Therefore, the user is able to accept the same login request if the link is saved. This means the web app should be able to handle the authentication decline as non-final so it works correctly. + +Afterwards, the login request is accepted and is immediately reflected in the browser console as follows: + +```bash +22:40:13.887 Connection status: +Object { device: {…}, provider: "http", account: {…} } + account: Object { address: "0:b2a1ec...", chain: "-239", walletStateInit: "te6cckECFgEAAwQAAgE0ARUBFP8A9..." } + device: Object {platform: "android", appName: "Tonkeeper", appVersion: "2.8.0.261", …} + provider: "http" +``` + +The results above take the following into consideration: + +1. **Account**: information: contains the address (workchain+hash), network (mainnet/testnet), and the wallet stateInit that is used for public key extraction. +2. **Device**: information: contains the name and wallet application version (the name should be equal to what was requested initially, but this can be verified to ensure authenticity), and the platform name and supported features list. +3. **Provider**: contains http -- which allows all requests and responses between the wallet and web applications to be served over the bridge. + +## Logging out and requesting TonProof + +Now we have logged into our Mini App, but... how does the backend know that it is the correct party? To verify this we must request the wallet ownership proof. + +This can be completed only using authentication, so we must log out. Therefore, we run the following code in the console: + +```js +connector.disconnect(); +``` + +When the disconnection process is complete, the `Connection status: null` will be displayed. + +Before the TonProof is added, let's alter the code to show that the current implementation is insecure: + +```js +let connHandler = connector.statusChangeSubscriptions[0]; +connHandler({ + device: { + appName: "Uber Singlesig Cold Wallet App", + appVersion: "4.0.1", + features: [], + maxProtocolVersion: 3, + platform: "ios" + }, + account: { + /* TON Foundation address */ + address: '0:83dfd552e63729b472fcbcc8c45ebcc6691702558b68ec7527e1ba403a0f31a8', + chain: '-239', + walletStateInit: 'te6ccsEBAwEAoAAFcSoCATQBAgDe/wAg3SCCAUyXuiGCATOcurGfcbDtRNDTH9MfMdcL/+ME4KTyYIMI1xgg0x/TH9Mf+CMTu/Jj7UTQ0x/TH9P/0VEyuvKhUUS68qIE+QFUEFX5EPKj+ACTINdKltMH1AL7AOjRAaTIyx/LH8v/ye1UAFAAAAAAKamjF3LJ7WtipuLroUqTuQRi56Nnd3vrijj7FbnzOETSLOL/HqR30Q==' + }, + provider: 'http' +}); +``` + +The resulting lines of code in the console are almost identical to those displayed when the connection was initiated in the first place. Therefore, if the backend doesn't perform user authentication correctly as expected, a way to test if it is working correctly is required. To accomplish this, it is possible to act as the TON Foundation within the console, so the legitimacy of token balances and token ownership parameters can be tested. Naturally, the provided code doesn't change any variables in the connector, but the user is able to use the app as desired unless that connector is protected by the closure. Even if that is the case, it is not difficult to extract it using a debugger and coding breakpoints. + +Now that the authentication of the user has been verified, let's proceed to writing the code. + +## Connection using TonProof + +According to TON Connect’s SDK documentation, the second argument refers to the `connect()` method which contains a payload that will be wrapped and signed by the wallet. Therefore, the result is new connection code: + +```js + if (wallet.embedded || wallet.injected) { + connectButton.onclick = () => { + connectButton.disabled = true; + connector.connect({jsBridgeKey: wallet.jsBridgeKey}, + {tonProof: 'doc-example-'}); + }; + } else if (wallet.bridgeUrl) { + connectButton.onclick = () => { + connectButton.disabled = true; + console.log('Connection link:', connector.connect({ + universalLink: wallet.universalLink, + bridgeUrl: wallet.bridgeUrl + }, {tonProof: 'doc-example-'})); + }; +``` + +Connection link: + +``` +https://app.tonkeeper.com/ton-connect?v=2&id=4b0a7e2af3b455e0f0bafe14dcdc93f1e9e73196ae2afaca4d9ba77e94484a44&r=%7B%22manifestUrl%22%3A%22https%3A%2F%2Fratingers.pythonanywhere.com%2Fratelance%2Ftonconnect-manifest.json%22%2C%22items%22%3A%5B%7B%22name%22%3A%22ton_addr%22%7D%2C%7B%22name%22%3A%22ton_proof%22%2C%22payload%22%3A%22doc-example-%3CBACKEND_AUTH_ID%3E%22%7D%5D%7D +``` + +Expanded and simplified `r` parameter: + +```js +{ + "manifestUrl": + "https://ratingers.pythonanywhere.com/ratelance/tonconnect-manifest.json", + "items": [ + {"name": "ton_addr"}, + {"name": "ton_proof", "payload": "doc-example-"} + ] +} +``` + +Next, the url address link is sent to a mobile device and opened using Tonkeeper. + +After this process is complete, the following wallet-specific information is received: + +```js +{ + "device": { + "platform": "android", + "appName": "Tonkeeper", + "appVersion": "2.8.0.261", + "maxProtocolVersion": 2, + "features": [ + "SendTransaction" + ] + }, + "provider": "http", + "account": { + "address": "0:b2a1ecf5545e076cd36ae516ea7ebdf32aea008caa2b84af9866becb208895ad", + "chain": "-239", + "walletStateInit": "te6cckECFgEAAwQAAgE0ARUBFP8A9KQT9LzyyAsCAgEgAxACAUgEBwLm0AHQ0wMhcbCSXwTgItdJwSCSXwTgAtMfIYIQcGx1Z70ighBkc3RyvbCSXwXgA/pAMCD6RAHIygfL/8nQ7UTQgQFA1yH0BDBcgQEI9ApvoTGzkl8H4AXTP8glghBwbHVnupI4MOMNA4IQZHN0crqSXwbjDQUGAHgB+gD0BDD4J28iMFAKoSG+8uBQghBwbHVngx6xcIAYUATLBSbPFlj6Ahn0AMtpF8sfUmDLPyDJgED7AAYAilAEgQEI9Fkw7UTQgQFA1yDIAc8W9ADJ7VQBcrCOI4IQZHN0coMesXCAGFAFywVQA88WI/oCE8tqyx/LP8mAQPsAkl8D4gIBIAgPAgEgCQ4CAVgKCwA9sp37UTQgQFA1yH0BDACyMoHy//J0AGBAQj0Cm+hMYAIBIAwNABmtznaiaEAga5Drhf/AABmvHfaiaEAQa5DrhY/AABG4yX7UTQ1wsfgAWb0kK29qJoQICga5D6AhhHDUCAhHpJN9KZEM5pA+n/mDeBKAG3gQFImHFZ8xhAT48oMI1xgg0x/TH9MfAvgju/Jk7UTQ0x/TH9P/9ATRUUO68qFRUbryogX5AVQQZPkQ8qP4ACSkyMsfUkDLH1Iwy/9SEPQAye1U+A8B0wchwACfbFGTINdKltMH1AL7AOgw4CHAAeMAIcAC4wABwAORMOMNA6TIyx8Syx/L/xESExQAbtIH+gDU1CL5AAXIygcVy//J0Hd0gBjIywXLAiLPFlAF+gIUy2sSzMzJc/sAyEAUgQEI9FHypwIAcIEBCNcY+gDTP8hUIEeBAQj0UfKnghBub3RlcHSAGMjLBcsCUAbPFlAE+gIUy2oSyx/LP8lz+wACAGyBAQjXGPoA0z8wUiSBAQj0WfKnghBkc3RycHSAGMjLBcsCUAXPFlAD+gITy2rLHxLLP8lz+wAACvQAye1UAFEAAAAAKamjFyM60x2mt5eboNyOTE+5RGOe9Ee2rK1Qcb+0ZuiP9vb7QJRlz/c=" + }, + "connectItems": { + "tonProof": { + "name": "ton_proof", + "proof": { + "timestamp": 1674392728, + "domain": { + "lengthBytes": 28, + "value": "ratingers.pythonanywhere.com" + }, + "signature": "trCkHit07NZUayjGLxJa6FoPnaGHkqPy2JyNjlUbxzcc3aGvsExCmHXi6XJGuoCu6M2RMXiLzIftEm6PAoy1BQ==", + "payload": "doc-example-" + } + } + } +} +``` + +서명을 검증하기 위해 Python을 사용할 수 있습니다. 이는 백엔드와 쉽게 상호작용할 수 있기 때문입니다. 이 과정을 수행하기 위해 필요한 라이브러리는 `tonsdk`와 `pynacl`입니다. + +Next, it is necessary to retrieve the wallet's public key. To accomplish this, `tonapi.io` or similar services are not used because the end result cannot be reliably trusted. Instead, this is accomplished by parsing the `walletStateInit`. + +It is also critical to ensure that the `address` and `walletStateInit` match, or the payload could be signed with their wallet key by providing their own wallet in the `stateInit` field and another wallet in the `address` field. + +The `StateInit` is made up of two reference types: one for code and one for data. In this context, the purpose is to retrieve the public key so the second reference (the data reference) is loaded. Then 8 bytes are skipped (4 bytes are used for the `seqno` field and 4 for `subwallet_id` in all modern wallet contracts) and the next 32 bytes are loaded (256 bits) -- the public key. + +```python +import nacl.signing +import tonsdk + +import hashlib +import base64 + +received_state_init = 'te6cckECFgEAAwQAAgE0ARUBFP8A9KQT9LzyyAsCAgEgAxACAUgEBwLm0AHQ0wMhcbCSXwTgItdJwSCSXwTgAtMfIYIQcGx1Z70ighBkc3RyvbCSXwXgA/pAMCD6RAHIygfL/8nQ7UTQgQFA1yH0BDBcgQEI9ApvoTGzkl8H4AXTP8glghBwbHVnupI4MOMNA4IQZHN0crqSXwbjDQUGAHgB+gD0BDD4J28iMFAKoSG+8uBQghBwbHVngx6xcIAYUATLBSbPFlj6Ahn0AMtpF8sfUmDLPyDJgED7AAYAilAEgQEI9Fkw7UTQgQFA1yDIAc8W9ADJ7VQBcrCOI4IQZHN0coMesXCAGFAFywVQA88WI/oCE8tqyx/LP8mAQPsAkl8D4gIBIAgPAgEgCQ4CAVgKCwA9sp37UTQgQFA1yH0BDACyMoHy//J0AGBAQj0Cm+hMYAIBIAwNABmtznaiaEAga5Drhf/AABmvHfaiaEAQa5DrhY/AABG4yX7UTQ1wsfgAWb0kK29qJoQICga5D6AhhHDUCAhHpJN9KZEM5pA+n/mDeBKAG3gQFImHFZ8xhAT48oMI1xgg0x/TH9MfAvgju/Jk7UTQ0x/TH9P/9ATRUUO68qFRUbryogX5AVQQZPkQ8qP4ACSkyMsfUkDLH1Iwy/9SEPQAye1U+A8B0wchwACfbFGTINdKltMH1AL7AOgw4CHAAeMAIcAC4wABwAORMOMNA6TIyx8Syx/L/xESExQAbtIH+gDU1CL5AAXIygcVy//J0Hd0gBjIywXLAiLPFlAF+gIUy2sSzMzJc/sAyEAUgQEI9FHypwIAcIEBCNcY+gDTP8hUIEeBAQj0UfKnghBub3RlcHSAGMjLBcsCUAbPFlAE+gIUy2oSyx/LP8lz+wACAGyBAQjXGPoA0z8wUiSBAQj0WfKnghBkc3RycHSAGMjLBcsCUAXPFlAD+gITy2rLHxLLP8lz+wAACvQAye1UAFEAAAAAKamjFyM60x2mt5eboNyOTE+5RGOe9Ee2rK1Qcb+0ZuiP9vb7QJRlz/c=' +received_address = '0:b2a1ecf5545e076cd36ae516ea7ebdf32aea008caa2b84af9866becb208895ad' + +state_init = tonsdk.boc.Cell.one_from_boc(base64.b64decode(received_state_init)) + +address_hash_part = base64.b16encode(state_init.bytes_hash()).decode('ascii').lower() +assert received_address.endswith(address_hash_part) + +public_key = state_init.refs[1].bits.array[8:][:32] + +print(public_key) +# bytearray(b'#:\xd3\x1d\xa6\xb7\x97\x9b\xa0\xdc\x8eLO\xb9Dc\x9e\xf4G\xb6\xac\xadPq\xbf\xb4f\xe8\x8f\xf6\xf6\xfb') + +verify_key = nacl.signing.VerifyKey(bytes(public_key)) +``` + +After the sequencing code above is implemented, the correct documentation is consulted to check which parameters are verified and signed using the wallet key: + +> ``` +> message = utf8_encode("ton-proof-item-v2/") ++ +> Address ++ +> AppDomain ++ +> Timestamp ++ +> Payload +> +> signature = Ed25519Sign( +> privkey, +> sha256(0xffff ++ utf8_encode("ton-connect") ++ sha256(message)) +> ) +> ``` + +> Whereby the: +> +> - `Address` denotes the wallet address encoded as a sequence: +> - `workchain`: 32-bit signed integer big endian; +> - `hash`: 256-bit unsigned integer big endian; +> - `AppDomain` is the Length ++ EncodedDomainName +> - `Length` uses a 32-bit value of utf-8 encoded app domain name length in bytes +> - `EncodedDomainName` id `Length`-byte utf-8 encoded app domain name +> - `Timestamp` denotes the 64-bit unix epoch time of the signing operation +> - `Payload` denotes a variable-length binary string +> - `utf8_encode` produces a plain byte string with no length prefixes. + +Let's reimplement this in Python. The endianness of some of the integers above is not specified, so several examples must be considered. Please refer to the following Tonkeeper implementation detailing some related examples: : [ConnectReplyBuilder.ts](https://github.com/tonkeeper/wallet/blob/77992c08c663dceb63ca6a8e918a2150c75cca3a/src/tonconnect/ConnectReplyBuilder.ts#L42). + +```python +received_timestamp = 1674392728 +signature = 'trCkHit07NZUayjGLxJa6FoPnaGHkqPy2JyNjlUbxzcc3aGvsExCmHXi6XJGuoCu6M2RMXiLzIftEm6PAoy1BQ==' + +message = (b'ton-proof-item-v2/' + + 0 .to_bytes(4, 'big') + si.bytes_hash() + + 28 .to_bytes(4, 'little') + b'ratingers.pythonanywhere.com' + + received_timestamp.to_bytes(8, 'little') + + b'doc-example-') +# b'ton-proof-item-v2/\x00\x00\x00\x00\xb2\xa1\xec\xf5T^\x07l\xd3j\xe5\x16\xea~\xbd\xf3*\xea\x00\x8c\xaa+\x84\xaf\x98f\xbe\xcb \x88\x95\xad\x1c\x00\x00\x00ratingers.pythonanywhere.com\x984\xcdc\x00\x00\x00\x00doc-example-' + +signed = b'\xFF\xFF' + b'ton-connect' + hashlib.sha256(message).digest() +# b'\xff\xffton-connectK\x90\r\xae\xf6\xb0 \xaa\xa9\xbd\xd1\xaa\x96\x8b\x1fp\xa9e\xff\xdf\x81\x02\x98\xb0)E\t\xf6\xc0\xdc\xfdx' + +verify_key.verify(hashlib.sha256(signed).digest(), base64.b64decode(signature)) +# b'\x0eT\xd6\xb5\xd5\xe8HvH\x0b\x10\xdc\x8d\xfc\xd3#n\x93\xa8\xe9\xb9\x00\xaaH%\xb5O\xac:\xbd\xcaM' +``` + +After implementing the above parameters, if an attacker tries to impersonate a user and doesn't provide a valid signature, the following error will be displayed: `nacl.exceptions.BadSignatureError: Signature was forged or corrupt`. + +## Next steps + +When writing a dApp, the following should also be considered: + +- after a successful connection is completed (either a restored or new connection), the `Disconnect` button should be displayed instead of several `Connect` buttons +- after a user disconnects, `Disconnect` buttons will need to be recreated +- wallet code should be checked, because + - newer wallet versions could place public keys in a different location and create issues + - the current user may sign in using another type of contract instead of a wallet. Thankfully, this will contain the public key in the expected location + +Good luck and have fun writing dApps! diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/message-builders.mdx b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/message-builders.mdx new file mode 100644 index 0000000000..5ac1958434 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/message-builders.mdx @@ -0,0 +1,1798 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Preparing Messages + +While using TON Connect, you should construct the Message Body for the Payload used in various transactions. On this page you can find the most relevant examples of payload for use with the TON Connect SDKs. + +:::info +It is expected, that you learn basics on the creating TON Connect connection. Learn more with the [integration manual](/develop/dapps/ton-connect/integration). +::: + +## TON Connect JS SDK Examples + +### Transaction Template + +No matter what level of the task developer are solving, typically it is necessary to use connector entity from @tonconnect/sdk or @tonconnect/ui. +Examples created based on @tonconnect/sdk and @tonconnect/ui: + + + + + +```js +import { useTonConnectUI } from '@tonconnect/ui-react'; +const [tonConnectUI] = useTonConnectUI(); + +const transaction = { + //transaction body +} + +export const Settings = () => { + const [tonConnectUI, setOptions] = useTonConnectUI(); + + return ( +
+ +
+ ); +}; +``` + +
+ + +```js +import TonConnectUI from '@tonconnect/ui'; + +const tonConnectUI = new TonConnectUI({ //connect application + manifestUrl: 'https:///tonconnect-manifest.json', + buttonRootId: '' +}); + +const transaction = { + //transaction body +} + +const result = await tonConnectUI.sendTransaction(transaction) + +``` + + + + +```js +import TonConnect from '@tonconnect/sdk'; +const connector = new TonConnect(); + +await connector.sendTransaction({ + //transaction body +}) + +``` + + + +
+ +### Regular TON Transfer + +TON Connect SDKs include wrappers for sending messages, making it easy to prepare regular transfers of Toncoins between two wallets as default transaction without payload. + +A regular TON transfer using the TON Connect JS SDKs can be executed as follows: + + + + +```js +import { useTonConnectUI } from '@tonconnect/ui-react'; +const [tonConnectUI] = useTonConnectUI(); + +const transaction = { + messages: [ + { + address: "0:412410771DA82CBA306A55FA9E0D43C9D245E38133CB58F1457DFB8D5CD8892F", // destination address + amount: "20000000" //Toncoin in nanotons + } + ] + +} + +export const Settings = () => { + const [tonConnectUI, setOptions] = useTonConnectUI(); + + return ( +
+ +
+ ); +}; +``` + +
+ + + +```js +import TonConnectUI from '@tonconnect/ui'; + +const tonConnectUI = new TonConnectUI({ //connect application + manifestUrl: 'https:///tonconnect-manifest.json', + buttonRootId: '' +}); + +const transaction = { + messages: [ + { + address: "0:412410771DA82CBA306A55FA9E0D43C9D245E38133CB58F1457DFB8D5CD8892F", // destination address + amount: "20000000" //Toncoin in nanotons + } + ] +} + +const result = await tonConnectUI.sendTransaction(transaction) +``` + + + + + +```js +import TonConnect from '@tonconnect/sdk'; +const connector = new TonConnect(); + +await connector.sendTransaction({ + messages: [ + { + address: "0:412410771DA82CBA306A55FA9E0D43C9D245E38133CB58F1457DFB8D5CD8892F", // destination address + amount: "20000000" //Toncoin in nanotons + } + ] +}) + +``` + + +
+ +:::tip +Learn more about [TON Smart Contract Addresses](/learn/overviews/addresses). +::: + +For specific custom transaction, a certain payload must be defined. + +### Transfer With a Comment + +The simplest example is adding a payload with a comment. See more details on [this page](/develop/smart-contracts/guidelines/internal-messages#simple-message-with-comment). +Before transaction, it is necessary prepare a `body` [cell](/develop/data-formats/cell-boc) via the [@ton/ton](https://github.com/ton-org/ton) JavaScript library. + +```js +import { beginCell } from '@ton/ton' + +const body = beginCell() + .storeUint(0, 32) // write 32 zero bits to indicate that a text comment will follow + .storeStringTail("Hello, TON!") // write our text comment + .endCell(); +``` + +The transaction body is created by the following: + + + + + +```js +import { useTonConnectUI } from '@tonconnect/ui-react'; +import { toNano } from '@ton/ton' + +const myTransaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: destination, + amount: toNano(0.05).toString(), + payload: body.toBoc().toString("base64") // payload with comment in body + } + ] +} + +export const Settings = () => { + const [tonConnectUI, setOptions] = useTonConnectUI(); + + return ( +
+ +
+ ); +}; +``` + +
+ + + +```js +import TonConnectUI from '@tonconnect/ui' +import { toNano } from '@ton/ton' + +const transaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: destination, + amount: toNano(0.05).toString(), + payload: body.toBoc().toString("base64") // payload with comment in body + } + ] +} + +const result = await tonConnectUI.sendTransaction(transaction) +``` + + + + + +```js +import TonConnect from '@tonconnect/sdk'; +import { toNano } from '@ton/ton' + +const connector = new TonConnect(); + +await connector.sendTransaction({ + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: destination, + amount: toNano(0.05).toString(), + payload: body.toBoc().toString("base64") // payload with comment in body + } + ] +}) +``` + + +
+ +### Jetton Transfer + +`Jetton Transfer`([TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md#1-transfer))의 `body`는 일반적으로 다음과 같은 방식으로 작성되어야 합니다: + +```js + import { beginCell, toNano, Address } from '@ton/ton' + // transfer#0f8a7ea5 query_id:uint64 amount:(VarUInteger 16) destination:MsgAddress + // response_destination:MsgAddress custom_payload:(Maybe ^Cell) + // forward_ton_amount:(VarUInteger 16) forward_payload:(Either Cell ^Cell) + // = InternalMsgBody; + + const body = beginCell() + .storeUint(0xf8a7ea5, 32) // jetton transfer op code + .storeUint(0, 64) // query_id:uint64 + .storeCoins(1000000) // amount:(VarUInteger 16) - Jetton amount for transfer (decimals = 6 - jUSDT, 9 - default) + .storeAddress(Address.parse(Wallet_DST)) // destination:MsgAddress + .storeAddress(Address.parse(Wallet_SRC)) // response_destination:MsgAddress + .storeUint(0, 1) // custom_payload:(Maybe ^Cell) + .storeCoins(toNano(0.05)) // forward_ton_amount:(VarUInteger 16) - if >0, will send notification message + .storeUint(0,1) // forward_payload:(Either Cell ^Cell) + .endCell(); +``` + +Next, sending the transaction with this body to sender's jettonWalletContract executed: + + + + +```js +import { useTonConnectUI } from '@tonconnect/ui-react'; +import { toNano } from '@ton/ton' + +const myTransaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: jettonWalletContract, // sender jetton wallet + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with jetton transfer body + } + ] +} + +export const Settings = () => { + const [tonConnectUI, setOptions] = useTonConnectUI(); + + return ( +
+ +
+ ); +}; +``` + +
+ + + +```js +import TonConnectUI from '@tonconnect/ui' +import { toNano } from '@ton/ton' + +const transaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: jettonWalletContract, // sender jetton wallet + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with jetton transfer body + } + ] +} + +const result = await tonConnectUI.sendTransaction(transaction) +``` + + + + + +```js +import TonConnect from '@tonconnect/sdk'; +import { toNano } from '@ton/ton' + +const connector = new TonConnect(); +//... +await connector.sendTransaction({ + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: jettonWalletContract, // sender jetton wallet + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with jetton transfer body + } + ] +}) +``` + + +
+ +- `validUntil` - UNIX-time until message valid +- `jettonWalletAddress` - Address, JettonWallet address, that defined based on JettonMaser and Wallet contracts +- `balance` - Integer, amount of Toncoin for gas payments in nanotons. +- `body` - payload for the jettonContract + +
+ Jetton Wallet State Init and Address preparation example + +```js +import { Address, TonClient, beginCell, StateInit, storeStateInit } from '@ton/ton' + +async function main() { + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + apiKey: 'put your api key' + }) + + const jettonWalletAddress = Address.parse('Sender_Jetton_Wallet'); + let jettonWalletDataResult = await client.runMethod(jettonWalletAddress, 'get_wallet_data'); + jettonWalletDataResult.stack.readNumber(); + const ownerAddress = jettonWalletDataResult.stack.readAddress(); + const jettonMasterAddress = jettonWalletDataResult.stack.readAddress(); + const jettonCode = jettonWalletDataResult.stack.readCell(); + const jettonData = beginCell() + .storeCoins(0) + .storeAddress(ownerAddress) + .storeAddress(jettonMasterAddress) + .storeRef(jettonCode) + .endCell(); + + const stateInit: StateInit = { + code: jettonCode, + data: jettonData + } + + const stateInitCell = beginCell() + .store(storeStateInit(stateInit)) + .endCell(); + + console.log(new Address(0, stateInitCell.hash())); +} +``` + +
+ +### Jetton Transfer with Comment + +`Jetton Transfer`([TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md#1-transfer))에서 `messageBody`에 댓글을 추가하려면, 일반적인 전송 `body`에 더해 댓글을 직렬화하고 이를 `forwardPayload`에 포함시켜야 합니다. + +```js + import { beginCell, toNano, Address } from '@ton/ton' + // transfer#0f8a7ea5 query_id:uint64 amount:(VarUInteger 16) destination:MsgAddress + // response_destination:MsgAddress custom_payload:(Maybe ^Cell) + // forward_ton_amount:(VarUInteger 16) forward_payload:(Either Cell ^Cell) + // = InternalMsgBody; + + const destinationAddress = Address.parse('put destination wallet address'); + + const forwardPayload = beginCell() + .storeUint(0, 32) // 0 opcode means we have a comment + .storeStringTail('Hello, TON!') + .endCell(); + + const body = beginCell() + .storeUint(0xf8a7ea5, 32) // opcode for jetton transfer + .storeUint(0, 64) // query id + .storeCoins(toNano(5)) // jetton amount, amount * 10^9 + .storeAddress(destinationAddress) // TON wallet destination address + .storeAddress(destinationAddress) // response excess destination + .storeBit(0) // no custom payload + .storeCoins(toNano(0.02).toString()) // forward amount (if >0, will send notification message) + .storeBit(1) // we store forwardPayload as a reference + .storeRef(forwardPayload) + .endCell(); + +``` + +Next, sending the transaction with this body to sender's jettonWalletContract executed: + + + + +```js + import { useTonConnectUI } from '@tonconnect/ui-react'; + import { toNano } from '@ton/ton' + + + const jettonWalletContract = Address.parse('put your jetton wallet address'); + + const myTransaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: jettonWalletContract, // sender jetton wallet + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with jetton transfer and comment body + } + ] + } + + export const Settings = () => { + const [tonConnectUI, setOptions] = useTonConnectUI(); + + return ( +
+ +
+); +}; +``` + +
+ + + +```js + import TonConnectUI from '@tonconnect/ui' + import { toNano } from '@ton/ton' + + const transaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ +{ + address: jettonWalletContract, // sender jetton wallet + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with jetton transfer and comment body +} + ] +} + + const result = await tonConnectUI.sendTransaction(transaction) +``` + + + + + +```js + import TonConnect from '@tonconnect/sdk'; + import { toNano } from '@ton/ton' + + const connector = new TonConnect(); + //... + await connector.sendTransaction({ + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ +{ + address: jettonWalletContract, // sender jetton wallet + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with jetton transfer and comment body +} + ] +}) +``` + + +
+ +- `validUntil` - UNIX-time until message valid +- `jettonWalletAddress` - Address, JettonWallet address, that defined based on JettonMaser and Wallet contracts +- `balance` - Integer, amount of Toncoin for gas payments in nanotons. +- `body` - payload for the jettonContract + +
+ Jetton Wallet State Init and Address preparation example + +```js + import { Address, TonClient, beginCell, StateInit, storeStateInit } from '@ton/ton' + + async function main() { + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + apiKey: 'put your api key' +}) + + const jettonWalletAddress = Address.parse('Sender_Jetton_Wallet'); + let jettonWalletDataResult = await client.runMethod(jettonWalletAddress, 'get_wallet_data'); + jettonWalletDataResult.stack.readNumber(); + const ownerAddress = jettonWalletDataResult.stack.readAddress(); + const jettonMasterAddress = jettonWalletDataResult.stack.readAddress(); + const jettonCode = jettonWalletDataResult.stack.readCell(); + const jettonData = beginCell() + .storeCoins(0) + .storeAddress(ownerAddress) + .storeAddress(jettonMasterAddress) + .storeRef(jettonCode) + .endCell(); + + const stateInit: StateInit = { + code: jettonCode, + data: jettonData +} + + const stateInitCell = beginCell() + .store(storeStateInit(stateInit)) + .endCell(); + + console.log(new Address(0, stateInitCell.hash())); +} +``` + +
+ +### Jetton Burn + +`Jetton Burn`([TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md#2-burn))의 `body`는 일반적으로 다음과 같은 방식으로 작성되어야 합니다: + +```js + import { beginCell, Address } from '@ton/ton' +// burn#595f07bc query_id:uint64 amount:(VarUInteger 16) +// response_destination:MsgAddress custom_payload:(Maybe ^Cell) +// = InternalMsgBody; + + const body = beginCell() + .storeUint(0x595f07bc, 32) // jetton burn op code + .storeUint(0, 64) // query_id:uint64 + .storeCoins(1000000) // amount:(VarUInteger 16) - Jetton amount in decimal + .storeAddress(Address.parse(Wallet_SRC)) // response_destination:MsgAddress - owner's wallet + .storeUint(0, 1) // custom_payload:(Maybe ^Cell) - w/o payload typically + .endCell(); +``` + +Message places into the following request: + + + + +```js +import { useTonConnectUI } from '@tonconnect/ui-react'; +import { toNano } from '@ton/ton' + +const myTransaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: jettonWalletContract, // owner's jetton wallet + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with a jetton burn body + } + ] +} + +export const Settings = () => { + const [tonConnectUI, setOptions] = useTonConnectUI(); + + return ( +
+ +
+ ); +}; +``` + +
+ + + +```js +import TonConnectUI from '@tonconnect/ui' +import { toNano } from '@ton/ton' + +const transaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: jettonWalletContract, // owner's jetton wallet + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with a jetton burn body + } + ] +} + +const result = await tonConnectUI.sendTransaction(transaction) +``` + + + + + +```js +await connector.sendTransaction({ + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: jettonWalletContract, // owner's jetton wallet + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with a jetton burn body + } + ] +}) +``` + + +
+ +- `jettonWalletAddress` - Jetton Wallet contract address, that defined based on JettonMaser and Wallet contracts +- `amount` - Integer, amount of Toncoin for gas payments in nanotons. +- `body` - payload for the jetton wallet with the `burn#595f07bc` op code + +### NFT Transfer + +The `body` message typically should be done according the following way: + +```js +import { beginCell, toNano } from '@ton/ton' + +// transfer#5fcc3d14 query_id:uint64 new_owner:MsgAddress response_destination:MsgAddress custom_payload:(Maybe ^Cell) +// forward_amount:(VarUInteger 16) forward_payload:(Either Cell ^Cell) = InternalMsgBody; + + const body = beginCell() + .storeUint(0x5fcc3d14, 32) // NFT transfer op code 0x5fcc3d14 + .storeUint(0, 64) // query_id:uint64 + .storeAddress(Address.parse(NEW_OWNER_WALLET)) // new_owner:MsgAddress + .storeAddress(Address.parse(Wallet_DST)) // response_destination:MsgAddress + .storeUint(0, 1) // custom_payload:(Maybe ^Cell) + .storeCoins(toNano(0.000000001).toString()) // forward_amount:(VarUInteger 16) + .storeUint(0,1) // forward_payload:(Either Cell ^Cell) + .endCell(); +``` + +`WALLET_DST` - Address - The address of the initial NFT owner for the receiving excess +Transfer the `NFTitem` to a new owner `NEW_OWNER_WALLET`. + + + + +```js +import { useTonConnectUI } from '@tonconnect/ui-react'; +import { toNano } from '@ton/ton' + +const myTransaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: jettonWalletContract, // NFT Item address, which will be transferred + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with a NFT transfer body + } + ] +} + +export const Settings = () => { + const [tonConnectUI, setOptions] = useTonConnectUI(); + + return ( +
+ +
+ ); +}; +``` + +
+ + + +```js +import TonConnectUI from '@tonconnect/ui' +import { toNano } from '@ton/ton' + +const transaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: NFTitem, // NFT Item address, which will be transferred + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with a NFT transfer body + } + ] +} + +const result = await tonConnectUI.sendTransaction(transaction) +``` + + + + + +```js +await connector.sendTransaction({ + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: NFTitem, // NFT Item address, which will be transferred + amount: toNano(0.05).toString(), // for commission fees, excess will be returned + payload: body.toBoc().toString("base64") // payload with a NFT transfer body + } + ] +}) +``` + + +
+ +- `NFTitem` - Address - The address of NFT item smart contract which we want transfer to a new owner `NEW_OWNER_WALLET`. +- `balance` - Integer, amount of Toncoin for gas payments in nanotons. +- `body` - payload for the NFT contract + +### NFT Sale (GetGems) + +여기 GetGems 마켓플레이스에서 [nft-fixprice-sale-v3r2](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/nft-fixprice-sale-v3r2.fc) 계약에 따라 메시지와 거래를 준비하는 예시가 있습니다. + +To place NFT on GetGems Sale Contract, we should prepare special message body `transferNftBody` that will be transfer NFT to special NFT Sale Contract. + +```js + const transferNftBody = beginCell() + .storeUint(0x5fcc3d14, 32) // Opcode for NFT transfer + .storeUint(0, 64) // query_id + .storeAddress(Address.parse(destinationAddress)) // new_owner - GetGems sale contracts deployer, should never change for this operation + .storeAddress(Address.parse(walletAddress)) // response_destination for excesses + .storeBit(0) // we do not have custom_payload + .storeCoins(toNano(1).toString()) // forward_amount + .storeBit(0) // we store forward_payload is this cell + .storeUint(0x0fe0ede, 31) // not 32, because previous 0 will be read as do_sale opcode in deployer + .storeRef(stateInitCell) + .storeRef(saleBody) + .endCell(); +``` + +Because message requires a lot of steps, the entire algorithm huge and could be found here: + +
+ Show entire algorithm for the creating NFT Sale message body + +```js +import { Address, beginCell, StateInit, storeStateInit, toNano, Cell } from '@ton/ton' + +async function main() { + const fixPriceV3R2Code = Cell.fromBase64('te6cckECCwEAArkAART/APSkE/S88sgLAQIBIAIDAgFIBAUAfvIw7UTQ0wDTH/pA+kD6QPoA1NMAMMABjh34AHAHyMsAFssfUATPFljPFgHPFgH6AszLAMntVOBfB4IA//7y8AICzQYHAFegOFnaiaGmAaY/9IH0gfSB9AGppgBgYaH0gfQB9IH0AGEEIIySsKAVgAKrAQH30A6GmBgLjYSS+CcH0gGHaiaGmAaY/9IH0gfSB9AGppgBgYOCmE44BgAEqYhOmPhW8Q4YBKGATpn8cIxbMbC3MbK2QV44LJOZlvKAVxFWAAyS+G8BJrpOEBFcCBFd0VYACRWdjYKdxjgthOjq+G6hhoaYPqGAD9gHAU4ADAgB92YIQO5rKAFJgoFIwvvLhwiTQ+kD6APpA+gAwU5KhIaFQh6EWoFKQcIAQyMsFUAPPFgH6AstqyXH7ACXCACXXScICsI4XUEVwgBDIywVQA88WAfoCy2rJcfsAECOSNDTiWnCAEMjLBVADzxYB+gLLaslx+wBwIIIQX8w9FIKAejy0ZSzjkIxMzk5U1LHBZJfCeBRUccF8uH0ghAFE42RFrry4fUD+kAwRlAQNFlwB8jLABbLH1AEzxZYzxYBzxYB+gLMywDJ7VTgMDcowAPjAijAAJw2NxA4R2UUQzBw8AXgCMACmFVEECQQI/AF4F8KhA/y8AkA1Dg5ghA7msoAGL7y4clTRscFUVLHBRWx8uHKcCCCEF/MPRQhgBDIywUozxYh+gLLassfFcs/J88WJ88WFMoAI/oCE8oAyYMG+wBxUGZFFQRwB8jLABbLH1AEzxZYzxYBzxYB+gLMywDJ7VQAlsjLHxPLPyPPFlADzxbKAIIJycOA+gLKAMlxgBjIywUmzxZw+gLLaszJgwb7AHFVUHAHyMsAFssfUATPFljPFgHPFgH6AszLAMntVNZeZYk='); + + const marketplaceAddress = Address.parse('EQBYTuYbLf8INxFtD8tQeNk5ZLy-nAX9ahQbG_yl1qQ-GEMS'); // GetGems Address + const marketplaceFeeAddress = Address.parse('EQCjk1hh952vWaE9bRguFkAhDAL5jj3xj9p0uPWrFBq_GEMS'); // GetGems Address for Fees + const destinationAddress = Address.parse("EQAIFunALREOeQ99syMbO6sSzM_Fa1RsPD5TBoS0qVeKQ-AR"); // GetGems sale contracts deployer + + const walletAddress = Address.parse('EQArLGBnGPvkxaJE57Y6oS4rwzDWuOE8l8_sghntXLkIt162'); + const royaltyAddress = Address.parse('EQArLGBnGPvkxaJE57Y6oS4rwzDWuOE8l8_sghntXLkIt162'); + const nftAddress = Address.parse('EQCUWoe7hLlklVxH8gduCf45vPNocsjRP4wbX42UJ0Ja0S2f'); + const price = toNano(5).toString(); // 5 TON + + const feesData = beginCell() + .storeAddress(marketplaceFeeAddress) + // 5% - GetGems fee + .storeCoins(price / BigInt(100) * BigInt(5)) + .storeAddress(royaltyAddress) + // 5% - Royalty, can be changed + .storeCoins(price / BigInt(100) * BigInt(5)) + .endCell(); + + const saleData = beginCell() + .storeBit(0) // is_complete + .storeUint(Math.round(Date.now() / 1000), 32) // created_at + .storeAddress(marketplaceAddress) // marketplace_address + .storeAddress(nftAddress) // nft_address + .storeAddress(walletAddress) // previous_owner_address + .storeCoins(price) // full price in nanotons + .storeRef(feesData) // fees_cell + .storeBit(0) // can_be_deployed_externally + .endCell(); + + const stateInit: StateInit = { + code: fixPriceV3R2Code, + data: saleData + }; + const stateInitCell = beginCell() + .store(storeStateInit(stateInit)) + .endCell(); + + // not needed, just for example + const saleContractAddress = new Address(0, stateInitCell.hash()); + + const saleBody = beginCell() + .storeUint(1, 32) // just accept coins on deploy + .storeUint(0, 64) + .endCell(); + + const transferNftBody = beginCell() + .storeUint(0x5fcc3d14, 32) // Opcode for NFT transfer + .storeUint(0, 64) // query_id + .storeAddress(destinationAddress) // new_owner + .storeAddress(walletAddress) // response_destination for excesses + .storeBit(0) // we do not have custom_payload + .storeCoins(toNano(1).toString()) // forward_amount + .storeBit(0) // we store forward_payload is this cell + // not 32, because we stored 0 bit before | do_sale opcode for deployer + .storeUint(0x0fe0ede, 31) + .storeRef(stateInitCell) + .storeRef(saleBody) + .endCell(); +} +``` + +
+ +Prepared `transferNftBody` should be sent to the NFT Item Contract with at least `1.08` TON, that expected for success processing. Excess will be returned to a sender's wallet. + + + + +```js +import { useTonConnectUI } from '@tonconnect/ui-react'; +import { toNano } from '@ton/ton' + +const myTransaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: NFTitem, //address of the NFT Item contract, that should be placed on market + amount: toNano(1.08).toString(), // amount that will require on gas fees, excess will be return + payload: transferNftBody.toBoc().toString("base64") // payload with the transferNftBody message + } + ] +} + +export const Settings = () => { + const [tonConnectUI, setOptions] = useTonConnectUI(); + + return ( +
+ +
+ ); +}; +``` + +
+ + + +```js +import TonConnectUI from '@tonconnect/ui' +import { toNano } from '@ton/ton' + +const transaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: NFTitem, //address of NFT Item contract, that should be placed on market + amount: toNano(1.08).toString(), // amount that will require on gas fees, excess will be return + payload: transferNftBody.toBoc().toString("base64") // payload with the transferNftBody message + } + ] +} + +const result = await tonConnectUI.sendTransaction(transaction) +``` + + + + + +```js +await connector.sendTransaction({ + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: NFTitem, //address of NFT Item contract, that should be placed on market + amount: toNano(1.08).toString(), // amount that will require on gas fees, excess will be return + payload: transferNftBody.toBoc().toString("base64") // payload with the transferNftBody message + } + ] +}) +``` + + +
+ +### NFT Buy (GetGems) + +[nft-fixprice-sale-v3r2](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/nft-fixprice-sale-v3r2.fc) 판매 계약에서 NFT를 구매하는 과정은 페이로드가 없는 일반적인 전송으로 수행할 수 있으며, 중요한 것은 정확한 TON 금액입니다. 그 금액은 다음과 같이 계산됩니다:\ +`buyAmount = Nftprice TON + 1.0 TON` + + + + +```js +import { useTonConnectUI } from '@tonconnect/ui-react'; +import { toNano } from '@ton/ton' + +const myTransaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: nftSaleContract, // NFT Sale contract, that is current desired NFT Item + amount: toNano(buyAmount), // NFT Price + exactly 1 TON, excess will be returned + } + ] +} + +export const Settings = () => { + const [tonConnectUI, setOptions] = useTonConnectUI(); + + return ( +
+ +
+ ); +}; +``` + +
+ + + +```js +import TonConnectUI from '@tonconnect/ui' +import { toNano } from '@ton/ton' + +const transaction = { + validUntil: Math.floor(Date.now() / 1000) + 360, + messages: [ + { + address: nftSaleContract, // NFT Sale contract, that is current desired NFT Item + amount: toNano(buyAmount), // NFT Price + exactly 1 TON, excess will be returned + } + ] +} + +const result = await tonConnectUI.sendTransaction(transaction) +``` + + + + +```js +await connector.sendTransaction({ +validUntil: Math.floor(Date.now() / 1000) + 360, +messages: [ + { + address: nftSaleContract, // NFT Sale contract, that is current desired NFT Item + amount: toNano(buyAmount), // NFT Price + exactly 1 TON, excess will be returned + } +] +}) +``` + + +
+ +## TON Connect Python SDK + +Python examples are using [PyTonConnect](https://github.com/XaBbl4/pytonconnect) and [pytoniq](https://github.com/yungwine/pytoniq). + +```python + from pytoniq_core import Address + from pytonconnect import TonConnect +``` + +:::tip +Read examples [source](https://github.com/yungwine/ton-connect-examples/blob/master/main.py). +::: + +### Regular TON Transfer + +```python +connector = TonConnect( + manifest_url='https://raw.githubusercontent.com/XaBbl4/pytonconnect/main/pytonconnect-manifest.json') +is_connected = await connector.restore_connection() + +transaction = { + 'valid_until': int(time.time() + 3600), + 'messages': [ + { + 'address' :'0:0000000000000000000000000000000000000000000000000000000000000000', # destination address + 'amount' : 1000000000, # amount should be specified in nanocoins, 1 TON + } + ] +} +``` + +### Transfer With Comment + +At first order, implement a message with comment via the following function: + +```python + def get_comment_message(destination_address: str, amount: int, comment: str) -> dict: + + data = { + 'address': destination_address, + 'amount': str(amount), + 'payload': urlsafe_b64encode( + begin_cell() + .store_uint(0, 32) # op code for comment message + .store_string(comment) # store comment + .end_cell() # end cell + .to_boc() # convert it to boc + ) + .decode() # encode it to urlsafe base64 + } + + return data +``` + +Final transaction body for transfer with comment: + +```python +transaction = { + 'valid_until': int(time.time() + 3600), + 'messages': [ + get_comment_message( + destination_address='0:0000000000000000000000000000000000000000000000000000000000000000', + amount=int(0.01 * 10**9), # amount should be specified in nanocoins + comment='hello world!' + ) + ] +} +``` + +:::tip +Learn more about [TON Smart Contract Addresses](/learn/overviews/addresses). +::: + +### Jetton Transfer + +Jetton 전송 거래를 생성하는 함수 예시: + +```python +from pytoniq_core import begin_cell +from base64 import urlsafe_b64encode + +def get_jetton_transfer_message(jetton_wallet_address: str, recipient_address: str, transfer_fee: int, jettons_amount: int, response_address: str = None) -> dict: + data = { + 'address': jetton_wallet_address, + 'amount': str(transfer_fee), + 'payload': urlsafe_b64encode( + begin_cell() + .store_uint(0xf8a7ea5, 32) # op code for jetton transfer message + .store_uint(0, 64) # query_id + .store_coins(jettons_amount) + .store_address(recipient_address) # destination address + .store_address(response_address or recipient_address) # address send excess to + .store_uint(0, 1) # custom payload + .store_coins(1) # forward amount + .store_uint(0, 1) # forward payload + .end_cell() # end cell + .to_boc() # convert it to boc + ) + .decode() # encode it to urlsafe base64 + } + + return data +``` + +Final transaction body: + +```python +transaction = { + 'valid_until': int(time.time() + 3600), + 'messages': [ + get_jetton_transfer_message( + jetton_wallet_address='EQCXsVvdxTVmSIvYv4tTQoQ-0Yq9mERGTKfbsIhedbN5vTVV', + recipient_address='0:0000000000000000000000000000000000000000000000000000000000000000', + transfer_fee=int(0.07 * 10**9), + jettons_amount=int(0.01 * 10**9), # replace 9 for jetton decimal. For example for jUSDT it should be (amount * 10**6) + response_address=wallet_address + ), + ] +} + +``` + +### Jetton Burn + +Jetton 소각 거래를 생성하는 함수 예시: + +```python +from pytoniq_core import begin_cell +from base64 import urlsafe_b64encode + +def get_jetton_burn_message(jetton_wallet_address: str, transfer_fee: int, jettons_amount: int, response_address: str = None) -> dict: + data = { + 'address': jetton_wallet_address, + 'amount': str(transfer_fee), + 'payload': urlsafe_b64encode( + begin_cell() + .store_uint(0x595f07bc, 32) # op code for jetton burn message + .store_uint(0, 64) # query_id + .store_coins(jettons_amount) + .store_address(response_address) # address send excess to + .end_cell() # end cell + .to_boc() # convert it to boc + ) + .decode() # encode it to urlsafe base64 + } + return data +``` + +The final transaction body: + +```python +transaction = { + 'valid_until': int(time.time() + 3600), + 'messages': [ + get_jetton_burn_message( + jetton_wallet_address='EQCXsVvdxTVmSIvYv4tTQoQ-0Yq9mERGTKfbsIhedbN5vTVV', + transfer_fee=int(0.07 * 10 ** 9), + jettons_amount=int(0.01 * 10 ** 9), # replace 9 for jetton decimal. For example for jUSDT it should be (amount * 10**6) + response_address=wallet_address + ), + ] +} +``` + +### NFT Transfer + +Example of function for a NFT transfer transaction: + +```python +from pytoniq_core import begin_cell +from base64 import urlsafe_b64encode + + +def get_nft_transfer_message(nft_address: str, recipient_address: str, transfer_fee: int, response_address: str = None) -> dict: + data = { + 'address': nft_address, + 'amount': str(transfer_fee), + 'payload': urlsafe_b64encode( + begin_cell() + .store_uint(0x5fcc3d14, 32) # op code for nft transfer message + .store_uint(0, 64) # query_id + .store_address(recipient_address) # new owner + .store_address(response_address or recipient_address) # address send excess to + .store_uint(0, 1) # custom payload + .store_coins(1) # forward amount + .store_uint(0, 1) # forward payload + .end_cell() # end cell + .to_boc() # convert it to boc + ) + .decode() # encode it to urlsafe base64 + } + return data + +``` + +The final transaction body: + +```python +transaction = { + 'valid_until': int(time.time() + 3600), + 'messages': [ + get_nft_transfer_message( + nft_address='EQDrA-3zsJXTfGo_Vdzg8d07Da4vSdHZllc6W9qvoNoMstF-', + recipient_address='0:0000000000000000000000000000000000000000000000000000000000000000', + transfer_fee=int(0.07 * 10**9), + response_address=wallet_address + ), + ] +} +``` + +### NFT Sale (GetGems) + +여기 GetGems 마켓플레이스에서 [nft-fixprice-sale-v3r2](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/nft-fixprice-sale-v3r2.fc) 계약에 따라 메시지와 거래를 준비하는 예시가 있습니다. + +To place NFT on GetGems Sale Contract, we should prepare special message body `transferNftBody` that will be transfer NFT to special NFT Sale Contract. + +
+Example of creating NFT Sale Body + +```python +import time +from base64 import urlsafe_b64encode + +from pytoniq_core.boc import Cell, begin_cell, Address +from pytoniq_core.tlb import StateInit + + +def get_sale_body(wallet_address: str, royalty_address: str, nft_address: str, price: int, amount: int): + + # contract code + nft_sale_code_cell = Cell.one_from_boc('te6cckECCwEAArkAART/APSkE/S88sgLAQIBIAIDAgFIBAUAfvIw7UTQ0wDTH/pA+kD6QPoA1NMAMMABjh34AHAHyMsAFssfUATPFljPFgHPFgH6AszLAMntVOBfB4IA//7y8AICzQYHAFegOFnaiaGmAaY/9IH0gfSB9AGppgBgYaH0gfQB9IH0AGEEIIySsKAVgAKrAQH30A6GmBgLjYSS+CcH0gGHaiaGmAaY/9IH0gfSB9AGppgBgYOCmE44BgAEqYhOmPhW8Q4YBKGATpn8cIxbMbC3MbK2QV44LJOZlvKAVxFWAAyS+G8BJrpOEBFcCBFd0VYACRWdjYKdxjgthOjq+G6hhoaYPqGAD9gHAU4ADAgB92YIQO5rKAFJgoFIwvvLhwiTQ+kD6APpA+gAwU5KhIaFQh6EWoFKQcIAQyMsFUAPPFgH6AstqyXH7ACXCACXXScICsI4XUEVwgBDIywVQA88WAfoCy2rJcfsAECOSNDTiWnCAEMjLBVADzxYB+gLLaslx+wBwIIIQX8w9FIKAejy0ZSzjkIxMzk5U1LHBZJfCeBRUccF8uH0ghAFE42RFrry4fUD+kAwRlAQNFlwB8jLABbLH1AEzxZYzxYBzxYB+gLMywDJ7VTgMDcowAPjAijAAJw2NxA4R2UUQzBw8AXgCMACmFVEECQQI/AF4F8KhA/y8AkA1Dg5ghA7msoAGL7y4clTRscFUVLHBRWx8uHKcCCCEF/MPRQhgBDIywUozxYh+gLLassfFcs/J88WJ88WFMoAI/oCE8oAyYMG+wBxUGZFFQRwB8jLABbLH1AEzxZYzxYBzxYB+gLMywDJ7VQAlsjLHxPLPyPPFlADzxbKAIIJycOA+gLKAMlxgBjIywUmzxZw+gLLaszJgwb7AHFVUHAHyMsAFssfUATPFljPFgHPFgH6AszLAMntVNZeZYk=') + + # fees cell + + marketplace_address = Address('EQBYTuYbLf8INxFtD8tQeNk5ZLy-nAX9ahQbG_yl1qQ-GEMS') + marketplace_fee_address = Address('EQCjk1hh952vWaE9bRguFkAhDAL5jj3xj9p0uPWrFBq_GEMS') + destination_address = Address('EQAIFunALREOeQ99syMbO6sSzM_Fa1RsPD5TBoS0qVeKQ-AR') + + wallet_address = Address(wallet_address) + royalty_address = Address(royalty_address) + nft_address = Address(nft_address) + + marketplace_fee = int(price * 5 / 100) # 5% + royalty_fee = int(price * 5 / 100) # 5% + + fees_data_cell = (begin_cell() + .store_address(marketplace_fee_address) + .store_coins(marketplace_fee) + .store_address(royalty_address) + .store_coins(royalty_fee) + .end_cell()) + + + sale_data_cell = (begin_cell() + .store_bit_int(0) + .store_uint(int(time.time()), 32) + .store_address(marketplace_address) + .store_address(nft_address) + .store_address(wallet_address) + .store_coins(price) + .store_ref(fees_data_cell) + .store_bit_int(0) + .end_cell()) + + state_init_cell = StateInit(code=nft_sale_code_cell, data=sale_data_cell).serialize() + + sale_body = (begin_cell() + .store_uint(1, 32) + .store_uint(0, 64) + .end_cell()) + + transfer_nft_body = (begin_cell() + .store_uint(0x5fcc3d14, 32) + .store_uint(0, 64) + .store_address(destination_address) + .store_address(wallet_address) + .store_bit_int(0) + .store_coins(int(1 * 10**9)) + .store_bit_int(0) + .store_uint(0x0fe0ede, 31) + .store_ref(state_init_cell) + .store_ref(sale_body) + .end_cell()) + + data = { + 'address': nft_address.to_str(), + 'amount': str(amount), + 'payload': urlsafe_b64encode(transfer_nft_body.to_boc()).decode() + } + + return data +``` + +
+ +The final transaction body: + +```python +transaction = { + 'valid_until': int(time.time() + 3600), + 'messages': [ + get_sale_body( + nft_address='EQDrA-3zsJXTfGo_Vdzg8d07Da4vSdHZllc6W9qvoNoMstF-', + wallet_address='0:0000000000000000000000000000000000000000000000000000000000000000', + royalty_address='0:0000000000000000000000000000000000000000000000000000000000000000', + price=int(5 * 10**9), + amount=int(1.08 * 10**9) + ), + ] +} +``` + +### NFT Buy (GetGems) + +[nft-fixprice-sale-v3r2](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/nft-fixprice-sale-v3r2.fc) 판매 계약에서 NFT를 구매하는 과정은 페이로드가 없는 일반적인 전송으로 수행할 수 있으며, 중요한 것은 정확한 TON 금액입니다. 그 금액은 다음과 같이 계산됩니다:\ +`buyAmount = Nftprice TON + 1.0 TON` + +```python +transaction = { + 'valid_until': int(time.time() + 3600), + 'messages': [ + { + 'address': nft_address, + 'amount': buyAmount, + } + ] +} +``` + +## TON Connect Go SDK + +Go examples are using [tonconnect](https://github.com/cameo-engineering/tonconnect) and [tonutils-go](https://github.com/xssnick/tonutils-go). + +```go +import "github.com/cameo-engineering/tonconnect" +import "github.com/xssnick/tonutils-go/address" +``` + +:::tip +Read [tonconnect](https://github.com/cameo-engineering/tonconnect/blob/master/examples/basic/main.go) and [tonutils-go](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#how-to-use) examples. +::: + +There you can find how to create tonconnect session and send transaction constructed with messages. + +```go +s, _ := tonconnect.NewSession() +// create ton links +// ... +// create new message msg and transaction +boc, _ := s.SendTransaction(ctx, *tx) +``` + +In further examples only messages and transactions will be created. + +### Regular TON Transfer + +Example of function for building regular TON transfer message: + +```go +import ( + "fmt" + + "github.com/cameo-engineering/tonconnect" +) + +func Transfer(dest string, amount uint64) (*tonconnect.Message, error) { + msg, err := tonconnect.NewMessage( + dest, + fmt.Sprintf("%d", amount), // nanocoins to transfer/compute message + ) + return msg, err +} +``` + +Final transaction body: + +```go +msg, err := Transfer("0QBZ_35Wy144n2GBM93YpcV4KOKcIjDJk8DdX4kyXEEHcbLZ", uint64(math.Pow(10, 9))) +if err != nil { + log.Fatal(err) +} +tx, err := tonconnect.NewTransaction( + tonconnect.WithTimeout(10*time.Minute), + tonconnect.WithTestnet(), + tonconnect.WithMessage(*msg), +) +if err != nil { + log.Fatal(err) +} +``` + +### Transfer with Comment + +Example of function for building transfer with comment message: + +```go +import ( + "fmt" + + "github.com/cameo-engineering/tonconnect" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +func TransferWithComment(dest string, amount uint64, comment string) (*tonconnect.Message, error) { + payload, _ := cell.BeginCell(). + MustStoreUInt(0, 32). + MustStoreStringSnake(comment). + EndCell().MarshalJSON() + msg, err := tonconnect.NewMessage( + dest, + fmt.Sprintf("%d", amount), // nanocoins to transfer/compute message + tonconnect.WithPayload(payload)) + return msg, err +} +``` + +Final transaction body: + +```go +msg, err := TransferWithComment("0QBZ_35Wy144n2GBM93YpcV4KOKcIjDJk8DdX4kyXEEHcbLZ", uint64(math.Pow(10, 9)), "new comment") +if err != nil { + log.Fatal(err) +} +tx, err := tonconnect.NewTransaction( + tonconnect.WithTimeout(10*time.Minute), + tonconnect.WithTestnet(), + tonconnect.WithMessage(*msg), +) +if err != nil { + log.Fatal(err) +} +``` + +### Jetton Transfer + +Jetton 전송 메시지를 생성하는 함수 예시: + +```go +import ( + "fmt" + + "github.com/cameo-engineering/tonconnect" + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +func JettonTransferMessage(jetton_wallet_address string, amount uint64, + jettons_amount uint64, recipient_address, response_address string, + fwd_amount uint64, fwd_payload *cell.Cell) (*tonconnect.Message, error) { + payload, _ := cell.BeginCell(). + MustStoreUInt(0xf8a7ea5, 32). // op code for jetton transfer message (op::transfer) + MustStoreUInt(0, 64). // query_id + MustStoreCoins(jettons_amount). + MustStoreAddr(address.MustParseAddr(recipient_address)). // address send excess to + MustStoreAddr(address.MustParseAddr(response_address)). + MustStoreUInt(0, 1). // custom payload + MustStoreCoins(fwd_amount). // set 0 if don't want transfer notification + MustStoreMaybeRef(fwd_payload). + EndCell().MarshalJSON() + + msg, err := tonconnect.NewMessage( + jetton_wallet_address, + fmt.Sprintf("%d", amount), // nanocoins to transfer/compute message + tonconnect.WithPayload(payload)) + + if err != nil { + return nil, err + } + + return msg, nil +} +``` + +Final transaction body: + +```go +msg, err := JettonTransferMessage("kQA8Q7m_pSNPr6FcqRYxllpAZv-0ieXy_KYER2iP195hBXiX", + uint64(math.Pow(10, 9)), + uint64(10), + "0QBZ_35Wy144n2GBM93YpcV4KOKcIjDJk8DdX4kyXEEHcbL2", + "EQBuObr2M7glm08w6cBGjIuuCbmvBFGwuVs6qb3AQpac9XpX", + uint64(0), nil) +if err != nil { + log.Fatal(err) +} +tx, err := tonconnect.NewTransaction( + tonconnect.WithTimeout(10*time.Minute), + tonconnect.WithTestnet(), + tonconnect.WithMessage(*msg), +) +if err != nil { + log.Fatal(err) +} +``` + +### Jetton Burn + +Jetton 소각 메시지를 생성하는 함수 예시: + +```go +import ( + "fmt" + + "github.com/cameo-engineering/tonconnect" + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +func JettonBurnMessage(jetton_wallet_address string, amount uint64, + jettons_amount uint64, response_address string) (*tonconnect.Message, error) { + + payload, _ := cell.BeginCell(). + MustStoreUInt(0xf8a7ea5, 32). // op code for jetton burn message (op::burn) + MustStoreUInt(0, 64). // query_id + MustStoreCoins(jettons_amount). // jetton amount to burn + MustStoreAddr(address.MustParseAddr(response_address)). // address send excess to + EndCell().MarshalJSON() + + msg, err := tonconnect.NewMessage( + jetton_wallet_address, + fmt.Sprintf("%d", amount), // nanocoins to transfer/compute message + tonconnect.WithPayload(payload)) + + if err != nil { + return nil, err + } + + return msg, nil +} +``` + +Final transaction body: + +```go +msg, err := JettonBurnMessage("kQA8Q7m_pSNPr6FcqRYxllpAZv-0ieXy_KYER2iP195hBXiX", + uint64(math.Pow(10, 9)), + uint64(10), + "EQBuObr2M7glm08w6cBGjIuuCbmvBFGwuVs6qb3AQpac9XpX") +if err != nil { + log.Fatal(err) +} +tx, err := tonconnect.NewTransaction( + tonconnect.WithTimeout(10*time.Minute), + tonconnect.WithTestnet(), + tonconnect.WithMessage(*msg), +) +if err != nil { + log.Fatal(err) +} +``` + +### NFT Transfer + +Example of function for NFT transfer message: + +```go +import ( + "fmt" + + "github.com/cameo-engineering/tonconnect" + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +func NftTransferMessage(nft_address string, amount uint64, recipient_address, response_address string, + fwd_amount uint64, fwd_payload *cell.Cell) (*tonconnect.Message, error) { + + payload, _ := cell.BeginCell(). + MustStoreUInt(0x5fcc3d14, 32). // op code for nft transfer message (op::transfer()) + MustStoreUInt(0, 64). // query_id + MustStoreAddr(address.MustParseAddr(recipient_address)). // new owner + MustStoreAddr(address.MustParseAddr(response_address)). // address send excess to + MustStoreUInt(0, 1). // custom payload + MustStoreCoins(fwd_amount). // set 0 if don't want transfer notification + MustStoreMaybeRef(fwd_payload). + EndCell().MarshalJSON() + + msg, err := tonconnect.NewMessage( + nft_address, + fmt.Sprintf("%d", amount), // nanocoins to transfer/compute message + tonconnect.WithPayload(payload)) + + if err != nil { + return nil, err + } + + return msg, nil +} +``` + +Final transaction body: + +```go +msg, err := NftTransferMessage("EQDrA-3zsJXTfGo_Vdzg8d07Da4vSdHZllc6W9qvoNoMstF-", + uint64(math.Pow(10, 9)), + "0QBZ_35Wy144n2GBM93YpcV4KOKcIjDJk8DdX4kyXEEHcbL2", + "0QBZ_35Wy144n2GBM93YpcV4KOKcIjDJk8DdX4kyXEEHcbL2", + uint64(0), nil) +if err != nil { + log.Fatal(err) +} +tx, err := tonconnect.NewTransaction( + tonconnect.WithTimeout(10*time.Minute), + tonconnect.WithTestnet(), + tonconnect.WithMessage(*msg), +) +if err != nil { + log.Fatal(err) +} +``` + +### NFT Sale (GetGems) + +여기 GetGems 마켓플레이스에서 [nft-fixprice-sale-v3r2](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/nft-fixprice-sale-v3r2.fc) 계약에 따라 메시지와 거래를 준비하는 예시가 있습니다. + +To place NFT on GetGems Sale Contract, we should prepare special message body `transferNftBody` that will be transfer NFT to special NFT Sale Contract. + +```go +transferNftBody := cell.BeginCell(). + MustStoreUInt(0x5fcc3d14, 32). // opcode for NFT transfer + MustStoreUInt(0, 64). // query_id + MustStoreAddress(destinationAddress). // new_owner - GetGems sale contracts deployer, should never change for this operation + MustStoreAddress(walletAddress). // response_destination for excesses + MustStoreUInt(0, 1). // we do not have custom_payload + MustStoreCoins(1.08*math.Pow(10, 9)). // forward_amount + MustStoreUInt(0, 1). // we store forward_payload is this cell + MustStoreUInt(0x0fe0ede, 31). // not 32, because previous 0 will be read as do_sale opcode in deployer (op::do_sale) + MustStoreRef(stateInitCell). + MustStoreRef(saleBody). + EndCell() +``` + +Because message requires a lot of steps, the entire algorithm huge and could be found here: + +
+ Show entire algorithm for the creating NFT Sale message body + +```go +import ( + "fmt" + "math" + "time" + + "github.com/cameo-engineering/tonconnect" + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +func NftSaleMessage(wallet, royalty, nft string, amount, price uint64) (*tonconnect.Message, error) { + fixPriceV3R2Code := new(cell.Cell) + fixPriceV3R2Code.UnmarshalJSON([]byte("te6cckECCwEAArkAART/APSkE/S88sgLAQIBIAIDAgFIBAUAfvIw7UTQ0wDTH/pA+kD6QPoA1NMAMMABjh34AHAHyMsAFssfUATPFljPFgHPFgH6AszLAMntVOBfB4IA//7y8AICzQYHAFegOFnaiaGmAaY/9IH0gfSB9AGppgBgYaH0gfQB9IH0AGEEIIySsKAVgAKrAQH30A6GmBgLjYSS+CcH0gGHaiaGmAaY/9IH0gfSB9AGppgBgYOCmE44BgAEqYhOmPhW8Q4YBKGATpn8cIxbMbC3MbK2QV44LJOZlvKAVxFWAAyS+G8BJrpOEBFcCBFd0VYACRWdjYKdxjgthOjq+G6hhoaYPqGAD9gHAU4ADAgB92YIQO5rKAFJgoFIwvvLhwiTQ+kD6APpA+gAwU5KhIaFQh6EWoFKQcIAQyMsFUAPPFgH6AstqyXH7ACXCACXXScICsI4XUEVwgBDIywVQA88WAfoCy2rJcfsAECOSNDTiWnCAEMjLBVADzxYB+gLLaslx+wBwIIIQX8w9FIKAejy0ZSzjkIxMzk5U1LHBZJfCeBRUccF8uH0ghAFE42RFrry4fUD+kAwRlAQNFlwB8jLABbLH1AEzxZYzxYBzxYB+gLMywDJ7VTgMDcowAPjAijAAJw2NxA4R2UUQzBw8AXgCMACmFVEECQQI/AF4F8KhA/y8AkA1Dg5ghA7msoAGL7y4clTRscFUVLHBRWx8uHKcCCCEF/MPRQhgBDIywUozxYh+gLLassfFcs/J88WJ88WFMoAI/oCE8oAyYMG+wBxUGZFFQRwB8jLABbLH1AEzxZYzxYBzxYB")) + + marketplaceAddress := address.MustParseAddr("EQBYTuYbLf8INxFtD8tQeNk5ZLy-nAX9ahQbG_yl1qQ-GEMS") // GetGems Address + marketplaceFeeAddress := address.MustParseAddr("EQCjk1hh952vWaE9bRguFkAhDAL5jj3xj9p0uPWrFBq_GEMS") // GetGems Address for Fees + destinationAddress := address.MustParseAddr("EQAIFunALREOeQ99syMbO6sSzM_Fa1RsPD5TBoS0qVeKQ-AR") // GetGems sale contracts deployer + + walletAddress := address.MustParseAddr(wallet) + royaltyAddress := address.MustParseAddr(royalty) + nftAddress := address.MustParseAddr(nft) + + feesData := cell.BeginCell(). + MustStoreAddr(marketplaceFeeAddress). + // 5% - GetGems fee + MustStoreCoins(price * 100 * 5). + MustStoreAddr(royaltyAddress). + // 5% - Royalty, can be changed + MustStoreCoins(price / 100 * 5). + EndCell() + + saleData := cell.BeginCell(). + MustStoreUInt(0, 1). // is_complete + MustStoreUInt(uint64(time.Now().UTC().Unix()), 32). // created_at + MustStoreAddr(marketplaceAddress). // marketplace_address + MustStoreAddr(nftAddress). // nft_address + MustStoreAddr(walletAddress). // previous_owner_address + MustStoreCoins(price). // full price in nanotons + MustStoreRef(feesData). // fees_cell + MustStoreUInt(0, 1). // can_be_deployed_externally + EndCell() + + stateInit := &tlb.StateInit{ + Data: saleData, + Code: fixPriceV3R2Code, + } + + stateInitCell, err := tlb.ToCell(stateInit) + if err != nil { + return nil, err + } + + // not needed, just for example + // saleContractAddress := address.NewAddress(0, 0, stateInitCell.Hash()) + + saleBody := cell.BeginCell(). + MustStoreUInt(1, 32). // just accept coins on deploy + MustStoreUInt(0, 64). + EndCell() + + transferNftBody, err := cell.BeginCell(). + MustStoreUInt(0x5fcc3d14, 32). // opcode for NFT transfer + MustStoreUInt(0, 64). // query_id + MustStoreAddr(destinationAddress). // new_owner - GetGems sale contracts deployer, should never change for this operation + MustStoreAddr(walletAddress). // response_destination for excesses + MustStoreUInt(0, 1). // we do not have custom_payload + MustStoreCoins(uint64(1*math.Pow(10, 9))). // forward_amount + MustStoreUInt(0, 1). // we store forward_payload is this cell + MustStoreUInt(0x0fe0ede, 31). // not 32, because previous 0 will be read as do_sale opcode in deployer (op::do_sale) + MustStoreRef(stateInitCell). + MustStoreRef(saleBody). + EndCell().MarshalJSON() + + if err != nil { + return nil, err + } + + msg, err := tonconnect.NewMessage( + nftAddress.String(), + fmt.Sprintf("%d", amount), + tonconnect.WithPayload(transferNftBody)) + + if err != nil { + return nil, err + } + + return msg, nil +} +``` + +The final transaction body: + +```go +msg, err := NftSaleMessage("EQArLGBnGPvkxaJE57Y6oS4rwzDWuOE8l8_sghntXLkIt162", + "EQArLGBnGPvkxaJE57Y6oS4rwzDWuOE8l8_sghntXLkIt162", + "EQCUWoe7hLlklVxH8gduCf45vPNocsjRP4wbX42UJ0Ja0S2f", + uint64(1.08*math.Pow(10, 9)), uint64(5*math.Pow(10, 9))) +if err != nil { + log.Fatal(err) +} +tx, err := tonconnect.NewTransaction( + tonconnect.WithTimeout(10*time.Minute), + tonconnect.WithTestnet(), + tonconnect.WithMessage(*msg), +) +if err != nil { + log.Fatal(err) +} +``` + +
+ +### NFT Buy (GetGems) + +[nft-fixprice-sale-v3r2](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/nft-fixprice-sale-v3r2.fc) 판매 계약에서 NFT를 구매하는 과정은 페이로드가 없는 일반적인 전송으로 수행할 수 있으며, 중요한 것은 정확한 TON 금액입니다. 그 금액은 다음과 같이 계산됩니다:\ +`buyAmount = Nftprice TON + 1.0 TON` + +```go +msg, err := tonconnect.NewMessage(nftAddress, buyAmount) +if err != nil { + log.Fatal(err) +} +tx, err := tonconnect.NewTransaction( + tonconnect.WithTimeout(10*time.Minute), + tonconnect.WithTestnet(), + tonconnect.WithMessage(*msg), +) +if err != nil { + log.Fatal(err) +} +``` + +## Authors + +- JavaScript examples provided by [@aSpite](https://t.me/aspite) +- Python examples provided by [@yunwine](https://t.me/yungwine) +- Go examples provided by [@gleb498](https://t.me/gleb498) + +## See Also + +- [TON Connect SDKs](/develop/dapps/ton-connect/developers) +- [TON Connect - Sending Messages](/develop/dapps/ton-connect/transactions) +- [Smart Contract Developmet - Sending Messages (Low Level)](/develop/smart-contracts/messages) +- [TON Jetton processing](/develop/dapps/asset-processing/jettons) +- [NFT processing on TON](/develop/dapps/asset-processing/nfts) diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx new file mode 100644 index 0000000000..4fe1ba4ab3 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx @@ -0,0 +1,113 @@ +import Button from '@site/src/components/button' + +# About TON Connect + +TON Connect is a powerful open-source toolkit that serves as a universal application authorization standard within the [TON](/learn/introduction) ecosystem, enabling users to securely and conveniently log into applications and services using their TON wallets instead of traditional logins and passwords. + +![](/img/docs/ton-connect/ton-connect-overview.png?raw=true) + +Feel free to use one of the following flows for integration of your application: + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Use Cases For Your DApp + +TON Ecosystem이 제공하는 DApp 통합을 위한 우수한 기능들을 탐구하세요. + +- **Traffic**. Drive additional user visits via crypto wallets that support TON Connect. +- **Authenticity**. Leverage TON user's wallets as ready-made accounts, removing the need for additional authentication steps and thus, boosting user experience. +- **결제**. Toncoin 또는 래핑된 스테이블 코인(jUSDC/jUSDT)을 사용하여 TON 블록체인을 통해 빠르고 안전하게 거래를 처리합니다. +- **Retention**. Enhance user retention through the in-app list-saving feature which allows users to keep track of recently opened and favorite apps. + +## For Wallet Developers + +If you are a wallet developer, you can connect your wallet to TON Connect and enable your users to interact with TON apps in a secure and convenient way, read how to [integrate TON Connect into your wallet](/develop/dapps/ton-connect/wallet/). + +## Success Stories + +- [GetGems — The Open Network Marketplace](https://getgems.io/) +- [STON.fi — AMM DEX for TON blockchain](https://ston.fi/) +- [Tonstarter](http://tonstarter.com/) + +
+ Show the entire list + +- [getgems.io](https://getgems.io/) +- [fragment.com](https://fragment.com/) (Ton Connect v.1) +- [ston.fi](https://ston.fi/) +- [ton.diamonds](https://ton.diamonds/) +- [beta.disintar.io](https://beta.disintar.io/) +- [tegro.finance](https://tegro.finance/liquidity) +- [minter.ton.org](https://minter.ton.org/) +- [libermall.com](https://libermall.com/) +- [dedust.io](https://dedust.io/swap) +- [toncap.net](https://toncap.net/) +- [cryptomus.com](https://cryptomus.com/) +- [avanchange.com](https://avanchange.com/) +- [wton.dev](https://wton.dev/) +- [mint.spiroverse.io/shop](https://mint.spiroverse.io/shop) +- [vk.com/vk_nft_hub](https://vk.com/vk_nft_hub) +- [tonverifier.live](https://verifier.ton.org/) +- [stickerface.io/member](https://stickerface.io/member) +- [tonstarter.com](https://tonstarter.com/) +- [cryptogas.shop/ton](https://cryptogas.shop/ton) +- [megaton.fi](https://megaton.fi/) +- [dns.ton.org](https://dns.ton.org/) +- [coinpaymaster.com](https://coinpaymaster.com/) +- [ton.gagarin.world/app/](https://ton.gagarin.world/app) +- [daolama.co](https://daolama.co/) +- [marketplace.playmuse.org](http://marketplace.playmuse.org/) +- [ton.vote](https://ton.vote/) +- [plane.tonfancy.io](https://plane.tonfancy.io/) +- [pi.oberton.io](https://pi.oberton.io/) +- [business.thetonpay.app](https://business.thetonpay.app/) +- [bridge.orbitchain.io](https://bridge.orbitchain.io/) +- [connecton-web-new.vercel.app](https://connecton-web-new.vercel.app/) +- [app.fanz.ee/staking](https://app.fanz.ee/staking) +- [testnet.pton.fi](https://testnet.pton.fi/) +- [tonft.app](https://tonft.app/) +- [cardify.casino](https://cardify.casino/) +- [4riends.org](https://4riends.org/#/) +- [tonflex.fi](https://tonflex.fi/swap) +- [soquest.xyz](https://soquest.xyz/) +- [app.evaa.finance](https://app.evaa.finance/) + +
+ +## Join the TON Ecosystem + +To connect your service with the TON Ecosystem, you need to implement the following: + +- **TON Connect**. Incorporate the TON Connect protocol within your application. +- **Transactions**. Create specified transaction messages using TON libraries. Dive into the process of [sending messages](/develop/dapps/ton-connect/message-builders) with our comprehensive guide. +- **Payments**. Process payments via the public API ([tonapi](https://tonapi.io/)) or your own indexer, for instance, [gobycicle](http://github.com/gobicycle/bicycle). Learn more from our extensive guide on [asset processing](/develop/dapps/asset-processing). diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/protocol/README.md b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/protocol/README.md new file mode 100644 index 0000000000..6bfcb404a1 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/protocol/README.md @@ -0,0 +1,55 @@ +# Protocol specifications + +Understand how TON Connect works under the hood. + +## Who is this section for? + +- If you implement a wallet +- If you develop an SDK +- If you want to learn how TON Connect works + +## Sections overview + +- [Protocol workflows](/develop/dapps/ton-connect/protocol/workflow) is an overview of all the protocols involved in TON Connect. +- [Bridge API](/develop/dapps/ton-connect/protocol/bridge) specifies how the data is transmitted between the app and the wallet. +- [Session protocol](/develop/dapps/ton-connect/protocol/session) ensures end-to-end encrypted communication over the bridge. +- [Requests protocol](/develop/dapps/ton-connect/protocol/requests-responses) defines requests and responses for the app and the wallet. +- [Wallet guidelines](/develop/dapps/ton-connect/protocol/wallet-guidelines) defines guidelines for wallet developers. + +## FAQ + +#### I am building an HTML/JS app, what should I read? + +Simply use the [Supported SDKs](/develop/dapps/ton-connect/developers) and do not worry about the underlying protocols. + +#### I need an SDK in my favorite language + +Please take the [JS SDK](/develop/dapps/ton-connect/developers) as a reference and check out the protocol docs above. + +#### How do you detect whether the app is embedded in the wallet? + +JS SDK does that for you; just get wallets list `connector.getWallets()` and check `embedded` property of the corresponding list item. If you build your own SDK you should check `window.[targetWalletJsBridgeKey].tonconnect.isWalletBrowser`. + +#### How do you detect if the wallet is a browser extension? + +Like with embedded apps (see above), JS SDK detects it for you via `injected` property of the corresponding `connector.getWallets()` list item. If you build your own SDK you should check that `window.[targetWalletJsBridgeKey].tonconnect` exists. + +#### How to implement backend authorization with tonconnect? + +[See an example of dapp-backend](https://github.com/ton-connect/demo-dapp-backend) + +#### How do I make my own bridge? + +You don’t need to, unless you are building a wallet. + +If you build a wallet, you will need to provide a bridge. See our [reference implementation in Go](https://github.com/ton-connect/bridge). + +Keep in mind that the wallet’s side of the bridge API is not mandated. + +빠른 시작을 위해 일반적으로 사용되는 TON Connect 브릿지 [https://bridge.tonapi.io/bridge](https://bridge.tonapi.io/bridge)을 사용할 수 있습니다. + +#### I make a wallet, how do I add it to the list of wallets? + +Submit a pull request for the [wallets-list](https://github.com/ton-blockchain/wallets-list) repository and fill our all the necessary metadata. + +Apps may also add wallets directly through the SDK. diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/protocol/wallet-guidelines.md b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/protocol/wallet-guidelines.md new file mode 100644 index 0000000000..ee2277dade --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/protocol/wallet-guidelines.md @@ -0,0 +1,61 @@ +# Wallet Guidelines + +## Networks + +### There aren't many networks. + +At the moment, there are only two networks - Mainnet and Testnet. +In the foreseeable future, the emergence of new Mainnet TON-like networks is not expected. Note that the current Mainnet has a built-in mechanism for alternative networks - workchains. + +### Hide the Testnet from ordinary users. + +Testnet is used exclusively by developers. Ordinary users should not see the Testnet. +This means that switching to Testnet should not be readily available and users SHOULD NOT be prompted to switch wallet to Testnet even if DAppis in Testnet. +Users switch to Testnet, don't understand this action, can't switch back to Mainnet. + +For these reasons, dapps do not need to switch networks in runtime, on the contrary, it is more preferable to have different instances of DAppon different domains dapp.com, Testnet.dapp.com. +For the same reason there is no `NetworkChanged` or `ChainChanged` event in the Ton Connect protocol. + +### Do not send anything if the DAppis in Testnet and the wallet is in Mainnet. + +It is necessary to prevent loss of funds when DApptries to send a transaction in Testnet, and the wallet sends it in Mainnet. + +Dapps should explicitly indicate `network` field in `SendTransaction` request. + +If the `network` parameter is set, but the wallet has a different network set, the wallet should show an alert and DO NOT ALLOW TO SEND this transaction. + +The wallet SHOULD NOT offer to switch to another network in this case. + +## Multi accounts + +Multiple network accounts can be created for one key pair. Implement this functionality in your wallet - users will find it useful. + +### In general, there is no current "active" account + +At the moment, the TON Connect is not built on the paradigm that there is one selected account in the wallet, and when the user switches to another account, the `AccountChanged` event is sent to dapp. + +We think of a wallet as a physical wallet that can contain many "bank cards" (accounts). + +In most cases the sender address is not important to dapp, in these cases the user can select the appropriate account at the time of approving the transaction and the transaction will be sent from selected account. + +In some cases, it is important for DAppto send the transaction from a specific address, in which case it explicitly specifies the `from` field in `SendTransaction` request. If `from` parameter is set, the wallet should DO NOT ALLOW user to select the sender's address; If sending from the specified address is impossible, the wallet should show an alert and DO NOT ALLOW TO SEND this transaction. + +### Login flow + +When DAppconnects the wallet, the user selects in the wallet one of their accounts that they want to log into dapp. + +Regardless of what accounts the user uses next in the wallet, DAppworks with the account he received on the connection. + +Just like if you logged into a web service with one of your email accounts - if you then change the email account in the email service, the web service continues to use the one he got when you logged in. + +For this reason, the protocol does not provide the `AccountChanged` event. + +To switch account user need to disconnect (Log out) and connect (Login) again in DAppUI. + +We recommend wallets provide the ability to disconnect session with a specified DAppbecause the DAppmay have an incomplete UI. + +## See Also + +- [TON Connect Overview](/dapps/ton-connect/overview) +- [프로토콜 사양](/dapps/ton-connect/protocol/) +- [Connect a Wallet](/dapps/ton-connect/wallet) diff --git a/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/react.mdx b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/react.mdx new file mode 100644 index 0000000000..59563613e9 --- /dev/null +++ b/i18n/ko/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/react.mdx @@ -0,0 +1,332 @@ +# TON Connect for React + +Recommended SDK for React Apps is a [UI React SDK](/develop/dapps/ton-connect/developers#ton-connect-react). It is a React component that provides a high-level way to interact with TON Connect. + +## Implementation + +### 1. 설치 + +To start integrating TON Connect into your DApp, you need to install the `@tonconnect/ui-react` package. You can use npm or yarn for this purpose: + +```bash npm2yarn +npm i @tonconnect/ui-react +``` + +### 2. TON Connect 시작 + +After installing the package, you should create a `manifest.json` file for your application. More information on how to create a manifest.json file can be found [here](/develop/dapps/ton-connect/manifest). + +After creating the manifest file, import TonConnectUIProvider to the root of your Mini App and pass the manifest URL: + +```tsx +import { TonConnectUIProvider } from '@tonconnect/ui-react'; + +export function App() { + return ( + + { /* Your app */ } + + ); +} + +``` + +### 3. 지갑에 연결 + +Add the `TonConnectButton`. The TonConnect Button is a universal UI component for initializing a connection. After the wallet is connected, it transforms into a wallet menu. It is recommended to place it in the top right corner of your app. + +```tsx +export const Header = () => { + return ( +
+ My App with React UI + +
+ ); +}; +``` + +You can add className and style props to the button as well. Note that you cannot pass child to the TonConnectButton: + +```js + +``` + +Moreover, you always can initiate the connection manually, using `useTonConnectUI` hook and [connectWallet](https://github.com/ton-connect/sdk/tree/main/packages/ui#call-connect) method. + +### 4. 리다이렉트 + +If you want to redirect user to a specific page after wallet connection, you can use `useTonConnectUI` hook and [customize your return strategy](https://github.com/ton-connect/sdk/tree/main/packages/ui#add-the-return-strategy). + +#### Telegram Mini Apps + +If you want to redirect user to a [Telegram Mini App](/develop/dapps/telegram-apps/) after wallet connection, you can customize the `TonConnectUIProvider` element: + +```tsx + ' + }} + > + +``` + +[Open example on GitHub](https://github.com/ton-connect/demo-dapp-with-wallet/blob/master/src/App.tsx) + +### 5. UI 사용자 지정 + +To [customize UI](https://github.com/ton-connect/sdk/tree/main/packages/ui#ui-customisation) of the modal you can use `useTonConnectUI` hook and `setOptions` function. See more about useTonConnectUI hook in [Hooks](#hooks) section. + +## Hooks + +If you want to use some low-level TON Connect UI SDK features in your React app, you can use hooks from `@tonconnect/ui-react` package. + +### useTonAddress + +Use it to get user's current ton wallet address. Pass boolean parameter isUserFriendly to choose format of the address. If wallet is not connected hook will return empty string. + +```tsx +import { useTonAddress } from '@tonconnect/ui-react'; + +export const Address = () => { + const userFriendlyAddress = useTonAddress(); + const rawAddress = useTonAddress(false); + + return ( + userFriendlyAddress && ( +
+ User-friendly address: {userFriendlyAddress} + Raw address: {rawAddress} +
+ ) + ); +}; +``` + +### useTonWallet + +Use it to get user's current ton wallet. If wallet is not connected hook will return null. + +See all wallet's properties + +[Wallet interface](https://ton-connect.github.io/sdk/interfaces/_tonconnect_sdk.Wallet.html) +[WalletInfo interface](https://ton-connect.github.io/sdk/types/_tonconnect_sdk.WalletInfo.html) + +```tsx +import { useTonWallet } from '@tonconnect/ui-react'; + +export const Wallet = () => { + const wallet = useTonWallet(); + + return ( + wallet && ( +
+ Connected wallet: {wallet.name} + Device: {wallet.device.appName} +
+ ) + ); +}; +``` + +### useTonConnectUI + +Use it to get access to the `TonConnectUI` instance and UI options updating function. + +[See more about TonConnectUI instance methods](https://github.com/ton-connect/sdk/tree/main/packages/ui#send-transaction) + +[See more about setOptions function](https://github.com/ton-connect/sdk/tree/main/packages/ui#change-options-if-needed) + +```tsx +import { Locales, useTonConnectUI } from '@tonconnect/ui-react'; + +export const Settings = () => { + const [tonConnectUI, setOptions] = useTonConnectUI(); + + const onLanguageChange = (lang: string) => { + setOptions({ language: lang as Locales }); + }; + + return ( +
+ + +
+ + +
+
+ ); +}; +``` + +### useIsConnectionRestored + +Indicates current status of the connection restoring process. +You can use it to detect when connection restoring process if finished. + +```tsx +import { useIsConnectionRestored } from '@tonconnect/ui-react'; + +export const EntrypointPage = () => { + const connectionRestored = useIsConnectionRestored(); + + if (!connectionRestored) { + return Please wait...; + } + + return ; +}; +``` + +## Usage + +Let's take a look at how to use the React UI SDK on practice. + +### Sending transactions + +Send TON coins (in nanotons) to a specific address: + +```js +import { useTonConnectUI } from '@tonconnect/ui-react'; + +const transaction = { + messages: [ + { + address: "0:412410771DA82CBA306A55FA9E0D43C9D245E38133CB58F1457DFB8D5CD8892F", // destination address + amount: "20000000" //Toncoin in nanotons + } + ] + +} + +export const Settings = () => { + const [tonConnectUI, setOptions] = useTonConnectUI(); + + return ( +
+ +
+ ); +}; +``` + +- Get more examples here: [Preparing Messages](/develop/dapps/ton-connect/message-builders) + +### Understanding Transaction Status by Hash + +The principle located in Payment Processing (using tonweb). [See more](/develop/dapps/asset-processing/#checking-contracts-transactions) + +### Optional Check (ton_proof) on the Backend + +:::tip +Understand how to sign and verify messages: [Signing and Verification](/develop/dapps/ton-connect/sign) +::: + +Use `tonConnectUI.setConnectRequestParameters` function to pass your connect request parameters. + +This function takes one parameter: + +Set state to 'loading' while you are waiting for the response from your backend. If user opens connect wallet modal at this moment, he will see a loader. + +```ts +const [tonConnectUI] = useTonConnectUI(); + +tonConnectUI.setConnectRequestParameters({ + state: 'loading' +}); +``` + +or + +Set state to 'ready' and define `tonProof` value. Passed parameter will be applied to the connect request (QR and universal link). + +```ts +const [tonConnectUI] = useTonConnectUI(); + +tonConnectUI.setConnectRequestParameters({ + state: 'ready', + value: { + tonProof: '' + } +}); +``` + +or + +Remove loader if it was enabled via `state: 'loading'` (e.g. you received an error instead of a response from your backend). Connect request will be created without any additional parameters. + +```ts +const [tonConnectUI] = useTonConnectUI(); + +tonConnectUI.setConnectRequestParameters(null); +``` + +You can call `tonConnectUI.setConnectRequestParameters` multiple times if your tonProof payload has bounded lifetime (e.g. you can refresh connect request parameters every 10 minutes). + +```ts +const [tonConnectUI] = useTonConnectUI(); + +// enable ui loader +tonConnectUI.setConnectRequestParameters({ state: 'loading' }); + +// fetch you tonProofPayload from the backend +const tonProofPayload: string | null = await fetchTonProofPayloadFromBackend(); + +if (!tonProofPayload) { + // remove loader, connect request will be without any additional parameters + tonConnectUI.setConnectRequestParameters(null); +} else { + // add tonProof to the connect request + tonConnectUI.setConnectRequestParameters({ + state: "ready", + value: { tonProof: tonProofPayload } + }); +} + +``` + +You can find `ton_proof` result in the `wallet` object when wallet will be connected: + +```ts +import {useTonConnectUI} from "@tonconnect/ui-react"; + +const [tonConnectUI] = useTonConnectUI(); + +useEffect(() => + tonConnectUI.onStatusChange(wallet => { + if (wallet.connectItems?.tonProof && 'proof' in wallet.connectItems.tonProof) { + checkProofInYourBackend(wallet.connectItems.tonProof.proof, wallet.account); + } + }), []); +``` + +### Wallet Disconnection + +Call to disconnect the wallet: + +```js +import { useTonConnectUI } from '@tonconnect/ui-react'; + +const [tonConnectUI] = useTonConnectUI(); + +await tonConnectUI.disconnect(); +``` + +## API Documentation + +[Latest API documentation](https://ton-connect.github.io/sdk/modules/_tonconnect_ui_react.html) + +## Examples + +- Step-by-step [TON Hello World guide](https://ton-community.github.io/tutorials/03-client/) to create a simple DAppwith React UI. +- [Demo dApp](https://github.com/ton-connect/demo-dapp-with-react-ui) - `@tonconnect/ui-react`를 사용한 DApp 예시. +- [ton.vote](https://github.com/orbs-network/ton-vote) - Example of React website with TON Connect implementation. diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md b/i18n/pl/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md new file mode 100644 index 0000000000..d6d5f64219 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md @@ -0,0 +1,39 @@ +# Program lokalizacji + +Program tłumaczeń to wspólny wysiłek mający na celu przetłumaczenie różnych dokumentów związanych z TON na wiele języków, dzięki czemu strona jest bardziej dostępna dla miliardów osób nie mówiących po angielsku na całym świecie. + +## Filozofia projektowania systemu + +![jak to działa](/img/localizationProgramGuideline/localization-program.png) + +Program lokalizacji jest **uruchamiany** i **aktywnie utrzymywany** przez [**TownSquare Labs**](https://github.com/TownSquareXYZ), jednego z najbliższych partnerów **TON**. + +Jesteśmy zaangażowani w tworzenie otwartej infrastruktury dla wielojęzycznej współpracy społeczności, aby **awansować TON do lepszej fazy**, która obejmuje: + +1. **Odpowiedni dla wielojęzycznych społeczności**\ + Program obsługuje wiele języków, zapewniając integrację i łatwy dostęp dla użytkowników z różnych środowisk językowych. + +2. **Automatyzacja rozwoju, integracji i wdrażania**\ + Wykorzystując narzędzia do automatyzacji, program usprawnia procesy rozwoju, integracji i wdrażania, zmniejszając wysiłki manualne oraz zwiększając wydajność i spójność wszystkich działań lokalizacyjnych. + +3. **Rozdzielenie ról programisty, tłumacza i weryfikatora**\ + Nasze podejście rozdziela obowiązki programistów, tłumaczy i weryfikatorów, pozwalając każdej roli skupić się na swoich konkretnych zadaniach. Zapewnia to wysoką jakość tłumaczeń i płynną współpracę bez nakładania się lub konfliktu obowiązków. + +4. **Zachęta dla społeczności**\ + Zapewniamy zachęty dla członków społeczności, którzy przyczyniają się do procesu lokalizacji. Zachęca to do aktywnego uczestnictwa i nagradza tych, którzy pomagają ulepszać program, wspierając poczucie własności i ducha społeczności. + +5. **Integracja zaawansowanych systemów AI**\ + Zaawansowane systemy AI zwiększają dokładność i wydajność tłumaczenia poprzez dostarczanie inteligentnych sugestii i automatyzację powtarzalnych zadań, zapewniając wysokiej jakości wyniki przy mniejszym wysiłku. + +Ten projekt nie jest przeznaczony tylko dla osób posługujących się jednym językiem; naszym celem jest **służyć globalnemu ekosystemowi programistów**. + +## Podziękowania + +Jesteśmy bardzo wdzięczni tysiącom członków społeczności, którzy są kluczową częścią Programu Tłumaczeń. Chcemy docenić naszych tłumaczy i wspierać ich na ścieżce kariery. W niedalekiej przyszłości wyróżnimy naszych najlepszych tłumaczy, tworząc rankingi i listę wszystkich osób, które przyczyniły się do rozwoju Programu Tłumaczeń. + +## Przewodniki i zasoby + +Jeśli uczestniczą Państwo w Programie Tłumaczeń lub rozważają zaangażowanie się w niego, prosimy zapoznać się z poniższymi przewodnikami po tłumaczeniach: + +- [**Translation Style Guide**](/contribute/localization-program/translation-style-guide) - Instrukcje i wskazówki dla tłumaczy. +- [**Crowdin Online Editor Guide**](https://support.crowdin.com/online-editor/) - Szczegółowy przewodnik po korzystaniu z edytora Crowdin online i niektórych zaawansowanych funkcji Crowdin. diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md b/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md new file mode 100644 index 0000000000..a8e832ce87 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md @@ -0,0 +1,587 @@ +import Button from '@site/src/components/button' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Przetwarzanie płatności + +Ta strona **wyjaśnia, jak przetwarzać** (wysyłać i akceptować) "aktywa cyfrowe" na blockchainie TON. +Opisuje **głównie** jak pracować z `monetami TON`, ale **część teoretyczna** jest **ważna**, nawet jeśli chcą Państwo przetwarzać tylko `jettony`. + +## Inteligentny kontrakt portfela + +Inteligentne kontrakty Wallet to kontrakty w sieci TON, których zadaniem jest umożliwienie podmiotom spoza łańcucha bloków interakcji z podmiotami łańcucha bloków. Ogólnie rzecz biorąc, rozwiązują one trzy wyzwania: + +- uwierzytelnia właściciela: Odmawia przetwarzania i uiszczania opłat za wnioski osób niebędących właścicielami. +- Ochrona przed powtórzeniami: Zabrania powtarzalnego wykonywania jednego żądania, na przykład wysyłania aktywów do innego inteligentnego kontraktu. +- inicjuje dowolną interakcję z innymi inteligentnymi kontraktami. + +Standardowym rozwiązaniem dla pierwszego wyzwania jest kryptografia klucza publicznego: `wallet` przechowuje klucz publiczny i sprawdza, czy przychodząca wiadomość z żądaniem jest podpisana odpowiednim kluczem prywatnym, który jest znany tylko właścicielowi. + +Rozwiązanie trzeciego wyzwania jest również powszechne; ogólnie rzecz biorąc, żądanie zawiera w pełni uformowaną wewnętrzną wiadomość, którą `wallet` wysyła do sieci. Jednak w przypadku ochrony przed powtórkami istnieje kilka różnych podejść. + +### Portfele oparte na sekwencji + +Portfele oparte na Seqno stosują najprostsze podejście do sekwencjonowania wiadomości. Każda wiadomość ma specjalną liczbę całkowitą `seqno`, która musi pokrywać się z licznikiem przechowywanym w inteligentnym kontrakcie `wallet`. `wallet` aktualizuje swój licznik przy każdym żądaniu, zapewniając w ten sposób, że jedno żądanie nie zostanie przetworzone dwukrotnie. Istnieje kilka wersji `wallet`, które różnią się publicznie dostępnymi metodami: możliwość ograniczenia żądań według czasu wygaśnięcia oraz możliwość posiadania wielu portfeli z tym samym kluczem publicznym. Jednak nieodłącznym wymogiem tego podejścia jest wysyłanie żądań jedno po drugim, ponieważ każda luka w sekwencji `seqno` spowoduje niemożność przetworzenia wszystkich kolejnych żądań. + +### Portfele o dużym obciążeniu + +Ten typ `wallet` stosuje podejście oparte na przechowywaniu identyfikatora niewygasłych przetworzonych żądań w pamięci smart-contract. W tym podejściu każde żądanie jest sprawdzane pod kątem bycia duplikatem już przetworzonego żądania i, jeśli zostanie wykryta powtórka, jest odrzucane. Ze względu na wygaśnięcie, kontrakt może nie przechowywać wszystkich żądań na zawsze, ale usunie te, które nie mogą zostać przetworzone ze względu na limit wygaśnięcia. Żądania do tego "portfela" mogą być wysyłane równolegle bez zakłócania siebie nawzajem; jednak takie podejście wymaga bardziej zaawansowanego monitorowania przetwarzania żądań. + +### Wdrożenie portfela + +Aby wdrożyć portfel za pośrednictwem TonLib, należy: + +1. Proszę wygenerować parę kluczy prywatny/publiczny za pomocą funkcji [createNewKey](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L244) lub jej funkcji opakowujących (przykład w [tonlib-go](https://github.com/mercuryoio/tonlib-go/tree/master/v2#create-new-private-key)). Proszę zauważyć, że klucz prywatny jest generowany lokalnie i nie opuszcza komputera hosta. +2. Formularz [InitialAccountWallet](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L62) struktury odpowiadającej jednemu z włączonych `wallets`. Obecnie dostępne są `wallet.v3`, `wallet.v4`, `wallet.highload.v1`, `wallet.highload.v2`. +3. Proszę obliczyć adres nowego inteligentnego kontraktu `wallet` za pomocą metody [getAccountAddress](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L283). Zalecamy użycie domyślnej wersji `0`, a także wdrożenie portfeli w łańcuchu bazowym `workchain=0` w celu obniżenia opłat za przetwarzanie i przechowywanie. +4. Proszę wysłać Toncoin na obliczony adres. Proszę zauważyć, że należy wysłać je w trybie `non-bounce`, ponieważ ten adres nie ma jeszcze kodu, a zatem nie może przetwarzać przychodzących wiadomości. Flaga `non-bounce` wskazuje, że nawet jeśli przetwarzanie nie powiedzie się, pieniądze nie powinny zostać zwrócone z wiadomością bounce. Nie zalecamy używania flagi `non-bounce` w innych transakcjach, szczególnie w przypadku dużych kwot, ponieważ mechanizm bounce zapewnia pewien stopień ochrony przed błędami. +5. Proszę utworzyć żądaną [akcję](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L154), na przykład `actionNoop` tylko do wdrożenia. Następnie proszę użyć [createQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L292) i [sendQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L300), aby zainicjować interakcję z blockchainem. +6. Proszę sprawdzić umowę w ciągu kilku sekund za pomocą metody [getAccountState](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L288). + +:::tip +Proszę przeczytać więcej w [Wallet Tutorial] (/develop/smart-contracts/tutorials/wallet#-deploying-a-wallet). +::: + +### Proszę sprawdzić ważność adresu portfela + +Większość zestawów SDK wymusza weryfikację adresu (większość weryfikuje go podczas tworzenia portfela lub procesu przygotowywania transakcji), więc zazwyczaj nie wymaga to od użytkownika żadnych dodatkowych skomplikowanych kroków. + + + + + +```js + const TonWeb = require("tonweb") + TonWeb.utils.Address.isValid('...') +``` + + + + +```python +package main + +import ( + "fmt" + "github.com/xssnick/tonutils-go/address" +) + +if _, err := address.ParseAddr("EQCD39VS5j...HUn4bpAOg8xqB2N"); err != nil { + return errors.New("invalid address") +} +``` + + + + +```javascript +try { + Address.of("..."); + } catch (e) { + // not valid address +} +``` + + + + +```javascript + try { + AddrStd("...") + } catch(e: IllegalArgumentException) { + // not valid address + } +``` + + + + +:::tip +Pełny opis adresu na stronie [Smart Contract Addresses](/learn/overviews/addresses). +::: + +## Praca z transferami + +### Proszę sprawdzić transakcje kontraktu + +Transakcje kontraktu można uzyskać za pomocą [getTransactions](https://toncenter.com/api/v2/#/accounts/get_transactions_getTransactions_get). Metoda ta pozwala uzyskać 10 transakcji od pewnego `last_transaction_id` i wcześniejszych. Aby przetworzyć wszystkie przychodzące transakcje, należy wykonać następujące kroki: + +1. Najnowszy `last_transaction_id` można uzyskać za pomocą [getAddressInformation](https://toncenter.com/api/v2/#/accounts/get_address_information_getAddressInformation_get). +2. Lista 10 transakcji powinna zostać załadowana za pomocą metody `getTransactions`. +3. Przetwarzanie transakcji z niepustym źródłem w wiadomości przychodzącej i miejscem docelowym równym adresowi konta. +4. Należy wczytać kolejne 10 transakcji i powtarzać kroki 2,3,4,5 aż do przetworzenia wszystkich przychodzących transakcji. + +### Proszę pobrać transakcje przychodzące/wychodzące + +Możliwe jest śledzenie przepływu wiadomości podczas przetwarzania transakcji. Ponieważ przepływ wiadomości jest DAG, wystarczy pobrać bieżącą transakcję za pomocą metody [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) i znaleźć transakcję przychodzącą przez `out_msg` za pomocą [tryLocateResultTx](https://testnet.toncenter.com/api/v2/#/transactions/get_try_locate_result_tx_tryLocateResultTx_get) lub transakcje wychodzące przez `in_msg` za pomocą [tryLocateSourceTx](https://testnet.toncenter.com/api/v2/#/transactions/get_try_locate_source_tx_tryLocateSourceTx_get). + + + + +```ts +import { TonClient, Transaction } from '@ton/ton'; +import { getHttpEndpoint } from '@orbs-network/ton-access'; +import { CommonMessageInfoInternal } from '@ton/core'; + +async function findIncomingTransaction(client: TonClient, transaction: Transaction): Promise { + const inMessage = transaction.inMessage?.info; + if (inMessage?.type !== 'internal') return null; + return client.tryLocateSourceTx(inMessage.src, inMessage.dest, inMessage.createdLt.toString()); +} + +async function findOutgoingTransactions(client: TonClient, transaction: Transaction): Promise { + const outMessagesInfos = transaction.outMessages.values() + .map(message => message.info) + .filter((info): info is CommonMessageInfoInternal => info.type === 'internal'); + + return Promise.all( + outMessagesInfos.map((info) => client.tryLocateResultTx(info.src, info.dest, info.createdLt.toString())), + ); +} + +async function traverseIncomingTransactions(client: TonClient, transaction: Transaction): Promise { + const inTx = await findIncomingTransaction(client, transaction); + // now you can traverse this transaction graph backwards + if (!inTx) return; + await traverseIncomingTransactions(client, inTx); +} + +async function traverseOutgoingTransactions(client: TonClient, transaction: Transaction): Promise { + const outTxs = await findOutgoingTransactions(client, transaction); + // do smth with out txs + for (const out of outTxs) { + await traverseOutgoingTransactions(client, out); + } +} + +async function main() { + const endpoint = await getHttpEndpoint({ network: 'testnet' }); + const client = new TonClient({ + endpoint, + apiKey: '[API-KEY]', + }); + + const transaction: Transaction = ...; // Obtain first transaction to start traversing + await traverseIncomingTransactions(client, transaction); + await traverseOutgoingTransactions(client, transaction); +} + +main(); +``` + + + + +### Proszę wysyłać płatności + +1. Usługa powinna wdrożyć "portfel" i utrzymywać go w stanie finansowania, aby zapobiec zniszczeniu kontraktu z powodu opłat za przechowywanie. Proszę zauważyć, że opłaty za przechowywanie są zazwyczaj niższe niż 1 Toncoin rocznie. +2. Usługa powinna otrzymać od użytkownika `destination_address` i opcjonalnie `comment`. Proszę zauważyć, że w międzyczasie zalecamy zakazanie niedokończonych płatności wychodzących z tym samym zestawem (`destination_address`, `value`, `comment`) lub odpowiednie zaplanowanie tych płatności; w ten sposób następna płatność zostanie zainicjowana dopiero po potwierdzeniu poprzedniej. +3. Formularz [msg.dataText](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L103) z `komentarzem` jako tekstem. +4. Formularz [msg.message](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L113), który zawiera `destination_address`, pusty `public_key`, `amount` i `msg.dataText`. +5. Formularz [Action](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L154) zawierający zestaw wiadomości wychodzących. +6. Do wysyłania płatności wychodzących proszę używać zapytań [createQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L292) i [sendQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L300). +7. Usługa powinna regularnie sprawdzać metodę [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) dla kontraktu `wallet`. Dopasowanie potwierdzonych transakcji do wychodzących płatności według (`destination_address`, `value`, `comment`) pozwala oznaczyć płatności jako zakończone; wykryć i pokazać użytkownikowi odpowiedni hash transakcji i lt (czas logiczny). +8. Żądania do `v3` portfeli `high-load` mają domyślnie czas wygaśnięcia równy 60 sekund. Po tym czasie nieprzetworzone żądania mogą być bezpiecznie ponownie wysłane do sieci (proszę zobaczyć kroki 3-6). + +### Proszę pobrać identyfikator transakcji + +Może być niejasne, że aby uzyskać więcej informacji na temat transakcji, użytkownik musi przeskanować blockchain za pomocą funkcji [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get). +Niemożliwe jest pobranie identyfikatora transakcji natychmiast po wysłaniu wiadomości, ponieważ transakcja musi najpierw zostać potwierdzona przez sieć blockchain. +Aby zrozumieć wymagany potok, proszę uważnie przeczytać [Wyślij płatności] (https://docs.ton.org/develop/dapps/asset-processing/#send-payments), zwłaszcza punkt 7. + +## Podejście oparte na fakturach + +Aby akceptować płatności na podstawie załączonych komentarzy, usługa powinna + +1. Proszę wdrożyć kontrakt `wallet`. +2. Proszę wygenerować unikalną `fakturę` dla każdego użytkownika. Wystarczy ciąg znaków reprezentujący uuid32. +3. Użytkownicy powinni zostać poinstruowani, aby wysłać Toncoin do umowy "portfela" usługi z załączoną "fakturą" jako komentarzem. +4. Usługa powinna regularnie sprawdzać metodę [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) dla kontraktu `wallet`. +5. W przypadku nowych transakcji, przychodząca wiadomość powinna zostać wyodrębniona, `komentarz` dopasowany do bazy danych, a **wartość przychodzącej wiadomości** zdeponowana na koncie użytkownika. + +Aby obliczyć **wartość przychodzącej wiadomości**, którą wiadomość wnosi do umowy, należy przeanalizować transakcję. Dzieje się tak, gdy wiadomość trafia do kontraktu. Transakcję można uzyskać za pomocą [getTransactions](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L268). W przypadku przychodzącej transakcji portfela prawidłowe dane składają się z jednej wiadomości przychodzącej i zero wiadomości wychodzących. W przeciwnym razie albo wiadomość zewnętrzna zostanie wysłana do portfela, w którym to przypadku właściciel wyda Toncoin, albo portfel nie zostanie wdrożony, a transakcja przychodząca zostanie odrzucona. + +W każdym razie, ogólnie rzecz biorąc, kwota, którą wiadomość wnosi do kontraktu może być obliczona jako wartość wiadomości przychodzącej minus suma wartości wiadomości wychodzących minus opłata: `value_{in_msg} - SUM(value_{out_msg}) - fee`. Technicznie, reprezentacja transakcji zawiera trzy różne pola z `fee` w nazwie: `fee`, `storage_fee` i `other_fee`, czyli całkowitą opłatę, część opłaty związaną z kosztami przechowywania i część opłaty związaną z przetwarzaniem transakcji. Tylko pierwsza z nich powinna być używana. + +### Faktury z TON Connect + +Najlepiej nadaje się do aplikacji dApps, które muszą podpisywać wiele płatności/transakcji w ramach sesji lub muszą utrzymywać połączenie z portfelem przez pewien czas. + +- ✅ Istnieje stały kanał komunikacji z portfelem, informacje o adresie użytkownika + +- Użytkownicy muszą zeskanować kod QR tylko raz. + +- ✅ Możliwe jest sprawdzenie, czy użytkownik potwierdził transakcję w portfelu, śledzenie transakcji przez zwrócony BOC + +- Gotowe zestawy SDK i UI są dostępne dla różnych platform. + +- Jeśli wystarczy wysłać tylko jedną płatność, użytkownik musi wykonać dwie czynności: połączyć portfel i potwierdzić transakcję. + +- Integracja jest bardziej złożona niż link ton:// + +```mdx-code-block + +``` + +### Faktury z linkiem ton:// + +:::warning +Ton link jest przestarzały, proszę go nie używać +::: + +Jeśli potrzebują Państwo łatwej integracji dla prostego przepływu użytkowników, odpowiednie jest użycie łącza ton://. +Najlepiej nadaje się do jednorazowych płatności i faktur. + +```bash +ton://transfer/? + [nft=&] + [fee-amount=&] + [forward-amount=] +``` + +- Łatwa integracja + +- Nie ma potrzeby podłączania portfela + +- Użytkownicy muszą zeskanować nowy kod QR dla każdej płatności. + +- Nie jest możliwe śledzenie, czy użytkownik podpisał transakcję, czy nie. + +- Brak informacji o adresie użytkownika + +- Obejścia są potrzebne na platformach, na których takie linki nie są klikalne (np. wiadomości od botów dla klientów Telegram na komputery stacjonarne). + +[Więcej informacji na temat ton linków tutaj](https://github.com/tonkeeper/wallet-api#payment-urls) + +## Odkrywcy + +Eksplorator blockchain to https://tonscan.org. + +Aby wygenerować link do transakcji w eksploratorze, usługa musi uzyskać lt (czas logiczny), hash transakcji i adres konta (adres konta, dla którego lt i txhash zostały pobrane za pomocą metody [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get)). https://tonscan.org i https://explorer.toncoin.org/ mogą następnie wyświetlać stronę dla tego tx w następującym formacie: + +`https://tonviewer.com/transaction/{txhash as base64url}` + +`https://tonscan.org/tx/{lt as int}:{txhash as base64url}:{account address}` + +`https://explorer.toncoin.org/transaction?account={account address}<={lt as int}&hash={txhash as base64url}` + +## Najlepsze praktyki + +### Tworzenie portfela + + + + +- **toncenter:** + - [Utworzenie portfela + pobranie adresu portfela](https://github.com/toncenter/examples/blob/main/common.js) + +- **ton-community/ton:** + - [Utworzenie portfela + uzyskanie salda](https://github.com/ton-community/ton#usage) + + + + + +- **xssnick/tonutils-go:**. + - [Utworzenie portfela + uzyskanie salda](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#wallet) + + + + + +- **psylopunk/pythonlib:** + - [Utworzenie portfela + pobranie adresu portfela](https://github.com/psylopunk/pytonlib/blob/main/examples/generate_wallet.py) +- **yungwine/pytoniq:** + +```py +import asyncio + +from pytoniq.contract.wallets.wallet import WalletV4R2 +from pytoniq.liteclient.balancer import LiteBalancer + + +async def main(): + provider = LiteBalancer.from_mainnet_config(2) + await provider.start_up() + + mnemonics, wallet = await WalletV4R2.create(provider) + print(f"{wallet.address=} and {mnemonics=}") + + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + + + + +### Depozyty toncoinów (Zdobądź toncoiny) + + + + +- **toncenter:** + - [Przetwórz depozyt Toncoins](https://github.com/toncenter/examples/blob/main/deposits.js) + - [Przetwarzaj wpłaty Toncoins w wielu portfelach] (https://github.com/toncenter/examples/blob/main/deposits-multi-wallets.js) + + + + + +- **xssnick/tonutils-go:**. + +
+Depozyty czekowe + +```go +package main + +import ( + "context" + "encoding/base64" + "log" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/liteclient" + "github.com/xssnick/tonutils-go/ton" +) + +const ( + num = 10 +) + +func main() { + client := liteclient.NewConnectionPool() + err := client.AddConnectionsFromConfigUrl(context.Background(), "https://ton.org/global.config.json") + if err != nil { + panic(err) + } + + api := ton.NewAPIClient(client, ton.ProofCheckPolicyFast).WithRetry() + + accountAddr := address.MustParseAddr("0QA__NJI1SLHyIaG7lQ6OFpAe9kp85fwPr66YwZwFc0p5wIu") + + // we need fresh block info to run get methods + b, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + log.Fatal(err) + } + + // we use WaitForBlock to make sure block is ready, + // it is optional but escapes us from liteserver block not ready errors + res, err := api.WaitForBlock(b.SeqNo).GetAccount(context.Background(), b, accountAddr) + if err != nil { + log.Fatal(err) + } + + lastTransactionId := res.LastTxHash + lastTransactionLT := res.LastTxLT + + headSeen := false + + for { + trxs, err := api.ListTransactions(context.Background(), accountAddr, num, lastTransactionLT, lastTransactionId) + if err != nil { + log.Fatal(err) + } + + for i, tx := range trxs { + // should include only first time lastTransactionLT + if !headSeen { + headSeen = true + } else if i == 0 { + continue + } + + if tx.IO.In == nil || tx.IO.In.Msg.SenderAddr().IsAddrNone() { + // external message should be omitted + continue + } + + if tx.IO.Out != nil { + // no outgoing messages - this is incoming Toncoins + continue + } + + // process trx + log.Printf("found in transaction hash %s", base64.StdEncoding.EncodeToString(tx.Hash)) + } + + if len(trxs) == 0 || (headSeen && len(trxs) == 1) { + break + } + + lastTransactionId = trxs[0].Hash + lastTransactionLT = trxs[0].LT + } +} +``` + +
+
+ + + +- **yungwine/pytoniq:** + +Depozyty czekowe + +```python +import asyncio + +from pytoniq_core import Transaction + +from pytoniq import LiteClient, Address + +MY_ADDRESS = Address("kf8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM_BP") + + +async def main(): + client = LiteClient.from_mainnet_config(ls_i=0, trust_level=2) + + await client.connect() + + last_block = await client.get_trusted_last_mc_block() + + _account, shard_account = await client.raw_get_account_state(MY_ADDRESS, last_block) + assert shard_account + + last_trans_lt, last_trans_hash = ( + shard_account.last_trans_lt, + shard_account.last_trans_hash, + ) + + while True: + print(f"Waiting for{last_block=}") + + transactions = await client.get_transactions( + MY_ADDRESS, 1024, last_trans_lt, last_trans_hash + ) + toncoin_deposits = [tx for tx in transactions if filter_toncoin_deposit(tx)] + print(f"Got {len(transactions)=} with {len(toncoin_deposits)=}") + + for deposit_tx in toncoin_deposits: + # Process toncoin deposit transaction + print(deposit_tx.cell.hash.hex()) + + last_trans_lt = transactions[0].lt + last_trans_hash = transactions[0].cell.hash + + +def filter_toncoin_deposit(tx: Transaction): + if tx.out_msgs: + return False + + if tx.in_msg: + return False + + return True + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + +
+ +### Wypłaty toncoinów (proszę wysłać toncoiny) + + + + +- **toncenter:** + - [Wypłacanie toncoinów z portfela partiami](https://github.com/toncenter/examples/blob/main/withdrawals-highload-batch.js) + - [Wypłata toncoinów z portfela](https://github.com/toncenter/examples/blob/main/withdrawals-highload.js) + +- **ton-community/ton:** + - [Wypłata toncoinów z portfela](https://github.com/ton-community/ton#usage) + + + + + +- **xssnick/tonutils-go:**. + - [Wypłata toncoinów z portfela](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#wallet) + + + + + +- **psylopunk/pythonlib:** + - [Wypłata toncoinów z portfela](https://github.com/psylopunk/pytonlib/blob/main/examples/transactions.py) + +- **yungwine/pytoniq:** + +```python +import asyncio + +from pytoniq_core import Address +from pytoniq.contract.wallets.wallet import WalletV4R2 +from pytoniq.liteclient.balancer import LiteBalancer + + +MY_MNEMONICS = "one two tree ..." +DESTINATION_WALLET = Address("Destination wallet address") + + +async def main(): + provider = LiteBalancer.from_mainnet_config() + await provider.start_up() + + wallet = await WalletV4R2.from_mnemonic(provider, MY_MNEMONICS) + + await wallet.transfer(DESTINATION_WALLET, 5) + + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + + + + +### Proszę pobrać transakcje kontraktu + + + + +- **ton-community/ton:** + - [Klient z metodą getTransaction](https://github.com/ton-community/ton/blob/master/src/client/TonClient.ts) + + + + + +- **xssnick/tonutils-go:**. + - [Proszę pobrać transakcje](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#account-info-and-transactions) + + + + + +- **psylopunk/pythonlib:** + - [Proszę pobrać transakcje](https://github.com/psylopunk/pytonlib/blob/main/examples/transactions.py) +- **yungwine/pytoniq:** + - [Proszę pobrać transakcje](https://github.com/yungwine/pytoniq/blob/master/examples/transactions.py) + + + + + +## SDK + +Listę zestawów SDK dla różnych języków (JS, Python, Golang, C#, Rust itp.) można znaleźć [tutaj] (/develop/dapps/apis/sdk). diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md b/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md new file mode 100644 index 0000000000..53609e9509 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md @@ -0,0 +1,1205 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Button from '@site/src/components/button'; + +# Przetwarzanie TON Jetton + +:::info +Dla jasnego zrozumienia, czytelnik powinien być zaznajomiony z podstawowymi zasadami przetwarzania aktywów opisanymi w [sekcji przetwarzania płatności](/develop/dapps/asset-processing/) naszej dokumentacji. +::: + +Jettony to tokeny na TON Blockchain - można je traktować podobnie do tokenów ERC-20 na Ethereum. + +W tej analizie zagłębiamy się w formalne standardy wyszczególniające jetton [zachowanie](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) i [metadane](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md). +Mniej formalny przegląd architektury jetton skoncentrowany na shardingu można znaleźć w naszym wpisie na blogu +[anatomy of jettons](https://blog.ton.org/how-to-shard-your-ton-smart-contract-and-why-studying-the-anatomy-of-tons-jettons). + +Należy również pamiętać, że istnieją dwa podejścia do pracy z wypłatami jetton: + +- [Memo Deposits](https://github.com/toncenter/examples/blob/main/deposits-jettons.js) - Pozwala to na utrzymanie jednego portfela depozytowego, a użytkownicy dodają notatkę w celu identyfikacji przez system. Oznacza to, że nie trzeba skanować całego łańcucha bloków, ale jest to nieco mniej łatwe dla użytkowników. +- [Depozyty bez notatek](https://github.com/gobicycle/bicycle) - To rozwiązanie również istnieje, ale jest trudniejsze do zintegrowania. Możemy jednak w tym pomóc, jeśli wolą Państwo wybrać tę drogę. Proszę powiadomić nas przed podjęciem decyzji o wdrożeniu tego podejścia. + +## Architektura Jetton + +Standardowe tokeny w TON są wdrażane przy użyciu zestawu inteligentnych kontraktów, w tym: + +- Inteligentny kontrakt [Jetton master](https://github.com/ton-blockchain/token-contract/blob/main/ft/jetton-minter.fc) +- [portfel Jetton](https://github.com/ton-blockchain/token-contract/blob/main/ft/jetton-wallet.fc) inteligentne kontrakty + +

+
+ contracts scheme +
+

+ +## Główny inteligentny kontrakt Jetton + +Główny inteligentny kontrakt jetton przechowuje ogólne informacje o jetton (w tym całkowitą podaż, link do metadanych lub same metadane). + +:::warning Proszę uważać na oszustwo Jetton + +Jettony z `symbolem`==`TON` lub te, które zawierają powiadomienia systemowe, takie jak: +`ERROR`, `SYSTEM` i inne. Proszę upewnić się, że jettony są wyświetlane w interfejsie w taki sposób, że nie mogą +być mieszane z transferami TON, powiadomieniami systemowymi itp. Czasami nawet `symbol`, `name` i `image` +będą tworzone tak, by wyglądały niemal identycznie do oryginału z nadzieją na wprowadzenie użytkowników w błąd. + +Aby wyeliminować możliwość oszustwa dla użytkowników TON, proszę sprawdzić **oryginalny adres jetton** (umowa główna Jetton) dla określonych typów jetton lub **śledzić oficjalne media społecznościowe projektu** lub stronę internetową, aby znaleźć **prawidłowe informacje**. Proszę sprawdzić aktywa, aby wyeliminować możliwość oszustwa za pomocą [Tonkeeper ton-assets list](https://github.com/tonkeeper/ton-assets). +::: + +### Pobieranie danych Jetton + +Aby pobrać bardziej szczegółowe dane Jetton, proszę użyć metody *get* kontraktu `get_jetton_data()`. + +Metoda ta zwraca następujące dane: + +| Nazwa | Typ | Opis | +| -------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `total_supply` | `int` | całkowita liczba wydanych jettonów mierzona w niepodzielnych jednostkach. | +| `mintable` | `int` | określa, czy nowe jettony mogą zostać wybite, czy nie. Wartość ta wynosi -1 (można wybijać) lub 0 (nie można wybijać). | +| `admin_address` | `slice` | | +| `jetton_content` | `cell` | dane zgodnie z [TEP-64](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md), proszę sprawdzić [jetton metadata parsing page](/develop/dapps/asset-processing/metadata), aby dowiedzieć się więcej. | +| `jetton_wallet_code` | `cell` | | + +Można go wywołać za pomocą [Toncenter API](https://toncenter.com/api/v3/#/default/get_jetton_masters_api_v3_jetton_masters_get) lub jednego z [SDK](https://docs.ton.org/develop/dapps/apis/sdk). + + + + +> Proszę uruchomić metodę `jetton/masters` z [Toncenter API](https://toncenter.com/api/v3/#/default/get_jetton_masters_api_v3_jetton_masters_get). + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: ""}); +const data = await jettonMinter.getJettonData(); +console.log('Total supply:', data.totalSupply.toString()); +console.log('URI to off-chain metadata:', data.jettonContentUri); +``` + + + + +### Górnik Jetton + +Jak wspomniano wcześniej, jettony mogą być `mintable` lub `non-mintable`. + +Jeśli nie można ich wybić, logika staje się prosta - nie ma możliwości wybicia dodatkowych tokenów. Aby wybić jettony po raz pierwszy, proszę zapoznać się ze stroną [Mint your first jetton](/develop/dapps/tutorials/jetton-minter). + +Jeśli jettony mogą być bite, istnieje specjalna funkcja w [kontrakcie mintera](https://github.com/ton-blockchain/minter-contract/blob/main/contracts/jetton-minter.fc) do bicia dodatkowych jettonów. Funkcja ta może zostać wywołana poprzez wysłanie `wewnętrznej wiadomości` z określonym kodem operacyjnym z adresu administratora. + +Jeśli administrator jetton chce ograniczyć tworzenie jetton, może to zrobić na trzy sposoby: + +1. Jeśli nie mogą lub nie chcą Państwo zaktualizować kodu umowy, administrator musi przenieść własność z obecnego administratora na adres zerowy. Spowoduje to, że kontrakt pozostanie bez ważnego administratora, co uniemożliwi komukolwiek wybijanie jettonów. Zapobiegnie to jednak również jakimkolwiek zmianom w metadanych jettona. +2. Jeśli mają Państwo dostęp do kodu źródłowego i mogą go zmienić, można utworzyć metodę w kontrakcie, która ustawia flagę przerywającą proces wybijania po jej wywołaniu i dodać instrukcję sprawdzającą tę flagę w funkcji mint. +3. Jeśli można zaktualizować kod umowy, można dodać ograniczenia, aktualizując kod już wdrożonej umowy. + +## Inteligentny kontrakt portfela Jetton + +Kontrakty `portfela jettona` są używane do **wysyłania**, **odbierania** i **spalania** jettonów. Każdy kontrakt *portfela jettona* przechowuje informacje o saldzie portfela dla określonych użytkowników. +W określonych przypadkach, portfele jettona są używane dla indywidualnych posiadaczy jettona dla każdego typu jettona. + +"Portfeli jetton" **nie należy mylić z portfelami** przeznaczonymi do interakcji z blockchainem i przechowywania +tylko aktywów Toncoin (np. portfele v3R2, portfele highload i inne), +które są odpowiedzialne za obsługę i zarządzanie **tylko określonym typem jetton**. + +### Wdrożenie portfela Jetton + +Podczas `przekazywania jettonów` między portfelami, transakcje (wiadomości) wymagają pewnej ilości TON +jako zapłaty za **opłaty gazowe** sieci i wykonanie działań zgodnie z kodem kontraktu portfela Jetton. +Oznacza to, że **odbiorca nie musi wdrażać portfela jetton przed otrzymaniem jettonów**. +Portfel Jetton odbiorcy zostanie wdrożony automatycznie, o ile nadawca posiada wystarczającą ilość TON +w portfelu, aby uiścić wymagane opłaty za gaz. + +### Pobieranie adresów portfela Jetton dla danego użytkownika + +Aby pobrać `adres portfela Jetton` przy użyciu `adresu właściciela` (adres portfela TON), +`kontrakt główny Jetton` udostępnia metodę get `get_wallet_address(slice owner_address)`. + + + + +> Proszę uruchomić `get_wallet_address(slice owner_address)` poprzez metodę `/runGetMethod` z [Toncenter API](https://toncenter.com/api/v3/#/default/run_get_method_api_v3_runGetMethod_post). + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: ""}); +const address = await jettonMinter.getJettonWalletAddress(new TonWeb.utils.Address("")); +// It is important to always check that wallet indeed is attributed to desired Jetton Master: +const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider, { + address: jettonWalletAddress +}); +const jettonData = await jettonWallet.getData(); +if (jettonData.jettonMinterAddress.toString(false) !== new TonWeb.utils.Address(info.address).toString(false)) { + throw new Error('jetton minter address from jetton wallet doesnt match config'); +} + +console.log('Jetton wallet address:', address.toString(true, true, true)); +``` + + + + +### Pobieranie danych dla określonego portfela Jetton + +Aby pobrać saldo konta portfela, informacje identyfikacyjne właściciela i inne informacje związane z konkretnym kontraktem portfela jetton, należy użyć metody `get_wallet_data()` w kontrakcie portfela jetton. + +Metoda ta zwraca następujące dane: + +| Nazwa | Typ | +| -------------------- | --------- | +| `balance` | int | +| `właściciel` | plasterek | +| `jetton` | plasterek | +| `jetton_wallet_code` | komórka | + + + + +> Proszę użyć metody `/jetton/wallets` get z [Toncenter API](https://toncenter.com/api/v3/#/default/get_jetton_wallets_api_v3_jetton_wallets_get), aby pobrać wcześniej zdekodowane dane portfela jetton. + + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const walletAddress = "EQBYc3DSi36qur7-DLDYd-AmRRb4-zk6VkzX0etv5Pa-Bq4Y"; +const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider,{address: walletAddress}); +const data = await jettonWallet.getData(); +console.log('Jetton balance:', data.balance.toString()); +console.log('Jetton owner address:', data.ownerAddress.toString(true, true, true)); +// It is important to always check that Jetton Master indeed recognize wallet +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: data.jettonMinterAddress.toString(false)}); +const expectedJettonWalletAddress = await jettonMinter.getJettonWalletAddress(data.ownerAddress.toString(false)); +if (expectedJettonWalletAddress.toString(false) !== new TonWeb.utils.Address(walletAddress).toString(false)) { + throw new Error('jetton minter does not recognize the wallet'); +} + +console.log('Jetton master address:', data.jettonMinterAddress.toString(true, true, true)); +``` + + + + +## Przegląd komunikacji portfeli Jetton + +Komunikacja między portfelami Jetton a portfelami TON odbywa się poprzez następującą sekwencję komunikacji: + +![](/img/docs/asset-processing/jetton_transfer.svg) + +#### Wiadomość 0 + +`Nadawca -> portfel jetton nadawcy`. Wiadomość *Transfer* zawiera następujące dane: + +| Nazwa | Typ | Opis | +| ---------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `query_id` | uint64 | Umożliwia aplikacjom powiązanie ze sobą trzech typów wiadomości `Transfer`, `Powiadomienie o transferze` i `Excesses`. Aby proces ten został przeprowadzony poprawnie, zaleca się **zawsze używać unikalnego identyfikatora zapytania**. | +| `kwota` | monety | Całkowita kwota `ton monety`, która zostanie wysłana wraz z wiadomością. | +| `przeznaczenie` | adres | Adres nowego właściciela jettons | +| `response_destination` | adres | Adres portfela używany do zwracania pozostałych ton monet z wiadomością o przekroczeniu limitu. | +| `custom_payload` | może komórka | Rozmiar zawsze wynosi >= 1 bit. Dane niestandardowe (które są używane przez nadawcę lub odbiorcę portfela jetton dla wewnętrznej logiki). | +| `forward_ton_amount` | monety | Musi być > 0, jeśli chcesz wysłać `powiadomienie o transferze` z `przekazanym ładunkiem`. Jest to **część wartości `amount`** i **musi być mniejsza niż `amount`**. | +| `forward_payload` | może komórka | Rozmiar zawsze wynosi >= 1 bit. Jeśli pierwsze 32 bity = 0x0, jest to zwykła wiadomość. | + +#### Wiadomość 2 + +`portfel jetton odbiorcy płatności -> odbiorca płatności`. Wiadomość z powiadomieniem o przelewie. **Wysyłana tylko jeśli** `forward_ton_amount` **nie wynosi zero**. Zawiera następujące dane: + +| Nazwa | Typ | +| ----------------- | ------- | +| `query_id` | uint64 | +| `kwota` | monety | +| `nadawca` | adres | +| `forward_payload` | komórka | + +Tutaj `adres nadawcy` jest adresem `portfela Jetton` Alice. + +#### Wiadomość 2'' + +`payee's jetton wallet -> Sender`. Treść wiadomości. **Wysyłane tylko wtedy, gdy po uiszczeniu opłat pozostały jakiekolwiek monety tonowe**. Zawiera następujące dane: + +| Nazwa | Typ | +| ---------- | ------ | +| `query_id` | uint64 | + +:::tip Jettons standard +Szczegółowy opis pól kontraktu portfela jetton można znaleźć w opisie interfejsu [TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) `Jetton standard`. +::: + +## Proszę wysłać Jettons z komentarzami + +Ten przelew wymaga kilku ton monet na **opłaty** i, opcjonalnie, **wiadomości o przelewie** (proszę sprawdzić pole kwoty przelewu). + +Aby wysłać **komentarz** należy skonfigurować `forward payload`. Proszę ustawić **pierwsze 32 bity na 0x0** i dołączyć **swój tekst**. + +`forward payload` jest wysyłany w wewnętrznej wiadomości `transfer notification`. Zostanie on wygenerowany tylko wtedy, gdy `forward amount` > 0. + +Wreszcie, aby pobrać wiadomość `Excess`, należy ustawić `miejsce docelowe odpowiedzi`. + +:::tip +Proszę sprawdzić [best practices](/develop/dapps/asset-processing/jettons#best-practices) dla przykładu *"send jettons with comments"*. +::: + +## Przetwarzanie poza łańcuchem Jetton + +:::info Potwierdzenie transakcji +Transakcje TON są nieodwracalne po jednym potwierdzeniu. Aby uzyskać najlepsze wrażenia użytkownika, zaleca się unikanie czekania na dodatkowe bloki po sfinalizowaniu transakcji na blockchainie TON. Więcej informacji znajdą Państwo w dokumencie [Catchain.pdf] (https://docs.ton.org/catchain.pdf#page=3). +::: + +Istnieją dwa sposoby akceptacji Jettonów: + +- w ramach \*\* scentralizowanego gorącego portfela\*\*. +- przy użyciu portfela z **oddzielnym adresem** dla **każdego indywidualnego użytkownika**. + +Ze względów bezpieczeństwa zaleca się posiadanie **oddzielnych gorących portfeli** dla **oddzielnych Jettonów** (wiele portfeli dla każdego typu aktywów). + +Podczas przetwarzania środków zaleca się również zapewnienie zimnego portfela do przechowywania nadwyżek środków, które nie uczestniczą w automatycznych procesach wpłat i wypłat. + +### Dodawanie nowych Jettonów do przetwarzania zasobów i wstępnej weryfikacji + +1. Proszę znaleźć poprawny adres [smart contract] (/develop/dapps/asset-processing/jettons#jetton-master-smart-contract). +2. Proszę pobrać [metadane](/develop/dapps/asset-processing/jettons#retrieving-jetton-data). +3. Proszę sprawdzić, czy nie ma [scam](/develop/dapps/asset-processing/jettons#jetton-master-smart-contract). + +### Identyfikacja nieznanego urządzenia Jetton podczas odbierania komunikatu powiadomienia o transferze + +Jeśli w Państwa portfelu zostanie odebrana wiadomość z powiadomieniem o transferze dotycząca nieznanego Jettona, oznacza to, że Państwa portfel +został utworzony w celu przechowywania konkretnego Jettona. + +Adres nadawcy wewnętrznej wiadomości zawierającej treść `Transfer notification` jest adresem nowego portfela Jetton. +Nie należy go mylić z polem `sender` w powiadomieniu `Transfer notification` [body] (/develop/dapps/asset-processing/jettons#jetton-wallets-communication-overview). + +1. Proszę pobrać adres główny Jetton dla nowego portfela Jetton poprzez [getting wallet data](/develop/dapps/asset-processing/jettons#retrieving-data-for-a-specific-jetton-wallet). +2. Proszę pobrać adres portfela Jetton dla swojego adresu portfela (jako właściciela) za pomocą głównego kontraktu Jetton: [Jak pobrać adres portfela Jetton dla danego użytkownika] (#retrieving-jetton-wallet-addresses-for-a-given-user) +3. Proszę porównać adres zwrócony przez główny kontrakt i rzeczywisty adres tokena portfela. + Jeśli się zgadzają, to idealnie. Jeśli nie, to prawdopodobnie otrzymali Państwo fałszywy token. +4. Pobieranie metadanych Jetton: [Jak otrzymać metadane Jetton](#retrieving-jetton-data). +5. Proszę sprawdzić pola `symbol` i `name` pod kątem oznak oszustwa. W razie potrzeby proszę ostrzec użytkownika. [Dodawanie nowych Jettons do przetwarzania i wstępnej weryfikacji](#adding-new-jettons-for-asset-processing-and-initial-verification). + +### Przyjmowanie Jettonów od użytkowników za pośrednictwem scentralizowanego portfela + +:::info +Aby zapobiec wąskiemu gardłu w transakcjach przychodzących do jednego portfela, sugeruje się przyjmowanie depozytów w wielu portfelach i zwiększanie liczby tych portfeli w razie potrzeby. +::: + +W tym scenariuszu usługa płatności tworzy unikalny identyfikator notatki dla każdego nadawcy, ujawniając +adres scentralizowanego portfela i wysyłane kwoty. Nadawca wysyła tokeny +na podany scentralizowany adres z obowiązkową notatką w komentarzu. + +**Zalety tej metody:** ta metoda jest bardzo prosta, ponieważ nie ma żadnych dodatkowych opłat przy przyjmowaniu tokenów i są one pobierane bezpośrednio do gorącego portfela. + +**Wady tej metody:** ta metoda wymaga od wszystkich użytkowników dołączenia komentarza do przelewu, co może prowadzić do większej liczby błędów wpłat (zapomniane notatki, nieprawidłowe notatki itp.), co oznacza większe obciążenie personelu pomocniczego. + +Przykłady Tonweb: + +1. [Przyjmowanie wpłat Jetton do indywidualnego portfela HOT z komentarzami (notatka)](https://github.com/toncenter/examples/blob/main/deposits-jettons.js) +2. [Przykład wypłat Jettons](https://github.com/toncenter/examples/blob/main/withdrawals-jettons.js) + +#### Przygotowania + +1. [Proszę przygotować listę zaakceptowanych Jettonów](/develop/dapps/asset-processing/jettons#adding-new-jettons-for-asset-processing-and-initial-verification) (adresy główne Jettonów). +2. Proszę wdrożyć gorący portfel (używając v3R2, jeśli nie oczekuje się wypłat Jetton; highload v3 - jeśli oczekuje się wypłat Jetton). [Wdrożenie portfela](/develop/dapps/asset-processing/#wallet-deployment). +3. Proszę wykonać testowy transfer Jetton przy użyciu adresu gorącego portfela, aby zainicjować portfel. + +#### Przetwarzanie przychodzących Jettonów + +1. Proszę załadować listę zaakceptowanych Jettonów. +2. [Odzyskaj adres portfela Jetton](#retrieving-jetton-wallet-addresses-for-a-given-user) dla wdrożonego gorącego portfela. +3. Proszę pobrać adres główny Jetton dla każdego portfela Jetton za pomocą [getting wallet data] (/develop/dapps/asset-processing/jettons#retrieving-data-for-a-specific-jetton-wallet). +4. Proszę porównać adresy umów głównych Jetton z kroku 1. i kroku 3 (bezpośrednio powyżej). + Jeśli adresy nie są zgodne, należy zgłosić błąd weryfikacji adresu Jetton. +5. Pobiera listę ostatnich nieprzetworzonych transakcji przy użyciu konta hot wallet i + iteruje ją (sortując każdą transakcję po kolei). Proszę zobaczyć: [Sprawdzanie transakcji kontraktu](https://docs.ton.org/develop/dapps/asset-processing/#checking-contracts-transactions). +6. Proszę sprawdzić wiadomość wejściową (in_msg) pod kątem transakcji i pobrać adres źródłowy z wiadomości wejściowej. [Przykład Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L84) +7. Jeśli adres źródłowy jest zgodny z adresem w portfelu Jetton, należy kontynuować przetwarzanie transakcji. + Jeśli nie, proszę pominąć przetwarzanie transakcji i sprawdzić następną transakcję. +8. Proszę upewnić się, że treść wiadomości nie jest pusta i że pierwsze 32 bity wiadomości pasują do kodu op `transfer notification` `0x7362d09c`. + [Przykład Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L91) + Jeśli treść wiadomości jest pusta lub kod op jest nieprawidłowy - proszę pominąć transakcję. +9. Proszę odczytać pozostałe dane wiadomości, w tym `query_id`, `amount`, `sender`, `forward_payload`. + [Układy wiadomości w kontraktach Jetton](#jetton-contract-message-layouts), [Przykład Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L105) +10. Proszę spróbować pobrać komentarze tekstowe z danych `forward_payload`. Pierwsze 32 bity muszą odpowiadać + kodowi op komentarza tekstowego `0x00000000`, a pozostałe - tekstowi zakodowanemu w UTF-8. + [Przykład Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L110) +11. Jeśli dane `forward_payload` są puste lub kod operacji jest nieprawidłowy - proszę pominąć transakcję. +12. Proszę porównać otrzymany komentarz z zapisanymi notatkami. Jeśli istnieje zgodność (identyfikacja użytkownika jest zawsze możliwa) - proszę wpłacić przelew. +13. Proszę zacząć od kroku 5 i powtarzać ten proces, aż przejdą Państwo przez całą listę transakcji. + +### Przyjmowanie Jettonów z adresów depozytowych użytkowników + +Aby akceptować Jettony z adresów depozytowych użytkowników, konieczne jest, aby usługa płatności utworzyła swój +indywidualny adres (depozyt) dla każdego uczestnika wysyłającego środki. Świadczenie usługi w tym przypadku obejmuje +wykonanie kilku równoległych procesów, w tym tworzenie nowych depozytów, skanowanie bloków w poszukiwaniu transakcji, +wypłacanie środków z depozytów do gorącego portfela i tak dalej. + +Ponieważ gorący portfel może korzystać z jednego portfela Jetton dla każdego typu Jetton, konieczne jest utworzenie wielu portfeli +w celu zainicjowania wpłat. Aby utworzyć dużą liczbę portfeli, ale jednocześnie zarządzać nimi za pomocą +jednej frazy seed (lub klucza prywatnego), konieczne jest określenie innego `subwallet_id` podczas tworzenia portfela. +W TON funkcjonalność wymagana do utworzenia subportfela jest obsługiwana przez portfele w wersji v3 i wyższych. + +#### Tworzenie subportfela w Tonweb + +```js +const WalletClass = tonweb.wallet.all['v3R2']; +const wallet = new WalletClass(tonweb.provider, { + publicKey: keyPair.publicKey, + wc: 0, + walletId: , +}); +``` + +#### Przygotowanie + +1. [Proszę przygotować listę zaakceptowanych Jettonów](#adding-new-jettons-for-asset-processing-and-initial-verification). +2. Proszę wdrożyć gorący portfel (używając v3R2, jeśli nie oczekuje się wypłat Jetton; highload v3 - jeśli oczekuje się wypłat Jetton). [Wdrożenie portfela](/develop/dapps/asset-processing/#wallet-deployment). + +#### Tworzenie depozytów + +1. Akceptuje żądanie utworzenia nowego depozytu dla użytkownika. +2. Proszę wygenerować nowy adres subwallet (v3R2) na podstawie seedu hot wallet. [Tworzenie subportfela w Tonweb](#creating-a-subwallet-in-tonweb) +3. Adres odbiorczy może być podany użytkownikowi jako adres używany do wpłat Jetton (jest to adres + właściciela portfela Jetton depozytu). Inicjalizacja portfela nie jest wymagana, można to zrobić + podczas wypłacania Jettonów z depozytu. +4. Aby uzyskać ten adres, konieczne jest obliczenie adresu portfela Jetton za pośrednictwem głównego kontraktu Jetton. + [Jak pobrać adres portfela Jetton dla danego użytkownika] (#retrieving-jetton-wallet-addresses-for-a-given-user). +5. Proszę dodać adres portfela Jetton do puli adresów w celu monitorowania transakcji i zapisać adres subportfela. + +#### Przetwarzanie transakcji + +:::info Potwierdzenie transakcji +Transakcje TON są nieodwracalne po jednym potwierdzeniu. Aby uzyskać najlepsze wrażenia użytkownika, zaleca się unikanie czekania na dodatkowe bloki po sfinalizowaniu transakcji na blockchainie TON. Więcej informacji znajdą Państwo w dokumencie [Catchain.pdf] (https://docs.ton.org/catchain.pdf#page=3). +::: + +Nie zawsze jest możliwe określenie dokładnej ilości Jettonów otrzymanych z wiadomości, ponieważ portfele Jetton +mogą nie wysyłać wiadomości `powiadomienia o transferze`, `nadwyżkach` i `przelewach wewnętrznych`. Nie są one ustandaryzowane. Oznacza to, że +nie ma gwarancji, że wiadomość `internal transfer` może zostać zdekodowana. + +W związku z tym, aby określić kwotę otrzymaną w portfelu, należy zażądać sald za pomocą metody get. +Aby pobrać kluczowe dane podczas żądania sald, bloki są używane zgodnie ze stanem konta dla określonego bloku w łańcuchu. +[Przygotowanie do akceptacji bloku przy użyciu Tonweb](https://github.com/toncenter/tonweb/blob/master/src/test-block-subscribe.js). + +Proces ten przebiega w następujący sposób: + +1. Przygotowanie do akceptacji bloków (poprzez przygotowanie systemu do akceptacji nowych bloków). +2. Pobiera nowy blok i zapisuje poprzedni identyfikator bloku. +3. Odbieranie transakcji z bloków. +4. Proszę filtrować transakcje używane tylko z adresami z puli portfela Jetton. +5. Dekodowanie wiadomości za pomocą treści `transfer notification` w celu otrzymania bardziej szczegółowych danych, w tym adresu + `nadawcy`, `kwoty` Jetton i komentarza. (Proszę zobaczyć: [Przetwarzanie przychodzących Jettonów](#processing-incoming-jettons)) +6. Jeśli istnieje co najmniej jedna transakcja z niedekodowalnymi komunikatami out (treść komunikatu nie zawiera kodów op dla + `powiadomienia o przelewie` i kodów op dla `przetargów`) lub bez komunikatów out obecnych na koncie + , wówczas saldo Jetton musi zostać zażądane przy użyciu metody get dla bieżącego bloku, podczas gdy poprzedni blok + jest używany do obliczenia różnicy sald. Teraz całkowite zmiany depozytu salda są ujawniane dzięki + transakcjom przeprowadzanym w bloku. +7. Jako identyfikator niezidentyfikowanego transferu Jettons (bez "powiadomienia o transferze") można użyć danych transakcji + , jeśli istnieje jedna taka transakcja lub dane bloku (jeśli kilka jest obecnych w bloku). +8. Teraz należy sprawdzić, czy saldo depozytu jest prawidłowe. Jeśli saldo depozytu jest wystarczające do zainicjowania transferu między gorącym portfelem a istniejącym portfelem Jetton, należy wypłacić Jettony, aby upewnić się, że saldo portfela zmniejszyło się. +9. Uruchomić ponownie od kroku 2 i powtórzyć cały proces. + +#### Wypłaty dokonane z depozytów + +Przelewy nie powinny być wykonywane z depozytu do gorącego portfela przy każdym uzupełnieniu depozytu, +ponieważ za operację przelewu pobierana jest prowizja w TON (płacona w opłatach za gaz sieciowy). +Ważne jest, aby określić pewną minimalną ilość Jettonów, które są wymagane, aby przelew +był opłacalny (a tym samym depozyt). + +Domyślnie właściciele portfeli depozytowych Jetton nie są inicjowani. Dzieje się tak, ponieważ nie ma z góry określonego +wymogu uiszczania opłat za przechowywanie. Portfele depozytowe Jetton mogą być wdrażane podczas wysyłania wiadomości z ciałem +`transfer`, które następnie można natychmiast zniszczyć. Aby to zrobić, inżynier musi użyć specjalnego mechanizmu +do wysyłania wiadomości: [128 + 32](/develop/smart-contracts/messages#message-modes). + +1. Pobieranie listy depozytów oznaczonych do wypłaty do gorącego portfela +2. Pobieranie zapisanych adresów właścicieli dla każdego depozytu +3. Wiadomości są następnie wysyłane na każdy adres właściciela (poprzez połączenie kilku takich wiadomości w partię) z portfela o wysokim obciążeniu + z dołączoną kwotą TON Jetton. Jest ona określana przez dodanie opłat za inicjalizację portfela v3R2* opłat za wysłanie wiadomości z treścią `transfer` + arbitralnej kwoty TON związanej z `forward_ton_amount` + (jeśli to konieczne). Załączona kwota TON jest określana przez dodanie opłat za inicjalizację portfela v3R2 (wartość) + + opłat za wysłanie wiadomości z treścią `transfer` (wartość) + dowolna kwota TON + dla `forward_ton_amount` (wartość) (jeśli to konieczne). +4. Gdy saldo na adresie stanie się niezerowe, status konta ulegnie zmianie. Proszę poczekać kilka sekund i sprawdzić status + konta, wkrótce zmieni się on ze stanu `nonexists` na `uninit`. +5. Dla każdego adresu właściciela (ze statusem `uninit`) konieczne jest wysłanie zewnętrznej wiadomości z portfelem v3R2 + init i ciałem z wiadomością `transfer` do wpłaty do portfela Jetton = 128 + 32. Dla `transfer`, + użytkownik musi określić adres gorącego portfela jako `destination` i `response destination`. + Można dodać komentarz tekstowy, aby ułatwić identyfikację transferu. +6. Możliwe jest zweryfikowanie dostawy Jetton za pomocą adresu depozytowego na adres gorącego portfela przez + , biorąc pod uwagę [przetwarzanie informacji o przychodzących Jettonach] (#processing-incoming-jettons). + +### Wypłaty Jetton + +:::info Ważne + +Poniżej znajdą Państwo przewodnik krok po kroku, jak przetwarzać wypłaty jetton. +::: + +Aby wypłacić Jettony, portfel wysyła wiadomości z treścią `transfer` do odpowiedniego portfela Jetton. +Portfel Jetton wysyła następnie Jettony do odbiorcy. W dobrej wierze ważne jest, aby dołączyć TON +jako `forward_ton_amount` (i opcjonalny komentarz do `forward_payload`), aby wywołać `powiadomienie o transferze`. +Proszę zobaczyć: [Układy wiadomości w kontraktach Jetton](#jetton-contract-message-layouts). + +#### Przygotowanie + +1. Proszę przygotować listę Jettonów do wypłaty: [Dodawanie nowych Jettonów do przetwarzania i wstępnej weryfikacji](#adding-new-jettons-for-asset-processing-and-initial-verification) +2. Rozpoczęto wdrażanie gorącego portfela. Zalecana jest wersja Highload v3. [Wdrożenie portfela](/develop/dapps/asset-processing/#wallet-deployment) +3. Proszę wykonać przelew Jetton przy użyciu adresu gorącego portfela, aby zainicjować portfel Jetton i uzupełnić jego saldo. + +#### Przetwarzanie wypłat + +1. Proszę załadować listę przetworzonych Jettonów +2. Pobieranie adresów portfela Jetton dla wdrożonego gorącego portfela: [Jak pobrać adresy portfela Jetton dla danego użytkownika] (#retrieving-jetton-wallet-addresses-for-a-given-user) +3. Proszę pobrać adresy główne Jetton dla każdego portfela Jetton: [Jak pobrać dane dla portfeli Jetton](#retrieving-data-for-a-specific-jetton-wallet). + Wymagany jest parametr `jetton` (który jest w rzeczywistości adresem głównego kontraktu Jetton). +4. Proszę porównać adresy z umów głównych Jetton z kroku 1. i kroku 3. Jeśli adresy nie są zgodne, należy zgłosić błąd weryfikacji adresu Jetton. +5. Otrzymywane są żądania wypłaty, które faktycznie wskazują rodzaj Jetton, kwotę przelewu i adres portfela odbiorcy. +6. Proszę sprawdzić saldo portfela Jetton, aby upewnić się, że na koncie znajduje się wystarczająca ilość środków do dokonania wypłaty. +7. Proszę wygenerować [wiadomość](/develop/dapps/asset-processing/jettons#message-0). +8. W przypadku korzystania z portfela o wysokim obciążeniu zaleca się zbieranie partii wiadomości i wysyłanie jednej partii na raz w celu optymalizacji opłat. +9. Proszę zapisać czas wygaśnięcia dla wychodzących wiadomości zewnętrznych (jest to czas do pomyślnego przetworzenia wiadomości przez portfel + , po jego upływie portfel nie będzie już akceptował wiadomości). +10. Wysłać pojedynczą wiadomość lub więcej niż jedną wiadomość (wiadomości wsadowe). +11. Pobiera listę ostatnich nieprzetworzonych transakcji na koncie hot wallet i iteruje ją. + Więcej informacji można znaleźć tutaj: [Sprawdzanie transakcji kontraktu](/develop/dapps/asset-processing/#checking-contracts-transactions), + [Przykład Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-single-wallet.js#L43) lub + proszę użyć metody Toncenter API `/getTransactions`. +12. Proszę sprawdzić wiadomości wychodzące na koncie. +13. Jeśli istnieje wiadomość z kodem operacyjnym `transfer`, należy ją zdekodować, aby pobrać wartość `query_id`. + Odzyskane `query_id` należy oznaczyć jako pomyślnie wysłane. +14. Jeśli czas potrzebny na przetworzenie bieżącej zeskanowanej transakcji jest dłuższy niż + czasu wygaśnięcia, a wiadomość wychodząca z podanym `query_id` + nie zostanie znaleziona, wówczas żądanie powinno (jest to opcjonalne) zostać oznaczone jako wygasłe i powinno zostać bezpiecznie wysłane ponownie. +15. Proszę sprawdzić przychodzące wiadomości na koncie. +16. Jeśli istnieje wiadomość, która używa kodu operacyjnego `excesses`, wiadomość powinna zostać zdekodowana, a wartość `query_id` + powinna zostać pobrana. Znaleziony `query_id` musi zostać oznaczony jako pomyślnie dostarczony. +17. Proszę przejść do kroku 5. Wygasłe żądania, które nie zostały pomyślnie wysłane, powinny zostać przesunięte z powrotem na listę wypłat. + +## Przetwarzanie w łańcuchu Jetton + +Ogólnie rzecz biorąc, aby zaakceptować i przetworzyć jettony, program obsługi wiadomości odpowiedzialny za wewnętrzne wiadomości używa kodu operacyjnego `op=0x7362d09c`. + +:::info Potwierdzenie transakcji +Transakcje TON są nieodwracalne po jednym potwierdzeniu. Aby uzyskać najlepsze wrażenia użytkownika, zaleca się unikanie czekania na dodatkowe bloki po sfinalizowaniu transakcji na blockchainie TON. Więcej informacji znajdą Państwo w dokumencie [Catchain.pdf] (https://docs.ton.org/catchain.pdf#page=3). +::: + +### Zalecenia dotyczące przetwarzania w łańcuchu + +Poniżej znajduje się "lista zaleceń", które należy wziąć pod uwagę podczas **przetwarzania jettonów w łańcuchu**: + +1. Proszę **identyfikować przychodzące jettony** używając ich typu portfela, a nie ich głównego kontraktu Jetton. Innymi słowy, Państwa kontrakt powinien wchodzić w interakcje (odbierać i wysyłać wiadomości) z konkretnym portfelem Jetton (a nie z jakimś nieznanym portfelem korzystającym z konkretnego głównego kontraktu Jetton). +2. Podczas łączenia portfela Jetton Wallet i Jetton Master, proszę **sprawdzić**, czy to **połączenie jest dwukierunkowe**, gdzie portfel rozpoznaje kontrakt główny i odwrotnie. Na przykład, jeśli Państwa system kontraktów otrzyma powiadomienie z portfela jetton (który uważa MySuperJetton za swój kontrakt główny), jego informacje o transferze muszą zostać wyświetlone użytkownikowi, przed wyświetleniem `symbolu`, `nazwy` i `obrazu` + kontraktu MySuperJetton, proszę sprawdzić, czy portfel MySuperJetton używa właściwego systemu kontraktów. Z kolei jeśli Państwa system kontraktowy z jakiegoś powodu musi wysyłać jettony przy użyciu kontraktów głównych MySuperJetton lub MySuperJetton, proszę sprawdzić, czy portfel X jest portfelem używającym tych samych parametrów kontraktu. + Dodatkowo, przed wysłaniem żądania `transfer` do X, proszę upewnić się, że rozpoznaje on MySuperJetton jako swój master. +3. **Prawdziwa moc** zdecentralizowanych finansów (DeFi) opiera się na możliwości układania protokołów jeden na drugim, jak klocki lego. Na przykład, powiedzmy, że jetton A jest zamieniany na jetton B, który z kolei jest następnie wykorzystywany jako dźwignia finansowa w ramach protokołu pożyczkowego (gdy użytkownik dostarcza płynność), który jest następnie wykorzystywany do zakupu NFT .... i tak dalej. W związku z tym proszę rozważyć, w jaki sposób umowa może służyć nie tylko użytkownikom poza łańcuchem, ale także podmiotom w łańcuchu, dołączając tokenizowaną wartość do powiadomienia o transferze, dodając niestandardowy ładunek, który można wysłać wraz z powiadomieniem o transferze. +4. \*\*Proszę pamiętać, że nie wszystkie umowy są zgodne z tymi samymi standardami. Niestety, niektóre jettony mogą być wrogie (wykorzystujące wektory ataku) i tworzone wyłącznie w celu atakowania niczego niepodejrzewających użytkowników. Ze względów bezpieczeństwa, jeśli dany protokół składa się z wielu kontraktów, proszę nie tworzyć dużej liczby portfeli jettton tego samego typu. W szczególności proszę nie wysyłać jetttonów wewnątrz protokołu pomiędzy kontraktem depozytowym, kontraktem skarbca lub kontraktem konta użytkownika itp. Atakujący mogą celowo zakłócać logikę kontraktu poprzez fałszowanie powiadomień o transferze, kwot jettona lub parametrów ładunku. Proszę zredukować potencjał ataku poprzez używanie tylko jednego portfela w systemie na jettona (dla wszystkich wpłat i wypłat). +5. Często dobrym pomysłem jest również **tworzenie subkontraktów** dla każdego zindywidualizowanego jettona, aby zmniejszyć ryzyko spoofingu adresów (na przykład, gdy wiadomość transferowa jest wysyłana do jettona B przy użyciu kontraktu przeznaczonego dla jettona A). +6. Zdecydowanie zaleca się \*\*pracę z niepodzielnymi jednostkami jetton na poziomie kontraktu. Logika związana z ułamkami dziesiętnymi jest zwykle używana do ulepszania interfejsu użytkownika aplikacji i nie jest związana z numerycznym przechowywaniem rekordów w łańcuchu. + +Aby dowiedzieć się **więcej** na temat [Secure Smart Contract Programming in FunC by CertiK](https://blog.ton.org/secure-smart-contract-programming-in-func), prosimy zapoznać się z tym zasobem. Zaleca się, aby programiści **obsługiwali wszystkie wyjątki inteligentnych kontraktów**, aby nigdy nie zostały one pominięte podczas tworzenia aplikacji. + +## Zalecenia dotyczące przetwarzania portfela Jetton + +Ogólnie rzecz biorąc, wszystkie procedury weryfikacji stosowane do przetwarzania Jetton poza łańcuchem są odpowiednie również dla portfeli. W przypadku przetwarzania portfela Jetton nasze najważniejsze zalecenia są następujące: + +1. Kiedy portfel otrzymuje powiadomienie o przelewie z nieznanego portfela jetton, bardzo ważne jest, aby zaufać portfelowi jetton i jego adresowi głównemu, ponieważ może to być złośliwa podróbka. Aby się zabezpieczyć, należy sprawdzić Jetton Master (główny kontrakt) przy użyciu podanego adresu, aby upewnić się, że procesy weryfikacji rozpoznają portfel jetton jako legalny. Po zaufaniu portfelowi i zweryfikowaniu go jako legalnego, można zezwolić mu na dostęp do sald kont i innych danych w portfelu. Jeśli Jetton Master nie rozpoznaje tego portfela, zaleca się, aby w ogóle nie inicjować ani nie ujawniać przelewów jetton i wyświetlać tylko przychodzące przelewy TON (Toncoin dołączone do powiadomień o przelewach). +2. W praktyce, jeśli użytkownik chce wejść w interakcję z Jetton, a nie z portfelem Jetton. Innymi słowy, użytkownicy wysyłają wTON/oUSDT/jUSDT, jUSDC, jDAI zamiast `EQAjN...`/`EQBLE...` + itd. Często oznacza to, że gdy użytkownik inicjuje transfer jetton, portfel pyta odpowiedniego mastera jetton, który portfel jetton (należący do użytkownika) powinien zainicjować żądanie transferu. Ważne jest, aby **nigdy nie ufać ślepo** tym danym od Mastera (głównego kontraktu). Przed wysłaniem żądania transferu do portfela jetton, proszę zawsze upewnić się, że portfel jetton rzeczywiście należy do Jetton Master, do którego rzekomo należy. +3. **Proszę pamiętać**, że wrodzy Mistrzowie Jetton/portfele Jetton **mogą z czasem zmienić** swoje portfele/Mistrzów. Dlatego konieczne jest, aby użytkownicy dołożyli należytej staranności i sprawdzili legalność wszystkich portfeli, z którymi wchodzą w interakcję przed każdym użyciem. +4. **Zawsze proszę upewnić się**, że wyświetlają Państwo jettony w swoim interfejsie w sposób, który **nie będzie mieszał się z transferami TON**, powiadomieniami systemowymi itp. Nawet parametry `symbol`, `name` i `image` + mogą zostać spreparowane w celu wprowadzenia użytkowników w błąd, pozostawiając poszkodowanych jako potencjalne ofiary oszustwa. Było kilka przypadków, w których złośliwe jettony były używane do podszywania się pod przelewy TON, błędy powiadomień, zarobki nagród lub ogłoszenia o zamrożeniu aktywów. +5. **Zawsze proszę zwracać uwagę na potencjalnych złośliwych aktorów**, którzy tworzą fałszywe jettony, zawsze dobrym pomysłem jest zapewnienie użytkownikom funkcji potrzebnych do wyeliminowania niechcianych jettonów w ich głównym interfejsie użytkownika. + +Autorami są [kosrk](https://github.com/kosrk), [krigga](https://github.com/krigga), [EmelyanenkoK](https://github.com/EmelyanenkoK/) i [tolya-yanot](https://github.com/tolya-yanot/). + +## Najlepsze praktyki + +Jeśli chcą Państwo przetestować gotowe przykłady, proszę sprawdzić [SDKs](/develop/dapps/asset-processing/jettons#sdks) i spróbować je uruchomić. Poniżej znajdują się fragmenty kodu, które pomogą Państwu zrozumieć przetwarzanie jettona poprzez przykłady kodu. + +### Proszę wysłać Jettons z komentarzem + + + + +
+ +Source code + + +```js +// first 4 bytes are tag of text comment +const comment = new Uint8Array([... new Uint8Array(4), ... new TextEncoder().encode('text comment')]); + +await wallet.methods.transfer({ + secretKey: keyPair.secretKey, + toAddress: JETTON_WALLET_ADDRESS, // address of Jetton wallet of Jetton sender + amount: TonWeb.utils.toNano('0.05'), // total amount of TONs attached to the transfer message + seqno: seqno, + payload: await jettonWallet.createTransferBody({ + jettonAmount: TonWeb.utils.toNano('500'), // Jetton amount (in basic indivisible units) + toAddress: new TonWeb.utils.Address(WALLET2_ADDRESS), // recepient user's wallet address (not Jetton wallet) + forwardAmount: TonWeb.utils.toNano('0.01'), // some amount of TONs to invoke Transfer notification message + forwardPayload: comment, // text comment for Transfer notification message + responseAddress: walletAddress // return the TONs after deducting commissions back to the sender's wallet address + }), + sendMode: 3, +}).send() +``` + +
+ +
+ + +
+ +Source code + + +```go +client := liteclient.NewConnectionPool() + +// connect to testnet lite server +err := client.AddConnectionsFromConfigUrl(context.Background(), "https://ton.org/global.config.json") +if err != nil { + panic(err) +} + +ctx := client.StickyContext(context.Background()) + +// initialize ton api lite connection wrapper +api := ton.NewAPIClient(client) + +// seed words of account, you can generate them with any wallet or using wallet.NewSeed() method +words := strings.Split("birth pattern then forest walnut then phrase walnut fan pumpkin pattern then cluster blossom verify then forest velvet pond fiction pattern collect then then", " ") + +w, err := wallet.FromSeed(api, words, wallet.V3R2) +if err != nil { + log.Fatalln("FromSeed err:", err.Error()) + return +} + +token := jetton.NewJettonMasterClient(api, address.MustParseAddr("EQD0vdSA_NedR9uvbgN9EikRX-suesDxGeFg69XQMavfLqIw")) + +// find our jetton wallet +tokenWallet, err := token.GetJettonWallet(ctx, w.WalletAddress()) +if err != nil { + log.Fatal(err) +} + +amountTokens := tlb.MustFromDecimal("0.1", 9) + +comment, err := wallet.CreateCommentCell("Hello from tonutils-go!") +if err != nil { + log.Fatal(err) +} + +// address of receiver's wallet (not token wallet, just usual) +to := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N") +transferPayload, err := tokenWallet.BuildTransferPayload(to, amountTokens, tlb.ZeroCoins, comment) +if err != nil { + log.Fatal(err) +} + +// your TON balance must be > 0.05 to send +msg := wallet.SimpleMessage(tokenWallet.Address(), tlb.MustFromTON("0.05"), transferPayload) + +log.Println("sending transaction...") +tx, _, err := w.SendWaitTransaction(ctx, msg) +if err != nil { + panic(err) +} +log.Println("transaction confirmed, hash:", base64.StdEncoding.EncodeToString(tx.Hash)) +``` + +
+ +
+ + +
+ +Source code + + +```py +my_wallet = Wallet(provider=client, mnemonics=my_wallet_mnemonics, version='v4r2') + +# for TonCenterClient and LsClient +await my_wallet.transfer_jetton(destination_address='address', jetton_master_address=jetton.address, jettons_amount=1000, fee=0.15) + +# for all clients +await my_wallet.transfer_jetton_by_jetton_wallet(destination_address='address', jetton_wallet='your jetton wallet address', jettons_amount=1000, fee=0.1) +``` + +
+ +
+ + + +
+ +Source code + + +```py +from pytoniq import LiteBalancer, WalletV4R2, begin_cell +import asyncio + +mnemonics = ["your", "mnemonics", "here"] + +async def main(): + provider = LiteBalancer.from_mainnet_config(1) + await provider.start_up() + + wallet = await WalletV4R2.from_mnemonic(provider=provider, mnemonics=mnemonics) + USER_ADDRESS = wallet.address + JETTON_MASTER_ADDRESS = "EQBlqsm144Dq6SjbPI4jjZvA1hqTIP3CvHovbIfW_t-SCALE" + DESTINATION_ADDRESS = "EQAsl59qOy9C2XL5452lGbHU9bI3l4lhRaopeNZ82NRK8nlA" + + USER_JETTON_WALLET = (await provider.run_get_method(address=JETTON_MASTER_ADDRESS, + method="get_wallet_address", + stack=[begin_cell().store_address(USER_ADDRESS).end_cell().begin_parse()]))[0].load_address() + forward_payload = (begin_cell() + .store_uint(0, 32) # TextComment op-code + .store_snake_string("Comment") + .end_cell()) + transfer_cell = (begin_cell() + .store_uint(0xf8a7ea5, 32) # Jetton Transfer op-code + .store_uint(0, 64) # query_id + .store_coins(1 * 10**9) # Jetton amount to transfer in nanojetton + .store_address(DESTINATION_ADDRESS) # Destination address + .store_address(USER_ADDRESS) # Response address + .store_bit(0) # Custom payload is None + .store_coins(1) # Ton forward amount in nanoton + .store_bit(1) # Store forward_payload as a reference + .store_ref(forward_payload) # Forward payload + .end_cell()) + + await wallet.transfer(destination=USER_JETTON_WALLET, amount=int(0.05*1e9), body=transfer_cell) + await provider.close_all() + +asyncio.run(main()) +``` + +
+ +
+
+ +### Proszę zaakceptować Jetton Transfer z parsowaniem komentarzy + + + + +
+ +Source code + + +```ts +import { + Address, + TonClient, + Cell, + beginCell, + storeMessage, + JettonMaster, + OpenedContract, + JettonWallet, + Transaction +} from '@ton/ton'; + + +export async function retry(fn: () => Promise, options: { retries: number, delay: number }): Promise { + let lastError: Error | undefined; + for (let i = 0; i < options.retries; i++) { + try { + return await fn(); + } catch (e) { + if (e instanceof Error) { + lastError = e; + } + await new Promise(resolve => setTimeout(resolve, options.delay)); + } + } + throw lastError; +} + +export async function tryProcessJetton(orderId: string) : Promise { + + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + apiKey: 'TONCENTER-API-KEY', // https://t.me/tonapibot + }); + + interface JettonInfo { + address: string; + decimals: number; + } + + interface Jettons { + jettonMinter : OpenedContract, + jettonWalletAddress: Address, + jettonWallet: OpenedContract + } + + const MY_WALLET_ADDRESS = 'INSERT-YOUR-HOT-WALLET-ADDRESS'; // your HOT wallet + + const JETTONS_INFO : Record = { + 'jUSDC': { + address: 'EQB-MPwrd1G6WKNkLz_VnV6WqBDd142KMQv-g1O-8QUA3728', // + decimals: 6 + }, + 'jUSDT': { + address: 'EQBynBO23ywHy_CgarY9NK9FTz0yDsG82PtcbSTQgGoXwiuA', + decimals: 6 + }, + } + const jettons: Record = {}; + + const prepare = async () => { + for (const name in JETTONS_INFO) { + const info = JETTONS_INFO[name]; + const jettonMaster = client.open(JettonMaster.create(Address.parse(info.address))); + const userAddress = Address.parse(MY_WALLET_ADDRESS); + + const jettonUserAddress = await jettonMaster.getWalletAddress(userAddress); + + console.log('My jetton wallet for ' + name + ' is ' + jettonUserAddress.toString()); + + const jettonWallet = client.open(JettonWallet.create(jettonUserAddress)); + + //const jettonData = await jettonWallet; + const jettonData = await client.runMethod(jettonUserAddress, "get_wallet_data") + + jettonData.stack.pop(); //skip balance + jettonData.stack.pop(); //skip owneer address + const adminAddress = jettonData.stack.readAddress(); + + + if (adminAddress.toString() !== (Address.parse(info.address)).toString()) { + throw new Error('jetton minter address from jetton wallet doesnt match config'); + } + + jettons[name] = { + jettonMinter: jettonMaster, + jettonWalletAddress: jettonUserAddress, + jettonWallet: jettonWallet + }; + } + } + + const jettonWalletAddressToJettonName = (jettonWalletAddress : Address) => { + const jettonWalletAddressString = jettonWalletAddress.toString(); + for (const name in jettons) { + const jetton = jettons[name]; + + if (jetton.jettonWallet.address.toString() === jettonWalletAddressString) { + return name; + } + } + return null; + } + + // Subscribe + const Subscription = async ():Promise =>{ + + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + apiKey: 'TONCENTER-API-KEY', // https://t.me/tonapibot + }); + + const myAddress = Address.parse('INSERT-YOUR-HOT-WALLET'); // Address of receiver TON wallet + const transactions = await client.getTransactions(myAddress, { + limit: 5, + }); + return transactions; + } + + return retry(async () => { + + await prepare(); + const Transactions = await Subscription(); + + for (const tx of Transactions) { + + const sourceAddress = tx.inMessage?.info.src; + if (!sourceAddress) { + // external message - not related to jettons + continue; + } + + if (!(sourceAddress instanceof Address)) { + continue; + } + + const in_msg = tx.inMessage; + + if (in_msg?.info.type !== 'internal') { + // external message - not related to jettons + continue; + } + + // jetton master contract address check + const jettonName = jettonWalletAddressToJettonName(sourceAddress); + if (!jettonName) { + // unknown or fake jetton transfer + continue; + } + + if (tx.inMessage === undefined || tx.inMessage?.body.hash().equals(new Cell().hash())) { + // no in_msg or in_msg body + continue; + } + + const msgBody = tx.inMessage; + const sender = tx.inMessage?.info.src; + const originalBody = tx.inMessage?.body.beginParse(); + let body = originalBody?.clone(); + const op = body?.loadUint(32); + if (!(op == 0x7362d09c)) { + continue; // op != transfer_notification + } + + console.log('op code check passed', tx.hash().toString('hex')); + + const queryId = body?.loadUint(64); + const amount = body?.loadCoins(); + const from = body?.loadAddress(); + const maybeRef = body?.loadBit(); + const payload = maybeRef ? body?.loadRef().beginParse() : body; + const payloadOp = payload?.loadUint(32); + if (!(payloadOp == 0)) { + console.log('no text comment in transfer_notification'); + continue; + } + + const comment = payload?.loadStringTail(); + if (!(comment == orderId)) { + continue; + } + + console.log('Got ' + jettonName + ' jetton deposit ' + amount?.toString() + ' units with text comment "' + comment + '"'); + const txHash = tx.hash().toString('hex'); + return (txHash); + } + throw new Error('Transaction not found'); + }, {retries: 30, delay: 1000}); +} +``` + +
+ +
+ + +
+ +Source code + + +```go +import ( + "context" + "fmt" + "log" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/liteclient" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/ton/jetton" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +const ( + MainnetConfig = "https://ton.org/global.config.json" + TestnetConfig = "https://ton.org/global.config.json" + MyWalletAddress = "INSERT-YOUR-HOT-WALLET-ADDRESS" +) + +type JettonInfo struct { + address string + decimals int +} + +type Jettons struct { + jettonMinter *jetton.Client + jettonWalletAddress string + jettonWallet *jetton.WalletClient +} + +func prepare(api ton.APIClientWrapped, jettonsInfo map[string]JettonInfo) (map[string]Jettons, error) { + userAddress := address.MustParseAddr(MyWalletAddress) + block, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + return nil, err + } + + jettons := make(map[string]Jettons) + + for name, info := range jettonsInfo { + jettonMaster := jetton.NewJettonMasterClient(api, address.MustParseAddr(info.address)) + jettonWallet, err := jettonMaster.GetJettonWallet(context.Background(), userAddress) + if err != nil { + return nil, err + } + + jettonUserAddress := jettonWallet.Address() + + jettonData, err := api.RunGetMethod(context.Background(), block, jettonUserAddress, "get_wallet_data") + if err != nil { + return nil, err + } + + slice := jettonData.MustCell(0).BeginParse() + slice.MustLoadCoins() // skip balance + slice.MustLoadAddr() // skip owneer address + adminAddress := slice.MustLoadAddr() + + if adminAddress.String() != info.address { + return nil, fmt.Errorf("jetton minter address from jetton wallet doesnt match config") + } + + jettons[name] = Jettons{ + jettonMinter: jettonMaster, + jettonWalletAddress: jettonUserAddress.String(), + jettonWallet: jettonWallet, + } + } + + return jettons, nil +} + +func jettonWalletAddressToJettonName(jettons map[string]Jettons, jettonWalletAddress string) string { + for name, info := range jettons { + if info.jettonWallet.Address().String() == jettonWalletAddress { + return name + } + } + return "" +} + +func GetTransferTransactions(orderId string, foundTransfer chan<- *tlb.Transaction) { + jettonsInfo := map[string]JettonInfo{ + "jUSDC": {address: "EQB-MPwrd1G6WKNkLz_VnV6WqBDd142KMQv-g1O-8QUA3728", decimals: 6}, + "jUSDT": {address: "EQBynBO23ywHy_CgarY9NK9FTz0yDsG82PtcbSTQgGoXwiuA", decimals: 6}, + } + + client := liteclient.NewConnectionPool() + + cfg, err := liteclient.GetConfigFromUrl(context.Background(), MainnetConfig) + if err != nil { + log.Fatalln("get config err: ", err.Error()) + } + + // connect to lite servers + err = client.AddConnectionsFromConfig(context.Background(), cfg) + if err != nil { + log.Fatalln("connection err: ", err.Error()) + } + + // initialize ton api lite connection wrapper + api := ton.NewAPIClient(client, ton.ProofCheckPolicySecure).WithRetry() + master, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + log.Fatalln("get masterchain info err: ", err.Error()) + } + + // address on which we are accepting payments + treasuryAddress := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N") + + acc, err := api.GetAccount(context.Background(), master, treasuryAddress) + if err != nil { + log.Fatalln("get masterchain info err: ", err.Error()) + } + + jettons, err := prepare(api, jettonsInfo) + if err != nil { + log.Fatalln("can't prepare jettons data: ", err.Error()) + } + + lastProcessedLT := acc.LastTxLT + + transactions := make(chan *tlb.Transaction) + + go api.SubscribeOnTransactions(context.Background(), treasuryAddress, lastProcessedLT, transactions) + + log.Println("waiting for transfers...") + + // listen for new transactions from channel + for tx := range transactions { + if tx.IO.In == nil || tx.IO.In.MsgType != tlb.MsgTypeInternal { + // external message - not related to jettons + continue + } + + msg := tx.IO.In.Msg + sourceAddress := msg.SenderAddr() + + // jetton master contract address check + jettonName := jettonWalletAddressToJettonName(jettons, sourceAddress.String()) + if len(jettonName) == 0 { + // unknown or fake jetton transfer + continue + } + + if msg.Payload() == nil || msg.Payload() == cell.BeginCell().EndCell() { + // no in_msg body + continue + } + + msgBodySlice := msg.Payload().BeginParse() + + op := msgBodySlice.MustLoadUInt(32) + if op != 0x7362d09c { + continue // op != transfer_notification + } + + // just skip bits + msgBodySlice.MustLoadUInt(64) + amount := msgBodySlice.MustLoadCoins() + msgBodySlice.MustLoadAddr() + + payload := msgBodySlice.MustLoadMaybeRef() + payloadOp := payload.MustLoadUInt(32) + if payloadOp == 0 { + log.Println("no text comment in transfer_notification") + continue + } + + comment := payload.MustLoadStringSnake() + if comment != orderId { + continue + } + + // process transaction + log.Printf("Got %s jetton deposit %d units with text comment %s\n", jettonName, amount, comment) + foundTransfer <- tx + } +} +``` + +
+
+ + + +
+ +Source code + + +```py +import asyncio + +from pytoniq import LiteBalancer, begin_cell + +MY_WALLET_ADDRESS = "EQAsl59qOy9C2XL5452lGbHU9bI3l4lhRaopeNZ82NRK8nlA" + + +async def parse_transactions(provider: LiteBalancer, transactions): + for transaction in transactions: + if not transaction.in_msg.is_internal: + continue + if transaction.in_msg.info.dest.to_str(1, 1, 1) != MY_WALLET_ADDRESS: + continue + + sender = transaction.in_msg.info.src.to_str(1, 1, 1) + value = transaction.in_msg.info.value_coins + if value != 0: + value = value / 1e9 + + if len(transaction.in_msg.body.bits) < 32: + print(f"TON transfer from {sender} with value {value} TON") + continue + + body_slice = transaction.in_msg.body.begin_parse() + op_code = body_slice.load_uint(32) + if op_code != 0x7362D09C: + continue + + body_slice.load_bits(64) # skip query_id + jetton_amount = body_slice.load_coins() / 1e9 + jetton_sender = body_slice.load_address().to_str(1, 1, 1) + if body_slice.load_bit(): + forward_payload = body_slice.load_ref().begin_parse() + else: + forward_payload = body_slice + + jetton_master = ( + await provider.run_get_method( + address=sender, method="get_wallet_data", stack=[] + ) + )[2].load_address() + jetton_wallet = ( + ( + await provider.run_get_method( + address=jetton_master, + method="get_wallet_address", + stack=[ + begin_cell() + .store_address(MY_WALLET_ADDRESS) + .end_cell() + .begin_parse() + ], + ) + )[0] + .load_address() + .to_str(1, 1, 1) + ) + + if jetton_wallet != sender: + print("FAKE Jetton Transfer") + continue + + if len(forward_payload.bits) < 32: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton" + ) + else: + forward_payload_op_code = forward_payload.load_uint(32) + if forward_payload_op_code == 0: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton and comment: {forward_payload.load_snake_string()}" + ) + else: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton and unknown payload: {forward_payload} " + ) + + print(f"Transaction hash: {transaction.cell.hash.hex()}") + print(f"Transaction lt: {transaction.lt}") + + +async def main(): + provider = LiteBalancer.from_mainnet_config(1) + await provider.start_up() + transactions = await provider.get_transactions(address=MY_WALLET_ADDRESS, count=5) + await parse_transactions(provider, transactions) + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +
+
+
+ +## SDK + +Listę SDK dla różnych języków (js, python, golang, C#, Rust itp.) można znaleźć [tutaj](/develop/dapps/apis/sdk). + +## Proszę zobaczyć również + +- [Przetwarzanie płatności](/develop/dapps/asset-processing/) +- [Przetwarzanie NFT na TON](/develop/dapps/asset-processing/nfts) +- [Parsowanie metadanych na TON](/develop/dapps/asset-processing/metadata) diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md b/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md new file mode 100644 index 0000000000..8d21593c15 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md @@ -0,0 +1,62 @@ +import Button from '@site/src/components/button' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Przegląd przetwarzania zasobów + +Tutaj znajdą Państwo **krótki przegląd** [jak działają przelewy TON](/develop/dapps/asset-processing/overview#overview-on-messages-and-transactions), jakie [typy aktywów](/develop/dapps/asset-processing/overview#digital-asset-types-on-ton) można znaleźć w TON (i o czym będą Państwo czytać [next](/develop/dapps/asset-processing/overview#read-next)) oraz jak [wchodzić w interakcję z ton](/develop/dapps/asset-processing/overview#interaction-with-ton-blockchain) przy użyciu języka programowania, zalecamy zapoznanie się ze wszystkimi informacjami, które znajdą Państwo poniżej, przed przejściem do następnych stron. + +## Przegląd wiadomości i transakcji + +Ucieleśniając w pełni asynchroniczne podejście, TON Blockchain obejmuje kilka koncepcji, które są niespotykane w tradycyjnych blockchainach. W szczególności, każda interakcja dowolnego aktora z blockchainem składa się z grafu asynchronicznie przesyłanych [wiadomości] (/develop/smart-contracts/guidelines/message-delivery-guarantees) pomiędzy inteligentnymi kontraktami i/lub światem zewnętrznym. Każda transakcja składa się z jednej wiadomości przychodzącej i do 512 wiadomości wychodzących. + +Istnieją 3 rodzaje wiadomości, które są w pełni opisane [tutaj](/develop/smart-contracts/messages#types-of-messages). Krótko mówiąc: + +- [wiadomość zewnętrzna](/develop/smart-contracts/guidelines/external-messages): + - "Zewnętrzna wiadomość" (czasami nazywana po prostu "zewnętrzną wiadomością") to wiadomość, która jest wysyłana z *zewnątrz* blockchaina do inteligentnego kontraktu *wewnątrz* blockchaina. + - `external out message` (zwykle nazywana `logs message`) jest wysyłana z *blockchain entity* do *świata zewnętrznego*. +- [wiadomość wewnętrzna] (/develop/smart-contracts/guidelines/internal-messages) jest wysyłana z jednego podmiotu *blockchain* do *innego*, może zawierać pewną ilość zasobów cyfrowych i dowolną porcję danych. + +Wspólna ścieżka każdej interakcji rozpoczyna się od zewnętrznej wiadomości wysłanej do inteligentnego kontraktu `wallet`, który uwierzytelnia nadawcę wiadomości za pomocą kryptografii klucza publicznego, przejmuje opłatę i wysyła wewnętrzne wiadomości blockchain. Kolejka wiadomości tworzy kierunkowy graf acykliczny lub drzewo. + +Na przykład: + +![](/img/docs/asset-processing/alicemsgDAG.svg) + +- Alice`użyje np. [Tonkeeper](https://tonkeeper.com/), aby wysłać`zewnętrzną wiadomość\` do swojego portfela. +- `external message` to wiadomość wejściowa dla kontraktu `wallet A v4` z pustym źródłem (wiadomość znikąd, taka jak [Tonkeeper](https://tonkeeper.com/)). +- "Wiadomość wychodząca" to wiadomość wyjściowa dla kontraktu "Portfel A v4" i wiadomość wejściowa dla kontraktu "Portfel B v4" ze źródłem "Portfel A v4" i miejscem docelowym "Portfel B v4". + +W rezultacie istnieją 2 transakcje z zestawem komunikatów wejściowych i wyjściowych. + +Każda akcja, gdy umowa przyjmuje wiadomość jako dane wejściowe (wyzwalane przez nią), przetwarza ją i generuje lub nie generuje wiadomości wychodzących jako dane wyjściowe, zwane `transakcją`. Proszę przeczytać więcej o transakcjach [tutaj](/develop/smart-contracts/guidelines/message-delivery-guarantees#what-is-a-transaction). + +Te "transakcje" mogą obejmować **długi okres czasu**. Technicznie rzecz biorąc, transakcje z kolejkami wiadomości są agregowane w bloki przetwarzane przez walidatory. Asynchroniczny charakter TON Blockchain **nie pozwala przewidzieć hasha i lt (czasu logicznego) transakcji** na etapie wysyłania wiadomości. + +Transakcja zaakceptowana do bloku jest ostateczna i nie może być modyfikowana. + +:::info Potwierdzenie transakcji +Transakcje TON są nieodwracalne po jednym potwierdzeniu. Aby uzyskać najlepsze wrażenia użytkownika, zaleca się unikanie czekania na dodatkowe bloki po sfinalizowaniu transakcji na blockchainie TON. Więcej informacji znajdą Państwo w dokumencie [Catchain.pdf] (https://docs.ton.org/catchain.pdf#page=3). +::: + +Inteligentne kontrakty płacą kilka rodzajów [opłat](/develop/smart-contracts/fees) za transakcje (zwykle z salda przychodzącej wiadomości, zachowanie zależy od [trybu wiadomości](/develop/smart-contracts/messages#message-modes)). Wysokość opłat zależy od konfiguracji łańcucha roboczego z maksymalnymi opłatami na `masterchain` i znacznie niższymi opłatami na `basechain`. + +## Typy zasobów cyfrowych w TON + +TON posiada trzy rodzaje zasobów cyfrowych. + +- Toncoin, główny token sieci. Jest on używany do wszystkich podstawowych operacji na blockchainie, na przykład do uiszczania opłat za gaz lub stakowania w celu walidacji. +- Aktywa kontraktowe, takie jak tokeny i NFT, które są analogiczne do standardów ERC-20/ERC-721 i są zarządzane przez dowolne kontrakty, a zatem mogą wymagać niestandardowych reguł przetwarzania. Więcej informacji na temat ich przetwarzania znajdą Państwo w artykułach [process NFTs](/develop/dapps/asset-processing/nfts) i [process Jettons](/develop/dapps/asset-processing/jettons). +- Natywny token, który jest specjalnym rodzajem aktywów, które można dołączyć do dowolnej wiadomości w sieci. Aktywa te nie są jednak obecnie używane, ponieważ funkcja wydawania nowych tokenów natywnych jest zamknięta. + +## Interakcja z blockchainem TON + +Podstawowe operacje na TON Blockchain mogą być wykonywane za pośrednictwem TonLib. Jest to biblioteka współdzielona, którą można skompilować wraz z węzłem TON i udostępnić interfejsy API do interakcji z blockchainem za pośrednictwem tak zwanych serwerów lite (serwerów dla klientów lite). TonLib stosuje podejście bez zaufania, sprawdzając dowody dla wszystkich przychodzących danych; w związku z tym nie ma potrzeby korzystania z zaufanego dostawcy danych. Metody dostępne dla TonLib są wymienione [w schemacie TL] (https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L234). Mogą być one używane jako biblioteka współdzielona poprzez [wrappers](/develop/dapps/asset-processing/#repositories). + +## Czytaj dalej + +Po przeczytaniu tego artykułu mogą Państwo sprawdzić: + +1. [Przetwarzanie płatności](/develop/dapps/asset-processing/), aby dowiedzieć się, jak pracować z `TON coins`. +2. [Przetwarzanie Jetton](/develop/dapps/asset-processing/jettons), aby dowiedzieć się, jak pracować z `jettons` (czasami nazywanymi `tokens`). +3. [Przetwarzanie NFT](/develop/dapps/asset-processing/nfts), aby dowiedzieć się, jak pracować z `NFT` (czyli specjalnym typem `jetton`). diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx b/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx new file mode 100644 index 0000000000..752bc83678 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx @@ -0,0 +1,113 @@ +import Button from '@site/src/components/button' + +# Informacje o TON Connect + +TON Connect to potężny zestaw narzędzi open-source, który służy jako uniwersalny standard autoryzacji aplikacji w ekosystemie [TON](/learn/introduction), umożliwiając użytkownikom bezpieczne i wygodne logowanie się do aplikacji i usług za pomocą portfeli TON zamiast tradycyjnych loginów i haseł. + +![](/img/docs/ton-connect/ton-connect-overview.png?raw=true) + +Proszę użyć jednego z poniższych przepływów do integracji swojej aplikacji: + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Przypadki użycia dla Państwa DApp + +Proszę zapoznać się z tymi rezultatami, które ekosystem TON zapewnia dla doskonałej integracji DApp. + +- **Ruch**. Dodatkowe wizyty użytkowników za pośrednictwem portfeli kryptowalutowych obsługujących TON Connect. +- **Uwierzytelnianie**. Wykorzystaj portfele użytkowników TON jako gotowe konta, eliminując potrzebę dodatkowych kroków uwierzytelniania, a tym samym zwiększając komfort użytkowania. +- **Płatności**. Przetwarzaj transakcje szybko i bezpiecznie za pośrednictwem TON Blockchain za pomocą Toncoin lub owiniętych stabilnych monet (jUSDC / jUSDT). +- **Retencja**. Zwiększenie retencji użytkowników dzięki funkcji zapisywania listy w aplikacji, która pozwala użytkownikom śledzić ostatnio otwierane i ulubione aplikacje. + +## Dla deweloperów portfeli + +Jeśli są Państwo deweloperem portfela, mogą Państwo połączyć swój portfel z TON Connect i umożliwić swoim użytkownikom interakcję z aplikacjami TON w bezpieczny i wygodny sposób, proszę przeczytać jak [zintegrować TON Connect ze swoim portfelem](/develop/dapps/ton-connect/wallet/). + +## Historie sukcesu + +- [GetGems - The Open Network Marketplace](https://getgems.io/) +- [STON.fi - AMM DEX dla TON blockchain](https://ston.fi/) +- [Tonstarter](http://tonstarter.com/) + +
+ Pokaż całą listę + +- [getgems.io](https://getgems.io/) +- [fragment.com](https://fragment.com/) (Ton Connect v.1) +- [ston.fi](https://ston.fi/) +- [ton.diamonds](https://ton.diamonds/) +- [beta.disintar.io](https://beta.disintar.io/) +- [tegro.finance](https://tegro.finance/liquidity) +- [minter.ton.org](https://minter.ton.org/) +- [libermall.com](https://libermall.com/) +- [dedust.io](https://dedust.io/swap) +- [toncap.net](https://toncap.net/) +- [cryptomus.com](https://cryptomus.com/) +- [avanchange.com](https://avanchange.com/) +- [wton.dev](https://wton.dev/) +- [mint.spiroverse.io/shop](https://mint.spiroverse.io/shop) +- [vk.com/vk_nft_hub](https://vk.com/vk_nft_hub) +- [tonverifier.live](https://verifier.ton.org/) +- [stickerface.io/member](https://stickerface.io/member) +- [tonstarter.com](https://tonstarter.com/) +- [cryptogas.shop/ton](https://cryptogas.shop/ton) +- [megaton.fi](https://megaton.fi/) +- [dns.ton.org](https://dns.ton.org/) +- [coinpaymaster.com](https://coinpaymaster.com/) +- [ton.gagarin.world/app/](https://ton.gagarin.world/app) +- [daolama.co](https://daolama.co/) +- [marketplace.playmuse.org](http://marketplace.playmuse.org/) +- [ton.vote](https://ton.vote/) +- [plane.tonfancy.io](https://plane.tonfancy.io/) +- [pi.oberton.io](https://pi.oberton.io/) +- [business.thetonpay.app](https://business.thetonpay.app/) +- [bridge.orbitchain.io](https://bridge.orbitchain.io/) +- [connecton-web-new.vercel.app](https://connecton-web-new.vercel.app/) +- [app.fanz.ee/staking](https://app.fanz.ee/staking) +- [testnet.pton.fi](https://testnet.pton.fi/) +- [tonft.app](https://tonft.app/) +- [cardify.casino](https://cardify.casino/) +- [4riends.org](https://4riends.org/#/) +- [tonflex.fi](https://tonflex.fi/swap) +- [soquest.xyz](https://soquest.xyz/) +- [app.evaa.finance](https://app.evaa.finance/) + +
+ +## Dołącz do ekosystemu TON + +Aby połączyć swoją usługę z ekosystemem TON, należy wdrożyć następujące elementy: + +- **TON Connect**. Proszę włączyć protokół TON Connect do swojej aplikacji. +- **Transakcje**. Tworzenie określonych wiadomości transakcyjnych przy użyciu bibliotek TON. Proszę zagłębić się w proces [wysyłania wiadomości](/develop/dapps/ton-connect/message-builders) z naszym kompleksowym przewodnikiem. +- **Płatności**. Płatności można przetwarzać za pośrednictwem publicznego interfejsu API ([tonapi](https://tonapi.io/)) lub własnego indeksatora, na przykład [gobycicle](http://github.com/gobicycle/bicycle). Proszę dowiedzieć się więcej z naszego obszernego przewodnika na temat [asset processing](/develop/dapps/asset-processing). diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/develop/fift/overview.mdx b/i18n/pl/docusaurus-plugin-content-docs/current/develop/fift/overview.mdx new file mode 100644 index 0000000000..8be16cb2ea --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/develop/fift/overview.mdx @@ -0,0 +1,57 @@ +import Button from '@site/src/components/button' + +# Przegląd + +Fift to oparty na stosie język programowania ogólnego przeznaczenia zoptymalizowany pod kątem tworzenia, debugowania i zarządzania inteligentnymi kontraktami TON Blockchain. +Fift został specjalnie zaprojektowany do interakcji z maszyną wirtualną TON (TON VM lub TVM) i TON Blockchain. + +```fift +{ ."hello " } execute ."world" +hello world ok +``` + +:::info +Zazwyczaj używanie języka Fift nie jest wymagane do programowania inteligentnych kontraktów w TON. Czasami jednak może być konieczne użycie języka Fift w celu rozwiązania nietypowych wyzwań technicznych w ramach zadania. +::: + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +



+ +## Dokumentacja + +- [Fift: A Brief Introduction](https://ton.org/fiftbase.pdf) +- [Maszyna wirtualna TON](/learn/tvm-instructions/tvm-overview) + +## Przykłady + +- [Przykłady inteligentnych umów Fift](/develop/smart-contracts/examples#fift-smart-contracts) + +## Samouczki + +- [Introduction To Fift](https://blog.ton.org/introduction-to-fift) +- [\[YouTube\]His majesty Fift](https://www.youtube.com/watch?v=HVsveTmVowc&list=PLtUBO1QNEKwttRsAs9eacL2oCMOhWaOZs) \[[RU version](https://www.youtube.com/playlist?list=PLyDBPwv9EPsCYG-hR4N5FRTKUkfM8POgh)] by **@MarcoDaTr0p0je** & **@Wikimar**. + +## Źródła + +- [Pięć skryptów dla standardowych inteligentnych kontraktów](https://github.com/ton-blockchain/ton/tree/master/crypto/smartcont) diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/develop/func/overview.mdx b/i18n/pl/docusaurus-plugin-content-docs/current/develop/func/overview.mdx new file mode 100644 index 0000000000..870efded52 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/develop/func/overview.mdx @@ -0,0 +1,157 @@ +import Button from '@site/src/components/button' + +# Przegląd + +Język wysokiego poziomu FunC jest używany do programowania inteligentnych kontraktów w TON. + +FunC jest specyficznym dla domeny, podobnym do C, statycznie typowanym językiem. +Poniżej znajduje się prosta przykładowa metoda wysyłania pieniędzy napisana w FunC: + +```func +() send_money(slice address, int amount) impure inline { + var msg = begin_cell() + .store_uint(0x10, 6) ;; nobounce + .store_slice(address) + .store_coins(amount) + .end_cell(); + + send_raw_message(msg, 64); +} +``` + +Programy FunC są kompilowane do kodu asemblera Fift, który generuje odpowiedni kod bajtowy dla [TON Virtual Machine] (/learn/tvm-instructions/tvm-overview). + +Ponadto ten kod bajtowy (w rzeczywistości [drzewo komórek] (/learn/overviews/cells), jak każde inne dane w TON Blockchain) może być wykorzystywany do tworzenia inteligentnych kontraktów w łańcuchu bloków lub może być uruchamiany w lokalnej instancji TVM. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Kompilator + +### Kompilacja z JS + +Najwygodniejszym i najszybszym sposobem na rozpoczęcie tworzenia i kompilowania inteligentnych kontraktów jest użycie frameworka Blueprint. Więcej informacji znajdą Państwo w sekcji [Blueprint](/develop/smart-contracts/sdk/javascript). + +```bash +npm create ton@latest +``` + +### Kompilacja z oryginalnymi plikami binarnymi + +Jeśli chcą Państwo używać natywnego kompilatora TON FunC lokalnie, potrzebne są binaria zainstalowane na Państwa komputerze. Binaria kompilatora FunC dla systemów Windows, MacOS (Intel/M1) i Ubuntu można pobrać ze strony: + +- [Strona konfiguracji środowiska](/develop/smart-contracts/environment/installation) + +:::info +Jednocześnie zawsze można utworzyć pliki binarne ze źródeł, np:\ +[kod źródłowy kompilatora FunC](https://github.com/ton-blockchain/ton/tree/master/crypto/func) (proszę przeczytać [jak skompilować](/develop/howto/compile#func) kompilator FunC ze źródeł). +::: + +## Kurs TON: FunC + +Kurs [TON Blockchain Course] (https://stepik.org/course/176754/) to kompleksowy przewodnik po rozwoju TON Blockchain. + +Moduł 4 w całości obejmuje język FunC i rozwój inteligentnych kontraktów. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Samouczki + +:::tip wskazówka dla początkujących +Najlepsze miejsce do rozpoczęcia programowania przy użyciu FunC: [WPROWADZENIE](/develop/smart-contracts/) +::: + +Inne materiały zostały z wdzięcznością dostarczone przez ekspertów ze społeczności: + +- [Seria TON Speed Run](https://tonspeedrun.com/) + - [🚩 Wyzwanie 1: Proste wdrożenie NFT](https://github.com/romanovichim/TONQuest1) + - [🚩 Wyzwanie 2: Umowa z Chatbotem](https://github.com/romanovichim/TONQuest2) + - [🚩 Wyzwanie 3: Automat Jetton](https://github.com/romanovichim/TONQuest3) + - [🚩 Wyzwanie 4: Loteria/Rafle](https://github.com/romanovichim/TONQuest4) + - [🚩 Wyzwanie 5: Stworzenie interfejsu użytkownika do interakcji z umową w 5 minut](https://github.com/romanovichim/TONQuest5) + - [🚩 Wyzwanie 6: Analiza sprzedaży NFT na rynku Getgems](https://github.com/romanovichim/TONQuest6) + + + +- [Func & Blueprint](https://www.youtube.com/watch?v=7omBDfSqGfA&list=PLtUBO1QNEKwtO_zSyLj-axPzc9O9rkmYa) by **@MarcoDaTr0p0je**. +- [Naucz się FunC w Y minut](https://learnxinyminutes.com/docs/func/) by **@romanowiczim** +- [TON Hello World: Przewodnik krok po kroku, jak napisać swój pierwszy inteligentny kontrakt](https://ton-community.github.io/tutorials/02-contract/) +- [TON Hello World: Przewodnik krok po kroku dotyczący testowania pierwszego inteligentnego kontraktu](https://ton-community.github.io/tutorials/04-testing/) +- [10 FunC Lessons](https://github.com/romanovichim/TonFunClessons_Eng) by **@romanovichim**, using blueprint +- [10 lekcji FunC (RU)](https://github.com/romanovichim/TonFunClessons_ru) przez **@romanovichim**, używając blueprintu +- [FunC Quiz](https://t.me/toncontests/60) by **Vadim** - Dobry do samodzielnego sprawdzenia. Zajmie to 10-15 minut. Pytania dotyczą głównie FunC z kilkoma ogólnymi pytaniami o TON +- [FunC Quiz (RU)](https://t.me/toncontests/58?comment=14888) by **Vadim** - FunC Quiz po rosyjsku + +## Konkursy + +Udział w [konkursach](https://t.me/toncontests) to świetny sposób na naukę FunC. + +Mogą Państwo również zapoznać się z poprzednimi konkursami w celach edukacyjnych. + +#### Konkursy Dziedzictwo + +| Opis konkursu | Zadania | Rozwiązania | +| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| TSC #5 (grudzień 2023 r.) | [Zadania](https://github.com/ton-community/tsc5) | | +| TSC #4 (wrzesień 2023 r.) | [Zadania](https://github.com/ton-community/tsc4) | [Rozwiązania](/develop/smart-contracts/examples#ton-smart-challenge-4) | +| TSC #3 (grudzień 2022 r.) | [Zadania](https://github.com/ton-blockchain/func-contest3) | [Rozwiązania](https://github.com/nns2009/TON-FunC-contest-3) | +| TSC #2 (lipiec 2022 r.) | [Zadania](https://github.com/ton-blockchain/func-contest2) | [Rozwiązania](https://github.com/ton-blockchain/func-contest2-solutions) | +| TSC #1 (marzec, 2022) | [Zadania](https://github.com/ton-blockchain/func-contest1) | [Rozwiązania](https://github.com/ton-blockchain/func-contest1-solutions) | + +## Przykłady inteligentnych kontraktów + +Standardowe podstawowe inteligentne kontrakty, takie jak portfele, elektorzy (zarządza walidacją w TON), portfele z wieloma podpisami itp. mogą być punktem odniesienia podczas nauki. + +- [Przykłady inteligentnych kontraktów](/develop/smart-contracts/examples) + +## Dziennik zmian + +[Historia aktualizacji funC](/develop/func/changelog). diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/develop/overview.mdx b/i18n/pl/docusaurus-plugin-content-docs/current/develop/overview.mdx new file mode 100644 index 0000000000..bbfeb710c2 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/develop/overview.mdx @@ -0,0 +1,207 @@ +import Button from '@site/src/components/button' +import Player from '@site/src/components/player' + +# Dokumentacja TON + +Witamy w oficjalnej dokumentacji deweloperskiej TON Blockchain! + +Niniejszy zasób ma na celu dostarczenie Państwu wszystkich niezbędnych informacji potrzebnych do tworzenia, testowania i wdrażania aplikacji na blockchainie TON. + +Jest to wspólna inicjatywa open-source, a wkład jest zawsze mile widziany. Całą dokumentację można edytować za pośrednictwem GitHub, wystarczy [postępować zgodnie z tymi instrukcjami](/contribute). + +- Seria _TON Hello World_ zawiera szczegółowe przewodniki krok po kroku dotyczące portfeli, inteligentnych kontraktów, miniaplikacji oraz testowania i debugowania inteligentnych kontraktów w TON. +- _Get Started with TON_ to przewodnik krok po kroku dotyczący interakcji z TON Blockchain. (dołączony samouczek wideo) + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +### Podstawy blockchain z TON + +Ten kurs wprowadza w podstawy blockchain, ze szczególnym naciskiem na praktyczne umiejętności w ekosystemie TON. Zrozumieją Państwo, jak działa blockchain i jakie są jego różnorodne zastosowania. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +### Kurs TON + +Z dumą prezentujemy **TON Blockchain Course**, który jest kompleksowym przewodnikiem po TON Blockchain. Kurs jest przeznaczony dla programistów, którzy chcą dowiedzieć się, jak tworzyć inteligentne kontrakty i zdecentralizowane aplikacje na TON Blockchain w angażujący i interaktywny sposób. + +Składa się on z **9 modułów** i obejmuje podstawy TON Blockchain, języka programowania FunC oraz TON Virtual Machine (TVM). + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Moduły rozwoju + +Jeśli są Państwo nowicjuszami w rozwoju TON Blockchain, zaleca się rozpoczęcie od początku i przejście przez te tematy. + +### Podstawowe pojęcia + +- [The Open Network](/learn/introduction) - Ogólny przegląd TON Blockchain. +- [Blockchain of Blockchains](/learn/overviews/ton-blockchain) - praktyczne wyjaśnienie TON Blockchain. +- [Smart Contract Addresses](/learn/overviews/addresses) - Szczegółowe wyjaśnienie adresów. +- [Komórki jako struktura danych](/learn/overviews/cells) - Wysokopoziomowe wyjaśnienie struktur danych. +- [TON Networking](/learn/networking/overview) - Ogólny przegląd protokołów TON peer-to-peer. +- [TON Virtual Machine (TVM)](/learn/tvm-instructions/tvm-overview) - Ogólny przegląd TON Virtual Machine. +- [Transakcje i fazy](/learn/tvm-instructions/tvm-overview#transactions-and-phases) - Szczegółowe wyjaśnienie transakcji i faz. +- [Opłaty transakcyjne](/develop/smart-contracts/fees) - Ogólne wyjaśnienie opłat transakcyjnych. + +### Infrastruktura + +- [Typy węzłów](/participate/nodes/node-types) - Szczegółowe wyjaśnienie typów węzłów. +- [Uruchom pełny węzeł](/participate/run-nodes/full-node) - Szczegółowe wyjaśnienie, jak uruchomić węzeł. +- [TON DNS & Sites](/participate/web3/dns) - Szczegółowe wyjaśnienie TON DNS & Sites. +- [TON Storage](/participate/ton-storage/storage-daemon) - Szczegółowe wyjaśnienie TON Storage. + +### Dodatkowe zasoby + +- [**FAQ**](/develop/howto/faq) - Często zadawane pytania +- [Dokumentacja FunC](/develop/func/overview) +- [Dokumentacja Fift](/develop/fift/overview) + +## Rozwój inteligentnych kontraktów + +Inteligentne kontrakty są elementami składowymi zdecentralizowanych aplikacji (DApps) na TON Blockchain. Jeśli chcą Państwo rozwijać własne dApps, ważne jest, aby zrozumieć, jak działają inteligentne kontrakty. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +



+ +Poniższe zasoby dostarczają cennych informacji dla rozwoju inteligentnych kontraktów TON: + +- [TON Hello World: Przewodnik krok po kroku, jak napisać swój pierwszy inteligentny kontrakt](https://ton-community.github.io/tutorials/02-contract/) - Przystępne i zwięzłe wyjaśnienie podstaw JS. +- [Jak pracować z inteligentnymi kontraktami portfela](/develop/smart-contracts/tutorials/wallet) - Szczegółowe i staranne wyjaśnienia podstaw inteligentnych kontraktów z wykorzystaniem JS i GO. +- [Nauka inteligentnych kontraktów na przykładach](/develop/smart-contracts/examples) (FunC, Fift) +- [Speed Run TON](/develop/smart-contracts/examples) - 6 interaktywnych wyzwań i samouczków krok po kroku do nauki tworzenia inteligentnych kontraktów. + +## Rozwój aplikacji + +Aplikacje zdecentralizowane (DApps) to aplikacje, które działają w sieci komputerów peer-to-peer, a nie na jednym komputerze (TON Blockchain). Są one podobne do tradycyjnych aplikacji internetowych, ale są zbudowane na szczycie sieci blockchain. Oznacza to, że DApps są zdecentralizowane, co oznacza, że żaden pojedynczy podmiot ich nie kontroluje. + +```mdx-code-block + +``` + +### DeFi Development + +- [TON Connect](/develop/dapps/ton-connect/overview) - integracja i uwierzytelnianie dla DApps. +- [Przetwarzanie płatności poza łańcuchem](/develop/dapps/asset-processing) - przykłady i koncepcje przetwarzania płatności. +- [Przetwarzanie TON Jetton](/develop/dapps/asset-processing/jettons) - przykłady i koncepcje przetwarzania Jettonów. +- [Fungible (FT) / Non-fungible (NFT) tokeny](/develop/dapps/defi/tokens) - inteligentne kontrakty, przykłady, narzędzia + +Proszę postawić pierwsze kroki w rozwoju DApps dzięki kompleksowemu przewodnikowi tworzenia DApps: + +- [TON Hello World: Przewodnik krok po kroku, jak zbudować swojego pierwszego klienta sieciowego](https://ton-community.github.io/tutorials/03-client/) +- [Integracja z botem Telegram za pośrednictwem TON Connect](/develop/dapps/ton-connect/tg-bot-integration) + +### API i SDK + +- [API](/develop/dapps/apis) +- [SDKs](/develop/dapps/apis/sdk) + +## Często zadawane pytania + +Proszę przejść do sekcji [Często zadawane pytania](/develop/howto/faq). diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/develop/smart-contracts/testing/overview.mdx b/i18n/pl/docusaurus-plugin-content-docs/current/develop/smart-contracts/testing/overview.mdx new file mode 100644 index 0000000000..c3aa30fefc --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/develop/smart-contracts/testing/overview.mdx @@ -0,0 +1,141 @@ +# Pisanie testów za pomocą Blueprint + +## Przegląd + +Zestaw narzędzi testowych (zwykle piaskownica) jest już zawarty w TypeScript SDK o nazwie [Blueprint](/develop/smart-contracts/sdk/javascript). Mogą Państwo utworzyć projekt demonstracyjny i uruchomić domyślny test w dwóch krokach: + +1. Proszę utworzyć nowy projekt Blueprint: + +```bash +npm create ton@latest MyProject +``` + +2. Proszę przeprowadzić test: + +```bash +cd MyProject +npx blueprint test +``` + +W rezultacie zobaczą Państwo odpowiednie dane wyjściowe w oknie terminala: + +```bash +% npx blueprint test + +> MyProject@0.0.1 test +> jest + + PASS tests/Main.spec.ts + Main + ✓ should deploy (127 ms) + +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: 1.224 s, estimated 2 s +Ran all test suites. +``` + +## Użycie podstawowe + +Testowanie inteligentnych kontraktów pozwala na pokrycie bezpieczeństwa, optymalizację wydatków na gaz i badanie przypadków brzegowych. +Pisanie testów w Blueprint (w oparciu o [Sandbox](https://github.com/ton-org/sandbox)) polega na definiowaniu dowolnych działań z kontraktem i porównywaniu wyników testów z oczekiwanym rezultatem, na przykład: + +```typescript +it('should execute with success', async () => { // description of the test case + const res = await main.sendMessage(sender.getSender(), toNano('0.05')); // performing an action with contract main and saving result in res + + expect(res.transactions).toHaveTransaction({ // configure the expected result with expect() function + from: main.address, // set expected sender for transaction we want to test matcher properties from + success: true // set the desirable result using matcher property success + }); + + printTransactionFees(res.transactions); // print table with details on spent fees +}); +``` + +### Pisanie testów dla złożonych twierdzeń + +Podstawowy proces tworzenia testu wygląda następująco: + +1. Proszę utworzyć konkretny opakowany podmiot `Contract` za pomocą `blockchain.openContract()`. +2. Proszę opisać akcje, które ma wykonać `Contract` i zapisać wynik wykonania w zmiennej `res`. +3. Proszę zweryfikować właściwości za pomocą funkcji `expect()` i matchera `toHaveTransaction()`. + +Matcher `toHaveTransaction` oczekuje obiektu z dowolną kombinacją pól z typu `FlatTransaction` zdefiniowanego z następującymi właściwościami + +| Nazwa | Typ | Opis | +| -------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| z | Adres? | Adres umowy nadawcy wiadomości | +| na | Adres | Adres umowny miejsca docelowego wiadomości (Alternatywna nazwa właściwości `to`). | +| wartość | bigint? | Ilość toncoinów w wiadomości w nanotonach | +| ciało | Komórka | Treść wiadomości zdefiniowana jako komórka | +| op | numer? | Op code to numer identyfikatora operacji (zazwyczaj crc32 z TL-B). Oczekiwany w pierwszych 32 bitach treści wiadomości. | +| sukces | boolean? | Niestandardowa flaga Sandbox, która definiuje wynikowy status określonej transakcji. True - jeśli zarówno faza obliczeniowa, jak i faza działania zakończyły się powodzeniem. W przeciwnym razie - False. | + +Mogą Państwo pominąć pola, które Państwa nie interesują i przekazać funkcje akceptujące typy zwracające wartości logiczne (`true` oznacza dobre), aby sprawdzić np. zakresy liczb, kody operacyjne wiadomości itp. Proszę zauważyć, że jeśli pole jest opcjonalne (jak `from?: Address`), to funkcja musi również akceptować opcjonalny typ. + +:::tip +Pełną listę pól matchera można znaleźć w [dokumentacji Sandbox] (https://github.com/ton-org/sandbox#test-a-transaction-with-matcher). +::: + +### Konkretny zestaw testów + +#### Extract SendMode + +Aby wyodrębnić tryb wysyłania wysłanej wiadomości, można użyć następującego kodu: + +```ts + +const smc = await blockchain.getContract(addr); + +const re = blockchain.executor.runTransaction({ + config: blockchain.configBase64, libs: null, verbosity: 'full', + now: Math. floor (Date.now) / 1000), + lt: BigInt(Date.now()), + randomSeed: null, + ignoreChksig: false, + debugEnabled: true, + shardAccount: beginCell() + .store (storeShardAccount (smc.account)) + .endCell() + .toBoc() + .toString('base64'), + message: beginCell() + .store (storeMessageRelaxed (...)) + .endCell(), +}); + +if (!re.result. success || !re.result.actions) { + throw new Error('fail'); +} +const actions = loadoutList(Cell.fromBase64(re.result.actions).beginParse()); +actions[0].type === 'sendMsg' && actions[0].mode; + +``` + +## Samouczki + +Dowiedz się więcej o testowaniu z najbardziej wartościowych samouczków społeczności na TON: + +- [Lekcja 2: Testowanie FunC dla inteligentnego kontraktu](https://github.com/romanovichim/TonFunClessons_Eng/blob/main/lessons/smartcontract/2lesson/secondlesson.md) +- [TON Hello World część 4: Przewodnik krok po kroku dotyczący testowania pierwszego inteligentnego kontraktu](https://ton-community.github.io/tutorials/04-testing/) +- [TON Smart Contract Pipeline](https://dev.to/roma_i_m/ton-smart-contract-pipeline-write-simple-contract-and-compile-it-4pnh) +- [YouTube]Szósta lekcja FunC & Blueprint. Gaz, opłaty, testy.](https://youtu.be/3XIpKZ6wNcg) + +## Przykłady + +Proszę sprawdzić zestawy testowe używane dla kontraktów TON Ecosystem i uczyć się na przykładach. + +- [liquid-staking-contract sandbox tests](https://github.com/ton-blockchain/liquid-staking-contract/tree/main/tests) +- [governance_tests](https://github.com/Trinketer22/governance_tests/blob/master/config_tests/tests/) +- [JettonWallet.spec.ts](https://github.com/EmelyanenkoK/modern_jetton/blob/master/tests/JettonWallet.spec.ts) +- [governance_tests](https://github.com/Trinketer22/governance_tests/blob/master/elector_tests/tests/complaint-test.fc) +- [MassSender.spec.ts](https://github.com/Gusarich/ton-mass-sender/blob/main/tests/MassSender.spec.ts) +- [TonForwarder.spec.ts](https://github.com/TrueCarry/ton-contract-forwarder/blob/main/src/contracts/ton-forwarder/TonForwarder.spec.ts) +- [Assurer.spec.ts](https://github.com/aSpite/dominant-assurance-contract/blob/main/tests/Assurer.spec.ts) + +## Proszę zobaczyć również + +- [Blueprint](/develop/smart-contracts/sdk/javascript) +- [toncli](/develop/smart-contracts/testing/toncli) diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/learn/academy/academy-overview.md b/i18n/pl/docusaurus-plugin-content-docs/current/learn/academy/academy-overview.md new file mode 100644 index 0000000000..8a42204f46 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/learn/academy/academy-overview.md @@ -0,0 +1,16 @@ +# Zasoby edukacyjne + +### TON Speedrun + +- [TON Speedrun](https://tonspeedrun.com/) - Specjalistyczna platforma zaprojektowana z myślą o praktycznym podejściu do nauki rozwoju TON. + +### Kursy + +- [Podstawy blockchain z TON](https://stepik.org/course/201294/promo) ([wersja RU](https://stepik.org/course/202221/), [wersja CHN](https://stepik.org/course/200976/)) - + Kurs ten wprowadza w podstawy blockchain, ze szczególnym naciskiem na praktyczne umiejętności w ekosystemie TON. Zrozumieją Państwo, jak działa blockchain i jakie są jego różnorodne zastosowania. + +## Proszę zobaczyć również + +- [Speedrun TON](https://tonspeedrun.com/) +- [TON Hello World](https://tonhelloworld.com/01-wallet/) +- [[YouTube] TON Dev Study PL ](https://www.youtube.com/@TONDevStudy)[[RU]](https://www.youtube.com/results?search_query=tondevstudy) diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/learn/introduction.mdx b/i18n/pl/docusaurus-plugin-content-docs/current/learn/introduction.mdx new file mode 100644 index 0000000000..008ea5d2e1 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/learn/introduction.mdx @@ -0,0 +1,81 @@ +import Player from '@site/src/components/player' +import Button from '@site/src/components/button' + +# Otwarta sieć + +**The Open Network (TON)** to zdecentralizowana i otwarta platforma internetowa składająca się z kilku komponentów. Należą do nich: TON Blockchain, TON DNS, TON Storage i TON Sites. TON Blockchain jest podstawowym protokołem, który łączy podstawową infrastrukturę TON, tworząc większy ekosystem TON. + +TON koncentruje się na osiągnięciu szerokiej interoperacyjności międzyłańcuchowej, działając jednocześnie w wysoce skalowalnej, bezpiecznej strukturze. TON został zaprojektowany do przetwarzania milionów transakcji na sekundę (TPS), a jego celem jest osiągnięcie setek milionów użytkowników. + +**TON Blockchain** został zaprojektowany jako rozproszony superkomputer lub "superserwer", mający na celu dostarczanie różnorodnych produktów i usług, aby przyczynić się do rozwoju zdecentralizowanej wizji nowego Internetu. + +- Proszę dowiedzieć się, jakie usługi TON zapewnia swoim użytkownikom, przeglądając tę sekcję: [Uczestnictwo w TON](/uczestnictwo/). +- Aby dowiedzieć się więcej o technicznych aspektach TON Blockchain, proszę zapoznać się z [Blockchain of Blockchains] (/learn/overviews/ton-blockchain). +- Proszę dowiedzieć się więcej o rozwoju wszystkich rzeczy związanych z TON, przeglądając tę sekcję: [Pierwsze kroki](/develop/overview). + +## Przegląd z lotu ptaka + +Aby zrozumieć prawdziwą wizję zdecentralizowanego Internetu i tego, w jaki sposób TON przyczynia się do tej nieuchronności, proszę zapoznać się z poniższym filmem: + + + +## Podstawy blockchain z TON + +Ten kurs wprowadza w podstawy blockchain, ze szczególnym naciskiem na praktyczne umiejętności w ekosystemie TON. Zrozumieją Państwo, jak działa blockchain i jego różnorodne zastosowania. Zdobędą Państwo również kluczowe umiejętności związane z TON, w tym konfigurację portfela, handel NFT, tworzenie Jetton i transakcje z monetami TON na zdecentralizowanych giełdach (DEX). Kurs wyposaży Państwa również w krytyczną wiedzę na temat zagrożeń i oszustw związanych z kryptowalutami oraz udzieli praktycznych wskazówek, jak chronić swoje aktywa kryptograficzne. + +- [Podstawy Blockchain z TON](https://stepik.org/course/201294/) ([wersja RU](https://stepik.org/course/202221/), [wersja CHN](https://stepik.org/course/200976/)) + +## Kurs TON Blockchain + +Z dumą prezentujemy **TON Blockchain Course**, który jest kompleksowym przewodnikiem po TON Blockchain. Kurs jest przeznaczony dla programistów, którzy chcą dowiedzieć się, jak tworzyć inteligentne kontrakty i zdecentralizowane aplikacje na TON Blockchain. + +Składa się on z **9 modułów** i obejmuje podstawy TON Blockchain, języka programowania FunC oraz TON Virtual Machine (TVM). + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Nowy w Blockchain? + +Jeśli są Państwo nowicjuszami w dziedzinie blockchain i nie rozumieją, co sprawia, że technologia ta jest tak rewolucyjna - proszę rozważyć zapoznanie się z tymi ważnymi zasobami: + +- [Co to jest Blockchain? Co to jest Smart Contract? Co to jest Gas?](https://blog.ton.org/what_is_blockchain) +- [Jak Blockchain może pomóc Państwu na bezludnej wyspie](https://talkol.medium.com/why-decentralized-consensus-blockchain-is-good-for-business-5ff263468210) +- [YouTube] Crypto Networks and Why They Matter](https://youtu.be/2wxtiNgXBaU) + +## Związek TON z Ethereum + +Dla osób zaznajomionych z rozwojem Ethereum napisaliśmy dwa artykuły wprowadzające, które pomogą Państwu zrozumieć, co wyróżnia TON w tym zakresie: + +- [Sześć unikalnych aspektów TON Blockchain, które zaskoczą deweloperów Solidity](https://blog.ton.org/six-unique-aspects-of-ton-blockchain-that-will-surprise-solidity-developers) +- [Czas wypróbować coś nowego: asynchroniczne inteligentne kontrakty](https://telegra.ph/Its-time-to-try-something-new-Asynchronous-smart-contracts-03-25). +- [Porównanie łańcuchów bloków](https://ton.org/comparison_of_blockchains.pdf) diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/learn/networking/overview.md b/i18n/pl/docusaurus-plugin-content-docs/current/learn/networking/overview.md new file mode 100644 index 0000000000..992d6e3f22 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/learn/networking/overview.md @@ -0,0 +1,19 @@ +# TON Networking + +Projekt TON wykorzystuje własne protokoły sieciowe peer-to-peer. + +- **TON Blockchain wykorzystuje te protokoły** do propagacji nowych bloków, wysyłania i zbierania kandydatów do transakcji i tak dalej. + + Podczas gdy wymagania sieciowe projektów single-blockchain, takich jak Bitcoin czy Ethereum, można spełnić dość łatwo (zasadniczo trzeba zbudować + sieć nakładkową peer-to-peer, a następnie propagować wszystkie nowe bloki i + kandydatów do transakcji za pośrednictwem protokołu [gossip](https://en.wikipedia.org/wiki/Gossip_protocol)), podczas gdy projekty multi-blockchain, takie + jak TON, są znacznie bardziej wymagające (np. trzeba być w stanie + subskrybować aktualizacje tylko niektórych shardchainów, niekoniecznie wszystkich). + +- \*\*Usługi ekosystemu TON (np. TON Proxy, TON Sites, TON Storage) działają w oparciu o te protokoły. + + Po wprowadzeniu bardziej wyrafinowanych protokołów sieciowych potrzebnych + do obsługi TON Blockchain, okazuje się, że można je łatwo + wykorzystać do celów niekoniecznie związanych z bezpośrednimi wymaganiami samego blockchaina + , zapewniając w ten sposób większe możliwości i elastyczność tworzenia + nowych usług w ekosystemie TON. diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/learn/overviews/addresses.md b/i18n/pl/docusaurus-plugin-content-docs/current/learn/overviews/addresses.md new file mode 100644 index 0000000000..3c8f3c9902 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/learn/overviews/addresses.md @@ -0,0 +1,220 @@ +# Adresy inteligentnych kontraktów + +Ta sekcja opisuje specyfikę adresów inteligentnych kontraktów na blockchainie TON. Wyjaśnimy również, w jaki sposób aktorzy są synonimami inteligentnych kontraktów na TON. + +## Wszystko jest inteligentnym kontraktem + +W TON inteligentne kontrakty są budowane przy użyciu modelu [Actor model](/learn/overviews/ton-blockchain#single-actor). W rzeczywistości aktorzy w TON są technicznie reprezentowani jako inteligentne kontrakty. Oznacza to, że nawet Państwa portfel jest prostym aktorem (i inteligentnym kontraktem). + +Zazwyczaj aktorzy przetwarzają przychodzące wiadomości, zmieniają swój stan wewnętrzny i w rezultacie generują wiadomości wychodzące. Dlatego też każdy aktor (tj. inteligentny kontrakt) na blockchainie TON musi mieć adres, aby móc odbierać wiadomości od innych aktorów. + +:::info DOŚWIADCZENIE Z EVM +W maszynie wirtualnej Ethereum (EVM) adresy są całkowicie oddzielone od inteligentnych kontraktów. Proszę dowiedzieć się więcej o różnicach, czytając nasz artykuł ["Sześć unikalnych aspektów TON Blockchain, które zaskoczą programistów Solidity"] (https://blog.ton.org/six-unique-aspects-of-ton-blockchain-that-will-surprise-solidity-developers) autorstwa Tal Kol. +::: + +## Adres inteligentnego kontraktu + +Adresy inteligentnych kontraktów działających na TON zazwyczaj składają się z dwóch głównych komponentów: + +- **(workchain_id)**: oznacza identyfikator łańcucha roboczego (32-bitowa liczba całkowita ze znakiem). + +- **(account_id)** oznacza adres konta (64-512 bitów, w zależności od łańcucha roboczego). + +W sekcji przeglądu nieprzetworzonych adresów w tej dokumentacji omówimy, jak prezentują się pary **(workchain_id, account_id)**. + +### Identyfikator łańcucha roboczego i identyfikator konta + +#### Identyfikator łańcucha roboczego + +[Jak widzieliśmy wcześniej](/learn/overviews/ton-blockchain#workchain-blockchain-with-your-own-rules), możliwe jest utworzenie aż `2^32` łańcuchów roboczych działających na TON Blockchain. Zauważyliśmy również, w jaki sposób 32-bitowe prefiksy adresów inteligentnych kontraktów identyfikują i są powiązane z adresami inteligentnych kontraktów w różnych łańcuchach roboczych. Pozwala to inteligentnym kontraktom na wysyłanie i odbieranie wiadomości do i z różnych łańcuchów roboczych na TON Blockchain. + +Obecnie w TON Blockchain działa tylko Masterchain (workchain_id=-1) i okazjonalnie podstawowy workchain (workchain_id=0). + +Oba mają 256-bitowe adresy, dlatego zakładamy, że workchain_id wynosi 0 lub -1, a adres w łańcuchu roboczym ma dokładnie 256 bitów. + +#### Identyfikator konta + +Wszystkie identyfikatory kont w TON wykorzystują 256-bitowe adresy w łańcuchach Masterchain i Basechain (lub podstawowym łańcuchu roboczym). + +W rzeczywistości identyfikator konta **(account_id)** zdefiniowano jako funkcje skrótu dla obiektów inteligentnych kontraktów (w szczególności SHA-256). Każdy inteligentny kontrakt działający na TON Blockchain przechowuje dwa główne komponenty. Należą do nich: + +1. Skompilowany kod_. Logika inteligentnego kontraktu skompilowana w postaci kodu bajtowego. +2. *Stan początkowy*. Wartości kontraktu w momencie jego wdrożenia w łańcuchu. + +Wreszcie, aby dokładnie wyprowadzić adres kontraktu, konieczne jest obliczenie skrótu odpowiadającego parze **(kod początkowy, stan początkowy)** obiektu. W tej chwili nie będziemy zagłębiać się w to, jak działa [TVM](/learn/tvm-instructions/tvm-overview), ale ważne jest, aby zrozumieć, że identyfikatory kont w TON są określane za pomocą tego wzoru: +: +**account_id = hash(kod początkowy, stan początkowy)**. + +Z czasem, w całej tej dokumentacji, zagłębimy się w specyfikacje techniczne i przegląd schematu TVM i TL-B. Teraz, gdy jesteśmy zaznajomieni z generowaniem **account_id** i ich interakcją z adresami inteligentnych kontraktów w TON, wyjaśnijmy adresy Raw i User-Friendly. + +## Adresy państwowe + +Każdy adres może znajdować się w jednym z możliwych stanów: + +- `nonexist` - nie było żadnych zaakceptowanych transakcji na tym adresie, więc nie ma on żadnych danych (lub umowa została usunięta). Możemy powiedzieć, że początkowo wszystkie adresy2256 są w tym stanie. +- `uninit` - adres ma pewne dane, które zawierają saldo i meta informacje. W tym stanie adres nie ma jeszcze żadnego kodu inteligentnego kontraktu/trwałych danych. Adres wchodzi w ten stan, na przykład, gdy nie istniał, a inny adres wysłał do niego tokeny. +- `active` - adres posiada kod inteligentnego kontraktu, trwałe dane i saldo. W tym stanie może wykonać pewną logikę podczas transakcji i zmienić swoje trwałe dane. Adres wchodzi w ten stan, gdy był `uninit` i nadeszła wiadomość z parametrem state_init (proszę zauważyć, że aby móc wdrożyć ten adres, hash z `state_init` i `code` musi być równy adresowi). +- `frozen` - adres nie może wykonywać żadnych operacji, ten stan zawiera tylko dwa skróty poprzedniego stanu (odpowiednio komórki kodu i stanu). Gdy ładunek pamięci adresu przekroczy jego saldo, przechodzi on w ten stan. Aby go odmrozić, można wysłać wewnętrzną wiadomość z `state_init` i `code`, które przechowują hashe opisane wcześniej i trochę Toncoin. Odzyskanie go może być trudne, więc nie należy dopuszczać do takiej sytuacji. Istnieje projekt odblokowania adresu, który można znaleźć [tutaj] (https://unfreezer.ton.org/). + +## Surowe i przyjazne dla użytkownika adresy + +Po przedstawieniu krótkiego przeglądu tego, w jaki sposób adresy inteligentnych kontraktów w TON wykorzystują łańcuchy robocze i identyfikatory kont (w szczególności dla Masterchain i Basechain), ważne jest, aby zrozumieć, że adresy te są wyrażane w dwóch głównych formatach: + +- **Surowe adresy**: Oryginalna pełna reprezentacja adresów inteligentnych kontraktów. +- **Adresy przyjazne dla użytkownika**: Adresy przyjazne dla użytkownika to ulepszony format surowego adresu, który zapewnia lepsze bezpieczeństwo i łatwość użytkowania. + +Poniżej wyjaśnimy więcej na temat różnic między tymi dwoma typami adresów i zagłębimy się w to, dlaczego adresy przyjazne dla użytkownika są używane w TON. + +### Nieprzetworzony adres + +Nieprzetworzone adresy inteligentnych kontraktów składają się z identyfikatora łańcucha roboczego i identyfikatora konta *(workchain_id, account_id)* i są wyświetlane w następującym formacie: + +- [decimal workchain_id\]:[64 cyfry szesnastkowe z account_id\]. + +Poniżej znajduje się przykład nieprzetworzonego adresu inteligentnego kontraktu przy użyciu identyfikatora łańcucha roboczego i identyfikatora konta (wyrażonego jako **workchain_id** i **account_id**): + +`-1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260` + +Proszę zauważyć `-1` na początku ciągu adresu, który oznacza *workchain_id* należący do Masterchain. + +:::note +Wielkie litery (takie jak "A", "B", "C", "D" itp.) mogą być używane w ciągach adresowych zamiast ich małych odpowiedników (takich jak "a", "b", "c", "d" itp.). +::: + +#### Problemy z surowymi adresami + +Korzystanie z formularza Raw Address wiąże się z dwoma głównymi problemami: + +1. W przypadku korzystania z nieprzetworzonego formatu adresu nie jest możliwa weryfikacja adresów w celu wyeliminowania błędów przed wysłaniem transakcji. + Oznacza to, że jeśli przypadkowo dodadzą lub usuną Państwo znaki w ciągu adresowym przed wysłaniem transakcji, zostanie ona wysłana do niewłaściwego miejsca docelowego, co spowoduje utratę środków. +2. Podczas korzystania z nieprzetworzonego formatu adresu niemożliwe jest dodanie specjalnych flag, takich jak te używane podczas wysyłania transakcji, które wykorzystują adresy przyjazne dla użytkownika. + Aby pomóc Państwu lepiej zrozumieć tę koncepcję, poniżej wyjaśnimy, które flagi mogą być używane. + +### Adres przyjazny dla użytkownika + +Przyjazne dla użytkownika adresy zostały opracowane w celu zabezpieczenia i uproszczenia doświadczenia użytkowników TON, którzy udostępniają adresy w Internecie (na przykład na publicznych platformach komunikacyjnych lub za pośrednictwem swoich dostawców usług poczty elektronicznej), a także w świecie rzeczywistym. + +#### Przyjazna dla użytkownika struktura adresów + +Przyjazne dla użytkownika adresy składają się łącznie z 36 bajtów i są uzyskiwane poprzez wygenerowanie następujących składników w kolejności: + +1. Flagi przypięte do adresów zmieniają sposób, w jaki inteligentne kontrakty reagują na otrzymaną wiadomość. + Typy flag, które wykorzystują przyjazny dla użytkownika format adresu obejmują: + + - isBounceable. Oznacza typ adresu bounceable lub non-bounceable. (*0x11* dla "bounceable", *0x51* dla "non-bounceable") + - isTestnetOnly. Oznacza typ adresu używany wyłącznie do celów sieci testowej. Adresy zaczynające się od *0x80* nie powinny być akceptowane przez oprogramowanie działające w sieci produkcyjnej. + - isUrlSafe. Oznacza przestarzałą flagę, która jest zdefiniowana jako URL-safe dla adresu. Wszystkie adresy są wtedy uważane za bezpieczne pod względem adresu URL. +2. *\[workchain_id - 1 bajt]* - Identyfikator łańcucha roboczego (*workchain_id*) jest zdefiniowany przez podpisaną 8-bitową liczbę całkowitą *workchain_id*.\ + (*0x00* dla BaseChain, *0xff* dla MasterChain) +3. Identyfikator konta składa się z ([big-endian](https://www.freecodecamp.org/news/what-is-endianness-big-endian-vs-little-endian/)) 256-bitowego adresu w łańcuchu roboczym. +4. Weryfikacja adresu - 2 bajty]_ - W adresach przyjaznych dla użytkownika weryfikacja adresu składa się z podpisu CRC16-CCITT z poprzednich 34 bajtów. ([Przykład](https://github.com/andreypfau/ton-kotlin/blob/ce9595ec9e2ad0eb311351c8a270ef1bd2f4363e/ton-kotlin-crypto/common/src/crc32.kt)) + W rzeczywistości idea weryfikacji adresów przyjaznych dla użytkownika jest dość podobna do [algorytmu Luhna](https://en.wikipedia.org/wiki/Luhn_algorithm), który jest używany na wszystkich kartach kredytowych, aby uniemożliwić użytkownikom omyłkowe wprowadzenie nieistniejących numerów kart. + +Dodanie tych 4 głównych składników oznacza, że: `1 + 1 + 32 + 2 = 36` bajtów łącznie (na adres przyjazny dla użytkownika). + +Aby wygenerować adres przyjazny dla użytkownika, programista musi zakodować wszystkie 36 bajtów za pomocą jednego z nich: + +- *base64* (tj. z cyframi, dużymi i małymi literami alfabetu łacińskiego, '/' i '+') +- *base64url* (z '_' i '-' zamiast '/' i '+') + +Po zakończeniu tego procesu generowany jest przyjazny dla użytkownika adres o długości 48 znaków bez odstępów. + +:::info FLAGI ADRESU DNS +W TON adresy DNS, takie jak mywallet.ton, są czasami używane zamiast surowych i przyjaznych dla użytkownika adresów. W rzeczywistości adresy DNS składają się z adresów przyjaznych dla użytkownika i zawierają wszystkie wymagane flagi, które umożliwiają programistom dostęp do wszystkich flag z rekordu DNS w domenie TON. +::: + +#### Przyjazne dla użytkownika przykłady kodowania adresów + +Przykładowo, inteligentny kontrakt "test giver" (specjalny inteligentny kontrakt rezydujący w łańcuchu głównym testnet, który wysyła 2 tokeny testowe do każdego, kto o nie poprosi) korzysta z następującego surowego adresu: + +`-1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260` + +Powyższy nieprzetworzony adres "dawcy testu" musi zostać przekonwertowany na przyjazną dla użytkownika formę adresu. Uzyskuje się to za pomocą formularzy base64 lub base64url (które wprowadziliśmy wcześniej) w następujący sposób: + +- `kf/8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15+KsQHFLbKSMiYIny` (base64) +- `kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny` (base64url) + +:::info +Proszę zauważyć, że obie formy (*base64* i *base64url*) są poprawne i muszą zostać zaakceptowane! +::: + +#### Adresy odrzucające i nieodrzucające + +Główną ideą stojącą za flagą adresu zwrotnego jest bezpieczeństwo funduszy nadawcy. + +Na przykład, jeśli docelowy inteligentny kontrakt nie istnieje lub jeśli wystąpi jakiś problem podczas transakcji, wiadomość zostanie "odbita" z powrotem do nadawcy i będzie stanowić pozostałą część pierwotnej wartości transakcji (pomniejszoną o wszystkie opłaty za przelew i gaz). Gwarantuje to, że nadawca nie straci środków, które zostały przypadkowo wysłane na adres, który nie może zaakceptować transakcji. + +W szczególności w odniesieniu do adresów odrzucających: + +1. Flaga **bounceable=false** zazwyczaj oznacza, że odbiornik jest portfelem. +2. Flaga **bounceable=true** zazwyczaj oznacza niestandardowy inteligentny kontrakt z własną logiką aplikacji (na przykład DEX). W tym przykładzie wiadomości nie podlegające bounceable nie powinny być wysyłane ze względów bezpieczeństwa. + +Proszę przeczytać więcej na ten temat w naszej dokumentacji, aby lepiej zrozumieć [non-bouncable messages] (/develop/smart-contracts/guidelines/non-bouncable-messages). + +#### Reprezentacje bazy pancernej64 + +Dodatkowe dane binarne związane z TON Blockchain wykorzystują podobne "pancerne", przyjazne dla użytkownika reprezentacje adresów base64. Różnią się one od siebie w zależności od pierwszych 4 znaków ich znacznika bajtowego. Na przykład 256-bitowe klucze publiczne Ed25519 są reprezentowane przez utworzenie najpierw 36-bajtowej sekwencji przy użyciu poniższego procesu w kolejności: + +- Jednobajtowy znacznik w formacie *0x3E* oznacza klucz publiczny +- Jednobajtowy znacznik w formacie *0xE6* oznacza klucz publiczny Ed25519 +- 32 bajty zawierające standardową reprezentację binarną klucza publicznego Ed25519 +- 2 bajty zawierające reprezentację big-endian CRC16-CCITT poprzednich 34 bajtów + +Wynikowa 36-bajtowa sekwencja jest konwertowana na 48-znakowy ciąg base64 lub base64url w standardowy sposób. Na przykład klucz publiczny Ed25519 `E39ECDA0A7B0C60A7107EC43967829DBE8BC356A49B9DFC6186B3EAC74B5477D` (zwykle reprezentowany przez sekwencję 32 bajtów, takich jak: `0xE3, 0x9E, ..., 0x7D`) przedstawia się poprzez "pancerną" reprezentację w następujący sposób: + +`Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2` + +### Konwersja adresów przyjaznych dla użytkownika i adresów nieprzetworzonych + +Najprostszym sposobem konwersji przyjaznych dla użytkownika i nieprzetworzonych adresów jest użycie jednego z kilku interfejsów API TON i innych narzędzi, w tym: + +- [ton.org/address](https://ton.org/address) +- [dton.io API method](https://dton.io/api/address/0:867ac2b47d1955de6c8e23f57994fad507ea3bcfe2a7d76ff38f29ec46729627) +- [metody API toncenter w sieci głównej](https://toncenter.com/api/v2/#/accounts/pack_address_packAddress_get) +- [metody API toncenter w testnet](https://testnet.toncenter.com/api/v2/#/accounts/pack_address_packAddress_get) + +Ponadto istnieją dwa sposoby konwertowania przyjaznych dla użytkownika i nieprzetworzonych adresów portfeli za pomocą JavaScript: + +- [Konwersja adresu z/do postaci przyjaznej dla użytkownika lub nieprzetworzonej przy użyciu ton.js](https://github.com/ton-org/ton-core/blob/main/src/address/Address.spec.ts) +- [Proszę przekonwertować adres z/do postaci przyjaznej dla użytkownika lub nieprzetworzonej za pomocą tonweb](https://github.com/toncenter/tonweb/tree/master/src/utils#address-class) + +Możliwe jest również wykorzystanie podobnych mechanizmów za pomocą [SDK](/develop/dapps/apis/sdk). + +### Przykłady adresów + +Więcej przykładów na temat adresów TON można znaleźć w książce kucharskiej [TON Cookbook] (/develop/dapps/cookbook#working-with-contracts-addresses). + +## Możliwe problemy + +Podczas interakcji z blockchainem TON kluczowe jest zrozumienie konsekwencji przesyłania monet TON na adresy portfeli `uninit`. W tej sekcji przedstawiono różne scenariusze i ich wyniki, aby zapewnić jasność co do sposobu obsługi takich transakcji. + +### Co się stanie, gdy przeleją Państwo Toncoin na niezainicjowany adres? + +#### Transakcja z włączonym `state_init` + +Jeśli dołączą Państwo `state_init` (który składa się z kodu i danych portfela lub inteligentnego kontraktu) do swojej transakcji. Inteligentny kontrakt jest najpierw wdrażany przy użyciu dostarczonego `state_init`. Po wdrożeniu, przychodząca wiadomość jest przetwarzana, podobnie jak w przypadku wysyłania na już zainicjalizowane konto. + +#### Transakcja bez ustawionej flagi `state_init` i `bounce` + +Wiadomość nie może zostać dostarczona do inteligentnego kontraktu `uninit` i zostanie odesłana z powrotem do nadawcy. Po odjęciu zużytych opłat za gaz, pozostała kwota jest zwracana na adres nadawcy. + +#### Transakcja bez ustawionej flagi `state_init` i `bounce` + +Wiadomość nie może zostać dostarczona, ale nie zostanie odesłana do nadawcy. Zamiast tego wysłana kwota zostanie przelana na adres odbiorcy, zwiększając jego saldo, nawet jeśli portfel nie został jeszcze zainicjowany. Będą one tam przechowywane, dopóki posiadacz adresu nie wdroży kontraktu inteligentnego portfela, a następnie będzie mógł uzyskać dostęp do salda. + +#### Jak zrobić to dobrze + +Najlepszym sposobem na wdrożenie portfela jest wysłanie pewnej ilości TON na jego adres (który nie jest jeszcze zainicjowany) z wyczyszczoną flagą `bounce`. Po tym kroku właściciel może wdrożyć i zainicjować portfel przy użyciu środków na bieżącym niezainicjalizowanym adresie. Ten krok zwykle ma miejsce przy pierwszej operacji portfela. + +### Blockchain TON zapewnia ochronę przed błędnymi transakcjami + +W blockchainie TON standardowe portfele i aplikacje automatycznie zarządzają złożonością transakcji na niezainicjowane adresy za pomocą adresów bounceable i non-bounceable, które są opisane [tutaj] (#bounceable-vs-non-bounceable-addresses). Powszechną praktyką portfeli podczas wysyłania monet na niezainicjowane adresy jest wysyłanie monet zarówno na adresy bounceable, jak i non-bounceable bez zwrotu. + +Jeśli istnieje potrzeba szybkiego uzyskania adresu w formie odbijającej/nieodbijającej, można to zrobić [tutaj](https://ton.org/address/). + +### Odpowiedzialność za produkty niestandardowe + +Jeśli opracowują Państwo niestandardowy produkt na blockchainie TON, konieczne jest wdrożenie podobnych kontroli i logiki: + +Przed wysłaniem środków należy upewnić się, że aplikacja weryfikuje, czy adres odbiorcy został zainicjowany. +W oparciu o stan adresu, proszę używać adresów odrzucających dla inteligentnych kontraktów użytkownika z niestandardową logiką aplikacji, aby zapewnić zwrot środków. W przypadku portfeli proszę używać adresów niepodlegających odrzuceniu. diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/learn/overviews/cells.md b/i18n/pl/docusaurus-plugin-content-docs/current/learn/overviews/cells.md new file mode 100644 index 0000000000..9970ad995a --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/learn/overviews/cells.md @@ -0,0 +1,52 @@ +# Komórki jako magazyn danych + +Wszystko w TON jest przechowywane w komórkach. Komórka jest strukturą danych zawierającą: + +- do **1023 bitów** danych (nie bajtów!) +- do **4 odniesień** do innych komórek + +Bity i referencje nie są mieszane (są przechowywane oddzielnie). Odwołania cykliczne są zabronione: dla dowolnej komórki, żadna z komórek potomnych nie może mieć tej oryginalnej komórki jako odwołania. + +W ten sposób wszystkie komórki tworzą skierowany graf acykliczny (DAG). Oto dobry obrazek ilustrujący: + +Ukierunkowany graf acykliczny](/img/docs/dag.png) + +## Typy komórek + +Obecnie istnieje 5 rodzajów komórek: *zwykłe* i 4 *egzotyczne*. +Egzotyczne typy są następujące: + +- Przycięta komórka gałęzi +- Komórka referencyjna biblioteki +- Komórka Merkle proof +- Komórka aktualizacji Merkle + +:::tip +Więcej informacji na temat egzotycznych komórek można znaleźć w: [**TVM Whitepaper, Section 3**](https://ton.org/tvm.pdf). +::: + +## Smaki komórkowe + +Komórka jest nieprzezroczystym obiektem zoptymalizowanym pod kątem kompaktowego przechowywania. + +W szczególności deduplikuje dane: jeśli istnieje kilka równoważnych podkomórek, do których odwołują się różne gałęzie, ich zawartość jest przechowywana tylko raz. Nieprzezroczystość oznacza jednak, że komórki nie można bezpośrednio modyfikować ani odczytywać. Istnieją zatem 2 dodatkowe wersje komórek: + +- *Builder* dla częściowo skonstruowanych komórek, dla których można zdefiniować szybkie operacje dołączania ciągów bitów, liczb całkowitych, innych komórek i odwołań do innych komórek. +- *Slice* dla "wyciętych" komórek reprezentujących pozostałą część częściowo przeanalizowanej komórki lub wartość (podkomórkę) znajdującą się wewnątrz takiej komórki i wyodrębnioną z niej za pomocą instrukcji parsowania. + +Kolejna specjalna odmiana komórek jest używana w TVM: + +- *Continuation* dla komórek zawierających kody operacyjne (instrukcje) dla TON Virtual Machine, proszę zobaczyć [TVM bird's-eye overview](/learn/tvm-instructions/tvm-overview). + +## Serializacja danych do komórek + +Każdy obiekt w TON (wiadomość, kolejka wiadomości, blok, cały stan blockchain, kod kontraktu i dane) serializuje się do komórki. + +Proces serializacji jest opisany przez schemat TL-B: formalny opis tego, jak ten obiekt może być serializowany do *Builder* lub jak przeanalizować obiekt danego typu z *Slice*. +TL-B dla komórek jest taki sam jak TL lub ProtoBuf dla strumieni bajtów. + +Jeśli chcą Państwo dowiedzieć się więcej na temat (de)serializacji komórek, proszę przeczytać artykuł [Cell & Bag of Cells](/develop/data-formats/cell-boc). + +## Proszę zobaczyć również + +- [Język TL-B](/develop/data-formats/tl-b-language) diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/learn/overviews/ton-blockchain.md b/i18n/pl/docusaurus-plugin-content-docs/current/learn/overviews/ton-blockchain.md new file mode 100644 index 0000000000..603a33a29f --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/learn/overviews/ton-blockchain.md @@ -0,0 +1,72 @@ +# Blockchain łańcuchów bloków + +:::tip +Terminy "**smart contract**", "**account**" i "**actor**" są używane zamiennie w tym dokumencie w celu opisania podmiotu blockchain. +::: + +## Pojedynczy aktor + +Rozważmy jeden inteligentny kontrakt. + +W TON jest to *rzecz* z właściwościami takimi jak `adres`, `kod`, `dane`, `bilans` i innymi. Innymi słowy, jest to obiekt, który posiada *storage* i *behavior*. +To zachowanie ma następujący wzór: + +- coś się dzieje (najczęstszą sytuacją jest to, że umowa otrzymuje wiadomość) +- Kontrakt obsługuje to zdarzenie zgodnie z jego własnymi właściwościami, wykonując swój "kod" w wirtualnej maszynie TON. +- kontrakt modyfikuje swoje własne właściwości (`code`, `data` i inne) +- umowa opcjonalnie generuje wiadomości wychodzące +- Kontrakt przechodzi w tryb czuwania do momentu wystąpienia kolejnego zdarzenia + +Kombinacja tych kroków nazywana jest **transakcją**. Ważne jest, aby zdarzenia były obsługiwane jedno po drugim, dlatego *transakcje* są ściśle uporządkowane i nie mogą się wzajemnie przerywać. + +Ten wzorzec zachowania jest dobrze znany i nazywany "aktorem". + +### Najniższy poziom: Łańcuch kont + +Sekwencję *transakcji* `Tx1 -> Tx2 -> Tx3 -> ....` można nazwać **łańcuchem**. W rozważanym przypadku jest on nazywany **AccountChain**, aby podkreślić, że jest to *łańcuch* pojedynczego konta transakcji. + +Teraz, ponieważ węzły przetwarzające transakcje muszą od czasu do czasu koordynować stan inteligentnego kontraktu (aby osiągnąć *konsensus* co do stanu), te *transakcje* są grupowane: +`[Tx1 -> Tx2] -> [Tx3 -> Tx4 -> Tx5] -> [] -> [Tx6]`. +Batching nie ingeruje w sekwencjonowanie, każda transakcja nadal ma tylko jeden "prev tx" i co najwyżej jeden "next tx", ale teraz ta sekwencja jest pocięta na **bloki**. + +Wskazane jest również dołączenie kolejek wiadomości przychodzących i wychodzących do *blocks*. W takim przypadku *block* będzie zawierał pełny zestaw informacji, które określają i opisują, co stało się z inteligentnym kontraktem podczas tego bloku. + +## Wiele łańcuchów kont: Shards + +Rozważmy teraz wiele kont. Możemy uzyskać kilka *AccountChains* i przechowywać je razem, taki zestaw *AccountChains* nazywany jest **ShardChain**. W ten sam sposób możemy podzielić **ShardChain** na **ShardBlocks**, które są agregacją poszczególnych *AccountBlocks*. + +### Dynamiczne dzielenie i łączenie łańcuchów ShardChains + +Proszę zauważyć, że ponieważ *ShardChain* składa się z łatwo rozróżnialnych *AccountChains*, możemy go łatwo podzielić. W ten sposób, jeśli mamy 1 *ShardChain*, który opisuje zdarzenia, które mają miejsce z 1 milionem kont i jest zbyt wiele transakcji na sekundę, aby mogły być przetwarzane i przechowywane w jednym węźle, więc po prostu podzielimy (lub **split**) ten łańcuch na dwa mniejsze *ShardChains* z każdym łańcuchem odpowiadającym za pół miliona kont i każdym łańcuchem przetwarzanym na oddzielnym podzbiorze węzłów. + +Analogicznie, jeśli niektóre odłamki stały się zbyt wolne, mogą zostać **połączone** w jeden większy odłamek. + +Istnieją oczywiście dwa ograniczające przypadki: gdy shard zawiera tylko jedno konto (a zatem nie może być dalej dzielony) i gdy shard zawiera wszystkie konta. + +Konta mogą wchodzić ze sobą w interakcje poprzez wysyłanie wiadomości. Istnieje specjalny mechanizm routingu, który przenosi wiadomości z kolejek wychodzących do odpowiednich kolejek przychodzących i zapewnia, że 1) wszystkie wiadomości zostaną dostarczone 2) wiadomości zostaną dostarczone kolejno (wiadomość wysłana wcześniej dotrze do celu wcześniej). + +:::info UWAGA BOCZNA +Aby podział i łączenie były deterministyczne, agregacja AccountChains w shardy opiera się na bitowej reprezentacji adresów kont. Na przykład, adres wygląda jak `(prefiks shardu, adres)`. W ten sposób wszystkie konta w shardchainie będą miały dokładnie taki sam prefiks binarny (na przykład wszystkie adresy będą zaczynać się od `0b00101`). +::: + +## Blockchain + +Agregacja wszystkich odłamków, która zawiera wszystkie konta zachowujące się zgodnie z jednym zestawem reguł, nazywana jest **Blockchain**. + +W TON może istnieć wiele zestawów reguł, a tym samym wiele łańcuchów bloków, które działają jednocześnie i mogą wchodzić ze sobą w interakcje poprzez wysyłanie wiadomości crosschain w taki sam sposób, w jaki konta jednego łańcucha mogą wchodzić ze sobą w interakcje. + +### Workchain: Blockchain z własnymi zasadami + +Jeśli chcą Państwo dostosować zasady grupy Shardchainów, można utworzyć **Workchain**. Dobrym przykładem jest stworzenie łańcucha roboczego, który działa w oparciu o EVM, aby uruchamiać na nim inteligentne kontrakty Solidity. + +Teoretycznie każdy w społeczności może stworzyć własny łańcuch roboczy. W rzeczywistości jest to dość skomplikowane zadanie, aby go zbudować, a następnie zapłacić (kosztowną) cenę za jego utworzenie i otrzymać 2/3 głosów od walidatorów, aby zatwierdzić utworzenie Workchaina. + +TON pozwala na utworzenie do `2^32` łańcuchów roboczych, każdy podzielony na do `2^60` shardów. + +Obecnie w TON istnieją tylko 2 łańcuchy robocze: MasterChain i BaseChain. + +BaseChain jest używany do codziennych transakcji między aktorami, ponieważ jest dość tani, podczas gdy MasterChain ma kluczową funkcję dla TON, więc omówmy, co robi! + +### Masterchain: Blockchain of Blockchains + +Istnieje konieczność synchronizacji routingu wiadomości i wykonywania transakcji. Innymi słowy, węzły w sieci potrzebują sposobu na ustalenie pewnego "punktu" w stanie multichain i osiągnięcie konsensusu co do tego stanu. W TON do tego celu wykorzystywany jest specjalny łańcuch o nazwie **MasterChain**. Bloki *masterchain* zawierają dodatkowe informacje (najnowsze skróty bloków) o wszystkich innych łańcuchach w systemie, dzięki czemu każdy obserwator jednoznacznie określa stan wszystkich systemów multichain w pojedynczym bloku masterchain. diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/learn/tvm-instructions/tvm-overview.mdx b/i18n/pl/docusaurus-plugin-content-docs/current/learn/tvm-instructions/tvm-overview.mdx new file mode 100644 index 0000000000..a97f0a8d75 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/learn/tvm-instructions/tvm-overview.mdx @@ -0,0 +1,133 @@ +import Button from '@site/src/components/button' + +# Przegląd TVM + +Wszystkie inteligentne kontrakty TON są wykonywane na własnej maszynie wirtualnej TON (TVM). TVM jest zbudowana na zasadzie _stack_, co czyni ją wydajną i łatwą do wdrożenia. + +Niniejszy dokument przedstawia z lotu ptaka sposób, w jaki TVM realizuje transakcje. + +:::tip + +- TVM Source - [**Implementacja TVM C++**](https://github.com/ton-blockchain/ton/tree/master/crypto/vm) + ::: + +## Kurs TON: TVM + +:::tip +Przed rozpoczęciem kursu prosimy upewnić się, że dobrze rozumieją Państwo podstawy technologii blockchain. Jeśli mają Państwo luki w wiedzy, zalecamy wzięcie udziału w kursie [Blockchain Basics with TON](https://stepik.org/course/201294/promo) ([wersja RU](https://stepik.org/course/202221/), [wersja CHN](https://stepik.org/course/200976/)). +::: + +Kurs [TON Blockchain Course] (https://stepik.org/course/176754/) to kompleksowy przewodnik po rozwoju TON Blockchain. + +Moduł 2 w całości obejmuje **TVM**, transakcje, skalowalność i przypadki biznesowe. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Transakcje i fazy + +Kiedy jakieś zdarzenie ma miejsce na koncie w jednym z łańcuchów TON, powoduje to **transakcję**. Najczęstszym zdarzeniem jest "nadejście jakiejś wiadomości", ale ogólnie rzecz biorąc mogą to być zdarzenia typu `tick-tock`, `merge`, `split` i inne. + +Każda transakcja składa się z maksymalnie 5 faz: + +1. **Faza przechowywania** - w tej fazie obliczane są opłaty za przechowywanie zgromadzone przez umowę z powodu zajęcia pewnej przestrzeni w stanie łańcucha. Proszę przeczytać więcej w [Storage Fees](/develop/smart-contracts/fees#storage-fee). +2. **Faza kredytowania** - w tej fazie obliczane jest saldo umowy w odniesieniu do (możliwej) wartości przychodzącej wiadomości i pobranej opłaty za przechowywanie. +3. **Faza obliczeniowa** - w tej fazie TVM wykonuje kontrakt (patrz poniżej), a wynikiem wykonania kontraktu jest agregacja `exit_code`, `actions` (serializowana lista działań), `gas_details`, `new_storage` i kilku innych. +4. **Faza akcji** - jeśli faza obliczeniowa zakończyła się sukcesem, w tej fazie przetwarzane są `akcje` z fazy obliczeniowej. W szczególności działania mogą obejmować wysyłanie wiadomości, aktualizację kodu inteligentnego kontraktu, aktualizację bibliotek itp. Proszę zauważyć, że niektóre akcje mogą zakończyć się niepowodzeniem podczas przetwarzania (na przykład, jeśli spróbujemy wysłać wiadomość z większą liczbą TON niż posiada kontrakt), w takim przypadku cała transakcja może zostać cofnięta lub ta akcja może zostać pominięta (zależy to od trybu akcji, innymi słowy, kontrakt może wysłać wiadomość typu `send-or-revert` lub `try-send-if-no-ignore`). +5. **Faza odbicia** - jeśli faza obliczeniowa nie powiodła się (zwróciła `exit_code >= 2`), w tej fazie tworzony jest _bounce message_ dla transakcji zainicjowanych przez przychodzącą wiadomość. + +## Faza obliczeniowa + +W tej fazie następuje wykonanie TVM. + +### Stan TVM + +W danym momencie stan TVM jest w pełni określony przez 6 właściwości: + +- Stos (patrz poniżej) +- Rejestry kontrolne - (patrz poniżej), mówiąc prościej, oznacza to do 16 zmiennych, które mogą być bezpośrednio ustawiane i odczytywane podczas wykonywania. +- Bieżąca kontynuacja - obiekt opisujący aktualnie wykonywaną sekwencję instrukcji +- Bieżąca strona kodowa - w uproszczeniu oznacza to wersję TVM, która jest obecnie uruchomiona +- Limity gazu - zestaw 4 wartości całkowitych: aktualny limit gazugl, maksymalny limit gazugm, pozostały gazgr i kredyt gazu gc. +- Kontekst biblioteki - mapa bibliotek, które mogą być wywoływane przez TVM + +### TVM jest maszyną stosową + +TVM jest maszyną stosową typu ostatnie wejście-pierwsze wyjście. W sumie istnieje 7 typów zmiennych, które mogą być przechowywane na stosie - trzy typy niekomórkowe: + +- Integer - 257-bitowe liczby całkowite ze znakiem +- Tuple - uporządkowany zbiór do 255 elementów o dowolnych typach wartości, w miarę możliwości odrębnych. +- Null + +I cztery różne smaki komórek: + +- Cell - podstawowa (ewentualnie zagnieżdżona) nieprzezroczysta struktura używana przez TON Blockchain do przechowywania wszystkich danych. +- Slice - specjalny obiekt umożliwiający odczyt z komórki +- Builder - specjalny obiekt umożliwiający tworzenie nowych komórek +- Kontynuacja - specjalny obiekt, który pozwala wykorzystać komórkę jako źródło instrukcji TVM + +### Rejestry kontrolne + +- `c0` - Zawiera następną kontynuację lub kontynuację powrotu (podobną do adresu powrotu podprogramu w konwencjonalnych projektach). Ta wartość musi być kontynuacją. +- `c1` - Zawiera alternatywną (powrotną) kontynuację; ta wartość musi być kontynuacją. +- `c2` - Zawiera procedurę obsługi wyjątku. Ta wartość jest kontynuacją, wywoływaną za każdym razem, gdy zostanie wyzwolony wyjątek. +- `c3` - Rejestr pomocniczy, zawiera bieżący słownik, zasadniczo hashmap zawierający kod wszystkich funkcji używanych w programie. Ta wartość musi być kontynuacją. +- `c4` - Zawiera główną część trwałych danych lub po prostu sekcję `data` kontraktu. Ta wartość jest komórką. +- `c5` - Zawiera akcje wyjściowe. Ta wartość to komórka. +- `c7` - Zawiera korzeń danych tymczasowych. Jest to krotka. + +### Inicjalizacja TVM + +TVM inicjalizuje się, gdy wykonanie transakcji osiągnie fazę obliczeniową, a następnie wykonuje polecenia (kody operacyjne) z _Current continuation_, dopóki nie będzie więcej poleceń do wykonania (i nie będzie kontynuacji dla skoków powrotnych). + +Szczegółowy opis procesu inicjalizacji można znaleźć tutaj: [Inicjalizacja TVM](/learn/tvm-instructions/tvm-initialization.md). + +## Instrukcje TVM + +Listę instrukcji TVM można znaleźć tutaj: [Instrukcje TVM](/learn/tvm-instructions/instructions). + +### Wynik wykonania TVM + +Oprócz danych exit_code i zużytego gazu, TVM pośrednio wysyła następujące dane: + +- Rejestr c4 - komórka, która zostanie zapisana jako nowe `dane` inteligentnego kontraktu (jeśli wykonanie nie zostanie cofnięte w tej lub późniejszych fazach) +- c5 register - (lista akcji wyjściowych) komórka z ostatnią akcją na liście i odwołanie do komórki z poprzednią akcją (rekurencyjnie) + +Wszystkie inne wartości rejestru zostaną pominięte. + +Proszę zauważyć, że ponieważ istnieje limit maksymalnej głębokości komórki `<1024`, a w szczególności limit głębokości c4 i c5 `<=512`, będzie istniał limit liczby akcji wyjściowych w jednym tx `<=255`. Jeśli kontrakt musi wysłać więcej niż to, może wysłać wiadomość z żądaniem `continue_sending` do siebie i wysłać wszystkie potrzebne wiadomości w kolejnych transakcjach. + +## Proszę zobaczyć również + +- [Instrukcje TVM](/learn/tvm-instructions/instructions) +- [TON TVM](https://ton.org/tvm.pdf) Koncepcje TVM (mogą zawierać nieaktualne informacje) diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/participate/README.md b/i18n/pl/docusaurus-plugin-content-docs/current/participate/README.md new file mode 100644 index 0000000000..fabf98e52a --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/participate/README.md @@ -0,0 +1,38 @@ +# Przegląd + +Sekcja participate naszej dokumentacji jest dostosowana do umożliwienia użytkownikom odkrycia możliwości pracy z TON +. Ma ona również na celu zaoferowanie niezbędnych ram (eksploratorów, portfeli, TEP), które są niezbędne do uczestnictwa w ekosystemie TON i tworzenia wizji TON World Wide Web (TWW). + +## Udział w ekosystemie TON + +- [Odkrywcy TON](/uczestnictwo/odkrywcy) +- [Aplikacje portfela (dla programistów)](/participate/wallets/apps) +- [Rodzaje umów portfela](/uczestnictwo/portfele/umowy) + +### Dołącz do społeczności TON + +- [TON Enhancement Proposals (TEPs)](https://github.com/ton-blockchain/TEPs) +- [Odkryj innowacje TON na TON Research](https://tonresear.ch/) +- [Stawka z nominatorami TON](/uczestnictwo/utrzymanie-sieci/nominatorzy) + +### Mosty + +- [Przegląd mostów](/participate/crosschain/overview) +- [Adresy mostków](/participate/crosschain/bridge-addresses) + +### Uruchom węzeł + +- [Odkryj typy węzłów w TON](/participate/nodes/node-types) +- [Uruchom pełny węzeł lub walidator](/participate/run-nodes/full-node) +- [Konserwacja i bezpieczeństwo walidatora TON](/participate/nodes/node-maintenance-and-security) + +## Udział w TON Web3 + +- [Przegląd TON Web3](/participate/web3/overview) +- [Proszę używać TON DNS dla swoich domen](/participate/web3/dns) +- [Zarządzanie witrynami i domenami](/participate/web3/site-management) +- [\[Tutorial\] Jak uruchomić własną witrynę TON?] (/develop/dapps/tutorials/how-to-run-ton-site) + +### TON Proxy + +- [Jak otworzyć dowolną witrynę TON?](/participate/web3/how-to-open-any-ton-site) diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/participate/crosschain/overview.md b/i18n/pl/docusaurus-plugin-content-docs/current/participate/crosschain/overview.md new file mode 100644 index 0000000000..da0fd9d3d1 --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/participate/crosschain/overview.md @@ -0,0 +1,57 @@ +# Mostki międzyłańcuchowe + +Zdecentralizowane mosty międzyłańcuchowe działają na TON Blockchain, umożliwiając przesyłanie aktywów z TON Blockchain do innych łańcuchów bloków i odwrotnie. + +## Most Toncoin + +Most Toncoin umożliwia przesyłanie Toncoinów między TON Blockchain a blockchainem Ethereum, a także między TON Blockchain a BNB Smart Chain. + +Most jest zarządzany przez [zdecentralizowane wyrocznie] (/participate/crosschain/bridge-addresses). + +### Jak go używać? + +Frontend Bridge jest hostowany na stronie https://ton.org/bridge. + +:::info +[Kod źródłowy interfejsu Bridge](https://github.com/ton-blockchain/bridge) +::: + +### Kody źródłowe inteligentnych kontraktów TON-Ethereum + +- [FunC (strona TON)](https://github.com/ton-blockchain/bridge-func) +- [Solidity (strona Ethereum)](https://github.com/ton-blockchain/bridge-solidity/tree/eth_mainnet) + +### Kody źródłowe inteligentnych kontraktów TON-BNB Smart Chain + +- [FunC (strona TON)](https://github.com/ton-blockchain/bridge-func/tree/bsc) +- [Solidity (strona BSC)](https://github.com/ton-blockchain/bridge-solidity/tree/bsc_mainnet) + +### Konfiguracje blockchain + +Rzeczywiste adresy inteligentnych kontraktów bridge i adresy oracle można uzyskać, sprawdzając odpowiednią konfigurację: + +TON-Ethereum: [#71](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L738). + +TON-BSC: [#72](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L739). + +TON-Polygon: [#73](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L740). + +### Dokumentacja + +- [Jak działa most](https://github.com/ton-blockchain/TIPs/issues/24) + +### Międzyłańcuchowa mapa drogowa + +- https://t.me/tonblockchain/146 + +## Most Tonana + +### Jak wziąć udział? + +:::caution projekt\ +To jest artykuł koncepcyjny. Wciąż szukamy kogoś doświadczonego, kto mógłby go napisać. +::: + +Front-end znajdą Państwo tutaj: https://tonana.org/ + +Kod źródłowy znajduje się tutaj: https://github.com/tonanadao diff --git a/i18n/pl/docusaurus-plugin-content-docs/current/participate/web3/overview.mdx b/i18n/pl/docusaurus-plugin-content-docs/current/participate/web3/overview.mdx new file mode 100644 index 0000000000..280e3f370b --- /dev/null +++ b/i18n/pl/docusaurus-plugin-content-docs/current/participate/web3/overview.mdx @@ -0,0 +1,17 @@ +# Przegląd + +## Koncepcje + +Proszę przeczytać więcej o pomysłach w: + +- [Płatności na TON](https://blog.ton.org/ton-payments) +- [TON DNS & Domains](/participate/web3/dns) +- [TON Sites, TON WWW i TON Proxy](https://blog.ton.org/ton-sites) + +## Przypadki użycia + +- [\*.ton przyjazne dla użytkownika domeny dla dowolnego inteligentnego kontraktu](/participate/web3/dns) +- [Proszę połączyć się z witrynami TON za pomocą TON Proxy](/participate/web3/setting-proxy) +- [Uruchom własny serwer proxy TON, aby połączyć się z witrynami TON](/participate/web3/sites-and-proxy) +- [Proszę połączyć swój portfel TON lub witrynę TON z domeną](/participate/web3/site-management) +- [Jak utworzyć subdomenę przy użyciu inteligentnych kontraktów TON DNS] (/participate/web3/site-management#how-to-set-up-subdomains) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/contribute/README.md b/i18n/ru/docusaurus-plugin-content-docs/current/contribute/README.md new file mode 100644 index 0000000000..7a0b86cd7f --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/contribute/README.md @@ -0,0 +1,50 @@ +# Как внести вклад + +## Определите область для вклада + +Есть несколько способов определить область, в которой Вы можете внести свой вклад в TON Docs: + +- Присоединяйтесь к чату [TON Docs Club](https://t.me/+c-0fVO4XHQsyOWM8) в Telegram и получайте информацию о последних задачах от сопровождающих. +- Если у Вас на примете есть конкретный вклад, но Вы не уверены в нём, уточните, подходит ли + этот вклад, обратившись напрямую к одному из сопровождающих [Docs](/contribute/maintainers). +- Ознакомьтесь с наиболее часто задаваемыми вопросами в чатах [TON Developers](https://t.me/tondev_eng). +- Пожалуйста, ознакомьтесь с [issues](https://github.com/ton-community/ton-docs/issues) в репозитории GitHub. +- Изучите доступные [footsteps](https://github.com/ton-society/ton-footsteps/issues?q=documentation) для документации. + +## TL;DR + +- Если Вам нужно добавить или изменить что-то в TON Docs, создайте запрос тяги + к ветке `main`. +- Команда разработчиков документации рассмотрит запрос на привлечение или свяжется с Вами при необходимости. +- Репозиторий: https://github.com/ton-community/ton-docs + +## Разработка + +### Онлайновая установка взносов в один клик + +Вы можете использовать Gitpod (бесплатную, онлайновую, похожую на VS code IDE) для внесения вклада. Он запустит рабочую область одним щелчком мыши и автоматически: + +[![Открыть в Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/ton-community/ton-docs) + +### Кодовые конвенции + +- **Самое важное**: оглянитесь вокруг. Соответствуйте общему стилю проекта. Это включает форматирование, именование файлов, именование объектов в коде, именование вещей в документации и так далее. +- **Для документации**: При редактировании документации не заворачивайте строки на 80 символов; вместо этого настройте свой редактор на мягкое заворачивание. + +Не беспокойтесь слишком сильно о стилях в целом; сопровождающие помогут Вам исправить их, когда будут просматривать Ваш код. + +### Pull Requests + +Итак, Вы решили внести свой код обратно в upstream, открыв запрос на исправление. Вы приложили много усилий, и мы ценим это. Мы сделаем все возможное, чтобы сотрудничать с Вами и добиться рассмотрения запроса. + +При подаче запроса на исправление, пожалуйста, убедитесь в следующем: + +1. **Сохраняйте свой запрос на исправление небольшим**. Маленькие запросы (~300 строк различий) легче просматривать и больше шансов, что они будут объединены. Убедитесь, что запрос на исправление делает только одну вещь, в противном случае, пожалуйста, разделите его. +2. **Используйте описательные заголовки**. Рекомендуется придерживаться стиля сообщений фиксации. +3. **Тестируйте свои изменения**. Опишите план тестирования в описании Вашего запроса на выгрузку. + +Все запросы на исправление должны быть открыты в ветке `main`. + +## Что происходит дальше? + +Команда TON Docs будет следить за запросами на доработку. Пожалуйста, помогите нам, следуя приведенным выше рекомендациям, чтобы запросы на доработку были согласованными. diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md b/i18n/ru/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md new file mode 100644 index 0000000000..bda8c8d345 --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md @@ -0,0 +1,39 @@ +# Программа локализации + +Программа переводов - это совместная работа по переводу различных документов, связанных с TON, на множество языков, что делает сайт более доступным для миллиардов людей, не говорящих по-английски, по всему миру. + +## Философия проектирования системы + +![как это работает](/img/localizationProgramGuideline/localization-program.png) + +Программа локализации **запущена** и **активно поддерживается** компанией [**TownSquare Labs**](https://github.com/TownSquareXYZ), одним из ближайших партнеров **TON**. + +Мы стремимся создать открытую инфраструктуру для сотрудничества многоязычного сообщества, чтобы **перевести TON в лучшую фазу**, что включает в себя: + +1. **Подходит для многоязычных сообществ**\ + Программа поддерживает несколько языков, обеспечивая инклюзивность и простоту доступа для пользователей из разных языковых сред. + +2. **Автоматизация разработки, интеграции и развертывания**\ + Используя инструменты автоматизации, программа упрощает процессы разработки, интеграции и развертывания, сокращая ручные усилия и повышая эффективность и согласованность всех усилий по локализации. + +3. **Разделение ролей разработчика, переводчика и верификатора**\ + Наш подход разделяет обязанности разработчиков, переводчиков и верификаторов, позволяя каждой роли сосредоточиться на своих конкретных задачах. Это обеспечивает высокое качество переводов и слаженную совместную работу без дублирования или конфликта обязанностей. + +4. **Поощрение за вклад сообщества**\ + Мы поощряем членов сообщества, которые вносят свой вклад в процесс локализации. Это поощряет активное участие и вознаграждает тех, кто помогает улучшить программу, развивая чувство сопричастности и дух сообщества. + +5. **Интеграция передовых систем искусственного интеллекта**\ + Передовые системы искусственного интеллекта повышают точность и эффективность перевода, предоставляя интеллектуальные предложения и автоматизируя повторяющиеся задачи, обеспечивая высокое качество результатов при меньших усилиях. + +Этот проект предназначен не только для носителей одного языка; наша цель - **служить глобальной экосистеме разработчиков**. + +## Благодарности + +Мы очень благодарны тысячам членов сообщества, которые являются ключевой частью Программы переводов. Мы хотим отметить наших переводчиков и поддержать их на их карьерном пути. В ближайшем будущем мы отметим наших лучших переводчиков, создав таблицы лидеров и список всех участников Программы переводов. + +## Руководства и ресурсы + +Если Вы вносите свой вклад в Программу переводов или думаете о том, чтобы принять в ней участие, ознакомьтесь с приведенными ниже руководствами по переводу: + +- [**Руководство по стилю перевода**](/contribute/localization-program/translation-style-guide) - Инструкции и советы для переводчиков. +- [**Руководство по онлайн-редактору Crowdin**](https://support.crowdin.com/online-editor/) - Подробное руководство по использованию онлайн-редактора Crowdin и некоторых расширенных возможностей Crowdin. diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md b/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md new file mode 100644 index 0000000000..47d5fac12e --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md @@ -0,0 +1,587 @@ +import Button from '@site/src/components/button' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Обработка платежей + +Эта страница **объясняет, как обрабатывать** (отправлять и принимать) `цифровые активы` на блокчейне TON. +Здесь **в основном** описывается работа с `монетами TON`, но **теоретическая часть** является **важной**, даже если Вы хотите обрабатывать только `джеттоны`. + +## Смарт-контракт кошелька + +Смарт-контракты кошелька - это контракты в сети TON, которые служат для того, чтобы позволить участникам, находящимся вне блокчейна, взаимодействовать с сущностями блокчейна. В целом, они решают три задачи: + +- удостоверяет подлинность владельца: Отказывается обрабатывать и оплачивать запросы лиц, не являющихся владельцами. +- Защита от повторов: Запрещает повторное выполнение одного запроса, например, отправку активов другому смарт-контракту. +- инициирует произвольное взаимодействие с другими смарт-контрактами. + +Стандартным решением первой задачи является криптография с открытым ключом: `кошелек` хранит открытый ключ и проверяет, что входящее сообщение с запросом подписано соответствующим закрытым ключом, который известен только его владельцу. + +Решение третьей задачи также является общим; обычно запрос содержит полностью сформированное внутреннее сообщение, которое `кошелек` отправляет в сеть. Однако для защиты от воспроизведения существует несколько различных подходов. + +### Кошельки на основе Seqno + +Кошельки на основе Seqno используют наиболее простой подход к определению последовательности сообщений. Каждое сообщение имеет специальное целое число `seqno`, которое должно совпадать со счетчиком, хранящимся в смарт-контракте `wallet`. `wallet` обновляет свой счетчик при каждом запросе, гарантируя тем самым, что один запрос не будет обработан дважды. Существует несколько версий `wallet`, которые отличаются от общедоступных методов: возможность ограничивать запросы по времени истечения срока действия и возможность иметь несколько кошельков с одним и тем же открытым ключом. Однако неотъемлемым требованием такого подхода является отправка запросов по одному, поскольку любой разрыв в последовательности `seqno` приведет к невозможности обработки всех последующих запросов. + +### Кошельки с высокой нагрузкой + +Этот тип `кошелька` использует подход, основанный на хранении идентификатора непросроченных обработанных запросов в хранилище смарт-контрактов. При таком подходе любой запрос проверяется на предмет дублирования уже обработанного запроса и, в случае обнаружения повтора, отбрасывается. Из-за истечения срока действия контракт не может хранить все запросы вечно, но он будет удалять те, которые не могут быть обработаны из-за ограничения срока действия. Запросы к этому `кошельку` могут отправляться параллельно, не мешая друг другу; однако такой подход требует более сложного контроля за обработкой запросов. + +### Развертывание кошелька + +Чтобы развернуть кошелек с помощью TonLib, необходимо: + +1. Сгенерируйте пару закрытый/открытый ключ с помощью [createNewKey](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L244) или ее функций-оберток (пример в [tonlib-go](https://github.com/mercuryoio/tonlib-go/tree/master/v2#create-new-private-key)). Обратите внимание, что закрытый ключ генерируется локально и не покидает хост-машину. +2. Сформируйте структуру [InitialAccountWallet](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L62), соответствующую одному из включенных `кошельков`. В настоящее время доступны `wallet.v3`, `wallet.v4`, `wallet.highload.v1`, `wallet.highload.v2`. +3. Вычислите адрес нового смарт-контракта `кошелька` с помощью метода [getAccountAddress](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L283). Мы рекомендуем использовать ревизию по умолчанию `0`, а также развертывать кошельки в базовой цепи `workchain=0` для снижения платы за обработку и хранение данных. +4. Отправьте несколько Toncoin на вычисленный адрес. Обратите внимание, что отправлять их нужно в режиме `non-bounce`, поскольку этот адрес еще не имеет кода и поэтому не может обрабатывать входящие сообщения. Флаг `non-bounce` указывает, что даже если обработка не удалась, деньги не должны быть возвращены с сообщением об отказе. Мы не рекомендуем использовать флаг `non-bounce` для других транзакций, особенно при переводе больших сумм, поскольку механизм отказов обеспечивает некоторую степень защиты от ошибок. +5. Сформируйте желаемое [действие](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L154), например, `actionNoop` только для развертывания. Затем используйте [createQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L292) и [sendQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L300), чтобы инициировать взаимодействие с блокчейном. +6. Проверьте контракт за несколько секунд с помощью метода [getAccountState](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L288). + +:::tip +Подробнее читайте в [Учебнике по кошельку] (/develop/smart-contracts/tutorials/wallet#-deploying-a-wallet) +::: + +### Проверьте действительность адреса кошелька + +Большинство SDK заставляют Вас проверять адрес (большинство проверяет его в процессе создания кошелька или подготовки транзакции), поэтому, как правило, это не требует от Вас никаких дополнительных сложных действий. + + + + + +```js + const TonWeb = require("tonweb") + TonWeb.utils.Address.isValid('...') +``` + + + + +```python +package main + +import ( + "fmt" + "github.com/xssnick/tonutils-go/address" +) + +if _, err := address.ParseAddr("EQCD39VS5j...HUn4bpAOg8xqB2N"); err != nil { + return errors.New("invalid address") +} +``` + + + + +```javascript +try { + Address.of("..."); + } catch (e) { + // not valid address +} +``` + + + + +```javascript + try { + AddrStd("...") + } catch(e: IllegalArgumentException) { + // not valid address + } +``` + + + + +:::tip +Полное описание адресов на странице [Адреса смарт-контрактов](/learn/overviews/addresses). +::: + +## Работа с переводами + +### Проверьте сделки по контракту + +Транзакции контракта можно получить с помощью метода [getTransactions](https://toncenter.com/api/v2/#/accounts/get_transactions_getTransactions_get). Этот метод позволяет получить 10 транзакций с некоторого `последнего_transaction_id` и более ранних. Чтобы обработать все входящие транзакции, необходимо выполнить следующие шаги: + +1. Последний `последний_транзакционный_ид` можно получить с помощью [getAddressInformation](https://toncenter.com/api/v2/#/accounts/get_address_information_getAddressInformation_get) +2. Список из 10 транзакций должен быть загружен с помощью метода `getTransactions`. +3. Обрабатывайте транзакции с непустым источником во входящем сообщении и адресом назначения, равным адресу счета. +4. Следующие 10 транзакций должны быть загружены, и шаги 2,3,4,5 должны повторяться до тех пор, пока Вы не обработаете все входящие транзакции. + +### Получение входящих/исходящих транзакций + +Можно отслеживать поток сообщений во время обработки транзакций. Поскольку поток сообщений представляет собой DAG, достаточно получить текущую транзакцию с помощью метода [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) и найти входящую транзакцию по `out_msg` с помощью [tryLocateResultTx](https://testnet.toncenter.com/api/v2/#/transactions/get_try_locate_result_tx_tryLocateResultTx_get) или исходящую транзакцию по `in_msg` с помощью [tryLocateSourceTx](https://testnet.toncenter.com/api/v2/#/transactions/get_try_locate_source_tx_tryLocateSourceTx_get). + + + + +```ts +import { TonClient, Transaction } from '@ton/ton'; +import { getHttpEndpoint } from '@orbs-network/ton-access'; +import { CommonMessageInfoInternal } from '@ton/core'; + +async function findIncomingTransaction(client: TonClient, transaction: Transaction): Promise { + const inMessage = transaction.inMessage?.info; + if (inMessage?.type !== 'internal') return null; + return client.tryLocateSourceTx(inMessage.src, inMessage.dest, inMessage.createdLt.toString()); +} + +async function findOutgoingTransactions(client: TonClient, transaction: Transaction): Promise { + const outMessagesInfos = transaction.outMessages.values() + .map(message => message.info) + .filter((info): info is CommonMessageInfoInternal => info.type === 'internal'); + + return Promise.all( + outMessagesInfos.map((info) => client.tryLocateResultTx(info.src, info.dest, info.createdLt.toString())), + ); +} + +async function traverseIncomingTransactions(client: TonClient, transaction: Transaction): Promise { + const inTx = await findIncomingTransaction(client, transaction); + // now you can traverse this transaction graph backwards + if (!inTx) return; + await traverseIncomingTransactions(client, inTx); +} + +async function traverseOutgoingTransactions(client: TonClient, transaction: Transaction): Promise { + const outTxs = await findOutgoingTransactions(client, transaction); + // do smth with out txs + for (const out of outTxs) { + await traverseOutgoingTransactions(client, out); + } +} + +async function main() { + const endpoint = await getHttpEndpoint({ network: 'testnet' }); + const client = new TonClient({ + endpoint, + apiKey: '[API-KEY]', + }); + + const transaction: Transaction = ...; // Obtain first transaction to start traversing + await traverseIncomingTransactions(client, transaction); + await traverseOutgoingTransactions(client, transaction); +} + +main(); +``` + + + + +### Отправляйте платежи + +1. Сервис должен развернуть `кошелек` и постоянно пополнять его, чтобы предотвратить разрушение контракта из-за платы за хранение. Обратите внимание, что плата за хранение обычно составляет менее 1 Тонкоина в год. +2. Сервис должен получить от пользователя `адрес_назначения` и необязательный `комментарий`. Обратите внимание, что на данный момент мы рекомендуем либо запретить незавершенные исходящие платежи с одинаковым набором (`адрес_назначения`, `значение`, `комментарий`), либо правильно планировать эти платежи; таким образом, следующий платеж будет инициирован только после подтверждения предыдущего. +3. Сформируйте [msg.dataText](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L103) с `comment` в качестве текста. +4. Форма [msg.message](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L113), содержащая `адрес_назначения`, пустой `публичный_ключ`, `сумму` и `msg.dataText`. +5. Форма [Действие](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L154), содержащая набор исходящих сообщений. +6. Используйте запросы [createQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L292) и [sendQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L300) для отправки исходящих платежей. +7. Сервис должен регулярно опрашивать метод [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) для контракта `wallet`. Сопоставление подтвержденных транзакций с исходящими платежами по (`адрес_назначения`, `значение`, `комментарий`) позволяет пометить платежи как завершенные; обнаружить и показать пользователю соответствующий хэш транзакции и lt (логическое время). +8. Запросы к `v3` кошелькам с `высокой нагрузкой` по умолчанию имеют время истечения, равное 60 секундам. По истечении этого времени необработанные запросы могут быть безопасно повторно отправлены в сеть (см. шаги 3-6). + +### Получите идентификатор транзакции + +Может быть неясно, что для получения дополнительной информации о транзакции пользователь должен просканировать блокчейн с помощью функции [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get). +Невозможно получить идентификатор транзакции сразу после отправки сообщения, поскольку транзакция сначала должна быть подтверждена сетью блокчейн. +Чтобы понять, что требуется для этого, внимательно прочитайте [Send payments](https://docs.ton.org/develop/dapps/asset-processing/#send-payments), особенно 7-й пункт. + +## Подход на основе счета-фактуры + +Чтобы принимать платежи на основании прикрепленных комментариев, сервис должен + +1. Разверните контракт `wallet`. +2. Сгенерируйте уникальный `счет` для каждого пользователя. Строкового представления uuid32 будет достаточно. +3. Пользователям следует дать указание отправить Тонкоин на `кошелек` сервиса с приложенным `счетом-фактурой` в качестве комментария. +4. Сервис должен регулярно опрашивать метод [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) для контракта `wallet`. +5. Для новых транзакций входящее сообщение должно быть извлечено, `комментарий` сопоставлен с базой данных, а **значение входящего сообщения** зачислено на счет пользователя. + +Чтобы вычислить **значение входящего сообщения**, которое сообщение приносит контракту, необходимо разобрать транзакцию. Это происходит, когда сообщение попадает в контракт. Транзакцию можно получить с помощью [getTransactions](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L268). Для входящей транзакции кошелька правильные данные состоят из одного входящего сообщения и нуля исходящих сообщений. В противном случае либо в кошелек отправляется внешнее сообщение, и тогда владелец тратит Toncoin, либо кошелек не развернут, и входящая транзакция возвращается обратно. + +В любом случае, в общем случае, сумма, которую сообщение приносит контракту, может быть рассчитана как стоимость входящего сообщения минус сумма стоимостей исходящих сообщений минус комиссия: `value_{in_msg} - SUM(value_{out_msg}) - fee`. Технически, представление транзакций содержит три различных поля с `fee` в имени: `fee`, `storage_fee` и `other_fee`, то есть общая плата, часть платы, связанная с расходами на хранение, и часть платы, связанная с обработкой транзакций. Следует использовать только первую. + +### Счета-фактуры с помощью TON Connect + +Лучше всего подходит для dApp, которым нужно подписывать несколько платежей/транзакций в течение сессии или поддерживать соединение с кошельком в течение некоторого времени. + +- ✅ Существует постоянный канал связи с кошельком, информация об адресе пользователя + +- ✅ Пользователям нужно сканировать QR-код только один раз + +- ✅ Можно узнать, подтвердил ли пользователь транзакцию в кошельке, отследить транзакцию по возвращенному BOC + +- ✅ Готовые SDK и наборы пользовательского интерфейса доступны для разных платформ + +- ❌ Если Вам нужно отправить только один платеж, пользователю необходимо выполнить два действия: подключить кошелек и подтвердить транзакцию + +- ❌ Интеграция сложнее, чем просто ссылка ton://. + +```mdx-code-block + +``` + +### Счета-фактуры со ссылкой ton:// + +:::warning +Ссылка Ton устарела, избегайте ее использования +::: + +Если Вам нужна простая интеграция для простого потока пользователей, лучше всего использовать ссылку ton://. +Лучше всего подходит для разовых платежей и счетов-фактур. + +```bash +ton://transfer/? + [nft=&] + [fee-amount=&] + [forward-amount=] +``` + +- ✅ Легкая интеграция + +- ✅ Нет необходимости подключать кошелек + +- ❌ Пользователям необходимо сканировать новый QR-код для каждого платежа + +- ❌ Невозможно отследить, подписал ли пользователь транзакцию или нет. + +- ❌ Нет информации об адресе пользователя + +- ❌ Необходимы обходные пути на платформах, где такие ссылки не кликабельны (например, сообщения от ботов для настольных клиентов Telegram). + +[Подробнее о тонких ссылках здесь](https://github.com/tonkeeper/wallet-api#payment-urls) + +## Explorers + +Исследователь блокчейна - https://tonscan.org. + +Чтобы создать ссылку на транзакцию в проводнике, служба должна получить lt (логическое время), хэш транзакции и адрес счета (адрес счета, для которого lt и txhash были получены с помощью метода [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get)). https://tonscan.org и https://explorer.toncoin.org/ могут затем показать страницу для этого tx в следующем формате: + +`https://tonviewer.com/transaction/{txhash as base64url}`. + +`https://tonscan.org/tx/{lt as int}:{txhash as base64url}:{account address}` + +`https://explorer.toncoin.org/transaction?account={account address}<={lt as int}&hash={txhash as base64url}` + +## Лучшие практики + +### Создание кошелька + + + + +- **toncenter:** + - [Создание кошелька + получение адреса кошелька](https://github.com/toncenter/examples/blob/main/common.js) + +- **ton-community/ton:** + - [Создание кошелька + получение баланса](https://github.com/ton-community/ton#usage) + + + + + +- **xssnick/tonutils-go:**. + - [Создание кошелька + получение баланса](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#wallet) + + + + + +- **psylopunk/pythonlib:**. + - [Создание кошелька + получение адреса кошелька](https://github.com/psylopunk/pytonlib/blob/main/examples/generate_wallet.py) +- **yungwine/pytoniq:**. + +```py +import asyncio + +from pytoniq.contract.wallets.wallet import WalletV4R2 +from pytoniq.liteclient.balancer import LiteBalancer + + +async def main(): + provider = LiteBalancer.from_mainnet_config(2) + await provider.start_up() + + mnemonics, wallet = await WalletV4R2.create(provider) + print(f"{wallet.address=} and {mnemonics=}") + + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + + + + +### Депозиты в тонкоинах (Получите тонкоины) + + + + +- **toncenter:** + - [Обработать депозит в Toncoins](https://github.com/toncenter/examples/blob/main/deposits.js) + - [Обработка депозита Toncoins на несколько кошельков](https://github.com/toncenter/examples/blob/main/deposits-multi-wallets.js) + + + + + +- **xssnick/tonutils-go:**. + +
+Депозиты в чеках + +```go +package main + +import ( + "context" + "encoding/base64" + "log" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/liteclient" + "github.com/xssnick/tonutils-go/ton" +) + +const ( + num = 10 +) + +func main() { + client := liteclient.NewConnectionPool() + err := client.AddConnectionsFromConfigUrl(context.Background(), "https://ton.org/global.config.json") + if err != nil { + panic(err) + } + + api := ton.NewAPIClient(client, ton.ProofCheckPolicyFast).WithRetry() + + accountAddr := address.MustParseAddr("0QA__NJI1SLHyIaG7lQ6OFpAe9kp85fwPr66YwZwFc0p5wIu") + + // we need fresh block info to run get methods + b, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + log.Fatal(err) + } + + // we use WaitForBlock to make sure block is ready, + // it is optional but escapes us from liteserver block not ready errors + res, err := api.WaitForBlock(b.SeqNo).GetAccount(context.Background(), b, accountAddr) + if err != nil { + log.Fatal(err) + } + + lastTransactionId := res.LastTxHash + lastTransactionLT := res.LastTxLT + + headSeen := false + + for { + trxs, err := api.ListTransactions(context.Background(), accountAddr, num, lastTransactionLT, lastTransactionId) + if err != nil { + log.Fatal(err) + } + + for i, tx := range trxs { + // should include only first time lastTransactionLT + if !headSeen { + headSeen = true + } else if i == 0 { + continue + } + + if tx.IO.In == nil || tx.IO.In.Msg.SenderAddr().IsAddrNone() { + // external message should be omitted + continue + } + + if tx.IO.Out != nil { + // no outgoing messages - this is incoming Toncoins + continue + } + + // process trx + log.Printf("found in transaction hash %s", base64.StdEncoding.EncodeToString(tx.Hash)) + } + + if len(trxs) == 0 || (headSeen && len(trxs) == 1) { + break + } + + lastTransactionId = trxs[0].Hash + lastTransactionLT = trxs[0].LT + } +} +``` + +
+
+ + + +- **yungwine/pytoniq:**. + +Депозиты в чеках + +```python +import asyncio + +from pytoniq_core import Transaction + +from pytoniq import LiteClient, Address + +MY_ADDRESS = Address("kf8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM_BP") + + +async def main(): + client = LiteClient.from_mainnet_config(ls_i=0, trust_level=2) + + await client.connect() + + last_block = await client.get_trusted_last_mc_block() + + _account, shard_account = await client.raw_get_account_state(MY_ADDRESS, last_block) + assert shard_account + + last_trans_lt, last_trans_hash = ( + shard_account.last_trans_lt, + shard_account.last_trans_hash, + ) + + while True: + print(f"Waiting for{last_block=}") + + transactions = await client.get_transactions( + MY_ADDRESS, 1024, last_trans_lt, last_trans_hash + ) + toncoin_deposits = [tx for tx in transactions if filter_toncoin_deposit(tx)] + print(f"Got {len(transactions)=} with {len(toncoin_deposits)=}") + + for deposit_tx in toncoin_deposits: + # Process toncoin deposit transaction + print(deposit_tx.cell.hash.hex()) + + last_trans_lt = transactions[0].lt + last_trans_hash = transactions[0].cell.hash + + +def filter_toncoin_deposit(tx: Transaction): + if tx.out_msgs: + return False + + if tx.in_msg: + return False + + return True + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + +
+ +### Вывод Тонкоинов (Отправить Тонкоины) + + + + +- **toncenter:** + - [Вывод Тонкоинов из кошелька партиями](https://github.com/toncenter/examples/blob/main/withdrawals-highload-batch.js) + - [Вывести Тонкоины из кошелька](https://github.com/toncenter/examples/blob/main/withdrawals-highload.js) + +- **ton-community/ton:** + - [Вывести Тонкоины из кошелька](https://github.com/ton-community/ton#usage) + + + + + +- **xssnick/tonutils-go:**. + - [Вывести Тонкоины из кошелька](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#wallet) + + + + + +- **psylopunk/pythonlib:**. + - [Вывести Тонкоины из кошелька](https://github.com/psylopunk/pytonlib/blob/main/examples/transactions.py) + +- **yungwine/pytoniq:**. + +```python +import asyncio + +from pytoniq_core import Address +from pytoniq.contract.wallets.wallet import WalletV4R2 +from pytoniq.liteclient.balancer import LiteBalancer + + +MY_MNEMONICS = "one two tree ..." +DESTINATION_WALLET = Address("Destination wallet address") + + +async def main(): + provider = LiteBalancer.from_mainnet_config() + await provider.start_up() + + wallet = await WalletV4R2.from_mnemonic(provider, MY_MNEMONICS) + + await wallet.transfer(DESTINATION_WALLET, 5) + + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + + + + +### Получите транзакции контракта + + + + +- **ton-community/ton:** + - [Клиент с методом getTransaction](https://github.com/ton-community/ton/blob/master/src/client/TonClient.ts) + + + + + +- **xssnick/tonutils-go:**. + - [Получить транзакции] (https://github.com/xssnick/tonutils-go?tab=readme-ov-file#account-info-and-transactions) + + + + + +- **psylopunk/pythonlib:**. + - [Получить транзакции] (https://github.com/psylopunk/pytonlib/blob/main/examples/transactions.py) +- **yungwine/pytoniq:**. + - [Получить транзакции] (https://github.com/yungwine/pytoniq/blob/master/examples/transactions.py) + + + + + +## SDKs + +Вы можете найти список SDK для различных языков (JS, Python, Golang, C#, Rust и т.д.) список [здесь](/develop/dapps/apis/sdk). diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md b/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md new file mode 100644 index 0000000000..6ee3df699e --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md @@ -0,0 +1,1205 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Button from '@site/src/components/button'; + +# Тонна переработки Jetton + +:::info +Для ясного понимания читатель должен быть знаком с основными принципами обработки активов, описанными в [разделе обработки платежей](/develop/dapps/asset-processing/) нашей документации. +::: + +Джеттоны - это токены на блокчейне TON - их можно рассматривать аналогично токенам ERC-20 на Ethereum. + +В этом анализе мы глубже погружаемся в формальные стандарты, подробно описывающие [поведение] (https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) и [метаданные] (https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md) jetton. +Менее формальный обзор архитектуры jetton, ориентированный на шардинг, можно найти в нашем блоге +[анатомия jettons](https://blog.ton.org/how-to-shard-your-ton-smart-contract-and-why-studying-the-anatomy-of-tons-jettons). + +Также Вам следует помнить, что существует два подхода к работе с выводами средств из jetton: + +- [Memo Deposits](https://github.com/toncenter/examples/blob/main/deposits-jettons.js) - Это позволяет Вам держать один депозитный кошелек, а пользователи добавляют в него памятку, чтобы быть идентифицированными Вашей системой. Это означает, что Вам не нужно сканировать весь блокчейн, но это немного менее удобно для пользователей. +- [Депозиты без мемо](https://github.com/gobicycle/bicycle) - Это решение также существует, но его сложнее интегрировать. Тем не менее, мы можем помочь Вам, если Вы хотите пойти этим путем. Пожалуйста, уведомите нас, прежде чем принять решение о применении этого подхода. + +## Jetton Architecture + +Стандартизированные токены TON реализуются с помощью набора смарт-контрактов, включая: + +- [Jetton master](https://github.com/ton-blockchain/token-contract/blob/main/ft/jetton-minter.fc) смарт-контракт +- [Кошелек Jetton](https://github.com/ton-blockchain/token-contract/blob/main/ft/jetton-wallet.fc) смарт-контракты + +

+
+ contracts scheme +
+

+ +## Главный смарт-контракт Jetton + +Главный смарт-контракт jetton хранит общую информацию о джеттоне (включая общий запас, ссылку на метаданные или сами метаданные). + +:::warning Остерегайтесь мошенничества от Jetton + +Джеттоны с `символом`==`TON` или те, которые содержат системные уведомления, такие как: +`ERROR`, `SYSTEM` и другие. Обязательно проверьте, что джеттоны отображаются в Вашем интерфейсе таким образом, чтобы их нельзя было +смешать с передачей TON, системными уведомлениями и т.д.. Иногда даже `symbol`, `name` и `image` +создаются так, чтобы выглядеть почти идентично оригиналу, в надежде ввести пользователей в заблуждение. + +Чтобы исключить возможность мошенничества для пользователей TON, пожалуйста, посмотрите **оригинальный адрес джеттона** (Jetton master contract) для конкретных типов джеттонов или **следуйте за официальным каналом проекта в социальных сетях** или веб-сайтом, чтобы найти **корректную информацию**. Проверьте активы, чтобы исключить возможность мошенничества, с помощью [Tonkeeper ton-assets list](https://github.com/tonkeeper/ton-assets). +::: + +### Извлечение данных Jetton + +Чтобы получить более конкретные данные Jetton, используйте метод *get* контракта `get_jetton_data()`. + +Этот метод возвращает следующие данные: + +| Имя | Тип | Описание | +| -------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `total_supply` | `int` | общее количество выпущенных джеттонов, измеренное в неделимых единицах. | +| `mintable` | `int` | Подробно описывает, можно ли чеканить новые джеттоны или нет. Это значение равно либо -1 (можно чеканить), либо 0 (нельзя чеканить). | +| `admin_address` | `slice` | | +| `jetton_content` | `ячейка` | Данные в соответствии с [TEP-64](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md), подробнее смотрите на странице [jetton metadata parsing page](/develop/dapps/asset-processing/metadata). | +| `jetton_wallet_code` | `ячейка` | | + +Вы можете вызвать его через [Toncenter API](https://toncenter.com/api/v3/#/default/get_jetton_masters_api_v3_jetton_masters_get) или один из [SDK](https://docs.ton.org/develop/dapps/apis/sdk). + + + + +> Запустите метод `jetton/masters` из [Toncenter API] (https://toncenter.com/api/v3/#/default/get_jetton_masters_api_v3_jetton_masters_get) + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: ""}); +const data = await jettonMinter.getJettonData(); +console.log('Total supply:', data.totalSupply.toString()); +console.log('URI to off-chain metadata:', data.jettonContentUri); +``` + + + + +### Джеттон минтер + +Как уже упоминалось, джеттоны могут быть как `мятными`, так и `немятными`. + +Если они не чеканятся, логика становится простой - нет возможности чеканить дополнительные жетоны. Для первой чеканки джеттонов обратитесь к странице [Mint your first jetton](/develop/dapps/tutorials/jetton-minter). + +Если джеттоны можно чеканить, в контракте [minter contract](https://github.com/ton-blockchain/minter-contract/blob/main/contracts/jetton-minter.fc) есть специальная функция для чеканки дополнительных джеттонов. Эту функцию можно вызвать, отправив с адреса администратора `внутреннее сообщение` с указанным опкодом. + +Если администратор jetton хочет ограничить создание jetton, есть три способа сделать это: + +1. Если Вы не можете или не хотите обновлять код контракта, администратору необходимо передать право собственности от текущего администратора на нулевой адрес. В результате контракт останется без действующего администратора, что не позволит никому чеканить джеттоны. Однако это также предотвратит любые изменения в метаданных джеттона. +2. Если у Вас есть доступ к исходному коду и Вы можете его изменить, Вы можете создать метод в контракте, который устанавливает флаг для прерывания любого процесса чеканки после его вызова, и добавить оператор для проверки этого флага в функцию mint. +3. Если Вы можете обновить код контракта, Вы можете добавить ограничения, обновив код уже развернутого контракта. + +## Смарт-контракт для кошелька Jetton + +Контракты `Jetton wallet` используются для **отправки**, **получения** и **сжигания** джеттонов. Каждый контракт *кошелька джеттона* хранит информацию о балансе кошелька для конкретных пользователей. +В отдельных случаях джеттоновые кошельки используются для отдельных держателей джеттонов каждого типа. + +`Джеттон-кошельки` **не следует путать с кошельками**, предназначенными для взаимодействия с блокчейном и хранения +только актива Toncoin (например, кошельки v3R2, highload-кошельки и другие), +которые отвечают за поддержку и управление **только определенным типом джеттона**. + +### Развертывание кошелька Jetton + +При `передаче джеттонов` между кошельками транзакции (сообщения) требуют определенного количества TON +в качестве оплаты сетевых **газовых сборов** и выполнения действий в соответствии с кодом контракта кошелька Jetton. +Это означает, что **получателю не нужно разворачивать кошелек jetton перед получением джеттонов**. +Кошелек Jetton получателя будет развернут автоматически, пока отправитель имеет в кошельке достаточное количество TON +, чтобы оплатить необходимые сборы за газ. + +### Получение адресов кошельков Jetton для данного пользователя + +Чтобы получить `адрес` кошелька `jetton` с помощью `адреса владельца` (адреса кошелька TON), +главный контракт `Jetton` предоставляет метод get `get_wallet_address(slice owner_address)`. + + + + +> Запустите `get_wallet_address(slice owner_address)` через метод `/runGetMethod` из [Toncenter API](https://toncenter.com/api/v3/#/default/run_get_method_api_v3_runGetMethod_post). + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: ""}); +const address = await jettonMinter.getJettonWalletAddress(new TonWeb.utils.Address("")); +// It is important to always check that wallet indeed is attributed to desired Jetton Master: +const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider, { + address: jettonWalletAddress +}); +const jettonData = await jettonWallet.getData(); +if (jettonData.jettonMinterAddress.toString(false) !== new TonWeb.utils.Address(info.address).toString(false)) { + throw new Error('jetton minter address from jetton wallet doesnt match config'); +} + +console.log('Jetton wallet address:', address.toString(true, true, true)); +``` + + + + +### Получение данных для определенного кошелька Jetton + +Чтобы получить баланс кошелька, идентификационные данные владельца и другую информацию, относящуюся к конкретному контракту кошелька jetton, используйте метод `get_wallet_data()` для получения данных в контракте кошелька jetton. + +Этот метод возвращает следующие данные: + +| Имя | Тип | +| -------------------- | -------- | +| `баланс` | int | +| `владелец` | нарезать | +| `jetton` | нарезать | +| `jetton_wallet_code` | клетка | + + + + +> Используйте метод `/jetton/wallets` get из [Toncenter API](https://toncenter.com/api/v3/#/default/get_jetton_wallets_api_v3_jetton_wallets_get), чтобы получить ранее расшифрованные данные кошелька jetton. + + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const walletAddress = "EQBYc3DSi36qur7-DLDYd-AmRRb4-zk6VkzX0etv5Pa-Bq4Y"; +const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider,{address: walletAddress}); +const data = await jettonWallet.getData(); +console.log('Jetton balance:', data.balance.toString()); +console.log('Jetton owner address:', data.ownerAddress.toString(true, true, true)); +// It is important to always check that Jetton Master indeed recognize wallet +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: data.jettonMinterAddress.toString(false)}); +const expectedJettonWalletAddress = await jettonMinter.getJettonWalletAddress(data.ownerAddress.toString(false)); +if (expectedJettonWalletAddress.toString(false) !== new TonWeb.utils.Address(walletAddress).toString(false)) { + throw new Error('jetton minter does not recognize the wallet'); +} + +console.log('Jetton master address:', data.jettonMinterAddress.toString(true, true, true)); +``` + + + + +## Обзор коммуникаций с кошельками Jetton + +Обмен данными между кошельками Jetton и кошельками TON происходит в следующей последовательности: + +![](/img/docs/asset-processing/jetton_transfer.svg) + +#### Сообщение 0 + +`Отправитель -> кошелек jetton отправителя`. Сообщение *Transfer* содержит следующие данные: + +| Имя | Тип | Описание | +| ---------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `query_id` | uint64 | Позволяет приложениям связывать между собой три типа сообщений `Передача`, `Уведомление о передаче` и `Излишки`. Чтобы этот процесс выполнялся правильно, рекомендуется **всегда использовать уникальный идентификатор запроса**. | +| `сумма` | монеты | Общее количество `тонн монет`, которое будет отправлено с сообщением. | +| `назначение` | адрес | Адрес нового владельца джеттонов | +| `response_destination` | адрес | Адрес кошелька, используемый для возврата оставшихся тонн монет с сообщением о превышении. | +| `custom_payload` | возможно, клетка | Размер всегда >= 1 бит. Пользовательские данные (которые используются либо отправителем, либо получателем кошелька jetton для внутренней логики). | +| `передняя_тонна_суммы` | монеты | Должно быть > 0, если Вы хотите отправить `уведомление о передаче` с `передаваемой полезной нагрузкой`. Это **часть значения `суммы`** и **должно быть меньше, чем `сумма`**. | +| `forward_payload` | возможно, клетка | Размер всегда >= 1 биту. Если первые 32 бита = 0x0, то это простое сообщение. | + +#### Сообщение 2' + +Кошелек jetton -> payee`. Сообщение-уведомление о переводе. **Отправляется только в том случае, если** `переданная_тонная_сумма\` **не нулевая**. Содержит следующие данные: + +| Имя | Тип | +| ----------------- | ------ | +| `query_id` | uint64 | +| `сумма` | монеты | +| `sender` | адрес | +| `forward_payload` | клетка | + +Здесь адрес `отправителя` - это адрес `Джеттон-кошелька` Алисы. + +#### Сообщение 2'' + +Кошелек jetton от `payee` -> Отправитель\`. Тело сообщения. **Отправляется только в том случае, если после оплаты взносов остались монеты тонны**. Содержит следующие данные: + +| Имя | Тип | +| ---------- | ------ | +| `query_id` | uint64 | + +:::tip Стандартные джеттоны +Подробное описание полей контракта кошелька jetton можно найти в описании интерфейса [TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) `Jetton standard`. +::: + +## Отправить джеттоны с комментариями + +Для этого перевода потребуется несколько тонн монет для **fees** и, по желанию, **сообщение об уведомлении о переводе** (проверьте поле "Сумма перевода"). + +Для отправки **комментария** Вам необходимо настроить `передачу полезной нагрузки`. Установите **первые 32 бита в 0x0** и добавьте **ваш текст**. + +`Передаваемая полезная нагрузка` отправляется во внутреннем сообщении `уведомление о переводе`. Оно будет сгенерировано только в том случае, если `переданная сумма` > 0. + +Наконец, чтобы получить сообщение `Excess`, Вы должны настроить `назначение ответа`. + +:::tip +Проверьте [лучшие практики](/develop/dapps/asset-processing/jettons#best-practices) на примере *"отправлять джеттоны с комментариями"*. +::: + +## Внецепочечная обработка Jetton + +:::info Подтверждение транзакции +Транзакции TON становятся необратимыми после одного подтверждения. Для достижения наилучшего пользовательского опыта рекомендуется избегать ожидания дополнительных блоков после завершения транзакций на блокчейне TON. Подробнее читайте в [Catchain.pdf](https://docs.ton.org/catchain.pdf#page=3). +::: + +Существует два способа приема джеттонов: + +- в рамках **централизованного горячего кошелька**. +- использование кошелька с **отдельным адресом** для **каждого отдельного пользователя**. + +В целях безопасности предпочтительно иметь **отдельные горячие кошельки** для **отдельных джеттонов** (много кошельков для каждого типа активов). + +При обработке средств также рекомендуется предусмотреть "холодный" кошелек для хранения избыточных средств, которые не участвуют в процессах автоматического ввода и вывода. + +### Добавление новых джеттонов для обработки активов и первичной проверки + +1. Найдите правильный адрес [смарт-контракта] (/develop/dapps/asset-processing/jettons#jetton-master-smart-contract). +2. Получите [метаданные](/develop/dapps/asset-processing/jettons#retrieving-jetton-data). +3. Проверьте наличие [мошенничества](/develop/dapps/asset-processing/jettons#jetton-master-smart-contract). + +### Идентификация неизвестного Jetton при получении сообщения об уведомлении о передаче + +Если в Ваш кошелек поступило уведомление о переводе неизвестного Jetton, значит, Ваш кошелек +был создан для хранения конкретного Jetton. + +Адрес отправителя внутреннего сообщения, содержащего тело `Transfer notification`, - это адрес нового кошелька Jetton. +Его не следует путать с полем `отправитель` в теле сообщения `Уведомление о переводе` (/develop/dapps/asset-processing/jettons#jetton-wallets-communication-overview). + +1. Получите главный адрес Jetton для нового кошелька Jetton, используя [получение данных кошелька] (/develop/dapps/asset-processing/jettons#retrieving-data-for-a-specific-jetton-wallet). +2. Получите адрес кошелька Jetton для Вашего адреса кошелька (как владельца), используя главный контракт Jetton: [Как получить адрес кошелька Jetton для данного пользователя](#retrieving-jetton-wallet-addresses-for-a-given-user) +3. Сравните адрес, возвращенный главным контрактом, и фактический адрес токена в кошельке. + Если они совпадают, то это идеальный вариант. Если нет, то, скорее всего, Вы получили мошеннический токен, который является подделкой. +4. Получение метаданных Jetton: [Как получить метаданные Jetton] (#retrieving-jetton-data). +5. Проверьте поля `symbol` и `name` на наличие признаков мошенничества. При необходимости предупредите пользователя. [Добавление нового джеттона для обработки и первичной проверки](#adding-new-jettons-for-asset-processing-and-initial-verification). + +### Прием джеттонов от пользователей через централизованный кошелек + +:::info +Чтобы не допустить узкого места в транзакциях, поступающих на один кошелек, рекомендуется принимать депозиты на несколько кошельков и расширять их количество по мере необходимости. +::: + +В этом сценарии платежный сервис создает уникальный идентификатор мемо для каждого отправителя, раскрывая +адрес централизованного кошелька и отправляемые суммы. Отправитель посылает токены +на указанный централизованный адрес с обязательной памяткой в комментарии. + +**Плюсы этого метода:** Этот метод очень прост, поскольку при приеме токенов не взимается никаких дополнительных комиссий, и они поступают непосредственно в горячий кошелек. + +**Недостатки этого метода:** этот метод требует, чтобы все пользователи прикрепляли комментарий к переводу, что может привести к большему количеству ошибок при внесении средств (забытые записки, неправильные записки и т.д.), что означает большую нагрузку на сотрудников службы поддержки. + +Примеры Tonweb: + +1. [Прием депозитов Jetton на индивидуальный кошелек HOT с комментариями (памятка)](https://github.com/toncenter/examples/blob/main/deposits-jettons.js) +2. [Пример снятия денег с карты Jettons](https://github.com/toncenter/examples/blob/main/withdrawals-jettons.js) + +#### Препараты + +1. [Подготовьте список принятых джеттонов](/develop/dapps/asset-processing/jettons#adding-new-jettons-for-asset-processing-and-initial-verification) (адреса мастеров джеттонов). +2. Разверните горячий кошелек (используя v3R2, если не ожидается вывод средств с Jetton; highload v3 - если ожидается вывод средств с Jetton). [Развертывание кошелька](/develop/dapps/asset-processing/#wallet-deployment). +3. Выполните тестовый перевод Jetton, используя адрес "горячего" кошелька, чтобы инициализировать кошелек. + +#### Обработка поступающих джеттонов + +1. Загрузите список принятых джеттонов. +2. [Получите адрес кошелька Jetton] (#retrieving-jetton-wallet-addresses-for-a-given-user) для Вашего развернутого горячего кошелька. +3. Получите главный адрес Jetton для каждого кошелька Jetton, используя [получение данных кошелька] (/develop/dapps/asset-processing/jettons#retrieving-data-for-a-specific-jetton-wallet). +4. Сравните адреса основных контрактов Jetton из шага 1. и шага 3 (непосредственно выше). + Если адреса не совпадают, необходимо сообщить об ошибке проверки адреса Jetton. +5. Получите список последних необработанных транзакций по счету "горячего" кошелька и + проведите его итерацию (сортируя каждую транзакцию по очереди). См: [Проверка транзакций контракта](https://docs.ton.org/develop/dapps/asset-processing/#checking-contracts-transactions). +6. Проверьте входное сообщение (in_msg) на наличие транзакций и извлеките адрес источника из входного сообщения. [Пример Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L84) +7. Если исходный адрес совпадает с адресом в кошельке Jetton, то необходимо продолжить обработку транзакции. + Если нет, то пропустите обработку транзакции и проверьте следующую транзакцию. +8. Убедитесь, что тело сообщения не пустое и что первые 32 бита сообщения соответствуют коду операции `transfer notification` `0x7362d09c`. + [Пример Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L91) + Если тело сообщения пустое или оп-код недействителен - пропустите транзакцию. +9. Прочитайте другие данные тела сообщения, включая `query_id`, `amount`, `sender`, `forward_payload`. + [Макеты сообщений для контрактов Jetton](#jetton-contract-message-layouts), [Пример Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L105) +10. Попытайтесь извлечь текстовые комментарии из данных `forward_payload`. Первые 32 бита должны совпадать с + оп-кодом текстового комментария `0x000000`, а остальные - с текстом в кодировке UTF-8. + [Пример Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L110) +11. Если данные `forward_payload` пусты или код операции недействителен - пропустите транзакцию. +12. Сравните полученный комментарий с сохраненными заметками. Если есть совпадение (идентификация пользователя всегда возможна) - пополните счет. +13. Перезапустите с шага 5 и повторяйте процесс до тех пор, пока не пройдете весь список транзакций. + +### Прием джеттонов с депозитных адресов пользователей + +Чтобы принимать джеттоны с депозитных адресов пользователей, необходимо, чтобы платежный сервис создавал +собственный индивидуальный адрес (депозит) для каждого участника, отправляющего средства. Предоставление услуг в этом случае предполагает +выполнение нескольких параллельных процессов, включая создание новых депозитов, сканирование блоков на предмет транзакций, +вывод средств с депозитов на горячий кошелек и так далее. + +Поскольку горячий кошелек может использовать один кошелек Jetton для каждого типа Jetton, необходимо создать несколько кошельков +для инициирования депозитов. Чтобы создать большое количество кошельков, но в то же время управлять ими с помощью +одной начальной фразы (или закрытого ключа), необходимо указывать различные `subwallet_id` при создании кошелька. +На TON функциональность, необходимая для создания подкошелька, поддерживается кошельками версии v3 и выше. + +#### Создание субкошелька в Tonweb + +```js +const WalletClass = tonweb.wallet.all['v3R2']; +const wallet = new WalletClass(tonweb.provider, { + publicKey: keyPair.publicKey, + wc: 0, + walletId: , +}); +``` + +#### Подготовка + +1. [Подготовьте список принятых джеттонов](#adding-new-jettons-for-asset-processing-and-initial-verification). +2. Разверните горячий кошелек (используя v3R2, если не ожидается вывод средств с Jetton; highload v3 - если ожидается вывод средств с Jetton). [Развертывание кошелька](/develop/dapps/asset-processing/#wallet-deployment). + +#### Создание депозитов + +1. Примите запрос на создание нового депозита для пользователя. +2. Сгенерируйте новый адрес субкошелька (v3R2) на основе семян горячего кошелька. [Создание субкошелька в Tonweb](#creating-a-subwallet-in-tonweb) +3. Адрес получения может быть указан пользователю как адрес, используемый для депозитов Джеттон (это адрес + владельца депозитного кошелька Джеттон). Инициализация кошелька не требуется, это можно + сделать при выводе Джеттонов с депозита. +4. Для получения этого адреса необходимо вычислить адрес кошелька Jetton через главный контракт Jetton. + [Как получить адрес кошелька Jetton для данного пользователя] (#retrieving-jetton-wallet-addresses-for-a-given-user). +5. Добавьте адрес кошелька Jetton в пул адресов для мониторинга транзакций и сохраните адрес субкошелька. + +#### Обработка транзакций + +:::info Подтверждение транзакции +Транзакции TON становятся необратимыми после одного подтверждения. Для достижения наилучшего пользовательского опыта рекомендуется избегать ожидания дополнительных блоков после завершения транзакций на блокчейне TON. Подробнее читайте в [Catchain.pdf](https://docs.ton.org/catchain.pdf#page=3). +::: + +Не всегда можно определить точное количество джеттонов, полученных из сообщения, поскольку кошельки Jetton +могут не отправлять сообщения `уведомления о переводе`, `дополнения` и `внутренний перевод`. Они не стандартизированы. Это означает, +что нет никакой гарантии, что сообщение `внутренней передачи` может быть декодировано. + +Поэтому, чтобы определить сумму, поступившую в кошелек, необходимо запросить баланс с помощью метода get. +Для получения ключевых данных при запросе баланса используются блоки в соответствии с состоянием счета для конкретного блока на цепи. +[Подготовка к приему блоков с помощью Tonweb](https://github.com/toncenter/tonweb/blob/master/src/test-block-subscribe.js). + +Этот процесс осуществляется следующим образом: + +1. Подготовка к приему блоков (подготовка системы к приему новых блоков). +2. Извлеките новый блок и сохраните ID предыдущего блока. +3. Получайте транзакции из блоков. +4. Фильтруйте транзакции, используемые только с адресами из пула депозитных кошельков Jetton. +5. Декодируйте сообщения, используя тело `transfer notification`, чтобы получить более подробные данные, включая адрес + `отправителя`, сумму Джеттона и комментарий. (См.: [Обработка входящих джеттонов](#processing-incoming-jettons)) +6. Если в рамках счета + есть хотя бы одна транзакция с недекодируемыми исходящими сообщениями (в теле сообщения отсутствуют оп-коды для + `уведомления о переводе` и оп-коды для `выводов`) или без исходящих сообщений, то баланс Jetton должен быть запрошен методом get для текущего блока, а для расчета разницы в балансах используется предыдущий блок + . Теперь становится известно об изменении общего баланса благодаря + транзакциям, проводимым внутри блока. +7. В качестве идентификатора для неопознанной передачи Jettons (без `уведомления о передаче`) можно использовать данные транзакции + , если присутствует одна такая транзакция, или данные блока (если в блоке присутствует несколько). +8. Теперь необходимо проверить правильность баланса депозита. Если баланс депозита достаточен для того, чтобы инициировать перевод между горячим кошельком и существующим кошельком Jetton, необходимо вывести джеттоны, чтобы убедиться, что баланс кошелька уменьшился. +9. Перезапустите с шага 2 и повторите весь процесс. + +#### Снятие средств с депозитов + +Не следует осуществлять переводы с депозита на горячий кошелек при каждом пополнении депозита, +поскольку за операцию перевода берется комиссия в TON (оплачивается в виде платы за газ в сети). +Важно определить определенное минимальное количество джеттонов, которое необходимо для того, чтобы перевод +(и, соответственно, депозит) был выгодным. + +По умолчанию владельцы депозитных кошельков Jetton не инициализируются. Это связано с тем, что не существует заранее установленного требования +платить за хранение. Депозитные кошельки Jetton могут быть развернуты при отправке сообщений с телом +`transfer`, которое затем может быть немедленно уничтожено. Для этого инженер должен использовать специальный механизм +для отправки сообщений: [128 + 32](/develop/smart-contracts/messages#message-modes). + +1. Получите список депозитов, помеченных для вывода на горячий кошелек +2. Получите сохраненные адреса владельцев для каждого депозита +3. Затем сообщения отправляются на каждый адрес владельца (путем объединения нескольких таких сообщений в пакет) с высоконагруженного кошелька + с привязанной суммой TON Jetton. Эта сумма определяется путем сложения сборов, использованных для инициализации кошелька v3R2* сборов за отправку сообщения с телом `transfer` + произвольной суммы TON, связанной с `forward_ton_amount` + (если необходимо). Прилагаемая сумма TON определяется путем сложения платы за инициализацию кошелька v3R2 (значение) + + платы за отправку сообщения с телом `transfer` (значение) + произвольной суммы TON + для `forward_ton_amount` (значение) (если необходимо). +4. Когда баланс на адресе становится ненулевым, статус аккаунта меняется. Подождите несколько секунд и проверьте статус + аккаунта, вскоре он изменится с состояния `nonexists` на `uninit`. +5. Для каждого адреса владельца (со статусом `uninit`) необходимо отправить внешнее сообщение с кошельком v3R2 + init и телом с сообщением `transfer` для пополнения кошелька Jetton = 128 + 32. Для `перевода`, + пользователь должен указать адрес горячего кошелька в качестве `назначения` и `ответного назначения`. + Для упрощения идентификации перевода можно добавить текстовый комментарий. +6. Проверить доставку Джеттонов с помощью адреса депозита на адрес горячего кошелька можно по адресу + , принимая во внимание [информацию об обработке входящих Джеттонов, найденную здесь](#processing-incoming-jettons). + +### Вывод средств из оборота Jetton + +:::info Важно + +Ниже Вы найдете пошаговое руководство по снятию средств с карты jetton. +::: + +Чтобы вывести Джеттоны, кошелек отправляет сообщения с телом `transfer` на соответствующий кошелек Jetton. +Затем кошелек Jetton отправляет Джеттоны получателю. По доброй воле важно прикрепить некоторое количество TON +в качестве `forward_ton_amount` (и необязательный комментарий к `forward_payload`), чтобы вызвать уведомление о `переводе`. +См: [Макеты сообщений по контрактам Jetton](#jetton-contract-message-layouts) + +#### Подготовка + +1. Подготовьте список джеттонов для снятия средств: [Добавление новых джеттонов для обработки и первичной проверки](#adding-new-jettons-for-asset-processing-and-initial-verification) +2. Начато развертывание горячего кошелька. Рекомендуется использовать Highload v3. [Развертывание кошелька](/develop/dapps/asset-processing/#wallet-deployment) +3. Выполните перевод Jetton, используя адрес "горячего" кошелька, чтобы инициализировать кошелек Jetton и пополнить его баланс. + +#### Обработка снятия средств + +1. Загрузить список обработанных джеттонов +2. Получите адреса кошельков Jetton для развернутого горячего кошелька: [Как получить адреса кошельков Jetton для данного пользователя] (#retrieving-jetton-wallet-addresses-for-a-given-user) +3. Получите главные адреса Jetton для каждого кошелька Jetton: [Как получить данные для кошельков Jetton](#retrieving-data-for-a-specific-jetton-wallet). + Требуется параметр `jetton` (который на самом деле является адресом мастер-контракта Jetton). +4. Сравните адреса из основных контрактов Jetton из шага 1. и шага 3. Если адреса не совпадают, то следует сообщить об ошибке проверки адреса в Jetton. +5. Поступают запросы на вывод средств, в которых указывается тип Jetton, переводимая сумма и адрес кошелька получателя. +6. Проверьте баланс кошелька Jetton, чтобы убедиться в наличии достаточного количества средств для осуществления вывода. +7. Сгенерируйте [сообщение](/develop/dapps/asset-processing/jettons#message-0). +8. При использовании кошелька с высокой нагрузкой рекомендуется собирать партии сообщений и отправлять по одной партии за раз, чтобы оптимизировать комиссионные сборы. +9. Сохраните время истечения срока действия для исходящих внешних сообщений (это время, пока кошелек успешно + обработает сообщение, после этого кошелек больше не будет принимать сообщение) +10. Отправьте одно сообщение или несколько сообщений (пакетная передача сообщений). +11. Получите список последних необработанных транзакций на счете "горячего" кошелька и выполните его итерацию. + Подробнее здесь: [Проверка транзакций контракта](/develop/dapps/asset-processing/#checking-contracts-transactions), + [Пример Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-single-wallet.js#L43) или + используйте метод Toncenter API `/getTransactions`. +12. Просмотрите исходящие сообщения в аккаунте. +13. Если существует сообщение с кодом операции `transfer`, то его следует декодировать, чтобы получить значение `query_id`. + Полученные `query_id` должны быть отмечены как успешно отправленные. +14. Если время, необходимое для обработки текущей отсканированной транзакции, превышает + время истечения срока действия, а исходящее сообщение с заданным `query_id` + не найдено, то запрос должен (это необязательно) быть помечен как истекший и должен быть безопасно отправлен повторно. +15. Просмотрите входящие сообщения в аккаунте. +16. Если существует сообщение, в котором используется операционный код `excesses`, сообщение должно быть декодировано и в нем должно быть найдено значение `query_id` + . Найденный `query_id` должен быть помечен как успешно доставленный. +17. Перейдите к шагу 5. Просроченные запросы, которые не были успешно отправлены, должны быть перемещены обратно в список снятия. + +## Обработка цепи Jetton + +Как правило, для приема и обработки джеттонов обработчик сообщений, отвечающий за внутренние сообщения, использует оп-код `op=0x7362d09c`. + +:::info Подтверждение транзакции +Транзакции TON становятся необратимыми после одного подтверждения. Для достижения наилучшего пользовательского опыта рекомендуется избегать ожидания дополнительных блоков после завершения транзакций на блокчейне TON. Подробнее читайте в [Catchain.pdf](https://docs.ton.org/catchain.pdf#page=3). +::: + +### Рекомендации по обработке на цепочке + +Ниже приведен `список рекомендаций`, которые необходимо учитывать при **проведении обработки джеттона на цепи**: + +1. **Идентифицируйте входящие джеттоны** по типу их кошелька, а не по их мастер-контракту Jetton. Другими словами, Ваш контракт должен взаимодействовать (получать и отправлять сообщения) с конкретным кошельком Jetton (а не с каким-то неизвестным кошельком, использующим конкретный мастер-контракт Jetton). +2. При установлении связи между кошельком Jetton и мастер-контрактом Jetton, **убедитесь**, что эта **связь является двунаправленной**, когда кошелек распознает мастер-контракт и наоборот. Например, если Ваша контрактная система получает уведомление от кошелька Jetton (который считает свой MySuperJetton своим мастер-контрактом), то информация о переводе должна быть показана пользователю, прежде чем показывать `symbol`, `name` и `image` + контракта MySuperJetton, проверьте, что кошелек MySuperJetton использует правильную контрактную систему. В свою очередь, если Ваша контрактная система по каким-то причинам должна отправлять джеттоны, используя мастер-контракты MySuperJetton или MySuperJetton, проверьте, что кошелек X, как и кошелек, использует те же параметры контракта. + Кроме того, перед отправкой запроса `перевода` на X убедитесь, что он признает MySuperJetton своим мастером. +3. Истинная сила\*\* децентрализованных финансов (DeFi) основана на возможности складывать протоколы друг на друга, как блоки лего. Например, скажем, джеттон А обменивается на джеттон Б, который, в свою очередь, затем используется в качестве рычага в протоколе кредитования (когда пользователь предоставляет ликвидность), который затем используется для покупки NFT .... и так далее. Таким образом, рассмотрим, как контракт может обслуживать не только пользователей вне цепи, но и сущности на цепи, присоединяя токенизированную ценность к уведомлению о передаче, добавляя пользовательскую полезную нагрузку, которая может быть отправлена вместе с уведомлением о передаче. +4. **Обратите внимание**, что не все джеттоны следуют одним и тем же стандартам. К сожалению, некоторые джеттоны могут быть враждебными (использующими векторы атак) и созданными исключительно для того, чтобы атаковать ничего не подозревающих пользователей. В целях безопасности, если рассматриваемый протокол состоит из множества контрактов, не создавайте большое количество джеттон-кошельков одного типа. В частности, не отправляйте джеттоны внутри протокола между контрактом депозита, контрактом хранилища, контрактом пользовательского счета и т.д. Злоумышленники могут намеренно вмешиваться в логику контракта, подделывая уведомления о переводе, суммы джеттонов или параметры полезной нагрузки. Уменьшите вероятность атак, используя только один кошелек в системе для одного джеттона (для всех депозитов и снятий). +5. Также **часто хорошей идеей** является создание субконтрактов для каждого отдельного джеттона, чтобы снизить вероятность подмены адреса (например, когда сообщение о передаче отправляется на джеттон B с использованием контракта, предназначенного для джеттона A). +6. Настоятельно рекомендуется\*\* работать с неделимыми единицами джеттона на уровне контракта. Логика, связанная с десятичными единицами, обычно используется для улучшения пользовательского интерфейса (UI) дипломата и не связана с ведением числовых записей на цепи. + +Чтобы узнать **больше** о [Secure Smart Contract Programming in FunC by CertiK](https://blog.ton.org/secure-smart-contract-programming-in-func), не стесняйтесь читать этот ресурс. Разработчикам рекомендуется **разрабатывать все исключения смарт-контрактов**, чтобы не пропустить их во время разработки приложения. + +## Рекомендации по обработке кошельков Jetton + +Как правило, все процедуры проверки, используемые для обработки внецепочечного джеттона, подходят и для кошельков. Для обработки кошельков Jetton наши самые важные рекомендации заключаются в следующем: + +1. Когда кошелек получает уведомление о переводе средств от неизвестного кошелька jetton, **очень важно** доверять кошельку jetton и его мастер-адресу, поскольку это может быть вредоносная подделка. Чтобы защитить себя, проверьте Jetton Master (главный контракт) по указанному адресу, чтобы убедиться, что Ваши процессы верификации распознают кошелек jetton как легитимный. После того, как Вы доверитесь кошельку и он будет признан легитимным, Вы можете разрешить ему получить доступ к остаткам на Ваших счетах и другим данным в кошельке. Если Jetton Master не распознает этот кошелек, рекомендуется вообще не инициировать и не раскрывать свои переводы jetton, а показывать только входящие переводы TON (из Toncoin, прикрепленных к уведомлениям о переводе). +2. На практике, если пользователь хочет взаимодействовать с Jetton, а не с кошельком Jetton. Другими словами, пользователи отправляют wTON/oUSDT/jUSDT, jUSDC, jDAI вместо `EQAjN...`/`EQBLE...` + и т.д.. Часто это означает, что когда пользователь инициирует перевод на jetton, кошелек спрашивает у соответствующего мастера jetton, какой кошелек jetton (принадлежащий пользователю) должен инициировать запрос на перевод. Очень **важно никогда слепо не доверять** этим данным от мастера (мастер-контракта). Прежде чем отправлять запрос на перевод в кошелек jetton, всегда убедитесь, что кошелек jetton действительно принадлежит тому Мастеру Jetton, за которого он себя выдает. +3. **Примите во внимание**, что недружественные Jetton Masters/jetton wallets **могут со временем менять** свои кошельки/мастера. Поэтому пользователи должны проявлять должную осмотрительность и проверять легитимность любых кошельков, с которыми они взаимодействуют, перед каждым использованием. +4. **Всегда убедитесь**, что Вы отображаете джеттоны в своем интерфейсе таким образом, чтобы они **не смешивались с передачей TON**, системными уведомлениями и т.д.. Даже параметры `symbol`, `name` и `image` + могут быть составлены таким образом, чтобы ввести пользователей в заблуждение, оставив их потенциальными жертвами мошенничества. Было несколько случаев, когда вредоносные джеттоны использовались для выдачи себя за переводы TON, ошибки в уведомлениях, получение вознаграждений или объявления о замораживании активов. +5. **Всегда будьте начеку с потенциальными злоумышленниками**, которые создают поддельные джеттоны, и всегда хорошо предоставить пользователям функциональность, необходимую для устранения нежелательных джеттонов в их основном пользовательском интерфейсе. + +Авторы: [kosrk](https://github.com/kosrk), [krigga](https://github.com/krigga), [EmelyanenkoK](https://github.com/EmelyanenkoK/) и [tolya-yanot](https://github.com/tolya-yanot/). + +## Лучшие практики + +Если Вам нужны готовые к тестированию примеры, проверьте [SDKs](/develop/dapps/asset-processing/jettons#sdks) и попробуйте их запустить. Ниже приведены фрагменты кода, которые помогут Вам понять процесс обработки джеттонов на примерах кода. + +### Отправить Джеттоны с комментарием + + + + +
+ +Source code + + +```js +// first 4 bytes are tag of text comment +const comment = new Uint8Array([... new Uint8Array(4), ... new TextEncoder().encode('text comment')]); + +await wallet.methods.transfer({ + secretKey: keyPair.secretKey, + toAddress: JETTON_WALLET_ADDRESS, // address of Jetton wallet of Jetton sender + amount: TonWeb.utils.toNano('0.05'), // total amount of TONs attached to the transfer message + seqno: seqno, + payload: await jettonWallet.createTransferBody({ + jettonAmount: TonWeb.utils.toNano('500'), // Jetton amount (in basic indivisible units) + toAddress: new TonWeb.utils.Address(WALLET2_ADDRESS), // recepient user's wallet address (not Jetton wallet) + forwardAmount: TonWeb.utils.toNano('0.01'), // some amount of TONs to invoke Transfer notification message + forwardPayload: comment, // text comment for Transfer notification message + responseAddress: walletAddress // return the TONs after deducting commissions back to the sender's wallet address + }), + sendMode: 3, +}).send() +``` + +
+ +
+ + +
+ +Source code + + +```go +client := liteclient.NewConnectionPool() + +// connect to testnet lite server +err := client.AddConnectionsFromConfigUrl(context.Background(), "https://ton.org/global.config.json") +if err != nil { + panic(err) +} + +ctx := client.StickyContext(context.Background()) + +// initialize ton api lite connection wrapper +api := ton.NewAPIClient(client) + +// seed words of account, you can generate them with any wallet or using wallet.NewSeed() method +words := strings.Split("birth pattern then forest walnut then phrase walnut fan pumpkin pattern then cluster blossom verify then forest velvet pond fiction pattern collect then then", " ") + +w, err := wallet.FromSeed(api, words, wallet.V3R2) +if err != nil { + log.Fatalln("FromSeed err:", err.Error()) + return +} + +token := jetton.NewJettonMasterClient(api, address.MustParseAddr("EQD0vdSA_NedR9uvbgN9EikRX-suesDxGeFg69XQMavfLqIw")) + +// find our jetton wallet +tokenWallet, err := token.GetJettonWallet(ctx, w.WalletAddress()) +if err != nil { + log.Fatal(err) +} + +amountTokens := tlb.MustFromDecimal("0.1", 9) + +comment, err := wallet.CreateCommentCell("Hello from tonutils-go!") +if err != nil { + log.Fatal(err) +} + +// address of receiver's wallet (not token wallet, just usual) +to := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N") +transferPayload, err := tokenWallet.BuildTransferPayload(to, amountTokens, tlb.ZeroCoins, comment) +if err != nil { + log.Fatal(err) +} + +// your TON balance must be > 0.05 to send +msg := wallet.SimpleMessage(tokenWallet.Address(), tlb.MustFromTON("0.05"), transferPayload) + +log.Println("sending transaction...") +tx, _, err := w.SendWaitTransaction(ctx, msg) +if err != nil { + panic(err) +} +log.Println("transaction confirmed, hash:", base64.StdEncoding.EncodeToString(tx.Hash)) +``` + +
+ +
+ + +
+ +Source code + + +```py +my_wallet = Wallet(provider=client, mnemonics=my_wallet_mnemonics, version='v4r2') + +# for TonCenterClient and LsClient +await my_wallet.transfer_jetton(destination_address='address', jetton_master_address=jetton.address, jettons_amount=1000, fee=0.15) + +# for all clients +await my_wallet.transfer_jetton_by_jetton_wallet(destination_address='address', jetton_wallet='your jetton wallet address', jettons_amount=1000, fee=0.1) +``` + +
+ +
+ + + +
+ +Source code + + +```py +from pytoniq import LiteBalancer, WalletV4R2, begin_cell +import asyncio + +mnemonics = ["your", "mnemonics", "here"] + +async def main(): + provider = LiteBalancer.from_mainnet_config(1) + await provider.start_up() + + wallet = await WalletV4R2.from_mnemonic(provider=provider, mnemonics=mnemonics) + USER_ADDRESS = wallet.address + JETTON_MASTER_ADDRESS = "EQBlqsm144Dq6SjbPI4jjZvA1hqTIP3CvHovbIfW_t-SCALE" + DESTINATION_ADDRESS = "EQAsl59qOy9C2XL5452lGbHU9bI3l4lhRaopeNZ82NRK8nlA" + + USER_JETTON_WALLET = (await provider.run_get_method(address=JETTON_MASTER_ADDRESS, + method="get_wallet_address", + stack=[begin_cell().store_address(USER_ADDRESS).end_cell().begin_parse()]))[0].load_address() + forward_payload = (begin_cell() + .store_uint(0, 32) # TextComment op-code + .store_snake_string("Comment") + .end_cell()) + transfer_cell = (begin_cell() + .store_uint(0xf8a7ea5, 32) # Jetton Transfer op-code + .store_uint(0, 64) # query_id + .store_coins(1 * 10**9) # Jetton amount to transfer in nanojetton + .store_address(DESTINATION_ADDRESS) # Destination address + .store_address(USER_ADDRESS) # Response address + .store_bit(0) # Custom payload is None + .store_coins(1) # Ton forward amount in nanoton + .store_bit(1) # Store forward_payload as a reference + .store_ref(forward_payload) # Forward payload + .end_cell()) + + await wallet.transfer(destination=USER_JETTON_WALLET, amount=int(0.05*1e9), body=transfer_cell) + await provider.close_all() + +asyncio.run(main()) +``` + +
+ +
+
+ +### Примите Jetton Transfer с разбором комментария + + + + +
+ +Source code + + +```ts +import { + Address, + TonClient, + Cell, + beginCell, + storeMessage, + JettonMaster, + OpenedContract, + JettonWallet, + Transaction +} from '@ton/ton'; + + +export async function retry(fn: () => Promise, options: { retries: number, delay: number }): Promise { + let lastError: Error | undefined; + for (let i = 0; i < options.retries; i++) { + try { + return await fn(); + } catch (e) { + if (e instanceof Error) { + lastError = e; + } + await new Promise(resolve => setTimeout(resolve, options.delay)); + } + } + throw lastError; +} + +export async function tryProcessJetton(orderId: string) : Promise { + + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + apiKey: 'TONCENTER-API-KEY', // https://t.me/tonapibot + }); + + interface JettonInfo { + address: string; + decimals: number; + } + + interface Jettons { + jettonMinter : OpenedContract, + jettonWalletAddress: Address, + jettonWallet: OpenedContract + } + + const MY_WALLET_ADDRESS = 'INSERT-YOUR-HOT-WALLET-ADDRESS'; // your HOT wallet + + const JETTONS_INFO : Record = { + 'jUSDC': { + address: 'EQB-MPwrd1G6WKNkLz_VnV6WqBDd142KMQv-g1O-8QUA3728', // + decimals: 6 + }, + 'jUSDT': { + address: 'EQBynBO23ywHy_CgarY9NK9FTz0yDsG82PtcbSTQgGoXwiuA', + decimals: 6 + }, + } + const jettons: Record = {}; + + const prepare = async () => { + for (const name in JETTONS_INFO) { + const info = JETTONS_INFO[name]; + const jettonMaster = client.open(JettonMaster.create(Address.parse(info.address))); + const userAddress = Address.parse(MY_WALLET_ADDRESS); + + const jettonUserAddress = await jettonMaster.getWalletAddress(userAddress); + + console.log('My jetton wallet for ' + name + ' is ' + jettonUserAddress.toString()); + + const jettonWallet = client.open(JettonWallet.create(jettonUserAddress)); + + //const jettonData = await jettonWallet; + const jettonData = await client.runMethod(jettonUserAddress, "get_wallet_data") + + jettonData.stack.pop(); //skip balance + jettonData.stack.pop(); //skip owneer address + const adminAddress = jettonData.stack.readAddress(); + + + if (adminAddress.toString() !== (Address.parse(info.address)).toString()) { + throw new Error('jetton minter address from jetton wallet doesnt match config'); + } + + jettons[name] = { + jettonMinter: jettonMaster, + jettonWalletAddress: jettonUserAddress, + jettonWallet: jettonWallet + }; + } + } + + const jettonWalletAddressToJettonName = (jettonWalletAddress : Address) => { + const jettonWalletAddressString = jettonWalletAddress.toString(); + for (const name in jettons) { + const jetton = jettons[name]; + + if (jetton.jettonWallet.address.toString() === jettonWalletAddressString) { + return name; + } + } + return null; + } + + // Subscribe + const Subscription = async ():Promise =>{ + + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + apiKey: 'TONCENTER-API-KEY', // https://t.me/tonapibot + }); + + const myAddress = Address.parse('INSERT-YOUR-HOT-WALLET'); // Address of receiver TON wallet + const transactions = await client.getTransactions(myAddress, { + limit: 5, + }); + return transactions; + } + + return retry(async () => { + + await prepare(); + const Transactions = await Subscription(); + + for (const tx of Transactions) { + + const sourceAddress = tx.inMessage?.info.src; + if (!sourceAddress) { + // external message - not related to jettons + continue; + } + + if (!(sourceAddress instanceof Address)) { + continue; + } + + const in_msg = tx.inMessage; + + if (in_msg?.info.type !== 'internal') { + // external message - not related to jettons + continue; + } + + // jetton master contract address check + const jettonName = jettonWalletAddressToJettonName(sourceAddress); + if (!jettonName) { + // unknown or fake jetton transfer + continue; + } + + if (tx.inMessage === undefined || tx.inMessage?.body.hash().equals(new Cell().hash())) { + // no in_msg or in_msg body + continue; + } + + const msgBody = tx.inMessage; + const sender = tx.inMessage?.info.src; + const originalBody = tx.inMessage?.body.beginParse(); + let body = originalBody?.clone(); + const op = body?.loadUint(32); + if (!(op == 0x7362d09c)) { + continue; // op != transfer_notification + } + + console.log('op code check passed', tx.hash().toString('hex')); + + const queryId = body?.loadUint(64); + const amount = body?.loadCoins(); + const from = body?.loadAddress(); + const maybeRef = body?.loadBit(); + const payload = maybeRef ? body?.loadRef().beginParse() : body; + const payloadOp = payload?.loadUint(32); + if (!(payloadOp == 0)) { + console.log('no text comment in transfer_notification'); + continue; + } + + const comment = payload?.loadStringTail(); + if (!(comment == orderId)) { + continue; + } + + console.log('Got ' + jettonName + ' jetton deposit ' + amount?.toString() + ' units with text comment "' + comment + '"'); + const txHash = tx.hash().toString('hex'); + return (txHash); + } + throw new Error('Transaction not found'); + }, {retries: 30, delay: 1000}); +} +``` + +
+ +
+ + +
+ +Source code + + +```go +import ( + "context" + "fmt" + "log" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/liteclient" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/ton/jetton" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +const ( + MainnetConfig = "https://ton.org/global.config.json" + TestnetConfig = "https://ton.org/global.config.json" + MyWalletAddress = "INSERT-YOUR-HOT-WALLET-ADDRESS" +) + +type JettonInfo struct { + address string + decimals int +} + +type Jettons struct { + jettonMinter *jetton.Client + jettonWalletAddress string + jettonWallet *jetton.WalletClient +} + +func prepare(api ton.APIClientWrapped, jettonsInfo map[string]JettonInfo) (map[string]Jettons, error) { + userAddress := address.MustParseAddr(MyWalletAddress) + block, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + return nil, err + } + + jettons := make(map[string]Jettons) + + for name, info := range jettonsInfo { + jettonMaster := jetton.NewJettonMasterClient(api, address.MustParseAddr(info.address)) + jettonWallet, err := jettonMaster.GetJettonWallet(context.Background(), userAddress) + if err != nil { + return nil, err + } + + jettonUserAddress := jettonWallet.Address() + + jettonData, err := api.RunGetMethod(context.Background(), block, jettonUserAddress, "get_wallet_data") + if err != nil { + return nil, err + } + + slice := jettonData.MustCell(0).BeginParse() + slice.MustLoadCoins() // skip balance + slice.MustLoadAddr() // skip owneer address + adminAddress := slice.MustLoadAddr() + + if adminAddress.String() != info.address { + return nil, fmt.Errorf("jetton minter address from jetton wallet doesnt match config") + } + + jettons[name] = Jettons{ + jettonMinter: jettonMaster, + jettonWalletAddress: jettonUserAddress.String(), + jettonWallet: jettonWallet, + } + } + + return jettons, nil +} + +func jettonWalletAddressToJettonName(jettons map[string]Jettons, jettonWalletAddress string) string { + for name, info := range jettons { + if info.jettonWallet.Address().String() == jettonWalletAddress { + return name + } + } + return "" +} + +func GetTransferTransactions(orderId string, foundTransfer chan<- *tlb.Transaction) { + jettonsInfo := map[string]JettonInfo{ + "jUSDC": {address: "EQB-MPwrd1G6WKNkLz_VnV6WqBDd142KMQv-g1O-8QUA3728", decimals: 6}, + "jUSDT": {address: "EQBynBO23ywHy_CgarY9NK9FTz0yDsG82PtcbSTQgGoXwiuA", decimals: 6}, + } + + client := liteclient.NewConnectionPool() + + cfg, err := liteclient.GetConfigFromUrl(context.Background(), MainnetConfig) + if err != nil { + log.Fatalln("get config err: ", err.Error()) + } + + // connect to lite servers + err = client.AddConnectionsFromConfig(context.Background(), cfg) + if err != nil { + log.Fatalln("connection err: ", err.Error()) + } + + // initialize ton api lite connection wrapper + api := ton.NewAPIClient(client, ton.ProofCheckPolicySecure).WithRetry() + master, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + log.Fatalln("get masterchain info err: ", err.Error()) + } + + // address on which we are accepting payments + treasuryAddress := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N") + + acc, err := api.GetAccount(context.Background(), master, treasuryAddress) + if err != nil { + log.Fatalln("get masterchain info err: ", err.Error()) + } + + jettons, err := prepare(api, jettonsInfo) + if err != nil { + log.Fatalln("can't prepare jettons data: ", err.Error()) + } + + lastProcessedLT := acc.LastTxLT + + transactions := make(chan *tlb.Transaction) + + go api.SubscribeOnTransactions(context.Background(), treasuryAddress, lastProcessedLT, transactions) + + log.Println("waiting for transfers...") + + // listen for new transactions from channel + for tx := range transactions { + if tx.IO.In == nil || tx.IO.In.MsgType != tlb.MsgTypeInternal { + // external message - not related to jettons + continue + } + + msg := tx.IO.In.Msg + sourceAddress := msg.SenderAddr() + + // jetton master contract address check + jettonName := jettonWalletAddressToJettonName(jettons, sourceAddress.String()) + if len(jettonName) == 0 { + // unknown or fake jetton transfer + continue + } + + if msg.Payload() == nil || msg.Payload() == cell.BeginCell().EndCell() { + // no in_msg body + continue + } + + msgBodySlice := msg.Payload().BeginParse() + + op := msgBodySlice.MustLoadUInt(32) + if op != 0x7362d09c { + continue // op != transfer_notification + } + + // just skip bits + msgBodySlice.MustLoadUInt(64) + amount := msgBodySlice.MustLoadCoins() + msgBodySlice.MustLoadAddr() + + payload := msgBodySlice.MustLoadMaybeRef() + payloadOp := payload.MustLoadUInt(32) + if payloadOp == 0 { + log.Println("no text comment in transfer_notification") + continue + } + + comment := payload.MustLoadStringSnake() + if comment != orderId { + continue + } + + // process transaction + log.Printf("Got %s jetton deposit %d units with text comment %s\n", jettonName, amount, comment) + foundTransfer <- tx + } +} +``` + +
+
+ + + +
+ +Source code + + +```py +import asyncio + +from pytoniq import LiteBalancer, begin_cell + +MY_WALLET_ADDRESS = "EQAsl59qOy9C2XL5452lGbHU9bI3l4lhRaopeNZ82NRK8nlA" + + +async def parse_transactions(provider: LiteBalancer, transactions): + for transaction in transactions: + if not transaction.in_msg.is_internal: + continue + if transaction.in_msg.info.dest.to_str(1, 1, 1) != MY_WALLET_ADDRESS: + continue + + sender = transaction.in_msg.info.src.to_str(1, 1, 1) + value = transaction.in_msg.info.value_coins + if value != 0: + value = value / 1e9 + + if len(transaction.in_msg.body.bits) < 32: + print(f"TON transfer from {sender} with value {value} TON") + continue + + body_slice = transaction.in_msg.body.begin_parse() + op_code = body_slice.load_uint(32) + if op_code != 0x7362D09C: + continue + + body_slice.load_bits(64) # skip query_id + jetton_amount = body_slice.load_coins() / 1e9 + jetton_sender = body_slice.load_address().to_str(1, 1, 1) + if body_slice.load_bit(): + forward_payload = body_slice.load_ref().begin_parse() + else: + forward_payload = body_slice + + jetton_master = ( + await provider.run_get_method( + address=sender, method="get_wallet_data", stack=[] + ) + )[2].load_address() + jetton_wallet = ( + ( + await provider.run_get_method( + address=jetton_master, + method="get_wallet_address", + stack=[ + begin_cell() + .store_address(MY_WALLET_ADDRESS) + .end_cell() + .begin_parse() + ], + ) + )[0] + .load_address() + .to_str(1, 1, 1) + ) + + if jetton_wallet != sender: + print("FAKE Jetton Transfer") + continue + + if len(forward_payload.bits) < 32: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton" + ) + else: + forward_payload_op_code = forward_payload.load_uint(32) + if forward_payload_op_code == 0: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton and comment: {forward_payload.load_snake_string()}" + ) + else: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton and unknown payload: {forward_payload} " + ) + + print(f"Transaction hash: {transaction.cell.hash.hex()}") + print(f"Transaction lt: {transaction.lt}") + + +async def main(): + provider = LiteBalancer.from_mainnet_config(1) + await provider.start_up() + transactions = await provider.get_transactions(address=MY_WALLET_ADDRESS, count=5) + await parse_transactions(provider, transactions) + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +
+
+
+ +## SDKs + +Вы можете найти список SDK для различных языков (js, python, golang, C#, Rust и т.д.) список [здесь](/develop/dapps/apis/sdk). + +## См. также + +- [Обработка платежей](/develop/dapps/asset-processing/) +- [Обработка NFT на TON](/develop/dapps/asset-processing/nfts) +- [Разбор метаданных на TON](/develop/dapps/asset-processing/metadata) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md b/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md new file mode 100644 index 0000000000..b54b07a5b8 --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md @@ -0,0 +1,62 @@ +import Button from '@site/src/components/button' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Обзор обработки активов + +Здесь Вы найдете **краткий обзор** о том, [как работают переводы в TON](/develop/dapps/asset-processing/overview#overview-on-messages-and-transactions), какие [типы активов](/develop/dapps/asset-processing/overview#digital-asset-types-on-ton) вы можете найти в TON (и о чем вы будете читать [дальше](/develop/dapps/asset-processing/overview#read-next)) и как [взаимодействовать с ton](/develop/dapps/asset-processing/overview#interaction-with-ton-blockchain), используя ваш язык программирования, Рекомендуется ознакомиться со всей информацией, представленной ниже, прежде чем переходить к следующим страницам. + +## Обзор сообщений и транзакций + +Воплощая полностью асинхронный подход, блокчейн TON включает в себя несколько концепций, которые не характерны для традиционных блокчейнов. В частности, каждое взаимодействие любого актора с блокчейном состоит из графа асинхронно передаваемых [сообщений](/develop/smart-contracts/guidelines/message-delivery-guarantees) между смарт-контрактами и/или внешним миром. Каждая транзакция состоит из одного входящего сообщения и до 512 исходящих сообщений. + +Существует 3 типа сообщений, которые полностью описаны [здесь](/develop/smart-contracts/messages#types-of-messages). Если говорить кратко: + +- [внешнее сообщение](/develop/smart-contracts/guidelines/external-messages): + - Внешнее сообщение" (иногда его называют просто "внешнее сообщение") - это сообщение, которое отправляется из *вне* блокчейна смарт-контракту *внутри* блокчейна. + - Внешнее сообщение (обычно называемое "сообщение в журнале") отправляется от *блокчейн-субъекта* во *внешний мир*. +- [Внутреннее сообщение] (/develop/smart-contracts/guidelines/internal-messages) отправляется от одного *блокчейн-субъекта* к *другому*, может нести некоторое количество цифровых активов и произвольную порцию данных. + +Общий путь любого взаимодействия начинается с внешнего сообщения, отправленного смарт-контракту `wallet`, который аутентифицирует отправителя сообщения с помощью криптографии с открытым ключом, берет на себя оплату комиссии и отправляет внутренние сообщения блокчейна. Очередь этих сообщений образует направленный ациклический граф, или дерево. + +Например: + +![](/img/docs/asset-processing/alicemsgDAG.svg) + +- Алиса" использует, например, [Tonkeeper](https://tonkeeper.com/), чтобы отправить "внешнее сообщение" на свой кошелек. +- `Внешнее сообщение` - это входное сообщение для контракта `кошелек A v4` с пустым суром (сообщение из ниоткуда, например, [Tonkeeper](https://tonkeeper.com/)). +- `Исходящее сообщение` - это выходное сообщение для контракта `кошелек A v4` и входное сообщение для контракта `кошелек B v4` с источником `кошелек A v4` и пунктом назначения `кошелек B v4`. + +В результате существует 2 транзакции со своим набором входных и выходных сообщений. + +Каждое действие, когда контракт принимает сообщение на вход (инициируется им), обрабатывает его и генерирует или не генерирует исходящие сообщения на выходе, называется `транзакцией`. Подробнее о транзакциях читайте [здесь](/develop/smart-contracts/guidelines/message-delivery-guarantees#what-is-a-transaction). + +Эти `транзакции` могут охватывать **продолжительный период** времени. Технически, транзакции с очередями сообщений объединяются в блоки, обрабатываемые валидаторами. Асинхронная природа блокчейна TON **не позволяет предсказать хэш и lt (логическое время) транзакции** на этапе отправки сообщения. + +Принятая в блок `транзакция` является окончательной и не может быть изменена. + +:::info Подтверждение транзакции +Транзакции TON становятся необратимыми после одного подтверждения. Для достижения наилучшего пользовательского опыта рекомендуется избегать ожидания дополнительных блоков после завершения транзакций на блокчейне TON. Подробнее читайте в [Catchain.pdf](https://docs.ton.org/catchain.pdf#page=3). +::: + +Смарт-контракты платят несколько типов [сборов](/develop/smart-contracts/fees) за транзакции (обычно из баланса входящего сообщения, поведение зависит от [режима сообщения](/develop/smart-contracts/messages#message-modes)). Размер сборов зависит от конфигурации workchain: максимальные сборы на `masterchain` и значительно меньшие на `basechain`. + +## Типы цифровых активов на TON + +У TON есть три типа цифровых активов. + +- Тонкоин, основной токен сети. Он используется для всех основных операций в блокчейне, например, для оплаты газа или ставки для подтверждения. +- Контрактные активы, такие как токены и NFT, которые являются аналогом стандартов ERC-20/ERC-721, управляются произвольными контрактами и поэтому могут требовать пользовательских правил для обработки. Более подробную информацию об их обработке Вы можете найти в статьях [process NFTs](/develop/dapps/asset-processing/nfts) и [process Jettons](/develop/dapps/asset-processing/jettons). +- Нативные токены - это особый вид активов, которые могут быть прикреплены к любому сообщению в сети. Но в настоящее время эти активы не используются, поскольку функция выпуска новых нативных токенов закрыта. + +## Взаимодействие с блокчейном TON + +Основные операции с блокчейном TON можно выполнять с помощью TonLib. Это общая библиотека, которая может быть скомпилирована вместе с узлом TON и предоставляет API для взаимодействия с блокчейном через так называемые lite-серверы (серверы для lite-клиентов). TonLib придерживается бездоверительного подхода, проверяя доказательства для всех входящих данных; таким образом, нет необходимости в доверенном поставщике данных. Методы, доступные TonLib, перечислены [в схеме TL](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L234). Их можно использовать либо как общую библиотеку через [обертки](/develop/dapps/asset-processing/#repositories). + +## Читать далее + +Прочитав эту статью, Вы сможете проверить: + +1. [Обработка платежей](/develop/dapps/asset-processing/), чтобы узнать, как работать с `TON-монетами`. +2. [Обработка джеттонов](/develop/dapps/asset-processing/jettons), чтобы узнать, как работать с `джеттонами` (иногда их называют `токенами`) +3. [Обработка NFT](/develop/dapps/asset-processing/nfts), чтобы узнать, как работать с `NFT` (это специальный тип `jetton`) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx new file mode 100644 index 0000000000..408970bf2b --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx @@ -0,0 +1,113 @@ +import Button from '@site/src/components/button' + +# О компании TON Connect + +TON Connect - это мощный набор инструментов с открытым исходным кодом, который служит универсальным стандартом авторизации приложений в экосистеме [TON](/learn/introduction), позволяя пользователям безопасно и удобно входить в приложения и сервисы, используя свои TON-кошельки вместо традиционных логинов и паролей. + +![](/img/docs/ton-connect/ton-connect-overview.png?raw=true) + +Не стесняйтесь использовать один из следующих потоков для интеграции Вашего приложения: + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Примеры использования Вашего DApp + +Ознакомьтесь с этими результатами, которые экосистема TON предоставляет для превосходной интеграции DAppintegration. + +- **Трафик**. Обеспечьте дополнительные посещения пользователей через криптовалютные кошельки, поддерживающие TON Connect. +- **Аутентичность**. Используйте кошельки пользователей TON в качестве готовых учетных записей, устраняя необходимость в дополнительных шагах аутентификации и, таким образом, повышая удобство использования. +- **Платежи**. Быстро и безопасно обрабатывайте транзакции через блокчейн TON, используя Toncoin или обернутые стабильные монеты (jUSDC/jUSDT). +- **Удержание**. Повысьте уровень удержания пользователей благодаря функции сохранения списков в приложении, которая позволяет пользователям следить за недавно открытыми и любимыми приложениями. + +## Для разработчиков кошельков + +Если Вы являетесь разработчиком кошелька, Вы можете подключить свой кошелек к TON Connect и позволить своим пользователям взаимодействовать с приложениями TON безопасным и удобным способом, прочитайте, как [интегрировать TON Connect в свой кошелек](/develop/dapps/ton-connect/wallet/). + +## Истории успеха + +- [GetGems - Открытый сетевой рынок](https://getgems.io/) +- [STON.fi - AMM DEX для блокчейна TON](https://ston.fi/) +- [Tonstarter](http://tonstarter.com/) + +
+ Показать весь список + +- [getgems.io](https://getgems.io/) +- [fragment.com](https://fragment.com/) (Ton Connect v.1) +- [ston.fi](https://ston.fi/) +- [ton.diamonds](https://ton.diamonds/) +- [beta.disintar.io](https://beta.disintar.io/) +- [tegro.finance](https://tegro.finance/liquidity) +- [minter.ton.org](https://minter.ton.org/) +- [libermall.com](https://libermall.com/) +- [dedust.io](https://dedust.io/swap) +- [toncap.net](https://toncap.net/) +- [cryptomus.com](https://cryptomus.com/) +- [avanchange.com](https://avanchange.com/) +- [wton.dev](https://wton.dev/) +- [mint.spiroverse.io/shop](https://mint.spiroverse.io/shop) +- [vk.com/vk_nft_hub](https://vk.com/vk_nft_hub) +- [tonverifier.live](https://verifier.ton.org/) +- [stickerface.io/member](https://stickerface.io/member) +- [tonstarter.com](https://tonstarter.com/) +- [cryptogas.shop/ton](https://cryptogas.shop/ton) +- [megaton.fi](https://megaton.fi/) +- [dns.ton.org](https://dns.ton.org/) +- [coinpaymaster.com](https://coinpaymaster.com/) +- [ton.gagarin.world/app/](https://ton.gagarin.world/app) +- [daolama.co](https://daolama.co/) +- [marketplace.playmuse.org](http://marketplace.playmuse.org/) +- [ton.vote](https://ton.vote/) +- [plane.tonfancy.io](https://plane.tonfancy.io/) +- [pi.oberton.io](https://pi.oberton.io/) +- [business.thetonpay.app](https://business.thetonpay.app/) +- [bridge.orbitchain.io](https://bridge.orbitchain.io/) +- [connecton-web-new.vercel.app](https://connecton-web-new.vercel.app/) +- [app.fanz.ee/staking](https://app.fanz.ee/staking) +- [testnet.pton.fi](https://testnet.pton.fi/) +- [tonft.app](https://tonft.app/) +- [cardify.casino](https://cardify.casino/) +- [4riends.org](https://4riends.org/#/) +- [tonflex.fi](https://tonflex.fi/swap) +- [soquest.xyz](https://soquest.xyz/) +- [app.evaa.finance](https://app.evaa.finance/) + +
+ +## Присоединяйтесь к экосистеме TON + +Чтобы подключить свой сервис к экосистеме TON, Вам необходимо выполнить следующие действия: + +- **TON Connect**. Включите протокол TON Connect в свое приложение. +- **Транзакции**. Создавайте заданные сообщения транзакций с помощью библиотек TON. Погрузитесь в процесс [отправки сообщений](/develop/dapps/ton-connect/message-builders) с помощью нашего исчерпывающего руководства. +- **Платежи**. Обрабатывайте платежи через публичный API ([tonapi](https://tonapi.io/)) или Ваш собственный индексатор, например, [gobycicle](http://github.com/gobicycle/bicycle). Узнайте больше из нашего подробного руководства по [обработке активов](/develop/dapps/asset-processing). diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/develop/fift/overview.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/develop/fift/overview.mdx new file mode 100644 index 0000000000..1fd78849ba --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/develop/fift/overview.mdx @@ -0,0 +1,57 @@ +import Button from '@site/src/components/button' + +# Обзор + +Fift - это основанный на стеке язык программирования общего назначения, оптимизированный для создания, отладки и управления смарт-контрактами TON Blockchain. +Fift был специально разработан для взаимодействия с виртуальной машиной TON (TON VM или TVM) и блокчейном TON. + +```fift +{ ."hello " } execute ."world" +hello world ok +``` + +:::info +Обычно использование языка Fift не требуется для программирования смарт-контрактов в TON. Однако иногда Вам может понадобиться использовать язык Fift для решения нестандартных технических задач в рамках Вашего задания. +::: + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +



+ +## Документация + +- [Fift: A Brief Introduction](https://ton.org/fiftbase.pdf) +- [Виртуальная машина TON](/learn/tvm-instructions/tvm-overview) + +## Примеры + +- [Примеры смарт-контрактов Fift] (/develop/smart-contracts/examples#fift-smart-contracts) + +## Учебники + +- [Introduction To Fift](https://blog.ton.org/introduction-to-fift) +- [\[YouTube\]Его величество Фифт](https://www.youtube.com/watch?v=HVsveTmVowc&list=PLtUBO1QNEKwttRsAs9eacL2oCMOhWaOZs) \[[RU-версия](https://www.youtube.com/playlist?list=PLyDBPwv9EPsCYG-hR4N5FRTKUkfM8POgh)] от **@MarcoDaTr0p0je** & **@Wikimar**. + +## Источники + +- [Скрипты Fift для стандартных смарт-контрактов](https://github.com/ton-blockchain/ton/tree/master/crypto/smartcont) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/develop/overview.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/develop/overview.mdx new file mode 100644 index 0000000000..ead7734072 --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/develop/overview.mdx @@ -0,0 +1,207 @@ +import Button from '@site/src/components/button' +import Player from '@site/src/components/player' + +# Документация TON + +Добро пожаловать в официальную документацию по разработке TON Blockchain! + +Этот ресурс призван предоставить Вам всю необходимую информацию, которая понадобится Вам для создания, тестирования и развертывания приложений на блокчейне TON. + +Это совместная инициатива с открытым исходным кодом, и вклад всегда приветствуется. Вся документация может быть отредактирована через GitHub, просто [следуйте этим инструкциям](/contribute). + +- Серия _TON Hello World_ содержит подробные пошаговые руководства по кошелькам, смарт-контрактам, мини-приложениям, а также тестированию и отладке смарт-контрактов на TON. +- _Get Started with TON_ - это пошаговое руководство по взаимодействию с блокчейном TON. (Видеоурок прилагается) + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +### Основы блокчейна с TON + +Этот курс знакомит с основами блокчейна, уделяя особое внимание практическим навыкам работы в экосистеме TON. Вы поймете, как функционирует блокчейн и каковы его разнообразные применения. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +### Курс TON + +Мы с гордостью представляем курс **TON Blockchain Course**, который является исчерпывающим руководством по блокчейну TON. Курс предназначен для разработчиков, которые хотят научиться создавать смарт-контракты и децентрализованные приложения на блокчейне TON в увлекательной и интерактивной форме. + +Он состоит из **9 модулей** и охватывает основы блокчейна TON, языка программирования FunC и виртуальной машины TON (TVM). + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Модули разработки + +Если Вы новичок в разработке TON Blockchain, рекомендуем Вам начать с самого начала и пройти свой путь через эти темы. + +### Основополагающие концепции + +- [The Open Network](/learn/introduction) - высокоуровневый обзор блокчейна TON. +- [Blockchain of Blockchains](/learn/overviews/ton-blockchain) - приземленное объяснение TON Blockchain. +- [Адреса смарт-контрактов](/learn/overviews/addresses) - Подробное объяснение адресов. +- [Ячейки как структура данных](/learn/overviews/cells) - Высокоуровневое объяснение структур данных. +- [TON Networking](/learn/networking/overview) - Высокоуровневый обзор протоколов TON peer-to-peer. +- [Виртуальная машина TON (TVM)](/learn/tvm-instructions/tvm-overview) - Высокоуровневый обзор виртуальной машины TON. +- [Транзакции и фазы](/learn/tvm-instructions/tvm-overview#transactions-and-phases) - Подробное объяснение транзакций и фаз. +- [Комиссионные за транзакции](/develop/smart-contracts/fees) - высокоуровневое объяснение комиссионных за транзакции. + +### Инфраструктура + +- [Типы узлов](/participate/nodes/node-types) - Подробное объяснение типов узлов. +- [Run a Full Node](/participate/run-nodes/full-node) - Подробное объяснение того, как запустить узел. +- [TON DNS & Sites](/participate/web3/dns) - Подробное объяснение TON DNS & Sites. +- [TON Storage](/participate/ton-storage/storage-daemon) - Подробное объяснение работы TON Storage. + +### Дополнительные ресурсы + +- [**FAQ**](/develop/howto/faq) - Часто задаваемые вопросы +- [Документация FunC](/develop/func/overview) +- [Документация по Fift](/develop/fift/overview) + +## Разработка смарт-контрактов + +Смарт-контракты - это строительные блоки децентрализованных приложений (DApps) на блокчейне TON. Если Вы хотите разработать собственное dApps, очень важно понимать, как работают смарт-контракты. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +



+ +Следующие ресурсы предоставляют ценную информацию для разработки смарт-контрактов TON: + +- [TON Hello World: Пошаговое руководство по написанию Вашего первого смарт-контракта](https://ton-community.github.io/tutorials/02-contract/) - Доступное и лаконичное объяснение основ работы с JS. +- [Как работать со смарт-контрактами кошелька](/develop/smart-contracts/tutorials/wallet) - Подробное и тщательное объяснение основ смарт-контрактов с использованием JS и GO. +- [Изучение смарт-контрактов на примерах](/develop/smart-contracts/examples) (FunC, Fift) +- [Speed Run TON](/develop/smart-contracts/examples) - 6 интерактивных задач и пошаговых руководств для изучения разработки смарт-контрактов. + +## Разработка DApp + +Децентрализованные приложения (DApps) - это приложения, которые работают не на одном компьютере (блокчейн TON), а на одноранговой сети компьютеров. Они похожи на традиционные веб-приложения, но построены поверх сети блокчейн. Это означает, что DApps децентрализованы, то есть ни один субъект не контролирует их. + +```mdx-code-block + +``` + +### DeFi Development + +- [TON Connect](/develop/dapps/ton-connect/overview) - интеграция и аутентификация для DApps. +- [Обработка внецепочечных платежей](/develop/dapps/asset-processing) - примеры и концепции обработки платежей. +- [Обработка джеттонов TON](/develop/dapps/asset-processing/jettons) - примеры и концепции для обработки джеттонов. +- [Fungible (FT) / Non-fungible (NFT) tokens](/develop/dapps/defi/tokens) - смарт-контракты, примеры, инструменты + +Сделайте первые шаги в разработке DApps с помощью исчерпывающего руководства по созданию DApps: + +- [TON Hello World: пошаговое руководство по созданию вашего первого веб-клиента](https://ton-community.github.io/tutorials/03-client/) +- [Интеграция бота Telegram через TON Connect](/develop/dapps/ton-connect/tg-bot-integration) + +### API и SDK + +- [APIs](/develop/dapps/apis) +- [SDKs](/develop/dapps/apis/sdk) + +## Часто задаваемые вопросы + +Перейдите в раздел [Часто задаваемые вопросы](/develop/howto/faq). diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/develop/smart-contracts/testing/overview.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/develop/smart-contracts/testing/overview.mdx new file mode 100644 index 0000000000..32da941a50 --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/develop/smart-contracts/testing/overview.mdx @@ -0,0 +1,141 @@ +# Написание тестов с помощью Blueprint + +## Обзор + +Инструментарий для тестирования (обычно это песочница) уже включен в TypeScript SDK под названием [Blueprint](/develop/smart-contracts/sdk/javascript). Вы можете создать демо-проект и запустить тест по умолчанию в два этапа: + +1. Создайте новый проект Blueprint: + +```bash +npm create ton@latest MyProject +``` + +2. Проведите тест: + +```bash +cd MyProject +npx blueprint test +``` + +В результате Вы увидите соответствующий вывод в окне терминала: + +```bash +% npx blueprint test + +> MyProject@0.0.1 test +> jest + + PASS tests/Main.spec.ts + Main + ✓ should deploy (127 ms) + +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: 1.224 s, estimated 2 s +Ran all test suites. +``` + +## Базовое использование + +Тестирование смарт-контрактов позволяет обеспечить безопасность, оптимизировать расход газа и изучить крайние случаи. +Написание тестов в Blueprint (основанном на [Sandbox](https://github.com/ton-org/sandbox)) осуществляется путем определения произвольных действий с контрактом и сравнения результатов тестирования с ожидаемым результатом, например: + +```typescript +it('should execute with success', async () => { // description of the test case + const res = await main.sendMessage(sender.getSender(), toNano('0.05')); // performing an action with contract main and saving result in res + + expect(res.transactions).toHaveTransaction({ // configure the expected result with expect() function + from: main.address, // set expected sender for transaction we want to test matcher properties from + success: true // set the desirable result using matcher property success + }); + + printTransactionFees(res.transactions); // print table with details on spent fees +}); +``` + +### Написание тестов для сложных утверждений + +Основная схема создания теста такова: + +1. Создайте определенную обернутую сущность `Contract` с помощью функции `blockchain.openContract()`. +2. Опишите действия, которые должен выполнить Ваш `контракт`, и сохраните результат выполнения в переменной `res`. +3. Проверьте свойства с помощью функции `expect()` и матчера `toHaveTransaction()`. + +Матчер `toHaveTransaction` ожидает объект с любой комбинацией полей из типа `FlatTransaction`, определенных со следующими свойствами + +| Имя | Тип | Описание | +| --------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| с сайта | Адрес? | Контрактный адрес отправителя сообщения | +| на | Адрес | Контрактный адрес назначения сообщения (альтернативное имя свойства `to`). | +| значение | bigint? | Количество Тонкоинов в сообщении в нанотонах | +| тело | Клетка | Тело сообщения определяется как ячейка | +| op | число? | Код операции - это номер идентификатора операции (обычно crc32 из TL-B). Ожидается в первых 32 битах тела сообщения. | +| успех | булево? | Пользовательский флаг песочницы, определяющий результирующий статус определенной транзакции. True - если фаза вычислений и действий прошла успешно. В противном случае - False. | + +Вы можете опустить поля, которые Вас не интересуют, и передать функции, принимающие типы, возвращающие булевы (`true` означает "хорошо"), для проверки, например, диапазонов чисел, опкодов сообщений и т.д. Обратите внимание, что если поле является необязательным (например, `from?: Address`), то функция должна принимать и необязательный тип. + +:::tip +Весь список полей матчера Вы можете узнать из [Документации по песочнице](https://github.com/ton-org/sandbox#test-a-transaction-with-matcher). +::: + +### Конкретный набор тестов + +#### Извлечение SendMode + +Чтобы извлечь режим отправки отправленного сообщения, Вы можете использовать следующий код: + +```ts + +const smc = await blockchain.getContract(addr); + +const re = blockchain.executor.runTransaction({ + config: blockchain.configBase64, libs: null, verbosity: 'full', + now: Math. floor (Date.now) / 1000), + lt: BigInt(Date.now()), + randomSeed: null, + ignoreChksig: false, + debugEnabled: true, + shardAccount: beginCell() + .store (storeShardAccount (smc.account)) + .endCell() + .toBoc() + .toString('base64'), + message: beginCell() + .store (storeMessageRelaxed (...)) + .endCell(), +}); + +if (!re.result. success || !re.result.actions) { + throw new Error('fail'); +} +const actions = loadoutList(Cell.fromBase64(re.result.actions).beginParse()); +actions[0].type === 'sendMsg' && actions[0].mode; + +``` + +## Учебники + +Узнайте больше о тестировании из самых ценных уроков сообщества на TON: + +- [Урок 2: Тестирование FunC для смарт-контракта](https://github.com/romanovichim/TonFunClessons_Eng/blob/main/lessons/smartcontract/2lesson/secondlesson.md) +- [TON Hello World часть 4: Пошаговое руководство по тестированию вашего первого смарт-контракта](https://ton-community.github.io/tutorials/04-testing/) +- [TON Smart Contract Pipeline](https://dev.to/roma_i_m/ton-smart-contract-pipeline-write-simple-contract-and-compile-it-4pnh) +- [\[YouTube\]Шестой урок FunC & Blueprint. Газ, оплата, тесты](https://youtu.be/3XIpKZ6wNcg) + +## Примеры + +Проверьте тестовые наборы, используемые для контрактов экосистемы TON, и учитесь на примерах. + +- [тесты песочницы liquid-staking-contract](https://github.com/ton-blockchain/liquid-staking-contract/tree/main/tests) +- [governance_tests](https://github.com/Trinketer22/governance_tests/blob/master/config_tests/tests/) +- [JettonWallet.spec.ts](https://github.com/EmelyanenkoK/modern_jetton/blob/master/tests/JettonWallet.spec.ts) +- [governance_tests](https://github.com/Trinketer22/governance_tests/blob/master/elector_tests/tests/complaint-test.fc) +- [MassSender.spec.ts](https://github.com/Gusarich/ton-mass-sender/blob/main/tests/MassSender.spec.ts) +- [TonForwarder.spec.ts](https://github.com/TrueCarry/ton-contract-forwarder/blob/main/src/contracts/ton-forwarder/TonForwarder.spec.ts) +- [Assurer.spec.ts](https://github.com/aSpite/dominant-assurance-contract/blob/main/tests/Assurer.spec.ts) + +## См. также + +- [Blueprint](/develop/smart-contracts/sdk/javascript) +- [toncli](/develop/smart-contracts/testing/toncli) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/learn/academy/academy-overview.md b/i18n/ru/docusaurus-plugin-content-docs/current/learn/academy/academy-overview.md new file mode 100644 index 0000000000..67acdd7dcf --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/learn/academy/academy-overview.md @@ -0,0 +1,16 @@ +# Образовательные ресурсы + +### TON Speedrun + +- [TON Speedrun](https://tonspeedrun.com/) - специализированная платформа, предназначенная для практического подхода к обучению в разработке TON. + +### Курсы + +- [Основы блокчейна с TON](https://stepik.org/course/201294/promo) ([RU версия](https://stepik.org/course/202221/), [CHN версия](https://stepik.org/course/200976/)) - + Этот курс знакомит с основами блокчейна, уделяя особое внимание практическим навыкам работы в экосистеме TON. Вы поймете, как функционирует блокчейн и каковы его разнообразные применения. + +## См. также + +- [Speedrun TON](https://tonspeedrun.com/) +- [TON Hello World](https://tonhelloworld.com/01-wallet/) +- [[YouTube] TON Dev Study EN ](https://www.youtube.com/@TONDevStudy)[[RU]](https://www.youtube.com/results?search_query=tondevstudy) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/learn/introduction.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/learn/introduction.mdx new file mode 100644 index 0000000000..6a5fd4a4db --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/learn/introduction.mdx @@ -0,0 +1,81 @@ +import Player from '@site/src/components/player' +import Button from '@site/src/components/button' + +# Открытая сеть + +**The Open Network (TON)** - это децентрализованная и открытая интернет-платформа, состоящая из нескольких компонентов. К ним относятся: TON Blockchain, TON DNS, TON Storage и TON Sites. TON Blockchain - это основной протокол, который соединяет базовую инфраструктуру TON вместе, образуя большую экосистему TON. + +TON нацелен на достижение широкой межцепочечной совместимости, работая при этом в высокомасштабируемой безопасной системе. TON рассчитан на обработку миллионов транзакций в секунду (TPS), а в перспективе - на сотни миллионов пользователей. + +**TON Blockchain** разработан как распределенный суперкомпьютер, или "_суперсервер_", предназначенный для предоставления различных продуктов и услуг, способствующих развитию децентрализованного видения нового Интернета. + +- Узнайте, какие услуги TON предоставляет своим пользователям, просмотрев этот раздел: [Участвуйте в TON](/participate/) +- Чтобы узнать больше о технических аспектах TON Blockchain, ознакомьтесь с [Blockchain of Blockchains](/learn/overviews/ton-blockchain) +- Узнайте больше о разработке всех вещей TON, просмотрев этот раздел: [Начало работы](/develop/overview) + +## Обзор с высоты птичьего полета + +Чтобы понять истинное видение децентрализованного Интернета и то, как TON вносит свой вклад в эту неизбежность, ознакомьтесь с видео ниже: + + + +## Основы блокчейна с TON + +Этот курс знакомит с основами блокчейна, уделяя особое внимание практическим навыкам работы в экосистеме TON. Вы поймете, как функционирует блокчейн и каковы его разнообразные применения. Вы также получите важнейшие навыки, связанные с TON, включая настройку кошелька, торговлю NFT, создание Jetton и транзакции с монетами TON на децентрализованных биржах (DEX). Курс также вооружит Вас важнейшими знаниями о криптовалютных угрозах и мошенничестве и даст практические советы о том, как защитить свои криптоактивы. + +- [Основы блокчейна с TON](https://stepik.org/course/201294/) ([RU версия](https://stepik.org/course/202221/), [CHN версия](https://stepik.org/course/200976/)) + +## Курс TON Blockchain + +Мы с гордостью представляем **TON Blockchain Course**, который является исчерпывающим руководством по блокчейну TON. Курс предназначен для разработчиков, которые хотят научиться создавать смарт-контракты и децентрализованные приложения на блокчейне TON. + +Он состоит из **9 модулей** и охватывает основы блокчейна TON, языка программирования FunC и виртуальной машины TON (TVM). + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Новичок в блокчейне? + +Если Вы новичок в блокчейне и не понимаете, что делает эту технологию такой революционной, ознакомьтесь с этими важными ресурсами: + +- [Что такое блокчейн? Что такое смарт-контракт? Что такое газ?](https://blog.ton.org/what_is_blockchain) +- [Как блокчейн может помочь Вам на необитаемом острове](https://talkol.medium.com/why-decentralized-consensus-blockchain-is-good-for-business-5ff263468210) +- [\[YouTube\] Криптосети и почему они имеют значение](https://youtu.be/2wxtiNgXBaU) + +## Отношения TON с Ethereum + +Для тех, кто знаком с разработкой Ethereum, мы написали две вводные статьи, чтобы помочь Вам понять, что отличает TON в этом отношении: + +- [Шесть уникальных аспектов блокчейна TON, которые удивят разработчиков Solidity](https://blog.ton.org/six-unique-aspects-of-ton-blockchain-that-will-surprise-solidity-developers) +- [Пришло время попробовать что-то новое: асинхронные смарт-контракты](https://telegra.ph/Its-time-to-try-something-new-Asynchronous-smart-contracts-03-25) +- [Сравнение блокчейнов](https://ton.org/comparison_of_blockchains.pdf) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/learn/networking/overview.md b/i18n/ru/docusaurus-plugin-content-docs/current/learn/networking/overview.md new file mode 100644 index 0000000000..abb9281b21 --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/learn/networking/overview.md @@ -0,0 +1,19 @@ +# TON Networking + +Проект TON использует собственные протоколы одноранговой сети. + +- Блокчейн **TON использует эти протоколы** для распространения новых блоков, отправки и сбора кандидатов на транзакцию и так далее. + + В то время как сетевые требования одноблокчейновых проектов, таких как Bitcoin или Ethereum, могут быть удовлетворены довольно легко (по сути, необходимо построить + одноранговую оверлейную сеть и затем распространять все новые блоки и + кандидатов на транзакции с помощью протокола [gossip](https://en.wikipedia.org/wiki/Gossip_protocol)), многоблокчейновые проекты, такие как + TON, гораздо более требовательны (например, необходимо иметь возможность + подписаться на обновления только некоторых шардчейнов, не обязательно всех). + +- Сервисы экосистемы **TON (например, TON Proxy, TON Sites, TON Storage) работают на этих протоколах.**. + + Как только более сложные сетевые протоколы, необходимые + для поддержки блокчейна TON, будут созданы, окажется, что их можно легко + использовать для целей, не обязательно связанных с непосредственными потребностями самого + блокчейна, что дает больше возможностей и гибкости для создания + новых услуг в экосистеме TON. diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/learn/overviews/addresses.md b/i18n/ru/docusaurus-plugin-content-docs/current/learn/overviews/addresses.md new file mode 100644 index 0000000000..9090c650d1 --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/learn/overviews/addresses.md @@ -0,0 +1,220 @@ +# Адреса смарт-контрактов + +В этом разделе будут описаны особенности адресации смарт-контрактов в блокчейне TON. Также будет объяснено, как акторы являются синонимами смарт-контрактов на TON. + +## Все является умным контрактом + +В TON смарт-контракты строятся с использованием модели [Actor model] (/learn/overviews/ton-blockchain#single-actor). Фактически, акторы в TON технически представлены в виде смарт-контрактов. Это означает, что даже Ваш кошелек является простым актором (и смарт-контрактом). + +Как правило, акторы обрабатывают входящие сообщения, изменяют свое внутреннее состояние и в результате генерируют исходящие сообщения. Именно поэтому каждый актор (т.е. смарт-контракт) в блокчейне TON должен иметь адрес, чтобы иметь возможность получать сообщения от других акторов. + +:::info ОПЫТ РАБОТЫ С EVM +В виртуальной машине Ethereum (EVM) адреса полностью отделены от смарт-контрактов. Не стесняйтесь узнать больше о различиях, прочитав нашу статью ["Шесть уникальных аспектов блокчейна TON, которые удивят разработчиков Solidity"](https://blog.ton.org/six-unique-aspects-of-ton-blockchain-that-will-surprise-solidity-developers), написанную Талом Колом. +::: + +## Адрес смарт-контракта + +Адреса смарт-контрактов, работающих на TON, обычно состоят из двух основных компонентов: + +- **(workchain_id)**: обозначает ID рабочей цепи (знаковое 32-битное целое число) + +- **(account_id)** обозначает адрес аккаунта (64-512 бит, в зависимости от рабочего цепочки) + +В разделе этой документации, посвященном обзору сырых адресов, мы обсудим, как выглядят пары **(workchain_id, account_id)**. + +### Идентификатор рабочей цепи и идентификатор учетной записи + +#### Идентификатор рабочей цепи + +[Как мы уже видели ранее](/learn/overviews/ton-blockchain#workchain-blockchain-with-your-own-rules), на блокчейне TON можно создать до `2^32` рабочих цепей. Мы также отметили, что адреса смарт-контрактов с 32-битным префиксом идентифицируют и связываются с адресами смарт-контрактов в разных рабочих цепях. Это позволяет смарт-контрактам отправлять и получать сообщения в разные рабочие цепочки TON Blockchain и из них. + +В настоящее время в блокчейне TON работает только мастерчейн (workchain_id=-1) и время от времени основной workchain (workchain_id=0). + +Оба они имеют 256-битные адреса, поэтому мы предполагаем, что workchain_id равен либо 0, либо -1, а адрес внутри рабочей цепочки точно равен 256 битам. + +#### Идентификатор счета + +Все идентификаторы учетных записей на TON используют 256-битные адреса на Мастерчейне и Бейсчейне (или базовом рабочем цепочке). + +Фактически, идентификаторы аккаунта **(account_id)** определяются как хэш-функции для объектов смарт-контракта (в частности, SHA-256). Каждый смарт-контракт, работающий на блокчейне TON, хранит два основных компонента. К ним относятся: + +1. *Скомпилированный код*. Логика смарт-контракта, скомпилированная в виде байткода. +2. *Инициальное состояние*. Значения контракта в момент его развертывания на цепи. + +Наконец, чтобы точно определить адрес контракта, необходимо вычислить хэш, соответствующий паре **(Начальный код, Начальное состояние)** объектов. Сейчас мы не будем глубоко вникать в то, как работает [TVM](/learn/tvm-instructions/tvm-overview), но важно понимать, что идентификаторы счетов на TON определяются по такой формуле: +: +**account_id = hash(начальный код, начальное состояние)**. + +Со временем, на протяжении всей этой документации, мы будем углубляться в технические характеристики и обзор схемы TVM и TL-B. Теперь, когда мы знакомы с генерацией **account_id** и их взаимодействием с адресами смарт-контрактов на TON, давайте объясним, что такое Raw и User-Friendly адреса. + +## Обращается к государству + +Каждый адрес может находиться в одном из возможных состояний: + +- `nonexist` - по этому адресу не было принято ни одной транзакции, поэтому он не содержит никаких данных (или контракт был удален). Можно сказать, что изначально все2256 адресов находятся в таком состоянии. +- `uninit` - адрес имеет некоторые данные, которые содержат баланс и мета-информацию. В этом состоянии у адреса еще нет кода смарт-контракта/постоянных данных. Адрес переходит в это состояние, например, когда он не существовал, и какой-то другой адрес отправил ему токены. +- `Активный` - адрес имеет код смарт-контракта, постоянные данные и баланс. В этом состоянии он может выполнять некоторую логику во время транзакции и изменять свои постоянные данные. Адрес переходит в это состояние, когда он был `uninit` и поступило сообщение с параметром state_init (обратите внимание, что для развертывания этого адреса хэш из `state_init` и `code` должен быть равен адресу). +- `заморозка` - адрес не может выполнять никаких операций, это состояние содержит только два хэша предыдущего состояния (ячейки кода и состояния соответственно). Когда заряд памяти адреса превышает его баланс, он переходит в это состояние. Чтобы разморозить его, Вы можете послать внутреннее сообщение с `state_init` и `code`, которые хранят описанные ранее хэши и некоторое количество Toncoin. Восстановить его может быть сложно, поэтому не стоит допускать такой ситуации. Существует проект по размораживанию адреса, который Вы можете найти [здесь](https://unfreezer.ton.org/). + +## Сырые и удобные адреса + +После краткого обзора того, как адреса смарт-контрактов на TON используют рабочие цепи и идентификаторы учетных записей (для Мастерчейна и Бейсчейна в частности), важно понять, что эти адреса выражаются в двух основных форматах: + +- **Сырые адреса**: Оригинальное полное представление адресов смарт-контрактов. +- **Удобные для пользователя адреса**: Удобные для пользователя адреса - это улучшенный формат сырого адреса, который обеспечивает лучшую безопасность и простоту использования. + +Ниже мы расскажем о различиях между этими двумя типами адресов и более подробно рассмотрим, почему на TON используются удобные для пользователя адреса. + +### Сырой адрес + +Необработанные адреса смарт-контрактов состоят из идентификатора рабочей цепи и идентификатора учетной записи *(workchain_id, account_id)* и отображаются в следующем формате: + +- [десятичный workchain_id\]:[64 шестнадцатеричных цифр с account_id\]. + +Ниже приведен пример необработанного адреса смарт-контракта, в котором используются идентификатор рабочей цепи и идентификатор учетной записи вместе (выраженные как **workchain_id** и **account_id**): + +`-1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260` + +Обратите внимание на `-1` в начале строки адресов, которая обозначает *workchain_id*, принадлежащий Мастерчейну. + +:::note +Прописные буквы (такие как 'A', 'B', 'C', 'D' и т.д.) могут использоваться в адресных строках вместо их строчных аналогов (таких как 'a', 'b', 'c' 'd' и т.д.). +::: + +#### Проблемы с сырыми адресами + +При использовании формы "Сырой адрес" возникают две основные проблемы: + +1. При использовании необработанного формата адресов невозможно проверить адреса, чтобы исключить ошибки перед отправкой транзакции. + Это означает, что если Вы случайно добавите или удалите символы в адресной строке перед отправкой транзакции, Ваша транзакция будет отправлена не по назначению, что приведет к потере средств. +2. При использовании необработанного формата адреса невозможно добавить специальные флаги, подобные тем, что используются при отправке транзакций, в которых используются удобные для пользователя адреса. + Чтобы помочь Вам лучше понять эту концепцию, ниже мы объясним, какие флаги можно использовать. + +### Удобный для пользователя адрес + +Удобные адреса были разработаны для обеспечения безопасности и упрощения работы пользователей TON, которые обмениваются адресами в Интернете (например, на публичных платформах обмена сообщениями или через своих поставщиков услуг электронной почты), а также в реальном мире. + +#### Удобная структура адресов + +Удобные для пользователя адреса состоят всего из 36 байт и получаются путем генерации следующих компонентов по порядку: + +1. *[флаги - 1 байт]* - Флаги, которые прикрепляются к адресам, изменяют способ реакции смарт-контрактов на полученное сообщение. + Типы флагов, использующие удобный формат адреса, включают: + + - isBounceable. Обозначает отскакивающий или неотскакивающий тип адреса. (*0x11* для "bounceable", *0x51* для "non-bounceable") + - isTestnetOnly. Обозначает тип адреса, используемый только для целей тестовой сети. Адреса, начинающиеся с *0x80*, не должны приниматься программным обеспечением, работающим в рабочей сети + - isUrlSafe. Обозначает устаревший флаг, который определен как URL-safe для адреса. После этого все адреса считаются безопасными для URL. +2. *\[workchain_id - 1 байт]* - Идентификатор рабочей цепи (*workchain_id*) определяется подписанным 8-битным целым числом *workchain_id*.\ + (*0x00* для BaseChain, *0xff* для MasterChain) +3. *\[account_id - 32 байта]* - ID счета состоит из ([big-endian](https://www.freecodecamp.org/news/what-is-endianness-big-endian-vs-little-endian/)) 256-битного адреса в рабочей цепочке. +4. *\[Проверка адреса - 2 байта]* - В дружественных адресах проверка адреса состоит из CRC16-CCITT-подписи из предыдущих 34 байт. ([Пример](https://github.com/andreypfau/ton-kotlin/blob/ce9595ec9e2ad0eb311351c8a270ef1bd2f4363e/ton-kotlin-crypto/common/src/crc32.kt)) + На самом деле, идея, относящаяся к проверке для дружественных адресов, очень похожа на [алгоритм Luhn](https://en.wikipedia.org/wiki/Luhn_algorithm), который используется на всех кредитных картах, чтобы предотвратить ввод пользователями несуществующих номеров карт по ошибке. + +Сложение этих 4 основных компонентов означает, что: `1 + 1 + 32 + 2 = 36` байт в сумме (на один удобный для пользователя адрес). + +Чтобы сгенерировать удобный для пользователя адрес, разработчик должен закодировать все 36 байт, используя либо: + +- *base64* (т.е. с цифрами, латинскими буквами верхнего и нижнего регистра, '/' и '+') +- *base64url* (с '_' и '-' вместо '/' и '+') + +После этого процесса создание удобного для пользователя адреса длиной 48 символов без пробелов завершается. + +:::info ФЛАГИ АДРЕСОВ DNS +На TON вместо необработанных и удобных для пользователя адресов иногда используются DNS-адреса, такие как mywallet.ton. На самом деле, DNS-адреса состоят из удобных для пользователя адресов и включают в себя все необходимые флаги, которые позволяют разработчикам получить доступ ко всем флагам из DNS-записи в домене TON. +::: + +#### Примеры удобной кодировки адресов + +Например, смарт-контракт "test giver" (специальный смарт-контракт, находящийся в мастерчейне testnet, который отправляет 2 тестовых токена всем, кто их запрашивает) использует следующий сырой адрес: + +`-1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260` + +Приведенный выше сырой адрес "test giver" должен быть преобразован в удобную для пользователя форму адреса. Это можно сделать с помощью форм base64 или base64url (которые мы представили ранее) следующим образом: + +- `kf/8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15+KsQHFLbKSMiYIny` (base64) +- `kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny` (base64url) + +:::info +Обратите внимание, что обе формы (*base64* и *base64url*) действительны и должны быть приняты! +::: + +#### Отказоустойчивые и неотказоустойчивые адреса + +Основная идея, лежащая в основе флага отклоняемого адреса, заключается в безопасности средств отправителя. + +Например, если целевой смарт-контракт не существует, или если во время транзакции возникли какие-то проблемы, сообщение будет "отбито" обратно отправителю и составит остаток первоначальной стоимости транзакции (за вычетом всех комиссий за перевод и газ). Это гарантирует, что отправитель не потеряет свои средства, которые были случайно отправлены на адрес, который не может принять транзакцию. + +Что касается конкретно отказоустойчивых адресов: + +1. Флаг **bounceable=false** обычно означает, что получателем является кошелек. +2. Флаг **bounceable=true** обычно обозначает пользовательский смарт-контракт с собственной прикладной логикой (например, DEX). В этом примере сообщения, не подлежащие отмене, не должны отправляться по соображениям безопасности. + +Не стесняйтесь читать больше на эту тему в нашей документации, чтобы лучше понять [непрыгающие сообщения] (/develop/smart-contracts/guidelines/non-bouncable-messages). + +#### Представления Armored base64 + +Дополнительные двоичные данные, связанные с блокчейном TON, используют аналогичные "бронированные" представления адресов в формате base64. Они отличаются друг от друга в зависимости от первых 4 символов их байтовой метки. Например, 256-битные открытые ключи Ed25519 представляются путем создания 36-байтовой последовательности, используя следующий процесс по порядку: + +- Однобайтовая метка, использующая формат *0x3E*, обозначает открытый ключ +- Однобайтовая метка, использующая формат *0xE6*, обозначает открытый ключ Ed25519. +- 32 байта, содержащие стандартное двоичное представление открытого ключа Ed25519 +- 2 байта, содержащие представление CRC16-CCITT предыдущих 34 байт в большом порядке + +Полученная 36-байтовая последовательность преобразуется в 48-символьную строку base64 или base64url стандартным образом. Например, открытый ключ Ed25519 `E39ECDA0A7B0C60A7107EC43967829DBE8BC356A49B9DFC6186B3EAC74B5477D` (обычно представленный последовательностью из 32 байт, такой как: `0xE3, 0x9E, ..., 0x7D`) представляет себя через "бронированное" представление следующим образом: + +`Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2` + +### Преобразование адресов, удобных для пользователя, и сырых адресов + +Самый простой способ преобразовать удобные для пользователя и необработанные адреса - использовать один из нескольких API TON и других инструментов, включая: + +- [ton.org/address](https://ton.org/address) +- [dton.io API method](https://dton.io/api/address/0:867ac2b47d1955de6c8e23f57994fad507ea3bcfe2a7d76ff38f29ec46729627) +- [Методы API toncenter в mainnet](https://toncenter.com/api/v2/#/accounts/pack_address_packAddress_get) +- [методы API toncenter в testnet](https://testnet.toncenter.com/api/v2/#/accounts/pack_address_packAddress_get) + +Кроме того, существует два способа преобразования удобных и необработанных адресов кошельков с помощью JavaScript: + +- [Преобразование адреса из/в удобную для пользователя или сырую форму с помощью ton.js](https://github.com/ton-org/ton-core/blob/main/src/address/Address.spec.ts) +- [Преобразование адреса из/в удобную для пользователя или сырую форму с помощью tonweb](https://github.com/toncenter/tonweb/tree/master/src/utils#address-class) + +Также можно использовать подобные механизмы с помощью [SDKs](/develop/dapps/apis/sdk). + +### Примеры адресов + +Узнайте больше примеров по адресам TON в [Поваренной книге TON] (/develop/dapps/cookbook#working-with-contracts-addresses). + +## Возможные проблемы + +При взаимодействии с блокчейном TON крайне важно понимать последствия перевода монет TON на адреса `uninit` кошельков. В этом разделе описаны различные сценарии и их результаты, чтобы прояснить, как обрабатываются такие транзакции. + +### Что произойдет, если Вы переведете Toncoin на неинициативный адрес? + +#### Транзакция с включенным `state_init` + +Если Вы включите `state_init` (который состоит из кода и данных кошелька или смарт-контракта) в Вашу транзакцию. Сначала смарт-контракт развертывается с помощью предоставленного `state_init`. После развертывания входящее сообщение обрабатывается, аналогично отправке на уже инициализированный счет. + +#### Транзакция без установленного флага `state_init` и `bounce` + +Сообщение не может быть доставлено смарт-контракту `uninit`, и оно будет отклонено обратно отправителю. После вычета платы за потребленный газ оставшаяся сумма возвращается на адрес отправителя. + +#### Транзакция без установленного флага `state_init` и `bounce` + +Сообщение не может быть доставлено, но оно не вернется обратно к отправителю. Вместо этого отправленная сумма будет зачислена на адрес получателя, увеличив его баланс, даже если кошелек еще не инициализирован. Они будут храниться там до тех пор, пока владелец адреса не запустит контракт умного кошелька, после чего он сможет получить доступ к балансу. + +#### Как сделать это правильно + +Лучший способ развернуть кошелек - отправить несколько TON на его адрес (который еще не инициализирован) со снятым флагом `bounce`. После этого владелец может развернуть и инициализировать кошелек, используя средства на текущем неинициализированном адресе. Этот шаг обычно происходит при первой операции с кошельком. + +### В блокчейне TON реализована защита от ошибочных транзакций + +В блокчейне TON стандартные кошельки и приложения автоматически справляются со сложностями транзакций на неинициализированные адреса, используя отскакивающие и неотскакивающие адреса, которые описаны [здесь](#bounceable-vs-non-bounceable-addresses). Обычно кошельки, отправляя монеты на неинициализированные адреса, отправляют монеты как на bounceable, так и на non-bounceable адреса без возврата. + +Если необходимо быстро получить адрес в форме bounceable/non-bounceable, это можно сделать [здесь](https://ton.org/address/). + +### Ответственность за заказные продукты + +Если Вы разрабатываете собственный продукт на блокчейне TON, необходимо реализовать аналогичные проверки и логику: + +Перед отправкой средств убедитесь, что Ваше приложение проверяет, инициализирован ли адрес получателя. +Основываясь на состоянии адреса, используйте отказоустойчивые адреса для пользовательских смарт-контрактов с пользовательской логикой приложения для обеспечения возврата средств. Для кошельков используйте адреса без отказов. diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/learn/overviews/cells.md b/i18n/ru/docusaurus-plugin-content-docs/current/learn/overviews/cells.md new file mode 100644 index 0000000000..825b22232a --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/learn/overviews/cells.md @@ -0,0 +1,52 @@ +# Клетки как хранилище данных + +Все данные в TON хранятся в ячейках. Ячейка - это структура данных, содержащая: + +- до **1023 бит** данных (не байтов!) +- до **4 ссылок** на другие ячейки + +Биты и ссылки не смешиваются (они хранятся отдельно). Циклические ссылки запрещены: для любой ячейки ни одна из ее потомков не может иметь эту исходную ячейку в качестве ссылки. + +Таким образом, все клетки представляют собой направленный ациклический граф (DAG). Вот хороший рисунок для иллюстрации: + +![Directed Acylic Graph](/img/docs/dag.png) + +## Типы клеток + +В настоящее время существует 5 типов клеток: *обычные* и 4 *экзотических*. +К экзотическим типам относятся следующие: + +- Обрезанная клетка ветви +- Справочная ячейка библиотеки +- Ячейка с доказательством Меркла +- Ячейка обновления Меркле + +:::tip +Подробнее об экзотических клетках см: [**TVM Whitepaper, раздел 3**] (https://ton.org/tvm.pdf). +::: + +## Вкусовые качества клеток + +Ячейка - это непрозрачный объект, оптимизированный для компактного хранения. + +В частности, она дедуплицирует данные: если в разных ветвях есть несколько эквивалентных подячеек, на которые ссылаются разные ветви, их содержимое хранится только один раз. Однако непрозрачность означает, что ячейка не может быть изменена или прочитана напрямую. Таким образом, существует 2 дополнительных вида ячеек: + +- *Строитель* для частично построенных ячеек, для которых могут быть определены быстрые операции по добавлению битовых строк, целых чисел, других ячеек и ссылок на другие ячейки. +- *Slice* для "разрезанных" ячеек, представляющих собой либо остаток частично разобранной ячейки, либо значение (подячейку), находящееся внутри такой ячейки и извлеченное из нее с помощью инструкции синтаксического анализа. + +В TVM используется еще один особый клеточный вкус: + +- *Продолжение* для ячеек, содержащих оп-коды (инструкции) для виртуальной машины TON, смотрите [обзор TVM с высоты птичьего полета](/learn/tvm-instructions/tvm-overview). + +## Сериализация данных в ячейки + +Любой объект в TON (сообщение, очередь сообщений, блок, состояние всего блокчейна, код и данные контракта) сериализуется в ячейку. + +Процесс сериализации описывается схемой TL-B: формальное описание того, как данный объект может быть сериализован в *Builder* или как разобрать объект заданного типа из *Slice*. +TL-B для ячеек - это то же самое, что TL или ProtoBuf для байтовых потоков. + +Если Вы хотите узнать больше подробностей о (де)сериализации ячеек, Вы можете прочитать статью [Cell & Bag of Cells](/develop/data-formats/cell-boc). + +## См. также + +- [Язык TL-B](/develop/data-formats/tl-b-language) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/learn/overviews/ton-blockchain.md b/i18n/ru/docusaurus-plugin-content-docs/current/learn/overviews/ton-blockchain.md new file mode 100644 index 0000000000..6c8de1a137 --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/learn/overviews/ton-blockchain.md @@ -0,0 +1,72 @@ +# Блокчейн из блокчейнов + +:::tip +Термины "**умный контракт**", "**аккаунт**" и "**актор**" используются в этом документе как взаимозаменяемые для описания сущности блокчейна. +::: + +## Одиночный актер + +Давайте рассмотрим один смарт-контракт. + +В TON это *вещь* с такими свойствами, как `адрес`, `код`, `данные`, `баланс` и другими. Другими словами, это объект, который обладает некоторым *хранилищем* и *поведением*. +Это поведение имеет следующий вид: + +- Что-то происходит (наиболее распространенная ситуация - контракт получает сообщение) +- Контракт обрабатывает это событие в соответствии со своими свойствами, выполняя свой `код` в виртуальной машине TON. +- контракт изменяет свои собственные свойства (`код`, `данные` и другие) +- контракт опционально генерирует исходящие сообщения +- контракт переходит в режим ожидания до наступления следующего события + +Комбинация этих шагов называется **транзакцией**. Важно, чтобы события обрабатывались поочередно, поэтому *транзакции* строго упорядочены и не могут прерывать друг друга. + +Эта модель поведения хорошо известна и называется "Актер". + +### Самый низкий уровень: Цепочка счетов + +Последовательность *транзакций* `Tx1 -> Tx2 -> Tx3 -> ....` можно назвать **цепочкой**. А в рассматриваемом случае она называется **AccountChain**, чтобы подчеркнуть, что это *цепочка* одного счета транзакций. + +Теперь, поскольку узлам, обрабатывающим транзакции, необходимо время от времени согласовывать состояние смарт-контракта (чтобы достичь *консенсуса* по поводу состояния), эти *транзакции* разбиваются на блоки: +`[Tx1 -> Tx2] -> [Tx3 -> Tx4 -> Tx5] -> [] -> [Tx6]`. +Пакетирование не вмешивается в последовательность, каждая транзакция по-прежнему имеет только один "предыдущий tx" и максимум один "следующий tx", но теперь эта последовательность разбита на **блоки**. + +Также целесообразно включить в *блоки* очереди входящих и исходящих сообщений. В этом случае *блок* будет содержать полный набор информации, определяющей и описывающей, что произошло со смарт-контрактом во время этого блока. + +## Множество AccountChains: Осколки + +Теперь рассмотрим множество аккаунтов. Мы можем получить несколько *AccountChains* и хранить их вместе, такой набор *AccountChains* называется **ShardChain**. Таким же образом мы можем разрезать **ShardChain** на **ShardBlocks**, которые представляют собой совокупность отдельных *AccountBlocks*. + +### Динамическое разделение и объединение цепочек шардов + +Обратите внимание, что поскольку *ShardChain* состоит из легко различимых *AccountChain*, мы можем легко разделить его. Таким образом, если у нас есть 1 *ShardChain*, которая описывает события, происходящие с 1 миллионом аккаунтов, и в ней слишком много транзакций в секунду для обработки и хранения на одном узле, мы просто разделим (или **разделим**) эту цепочку на две меньшие *ShardChain*, каждая из которых будет учитывать полмиллиона аккаунтов, и каждая цепочка будет обрабатываться на отдельном подмножестве узлов. + +Аналогичным образом, если некоторые осколки стали слишком незанятыми, они могут быть **слиты** в один больший осколок. + +Очевидно, что существует два предельных случая: когда осколок содержит только одну учетную запись (и поэтому не может быть разделен дальше) и когда осколок содержит все учетные записи. + +Учетные записи могут взаимодействовать друг с другом, посылая сообщения. Существует специальный механизм маршрутизации, который перемещает сообщения из исходящих очередей в соответствующие входящие очереди и гарантирует, что 1) все сообщения будут доставлены 2) сообщения будут доставлены последовательно (сообщение, отправленное раньше, достигнет места назначения раньше). + +:::info БОКОВОЕ ПРИМЕЧАНИЕ +Чтобы сделать разделение и объединение детерминированным, объединение цепочек счетов в шарды основано на битовом представлении адресов счетов. Например, адрес выглядит как `(префикс шарда, адрес)`. Таким образом, все аккаунты в шард-цепочке будут иметь абсолютно одинаковый двоичный префикс (например, все адреса будут начинаться с `0b00101`). +::: + +## Блокчейн + +Совокупность всех шардов, содержащая все аккаунты, ведущие себя в соответствии с одним набором правил, называется **Блокчейн**. + +В TON может быть множество наборов правил и, соответственно, множество блокчейнов, которые работают одновременно и могут взаимодействовать друг с другом, отправляя сообщения кросс-чейн таким же образом, как счета одной цепи могут взаимодействовать друг с другом. + +### Workchain: Блокчейн с вашими собственными правилами + +Если Вы хотите настроить правила группы шардчейнов, Вы можете создать **Workchain**. Хороший пример - создать воркчейн, работающий на базе EVM, чтобы запускать на нем смарт-контракты Solidity. + +Теоретически, каждый член сообщества может создать свой собственный воркчейн. На самом деле, это довольно сложная задача - создать его, затем заплатить (дорогую) цену за его создание и получить 2/3 голосов от валидаторов, чтобы одобрить создание Вашего Workchain. + +TON позволяет создавать до `2^32` рабочих цепочек, каждая из которых подразделяется на до `2^60` шардов. + +В настоящее время в TON существует только 2 рабочих цепочки: MasterChain и BaseChain. + +BaseChain используется для повседневных транзакций между участниками, потому что он довольно дешевый, а MasterChain выполняет важнейшую функцию для TON, так что давайте рассмотрим, что он делает! + +### Мастерчейн: Блокчейн из блокчейнов + +Существует необходимость в синхронизации маршрутизации сообщений и выполнения транзакций. Другими словами, узлам сети нужен способ зафиксировать некоторую "точку" в состоянии мультицепочки и прийти к консенсусу относительно этого состояния. В TON для этой цели используется специальная цепочка, называемая **MasterChain**. Блоки *masterchain* содержат дополнительную информацию (последние хэши блоков) обо всех остальных цепочках в системе, поэтому любой наблюдатель однозначно определяет состояние всех мультичейн-систем по одному блоку masterchain. diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/learn/tvm-instructions/tvm-overview.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/learn/tvm-instructions/tvm-overview.mdx new file mode 100644 index 0000000000..662c2ff96c --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/learn/tvm-instructions/tvm-overview.mdx @@ -0,0 +1,133 @@ +import Button from '@site/src/components/button' + +# Обзор TVM + +Все смарт-контракты TON выполняются на собственной виртуальной машине TON (TVM). TVM построена по принципу _стека_, что делает ее эффективной и простой в реализации. + +Этот документ дает представление о том, как TVM выполняет транзакции с высоты птичьего полета. + +:::tip + +- TVM Source - [**TVM C++ implementation**](https://github.com/ton-blockchain/ton/tree/master/crypto/vm) + ::: + +## Курс TON: TVM + +:::tip +Прежде чем приступить к изучению курса, убедитесь, что Вы хорошо понимаете основы технологии блокчейн. Если у Вас есть пробелы в знаниях, мы рекомендуем пройти курс [Основы блокчейна с TON](https://stepik.org/course/201294/promo) ([RU версия](https://stepik.org/course/202221/), [CHN версия](https://stepik.org/course/200976/)). +::: + +Курс [TON Blockchain Course](https://stepik.org/course/176754/) - это полное руководство по разработке TON Blockchain. + +Модуль 2 полностью охватывает **TVM**, транзакции, масштабируемость и бизнес-кейсы. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Транзакции и фазы + +Когда на счете в одной из цепочек TON происходит какое-то событие, оно вызывает **транзакцию**. Наиболее распространенным событием является "прибытие какого-либо сообщения", но в общем случае это могут быть `tick-tock`, `merge`, `plit` и другие события. + +Каждая транзакция состоит из 5 этапов: + +1. **Фаза хранения** - на этой фазе рассчитывается плата за хранение, накопленная контрактом за занятие некоторого пространства в состоянии цепочки. Подробнее читайте в разделе [Плата за хранение] (/develop/smart-contracts/fees#storage-fee). +2. **Фаза кредитования** - на этой фазе рассчитывается баланс контракта в отношении (возможного) значения входящего сообщения и собранной платы за хранение. +3. **Фаза вычисления** - на этой фазе TVM выполняет контракт (см. ниже), и результатом выполнения контракта является агрегирование `exit_code`, `actions` (сериализованный список действий), `gas_details`, `new_storage` и некоторых других. +4. **Фаза действий** - если фаза вычислений прошла успешно, на этой фазе обрабатываются `действия`, полученные на фазе вычислений. В частности, действия могут включать отправку сообщений, обновление кода смарт-контракта, обновление библиотек и т.д. Обратите внимание, что некоторые действия могут быть неудачными во время обработки (например, если мы попытаемся отправить сообщение с большим количеством TON, чем есть у контракта), в этом случае вся транзакция может быть отменена или это действие может быть пропущено (это зависит от режима действий, другими словами, контракт может отправить сообщение типа `send-or-revert или `try-send-if-no-ignore\`). +5. **Фаза отскока** - если фаза вычисления завершилась неудачно (вернула `exit_code >= 2`), в этой фазе формируется _отскок сообщения_ для транзакций, инициированных входящим сообщением. + +## Вычислите фазу + +В этой фазе происходит выполнение TVM. + +### Состояние TVM + +В любой момент времени состояние TVM полностью определяется 6 свойствами: + +- Стек (см. ниже) +- Управляющие регистры - (см. ниже), проще говоря, это до 16 переменных, которые можно напрямую устанавливать и считывать во время выполнения. +- Текущее продолжение - объект, описывающий выполняемую в данный момент последовательность инструкций +- Текущая кодовая страница - простыми словами, это означает версию TVM, которая запущена в данный момент +- Лимиты газа - набор из 4 целых значений; текущий лимит газаgl, максимальный лимит газа gm, остаток газаgr и кредит газа gc +- Библиотечный контекст - хэшмап библиотек, которые могут быть вызваны TVM + +### TVM - это стековая машина + +TVM - это стековая машина с последним входом и первым выходом. Всего существует 7 типов переменных, которые могут храниться в стеке - три неклеточных типа: + +- Integer - подписанные 257-битные целые числа +- Кортеж - упорядоченная коллекция, включающая до 255 элементов с произвольными типами значений, возможно, различных. +- Null + +И четыре разных вкуса клеток: + +- Ячейка - базовая (возможно, вложенная) непрозрачная структура, используемая блокчейном TON для хранения всех данных +- Slice - специальный объект, который позволяет Вам читать из ячейки +- Конструктор - специальный объект, который позволяет Вам создавать новые ячейки +- Продолжение - специальный объект, который позволяет Вам использовать ячейку в качестве источника инструкций TVM + +### Регистры управления + +- `c0` - Содержит следующее продолжение или продолжение возврата (аналогично адресу возврата подпрограммы в обычных конструкциях). Это значение должно быть продолжением. +- `c1` - Содержит альтернативное (возвратное) продолжение; это значение должно быть продолжением. +- `c2` - Содержит обработчик исключений. Это значение представляет собой Продолжение, вызываемое всякий раз, когда срабатывает исключение. +- `c3` - Поддерживающий регистр, содержит текущий словарь, по сути, хэшмап, содержащий код всех функций, используемых в программе. Это значение должно быть продолжением. +- `c4` - Содержит корень постоянных данных, или просто раздел `data` контракта. Это значение представляет собой ячейку. +- `c5` - Содержит выходные действия. Это значение представляет собой ячейку. +- `c7` - Содержит корень временных данных. Это кортеж. + +### Инициализация TVM + +TVM инициализируется, когда транзакция переходит в фазу Вычисления, и затем выполняет команды (опкоды) из _Текущего продолжения_ до тех пор, пока не останется команд для выполнения (и продолжения для возвратных переходов). + +Подробное описание процесса инициализации можно найти здесь: [Инициализация TVM](/learn/tvm-instructions/tvm-initialization.md) + +## Инструкции TVM + +Список инструкций TVM можно найти здесь: [Инструкции TVM](/learn/tvm-instructions/instructions). + +### Результат выполнения TVM + +Помимо кода выхода (exit_code) и данных о потребленном газе, TVM косвенно выводит следующие данные: + +- c4 регистр - ячейка, которая будет сохранена как новые `данные` смарт-контракта (если выполнение не будет отменено на этой или последующих фазах) +- c5 register - (список действий на выходе) ячейка с последним действием в списке и ссылка на ячейку с предыдущим действием (рекурсивно) + +Все остальные значения регистров будут игнорироваться. + +Обратите внимание, что поскольку существует ограничение на максимальную глубину ячеек `<1024`, и особенно ограничение на глубину c4 и c5 `<=512`, будет существовать ограничение на количество выходных действий в одной tx `<=255`. Если контракту нужно отправить больше, он может послать сообщение с запросом `continue_sending` самому себе и отправить все необходимые сообщения в последующих транзакциях. + +## См. также + +- [Инструкции TVM](/learn/tvm-instructions/instructions) +- [TON TVM](https://ton.org/tvm.pdf) Концепции TVM (может содержать устаревшую информацию) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/participate/README.md b/i18n/ru/docusaurus-plugin-content-docs/current/participate/README.md new file mode 100644 index 0000000000..ce6f728345 --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/participate/README.md @@ -0,0 +1,38 @@ +# Обзор + +Раздел "Участвовать" нашей документации предназначен для того, чтобы пользователи могли открыть для себя возможности работы с TON +Он также призван предложить основные механизмы (explorers, wallets, TEPs), которые необходимы для участия в экосистеме TON и создании концепции TON для TON World Wide Web (TWWW). + +## Участвуйте в экосистеме TON + +- [TON Explorers](/participate/explorers) +- [Приложения для кошельков (для разработчиков)](/participate/wallets/apps) +- [Типы контрактов кошелька](/participate/wallets/contracts) + +### Присоединяйтесь к сообществу TON + +- [TON Enhancement Proposals (TEPs)](https://github.com/ton-blockchain/TEPs) +- [Откройте для себя инновации TON на сайте TON Research](https://tonresear.ch/) +- [Ставка с номинантами TON](/participate/network-maintenance/nominators) + +### Мосты + +- [Обзор мостов](/participate/crosschain/overview) +- [Адреса мостов] (/participate/crosschain/bridge-addresses) + +### Запустите узел + +- [Узнайте о типах узлов в TON] (/participate/nodes/node-types) +- [Запустите свой полный узел или валидатор] (/participate/run-nodes/full-node) +- [Обслуживание и безопасность валидатора TON] (/participate/nodes/node-maintenance-and-security) + +## Участвуйте в TON Web3 + +- [TON Web3 Overview](/participate/web3/overview) +- [Используйте TON DNS для своих доменов](/participate/web3/dns) +- [Управление сайтами и доменами](/participate/web3/site-management) +- [\[Tutorial\] Как запустить свой собственный TON-сайт?](/develop/dapps/tutorials/how-to-run-ton-site) + +### TON Proxy + +- [Как открыть любой сайт TON?] (/participate/web3/how-to-open-any-ton-site) diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/participate/crosschain/overview.md b/i18n/ru/docusaurus-plugin-content-docs/current/participate/crosschain/overview.md new file mode 100644 index 0000000000..e6ed75df04 --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/participate/crosschain/overview.md @@ -0,0 +1,57 @@ +# Межцепочечные мостики + +Децентрализованные межцепочечные мосты работают на блокчейне TON Blockchain, позволяя Вам переводить активы с блокчейна TON Blockchain на другие блокчейны и наоборот. + +## Тонкоинский мост + +Мост Toncoin позволяет Вам переводить Toncoin между блокчейном TON и блокчейном Ethereum, а также между блокчейном TON и смарт-цепочкой BNB. + +Мост управляется [децентрализованными оракулами](/participate/crosschain/bridge-addresses). + +### Как его использовать? + +Фронтенд Bridge размещен на сайте https://ton.org/bridge. + +:::info +[Исходный код фронтенда Bridge](https://github.com/ton-blockchain/bridge) +::: + +### Исходные коды смарт-контрактов TON-Ethereum + +- [FunC (сторона TON)](https://github.com/ton-blockchain/bridge-func) +- [Solidity (сторона Ethereum)](https://github.com/ton-blockchain/bridge-solidity/tree/eth_mainnet) + +### Исходные коды смарт-контрактов TON-BNB Smart Chain + +- [FunC (сторона TON)](https://github.com/ton-blockchain/bridge-func/tree/bsc) +- [Solidity (BSC side)](https://github.com/ton-blockchain/bridge-solidity/tree/bsc_mainnet) + +### Конфиги блокчейна + +Вы можете получить фактические адреса смарт-контрактов моста и адреса оракулов, просмотрев соответствующий конфиг: + +TON-Ethereum: [#71](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L738). + +TON-BSC: [#72](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L739). + +TON-Polygon: [#73](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L740). + +### Документация + +- [Как работает мост](https://github.com/ton-blockchain/TIPs/issues/24) + +### Дорожная карта межцепочечного взаимодействия + +- https://t.me/tonblockchain/146 + +## Мост Тонана + +### Как принять участие? + +:::caution проект\ +Это концептуальная статья. Мы все еще ищем кого-то опытного для ее написания. +::: + +Вы можете найти фронт-энд здесь: https://tonana.org/. + +Исходный код находится здесь: https://github.com/tonanadao diff --git a/i18n/ru/docusaurus-plugin-content-docs/current/participate/web3/overview.mdx b/i18n/ru/docusaurus-plugin-content-docs/current/participate/web3/overview.mdx new file mode 100644 index 0000000000..e774ee00b5 --- /dev/null +++ b/i18n/ru/docusaurus-plugin-content-docs/current/participate/web3/overview.mdx @@ -0,0 +1,17 @@ +# Обзор + +## Концепции + +Подробнее об идеях читайте в: + +- [Выплаты на TON](https://blog.ton.org/ton-payments) +- [TON DNS & Domains](/participate/web3/dns) +- [Сайты TON, TON WWW и TON Proxy](https://blog.ton.org/ton-sites) + +## Примеры использования + +- [\*.ton удобные домены для любого смарт-контракта](/participate/web3/dns) +- [Подключение к сайтам TON с помощью прокси-сервера TON] (/participate/web3/setting-proxy) +- [Запустите собственный TON-прокси для подключения к сайтам TON] (/participate/web3/sites-and-proxy) +- [Привяжите Ваш кошелек TON или сайт TON к домену](/participate/web3/site-management) +- [Как создать поддомен с помощью смарт-контрактов TON DNS](/participate/web3/site-management#how-to-set-up-subdomains) diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md b/i18n/uk/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md new file mode 100644 index 0000000000..e70c35b5e9 --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/contribute/localization-program/overview.md @@ -0,0 +1,39 @@ +# Програма локалізації + +Програма перекладу - це спільна робота над перекладом різних документів, пов'язаних з ТОН, на різні мови, що робить веб-сайт більш доступним для мільярдів неангломовних людей у всьому світі. + +## Філософія системного дизайну + +![як це працює](/img/localizationProgramGuideline/localization-program.png) + +Програму локалізації започаткувала та активно підтримує [**TownSquare Labs**] (https://github.com/TownSquareXYZ), один з найближчих партнерів **TON**. + +Ми прагнемо створити відкриту інфраструктуру для співпраці багатомовних спільнот, щоб **просунути TON до кращої фази**, що включає в себе + +1. **Підходить для багатомовних спільнот**\ + Програма підтримує кілька мов, забезпечуючи інклюзивність та легкий доступ для користувачів з різним мовним досвідом. + +2. **Автоматизуйте розробку, інтеграцію та розгортання**\ + Завдяки використанню інструментів автоматизації програма впорядковує процеси розробки, інтеграції та розгортання, зменшуючи ручну працю та підвищуючи ефективність і узгодженість усіх зусиль з локалізації. + +3. **Розмежування ролей розробника, перекладача та верифікатора**\ + Наш підхід розмежовує обов'язки розробників, перекладачів і верифікаторів, дозволяючи кожній ролі зосередитися на своїх конкретних завданнях. Це забезпечує високу якість перекладів і злагоджену співпрацю без дублювання або конфлікту обов'язків. + +4. **Заохочення за внесок громади**\ + Ми надаємо заохочення членам громади, які роблять внесок у процес локалізації. Це заохочує активну участь і винагороджує тих, хто допомагає покращити програму, сприяючи формуванню почуття причетності та духу спільноти. + +5. **Інтеграція передових систем штучного інтелекту**\ + Передові системи штучного інтелекту підвищують точність і ефективність перекладу, надаючи інтелектуальні пропозиції й автоматизуючи повторювані завдання, забезпечуючи якісні результати з меншими зусиллями. + +Цей проект не лише для носіїв однієї мови; наша мета - служити глобальній екосистемі розробників. + +## Подяки + +Ми дуже вдячні тисячам членів спільноти, які є ключовою частиною Перекладацької програми. Ми хочемо відзначити наших перекладачів і підтримати їх на їхньому кар'єрному шляху. Найближчим часом ми відзначимо наших найкращих перекладачів, створивши таблиці лідерів і список усіх, хто долучився до перекладацької програми. + +## Посібники та ресурси + +Якщо ви робите свій внесок у Програму перекладу або плануєте долучитися до неї, будь ласка, ознайомтеся з настановами для перекладачів, наведеними нижче: + +- [**Посібник зі стилю перекладу**](/contribute/localization-program/translation-style-guide) - Інструкції та поради для перекладачів. +- [**Посібник з онлайн-редактора Crowdin**](https://support.crowdin.com/online-editor/) - детальний посібник з використання онлайн-редактора Crowdin та деяких додаткових можливостей Crowdin. diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md b/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md new file mode 100644 index 0000000000..64d7d9a063 --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/README.md @@ -0,0 +1,587 @@ +import Button from '@site/src/components/button' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Обробка платежів + +Ця сторінка пояснює, як обробляти\*\* (відправляти і приймати) "цифрові активи" в блокчейні TON. +В основному тут описано, як працювати з монетами TON, але теоретична частина важлива, навіть якщо ви хочете обробляти тільки джеттони. + +## Смарт-контракт гаманця + +Смарт-контракти гаманців - це контракти в мережі TON, які слугують для того, щоб дозволити суб'єктам за межами блокчейну взаємодіяти з об'єктами блокчейну. Загалом, вони вирішують три завдання: + +- аутентифікує власника: Відмовляється обробляти та сплачувати збори за запити невласників. +- захист від повторів: Забороняє повторне виконання одного запиту, наприклад, надсилання активів іншому смарт-контракту. +- ініціює довільну взаємодію з іншими смарт-контрактами. + +Стандартним рішенням для першої проблеми є криптографія з відкритим ключем: "гаманець" зберігає відкритий ключ і перевіряє, що вхідне повідомлення із запитом підписане відповідним закритим ключем, який відомий лише власнику. + +Вирішення третьої проблеми також є поширеним: зазвичай запит містить повністю сформоване внутрішнє повідомлення, яке "гаманець" надсилає в мережу. Однак, для захисту від повторного відтворення існує декілька різних підходів. + +### Гаманці на основі Seqno + +Гаманці на основі Seqno використовують найпростіший підхід до впорядкування повідомлень. Кожне повідомлення має спеціальне ціле число `seqno`, яке повинно збігатися з лічильником, що зберігається в смарт-контракті `гаманця`. Гаманець оновлює свій лічильник при кожному запиті, таким чином гарантуючи, що один запит не буде оброблений двічі. Існує кілька версій "гаманця", які відрізняються загальнодоступними методами: можливість обмежувати запити за часом дії та можливість мати кілька гаманців з одним і тим же публічним ключем. Однак, невід'ємною вимогою такого підходу є надсилання запитів по одному, оскільки будь-яка прогалина в послідовності `seqno` призведе до неможливості обробки всіх наступних запитів. + +### Гаманці з високим навантаженням + +Цей тип "гаманця" використовує підхід, заснований на зберіганні ідентифікатора оброблених запитів, термін дії яких не закінчився, у сховищі смарт-контрактів. У цьому підході будь-який запит перевіряється на наявність дублікату вже обробленого запиту і, якщо виявлено повторення, відхиляється. Через закінчення терміну дії контракт не може зберігати всі запити вічно, але він буде видаляти ті, які не можуть бути оброблені через обмеження терміну дії. Запити до цього "гаманця" можуть надсилатися паралельно, не заважаючи один одному, але такий підхід вимагає більш складного моніторингу обробки запитів. + +### Розгортання гаманця + +Для розгортання гаманця через TonLib потрібно зробити наступне: + +1. Згенеруйте пару приватний/відкритий ключ за допомогою [createNewKey](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L244) або його функцій-обгорток (приклад у [tonlib-go](https://github.com/mercuryoio/tonlib-go/tree/master/v2#create-new-private-key)). Зверніть увагу, що приватний ключ генерується локально і не залишає хост-машину. +2. Сформуйте структуру [InitialAccountWallet](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L62), що відповідає одному з увімкнених `гаманців`. Наразі доступні `wallet.v3`, `wallet.v4`, `wallet.highload.v1`, `wallet.highload.v2`. +3. Обчисліть адресу нового смарт-контракту `гаманця` за допомогою методу [getAccountAddress](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L283). Ми рекомендуємо використовувати ревізію за замовчуванням `0`, а також розгортати гаманці в базовому ланцюжку `workchain=0` для зниження витрат на обробку та зберігання. +4. Надішліть трохи Toncoin на розраховану адресу. Зверніть увагу, що ви повинні відправити їх в режимі `non-bounce`, оскільки ця адреса ще не має коду і не може обробляти вхідні повідомлення. Прапорець `non-bounce` вказує на те, що навіть у разі невдалої обробки, гроші не повинні повертатися з повідомленням про відмову. Ми не рекомендуємо використовувати прапорець `non-bounce` для інших транзакцій, особливо при переказі великих сум, оскільки механізм відмов забезпечує певний захист від помилок. +5. Сформуйте потрібну [action](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L154), наприклад, `actionNoop` тільки для розгортання. Потім використовуйте [createQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L292) і [sendQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L300), щоб ініціювати взаємодію з блокчейном. +6. Перевірте контракт за кілька секунд за допомогою методу [getAccountState](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L288). + +:::tip +Дізнайтеся більше в [Навчальному посібнику з гаманця] (/develop/smart-contracts/tutorials/wallet#-deploying-a-wallet) +::: + +### Перевірте дійсність адреси гаманця + +Більшість SDK вимагають верифікації адреси (більшість перевіряє її під час створення гаманця або підготовки транзакції), тому, як правило, це не вимагає від вас ніяких додаткових складних кроків. + + + + + +```js + const TonWeb = require("tonweb") + TonWeb.utils.Address.isValid('...') +``` + + + + +```python +package main + +import ( + "fmt" + "github.com/xssnick/tonutils-go/address" +) + +if _, err := address.ParseAddr("EQCD39VS5j...HUn4bpAOg8xqB2N"); err != nil { + return errors.New("invalid address") +} +``` + + + + +```javascript +try { + Address.of("..."); + } catch (e) { + // not valid address +} +``` + + + + +```javascript + try { + AddrStd("...") + } catch(e: IllegalArgumentException) { + // not valid address + } +``` + + + + +:::tip +Повний опис адрес на сторінці [Адреси смарт-контрактів](/learn/overviews/addresses). +::: + +## Робота з переказами + +### Перевірте транзакції за контрактом + +Транзакції контракту можна отримати за допомогою [getTransactions](https://toncenter.com/api/v2/#/accounts/get_transactions_getTransactions_get). Цей метод дозволяє отримати 10 транзакцій, починаючи з деякого `last_transaction_id` і раніше. Щоб обробити всі отримані транзакції, слід виконати наступні кроки: + +1. Останній `last_transaction_id` можна отримати за допомогою [getAddressInformation](https://toncenter.com/api/v2/#/accounts/get_address_information_getAddressInformation_get) +2. Список з 10 транзакцій повинен бути завантажений за допомогою методу `getTransactions`. +3. Обробляти транзакції з не порожнім джерелом у вхідному повідомленні та призначенням, що дорівнює адресі акаунта. +4. Завантажте наступні 10 транзакцій і повторіть кроки 2,3,4,5, поки не обробите всі вхідні транзакції. + +### Отримуйте вхідні/вихідні транзакції + +Під час обробки транзакцій можна відстежувати потік повідомлень. Оскільки потік повідомлень є DAG, достатньо отримати поточну транзакцію методом [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) і знайти вхідну транзакцію за `out_msg` за допомогою [tryLocateResultTx](https://testnet.toncenter.com/api/v2/#/transactions/get_try_locate_result_tx_tryLocateResultTx_get) або вихідну за `in_msg` за допомогою [tryLocateSourceTx](https://testnet.toncenter.com/api/v2/#/transactions/get_try_locate_source_tx_tryLocateSourceTx_get). + + + + +```ts +import { TonClient, Transaction } from '@ton/ton'; +import { getHttpEndpoint } from '@orbs-network/ton-access'; +import { CommonMessageInfoInternal } from '@ton/core'; + +async function findIncomingTransaction(client: TonClient, transaction: Transaction): Promise { + const inMessage = transaction.inMessage?.info; + if (inMessage?.type !== 'internal') return null; + return client.tryLocateSourceTx(inMessage.src, inMessage.dest, inMessage.createdLt.toString()); +} + +async function findOutgoingTransactions(client: TonClient, transaction: Transaction): Promise { + const outMessagesInfos = transaction.outMessages.values() + .map(message => message.info) + .filter((info): info is CommonMessageInfoInternal => info.type === 'internal'); + + return Promise.all( + outMessagesInfos.map((info) => client.tryLocateResultTx(info.src, info.dest, info.createdLt.toString())), + ); +} + +async function traverseIncomingTransactions(client: TonClient, transaction: Transaction): Promise { + const inTx = await findIncomingTransaction(client, transaction); + // now you can traverse this transaction graph backwards + if (!inTx) return; + await traverseIncomingTransactions(client, inTx); +} + +async function traverseOutgoingTransactions(client: TonClient, transaction: Transaction): Promise { + const outTxs = await findOutgoingTransactions(client, transaction); + // do smth with out txs + for (const out of outTxs) { + await traverseOutgoingTransactions(client, out); + } +} + +async function main() { + const endpoint = await getHttpEndpoint({ network: 'testnet' }); + const client = new TonClient({ + endpoint, + apiKey: '[API-KEY]', + }); + + const transaction: Transaction = ...; // Obtain first transaction to start traversing + await traverseIncomingTransactions(client, transaction); + await traverseOutgoingTransactions(client, transaction); +} + +main(); +``` + + + + +### Надсилайте платежі + +1. Сервіс повинен розгорнути "гаманець" і підтримувати його фінансування, щоб запобігти розірванню контракту через плату за зберігання. Зауважте, що плата за зберігання зазвичай становить менше 1 тонкоїна на рік. +2. Сервіс повинен отримувати від користувача `адреса_призначення` та необов'язковий `коментар`. Зауважте, що поки що ми рекомендуємо або заборонити незавершені вихідні платежі з однаковим набором (`адреса_призначення`, `вартість`, `коментар`), або правильно розпланувати ці платежі - так, щоб наступний платіж ініціювався лише після підтвердження попереднього. +3. Сформуйте [msg.dataText](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L103) з `comment` як текстом. +4. Сформуйте [msg.message](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L113), що містить `адресу_одержувача`, порожній `публічний_ключ`, `суму` та `msg.dataText`. +5. Форма [Дія](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L154), яка містить набір вихідних повідомлень. +6. Для відправки вихідних платежів використовуйте запити [createQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L292) та [sendQuery](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L300). +7. Сервіс повинен регулярно опитувати метод [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) для контракту `гаманця`. Зіставлення підтверджених транзакцій з вихідними платежами за (`адреса_призначення`, `вартість`, `коментар`) дозволяє позначати платежі як завершені; визначати та показувати користувачеві відповідний хеш транзакції та lt (логічний час). +8. Запити до `v3` гаманців з високим навантаженням за замовчуванням мають термін дії, що дорівнює 60 секундам. Після закінчення цього часу необроблені запити можуть бути безпечно відправлені в мережу (див. кроки 3-6). + +### Отримати ідентифікатор транзакції + +Може бути незрозуміло, що для отримання додаткової інформації про транзакцію користувач повинен просканувати блокчейн за допомогою функції [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get). +Неможливо отримати ідентифікатор транзакції одразу після відправлення повідомлення, оскільки транзакція повинна бути підтверджена мережею блокчейн. +Щоб зрозуміти необхідний конвеєр, уважно прочитайте [Send payments](https://docs.ton.org/develop/dapps/asset-processing/#send-payments), особливо 7-й пункт. + +## Підхід на основі рахунків-фактур + +Щоб приймати платежі на основі прикріплених коментарів, сервіс повинен + +1. Розгорніть контракт "гаманця". +2. Згенеруйте унікальний `invoice` для кожного користувача. Рядкового представлення uuid32 буде достатньо. +3. Користувачам слід проінструктувати, щоб вони надсилали Toncoin на контракт "гаманця" сервісу з прикріпленим "рахунком-фактурою" в якості коментаря. +4. Сервіс повинен регулярно опитувати метод [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get) для контракту `гаманця`. +5. Для нових транзакцій вхідне повідомлення має бути витягнуто, `коментар` перевірено за базою даних, а **значення вхідного повідомлення** занесено до облікового запису користувача. + +Щоб обчислити **значення вхідного повідомлення**, яке повідомлення приносить контракту, потрібно розібрати транзакцію. Це відбувається, коли повідомлення потрапляє в контракт. Транзакцію можна отримати за допомогою [getTransactions](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L268). Для вхідної транзакції гаманця правильні дані складаються з одного вхідного повідомлення і нуля вихідних повідомлень. В іншому випадку, або на гаманець надсилається зовнішнє повідомлення, і тоді власник витрачає Toncoin, або гаманець не розгортається і вхідна транзакція повертається назад. + +Так чи інакше, в загальному випадку суму, яку приносить повідомлення в контракт, можна розрахувати як вартість вхідного повідомлення мінус сума вартостей вихідних повідомлень мінус комісія: `value_{in_msg} - SUM(value_{out_msg}) - fee`. Технічно представлення транзакції містить три різних поля з `fee` в назві: `fee`, `storage_fee` та `other_fee`, тобто загальну комісію, частину комісії, пов'язану з витратами на зберігання, та частину комісії, пов'язану з обробкою транзакції. Використовувати слід тільки першу з них. + +### Інвойси з TON Connect + +Найкраще підходить для dApps, яким потрібно підписувати кілька платежів/транзакцій протягом сесії або підтримувати з'єднання з гаманцем протягом певного часу. + +- ✅ Є постійний канал зв'язку з гаманцем, інформація про адресу користувача + +- ✅ Користувачам потрібно відсканувати QR-код лише один раз + +- ✅ Можна дізнатися, чи підтвердив користувач транзакцію в гаманці, відстежити транзакцію за поверненою BOC + +- ✅ Готові SDK та набори інтерфейсів доступні для різних платформ + +- ❌ Якщо потрібно відправити лише один платіж, користувачеві потрібно виконати дві дії: підключити гаманець і підтвердити транзакцію + +- ❌ Інтеграція складніша, ніж посилання ton:// + +```mdx-code-block + +``` + +### Інвойси з посиланням ton:// + +:::warning +Посилання Ton застаріле, не використовуйте його +::: + +Якщо вам потрібна легка інтеграція для простого потоку користувачів, підійде посилання ton://. +Найкраще підходить для одноразових платежів та інвойсів. + +```bash +ton://transfer/? + [nft=&] + [fee-amount=&] + [forward-amount=] +``` + +- ✅ Легка інтеграція + +- ✅ Не потрібно підключати гаманець + +- ❌ Користувачі повинні сканувати новий QR-код для кожного платежу + +- ❌ Неможливо відстежити, чи підписав користувач транзакцію чи ні + +- ❌ Немає інформації про адресу користувача + +- ❌ Обхідні шляхи потрібні на платформах, де такі посилання не можна натискати (наприклад, повідомлення від ботів для десктопних клієнтів Telegram) + +[Дізнайтеся більше про тонни посилань тут] (https://github.com/tonkeeper/wallet-api#payment-urls) + +## Дослідники + +Дослідник блокчейну - https://tonscan.org. + +Щоб згенерувати посилання на транзакцію в провіднику, сервіс має отримати lt (логічний час), хеш транзакції та адресу акаунта (адресу акаунта, для якого lt і txhash було отримано за допомогою методу [getTransactions](https://toncenter.com/api/v2/#/transactions/get_transactions_getTransactions_get)). https://tonscan.org і https://explorer.toncoin.org/ можуть показати сторінку для цього tx у наступному форматі: + +`https://tonviewer.com/transaction/{txhash as base64url}` + +`https://tonscan.org/tx/{lt as int}:{txhash as base64url}:{account address}` + +`https://explorer.toncoin.org/transaction?account={account address}<={lt as int}&hash={txhash as base64url}`. + +## Найкращі практики + +### Створення гаманця + + + + +- **toncenter:** + - [Створення гаманця + отримання адреси гаманця](https://github.com/toncenter/examples/blob/main/common.js) + +- **тон-спільнота/тон:**. + - [Створення гаманця + отримання балансу](https://github.com/ton-community/ton#usage) + + + + + +- **xssnick/tonutils-go:** + - [Створення гаманця + отримання балансу](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#wallet) + + + + + +- **psylopunk/pythonlib:** + - [Створення гаманця + отримання адреси гаманця](https://github.com/psylopunk/pytonlib/blob/main/examples/generate_wallet.py) +- **юнгвин/пітонік:** + +```py +import asyncio + +from pytoniq.contract.wallets.wallet import WalletV4R2 +from pytoniq.liteclient.balancer import LiteBalancer + + +async def main(): + provider = LiteBalancer.from_mainnet_config(2) + await provider.start_up() + + mnemonics, wallet = await WalletV4R2.create(provider) + print(f"{wallet.address=} and {mnemonics=}") + + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + + + + +### Депозити в тонкоїнах (отримати тонкоїни) + + + + +- **toncenter:** + - [Обробка депозиту Toncoins](https://github.com/toncenter/examples/blob/main/deposits.js) + - [Процес поповнення мультигаманців Toncoins](https://github.com/toncenter/examples/blob/main/deposits-multi-wallets.js) + + + + + +- **xssnick/tonutils-go:** + +
+Перевірка депозитів + +```go +package main + +import ( + "context" + "encoding/base64" + "log" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/liteclient" + "github.com/xssnick/tonutils-go/ton" +) + +const ( + num = 10 +) + +func main() { + client := liteclient.NewConnectionPool() + err := client.AddConnectionsFromConfigUrl(context.Background(), "https://ton.org/global.config.json") + if err != nil { + panic(err) + } + + api := ton.NewAPIClient(client, ton.ProofCheckPolicyFast).WithRetry() + + accountAddr := address.MustParseAddr("0QA__NJI1SLHyIaG7lQ6OFpAe9kp85fwPr66YwZwFc0p5wIu") + + // we need fresh block info to run get methods + b, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + log.Fatal(err) + } + + // we use WaitForBlock to make sure block is ready, + // it is optional but escapes us from liteserver block not ready errors + res, err := api.WaitForBlock(b.SeqNo).GetAccount(context.Background(), b, accountAddr) + if err != nil { + log.Fatal(err) + } + + lastTransactionId := res.LastTxHash + lastTransactionLT := res.LastTxLT + + headSeen := false + + for { + trxs, err := api.ListTransactions(context.Background(), accountAddr, num, lastTransactionLT, lastTransactionId) + if err != nil { + log.Fatal(err) + } + + for i, tx := range trxs { + // should include only first time lastTransactionLT + if !headSeen { + headSeen = true + } else if i == 0 { + continue + } + + if tx.IO.In == nil || tx.IO.In.Msg.SenderAddr().IsAddrNone() { + // external message should be omitted + continue + } + + if tx.IO.Out != nil { + // no outgoing messages - this is incoming Toncoins + continue + } + + // process trx + log.Printf("found in transaction hash %s", base64.StdEncoding.EncodeToString(tx.Hash)) + } + + if len(trxs) == 0 || (headSeen && len(trxs) == 1) { + break + } + + lastTransactionId = trxs[0].Hash + lastTransactionLT = trxs[0].LT + } +} +``` + +
+
+ + + +- **юнгвин/пітонік:** + +Перевірка депозитів + +```python +import asyncio + +from pytoniq_core import Transaction + +from pytoniq import LiteClient, Address + +MY_ADDRESS = Address("kf8zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM_BP") + + +async def main(): + client = LiteClient.from_mainnet_config(ls_i=0, trust_level=2) + + await client.connect() + + last_block = await client.get_trusted_last_mc_block() + + _account, shard_account = await client.raw_get_account_state(MY_ADDRESS, last_block) + assert shard_account + + last_trans_lt, last_trans_hash = ( + shard_account.last_trans_lt, + shard_account.last_trans_hash, + ) + + while True: + print(f"Waiting for{last_block=}") + + transactions = await client.get_transactions( + MY_ADDRESS, 1024, last_trans_lt, last_trans_hash + ) + toncoin_deposits = [tx for tx in transactions if filter_toncoin_deposit(tx)] + print(f"Got {len(transactions)=} with {len(toncoin_deposits)=}") + + for deposit_tx in toncoin_deposits: + # Process toncoin deposit transaction + print(deposit_tx.cell.hash.hex()) + + last_trans_lt = transactions[0].lt + last_trans_hash = transactions[0].cell.hash + + +def filter_toncoin_deposit(tx: Transaction): + if tx.out_msgs: + return False + + if tx.in_msg: + return False + + return True + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + +
+ +### Виведення токенів (надсилання токенів) + + + + +- **toncenter:** + - [Виводьте тонкоїни з гаманця партіями](https://github.com/toncenter/examples/blob/main/withdrawals-highload-batch.js) + - [Вивести тонкоїни з гаманця](https://github.com/toncenter/examples/blob/main/withdrawals-highload.js) + +- **тон-спільнота/тон:**. + - [Вивести тонкоїни з гаманця](https://github.com/ton-community/ton#usage) + + + + + +- **xssnick/tonutils-go:** + - [Вивести тонкоїни з гаманця](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#wallet) + + + + + +- **psylopunk/pythonlib:** + - [Вивести тонкоїни з гаманця](https://github.com/psylopunk/pytonlib/blob/main/examples/transactions.py) + +- **юнгвин/пітонік:** + +```python +import asyncio + +from pytoniq_core import Address +from pytoniq.contract.wallets.wallet import WalletV4R2 +from pytoniq.liteclient.balancer import LiteBalancer + + +MY_MNEMONICS = "one two tree ..." +DESTINATION_WALLET = Address("Destination wallet address") + + +async def main(): + provider = LiteBalancer.from_mainnet_config() + await provider.start_up() + + wallet = await WalletV4R2.from_mnemonic(provider, MY_MNEMONICS) + + await wallet.transfer(DESTINATION_WALLET, 5) + + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + + + + + +### Отримуйте транзакції за контрактом + + + + +- **тон-спільнота/тон:**. + - [Клієнт з методом getTransaction](https://github.com/ton-community/ton/blob/master/src/client/TonClient.ts) + + + + + +- **xssnick/tonutils-go:** + - [Отримати транзакції](https://github.com/xssnick/tonutils-go?tab=readme-ov-file#account-info-and-transactions) + + + + + +- **psylopunk/pythonlib:** + - [Отримати транзакції](https://github.com/psylopunk/pytonlib/blob/main/examples/transactions.py) +- **юнгвин/пітонік:** + - [Отримати транзакції](https://github.com/yungwine/pytoniq/blob/master/examples/transactions.py) + + + + + +## SDK + +Список SDK для різних мов (JS, Python, Golang, C#, Rust і т.д.) можна знайти [тут](/develop/dapps/apis/sdk). diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md b/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md new file mode 100644 index 0000000000..48823b983f --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/jettons.md @@ -0,0 +1,1205 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import Button from '@site/src/components/utton'; + +# Переробка TON Jetton + +:::info +Для чіткого розуміння читач повинен бути знайомий з основними принципами обробки активів, описаними в [розділі обробки платежів] (/develop/dapps/asset-processing/) нашої документації. +::: + +Джеттони - це токени в блокчейні TON - їх можна розглядати аналогічно токенам ERC-20 в Ethereum. + +У цьому аналізі ми заглиблюємося у формальні стандарти, що детально описують поведінку джеттонів (https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) та їхні метадані (https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md). +Менш формальний огляд архітектури джеттонів, зосереджений на шардингу, можна знайти у нашому блозі +[анатомія джеттонів](https://blog.ton.org/how-to-shard-your-ton-smart-contract-and-why-studying-the-anatomy-of-tons-jettons). + +Також слід пам'ятати, що існує два підходи до роботи з джеттон-виводами: + +- [Memo Deposits] (https://github.com/toncenter/examples/blob/main/deposits-jettons.js) - дозволяє вести один депозитний гаманець, а користувачі додають записку, щоб бути ідентифікованими вашою системою. Це означає, що вам не потрібно сканувати весь блокчейн, але це трохи менш зручно для користувачів. +- [Депозити без авізо] (https://github.com/gobicycle/bicycle) - Це рішення також існує, але його складніше інтегрувати. Однак ми можемо допомогти вам з цим, якщо ви віддаєте перевагу цьому шляху. Будь ласка, повідомте нас перед тим, як прийняти рішення про застосування цього підходу. + +## Jetton Architecture + +Стандартизовані токени на TON реалізуються за допомогою набору смарт-контрактів, в тому числі: + +- [Jetton master](https://github.com/ton-blockchain/token-contract/blob/main/ft/jetton-minter.fc) смарт-контракт +- [Гаманець Jetton](https://github.com/ton-blockchain/token-contract/blob/main/ft/jetton-wallet.fc) смарт-контракти + +

+
+ contracts scheme +
+

+ +## Головний смарт-контракт Jetton + +Головний смарт-контракт джеттона зберігає загальну інформацію про джеттон (включаючи загальну пропозицію, посилання на метадані або самі метадані). + +:::warning Остерігайтеся шахрайства з Jetton + +Джеттони з символом `==`TON\`\` або ті, що містять системні повідомлення, такі як: +`ERROR`, `SYSTEM` та інші. Переконайтеся, що джеттони відображаються у вашому інтерфейсі таким чином, щоб їх не можна було +змішати з TON-передачами, системними повідомленнями тощо. Іноді навіть `символ`, `ім'я` та `зображення` +створюються майже ідентичними до оригіналу з надією ввести користувачів в оману. + +Щоб виключити можливість шахрайства для користувачів TON, будь ласка, шукайте **оригінальну адресу джеттона** (основний договір на джеттон) для конкретних типів джеттонів або **перейдіть на офіційний канал проекту в соціальних мережах** чи веб-сайт, щоб знайти **правильну інформацію**. Перевірте активи, щоб виключити можливість шахрайства за допомогою [Tonkeeper ton-assets list] (https://github.com/tonkeeper/ton-assets). +::: + +### Отримання даних Jetton + +Для отримання більш конкретних даних Jetton використовуйте метод *get* контракту `get_jetton_data()`. + +Цей метод повертає наступні дані: + +| Ім'я | Тип | Опис | +| ------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `total_supply` | `int` | загальна кількість випущених джеттонів, виміряна в неподільних одиницях. | +| "монетний двір". | `int` | деталізує, чи можна карбувати нові джеттони чи ні. Це значення дорівнює -1 (можна карбувати) або 0 (не можна карбувати). | +| `адреса_адміністратора` | "шматочок | | +| \`jetton_content | "Cell | дані відповідно до [TEP-64](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md), див. [сторінку розбору метаданих jetton](/develop/dapps/asset-processing/metadata) для отримання додаткової інформації. | +| `jetton_wallet_code` | "Cell | | + +Ви можете викликати його за допомогою [Toncenter API](https://toncenter.com/api/v3/#/default/get_jetton_masters_api_v3_jetton_masters_get) або одного з [SDK](https://docs.ton.org/develop/dapps/apis/sdk). + + + + +> Запустіть метод `jetton/masters` з [Toncenter API](https://toncenter.com/api/v3/#/default/get_jetton_masters_api_v3_jetton_masters_get) + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: ""}); +const data = await jettonMinter.getJettonData(); +console.log('Total supply:', data.totalSupply.toString()); +console.log('URI to off-chain metadata:', data.jettonContentUri); +``` + + + + +### Jetton minter + +Як згадувалося раніше, джеттони можуть бути як "карбованими", так і "некарбованими". + +Якщо вони не карбуються, логіка стає простою - немає можливості карбувати додаткові токени. Для того, щоб вперше покарбувати джеттони, зверніться до сторінки [Покарбуйте свій перший джеттон](/develop/dapps/tutorials/jetton-minter). + +Якщо джеттони можна карбувати, в [контракті з майнером] (https://github.com/ton-blockchain/minter-contract/blob/main/contracts/jetton-minter.fc) є спеціальна функція для карбування додаткових джеттонів. Цю функцію можна викликати, відправивши `внутрішнє повідомлення` з вказаним опкодом з адреси адміністратора. + +Якщо адміністратор джеттона хоче обмежити створення джеттонів, є три способи зробити це: + +1. Якщо ви не можете або не хочете оновлювати код контракту, адміністратор повинен передати право власності від поточного адміністратора на нульову адресу. Це призведе до того, що контракт залишиться без дійсного адміністратора, і ніхто не зможе карбувати джеттони. Однак, це також унеможливить будь-які зміни в метаданих джеттона. +2. Якщо у вас є доступ до вихідного коду і ви можете його змінити, ви можете створити в контракті метод, який встановлює прапорець для переривання будь-якого процесу карбування після його виклику, і додати оператор для перевірки цього прапорця в функцію карбування. +3. Якщо ви можете оновити код контракту, ви можете додати обмеження, оновивши код вже розгорнутого контракту. + +## Смарт-контракт гаманця Jetton + +Контракти `гаманця Джеттона` використовуються для **відправлення**, **отримання** та **спалювання** джеттонів. Кожен *контракт гаманця джеттона* зберігає інформацію про баланс гаманця для конкретних користувачів. +В окремих випадках джеттон-гаманці використовуються для окремих власників джеттонів для кожного типу джеттонів. + +"Гаманці джеттонів" **не слід плутати з гаманцями**, призначеними для взаємодії з блокчейном і зберігання +тільки активу Toncoin (наприклад, гаманці v3R2, гаманці з високим навантаженням та інші), +які відповідають за підтримку і управління **тільки певним типом джеттона**. + +### Розгортання гаманця Jetton + +При `передачі джеттонів` між гаманцями транзакції (повідомлення) вимагають певної суми TON +в якості оплати мережевих **платежів** і виконання дій відповідно до коду контракту гаманця Jetton. +Це означає, що **одержувачу не потрібно розгортати джеттон-гаманець перед отриманням джеттонів**. +Гаманець одержувача буде розгорнутий автоматично, якщо відправник має на гаманці достатню кількість TON +для сплати необхідних зборів за газ. + +### Отримання адрес гаманців Jetton для певного користувача + +Щоб отримати `адресу `гаманця Jetton`за допомогою`адреси власника`(адреси гаманця TON), +в`магістерському контракті Jetton`передбачено метод get`get_wallet_address(slice_address_власника)\`. + + + + +> Запустіть `get_wallet_address(slice owner_address)` за допомогою методу `/runGetMethod` з [Toncenter API](https://toncenter.com/api/v3/#/default/run_get_method_api_v3_runGetMethod_post). + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: ""}); +const address = await jettonMinter.getJettonWalletAddress(new TonWeb.utils.Address("")); +// It is important to always check that wallet indeed is attributed to desired Jetton Master: +const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider, { + address: jettonWalletAddress +}); +const jettonData = await jettonWallet.getData(); +if (jettonData.jettonMinterAddress.toString(false) !== new TonWeb.utils.Address(info.address).toString(false)) { + throw new Error('jetton minter address from jetton wallet doesnt match config'); +} + +console.log('Jetton wallet address:', address.toString(true, true, true)); +``` + + + + +### Отримання даних для конкретного гаманця Jetton + +Щоб отримати баланс рахунку гаманця, ідентифікаційну інформацію про власника та іншу інформацію, пов'язану з конкретним контрактом джеттон-гаманця, використовуйте метод get `get_wallet_data()` в контракті джеттон-гаманця. + +Цей метод повертає наступні дані: + +| Ім'я | Тип | +| -------------------- | -------- | +| "Баланс | int | +| "власник | шматочок | +| "Джеттон | шматочок | +| `jetton_wallet_code` | клітина | + + + + +> Використовуйте метод `/jetton/wallets` get з [Toncenter API](https://toncenter.com/api/v3/#/default/get_jetton_wallets_api_v3_jetton_wallets_get), щоб отримати раніше декодовані дані jetton-гаманців. + + + + + +```js +import TonWeb from "tonweb"; +const tonweb = new TonWeb(); +const walletAddress = "EQBYc3DSi36qur7-DLDYd-AmRRb4-zk6VkzX0etv5Pa-Bq4Y"; +const jettonWallet = new TonWeb.token.jetton.JettonWallet(tonweb.provider,{address: walletAddress}); +const data = await jettonWallet.getData(); +console.log('Jetton balance:', data.balance.toString()); +console.log('Jetton owner address:', data.ownerAddress.toString(true, true, true)); +// It is important to always check that Jetton Master indeed recognize wallet +const jettonMinter = new TonWeb.token.jetton.JettonMinter(tonweb.provider, {address: data.jettonMinterAddress.toString(false)}); +const expectedJettonWalletAddress = await jettonMinter.getJettonWalletAddress(data.ownerAddress.toString(false)); +if (expectedJettonWalletAddress.toString(false) !== new TonWeb.utils.Address(walletAddress).toString(false)) { + throw new Error('jetton minter does not recognize the wallet'); +} + +console.log('Jetton master address:', data.jettonMinterAddress.toString(true, true, true)); +``` + + + + +## Огляд комунікації гаманців Jetton + +Зв'язок між гаманцями Jetton і TON відбувається в наступній послідовності: + +![](/img/docs/asset-processing/jetton_transfer.svg) + +#### Повідомлення 0 + +`Відправник -> джеттон-гаманець відправника`. Повідомлення *Transfer* містить наступні дані: + +| Ім'я | Тип | Опис | +| ----------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `query_id` | uint64 | Дозволяє програмам зв'язувати між собою три типи повідомлень `Передача`, `Повідомлення про передачу` і `Перевищення`. Для коректного виконання цього процесу рекомендується **завжди використовувати унікальний ідентифікатор запиту**. | +| "сума | монети | Загальна сума "тонни монет", яка буде надіслана у повідомленні. | +| "місце призначення | адреса | Адреса нового власника джеттонів | +| `відповідь_призначення` | адреса | Адреса гаманця для повернення монет з повідомленням про надлишок. | +| `custom_payload` | можливо, в камері. | Розмір завжди >= 1 біт. Користувацькі дані (які використовуються джеттон-гаманцем відправника або одержувача для внутрішньої логіки). | +| `forward_ton_amount` | монети | Повинно бути > 0, якщо ви хочете надіслати `повідомлення про передачу` з `переадресованим корисним навантаженням`. Це \*\*частина значення `mount` і **повинна бути меншою за `mount`**. | +| `forward_payload` | можливо, в камері. | Розмір завжди >= 1 біт. Якщо перші 32 біти = 0x0, то це просте повідомлення. | + +#### Послання 2''. + +`Jetton гаманець одержувача -> одержувач`. Повідомлення про переказ. **Відправляється тільки якщо** `сума_переказу_тонн` **не нульова**. Містить наступні дані: + +| Ім'я | Тип | +| ----------------- | ------- | +| `query_id` | uint64 | +| "сума | монети | +| "Відправник | адреса | +| `forward_payload` | клітина | + +Тут адреса відправника - це адреса "джеттон-гаманця" Аліси. + +#### Послання 2''. + +`Jetton гаманець одержувача -> Відправник`. Надлишкове тіло повідомлення. **Відправляється лише у випадку, якщо після сплати комісій залишилися монети тонни**. Містить наступні дані: + +| Ім'я | Тип | +| ---------- | ------ | +| `query_id` | uint64 | + +:::tip Джеттони стандартні +Детальний опис полів контрактів джеттон-гаманця можна знайти в [TEP-74](https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md) `Jetton standard` опис інтерфейсу. +::: + +## Надсилайте джеттони з коментарями + +Для цього переказу потрібно кілька тонних монет для сплати **комісії** і, за бажанням, **повідомлення про переказ** (поставте галочку в полі "Сума переказу"). + +Щоб надіслати **коментар**, вам потрібно налаштувати `переднє корисне навантаження`. Встановіть **перші 32 біти в 0x0** і додайте **ваш текст**. + +Внутрішнє повідомлення `forward payload` надсилається у внутрішньому повідомленні `transfer notification`. Воно буде згенероване тільки якщо `сума переказу` > 0. + +Нарешті, щоб отримати повідомлення `Excess`, ви повинні налаштувати `призначення відповіді`. + +:::tip +Перевірте [кращі практики](/develop/dapps/asset-processing/jettons#best-practices) для прикладу *"надсилати jettons з коментарями"*. +::: + +## Позачергова обробка Jetton + +:::info Підтвердження транзакції +Транзакції TON є незворотними після одного підтвердження. Для кращого користувацького досвіду рекомендується уникати очікування додаткових блоків після завершення транзакцій в блокчейні TON. Детальніше читайте в [Catchain.pdf] (https://docs.ton.org/catchain.pdf#page=3). +::: + +Існує два способи прийняття джеттонів: + +- в рамках **централізованого гарячого гаманця**. +- використання гаманця з **окремою адресою** для **кожного окремого користувача**. + +З міркувань безпеки бажано мати **окремі гарячі гаманці** для **окремих джеттонів** (багато гаманців для кожного типу активів). + +При обробці коштів також рекомендується передбачити "холодний гаманець" для зберігання надлишкових коштів, які не беруть участі в автоматичних процесах поповнення та зняття коштів. + +### Додавання нових джеттонів для обробки активів та первинної верифікації + +1. Знайдіть правильну [адресу смарт-контракту] (/develop/dapps/asset-processing/jettons#jetton-master-smart-contract). +2. Отримати [метадані](/develop/dapps/asset-processing/jettons#retrieving-jetton-data). +3. Перевірте, чи немає [шахрайства] (/develop/dapps/asset-processing/jettons#jetton-master-smart-contract). + +### Ідентифікація невідомого Jetton при отриманні повідомлення про переказ + +Якщо на ваш гаманець надійшло повідомлення про переказ на невідомий Jetton, це означає, що ваш гаманець +було створено для зберігання конкретного Jetton. + +Адреса відправника внутрішнього повідомлення, що містить тіло `Transfer notification` - це адреса нового гаманця Jetton. +Її не слід плутати з полем "відправник" у тілі "Повідомлення про переказ" (/develop/dapps/asset-processing/jettons#jetton-wallets-communication-oview). + +1. Отримайте головну адресу Jetton для нового гаманця Jetton за допомогою [отримання даних гаманця](/develop/dapps/asset-processing/jettons#retrieving-data-for-a-specific-jetton-wallet). +2. Отримайте адресу гаманця Jetton для вашої адреси гаманця (як власника) за допомогою генерального договору Jetton: [Як отримати адресу гаманця Jetton для даного користувача] (#retrieving-jetton-wallet-addresses-for-a-given-user) +3. Порівняйте адресу, повернуту головним контрактом, і фактичну адресу токена гаманця. + Якщо вони збігаються, це ідеально. Якщо ні, то, швидше за все, ви отримали шахрайський токен, який є підробкою. +4. Отримати метадані Jetton: [Як отримати метадані Jetton](#retrieving-jetton-data). +5. Перевірте поля "символ" та "ім'я" на наявність ознак шахрайства. За необхідності попередьте користувача. [Додавання нового джеттона для обробки та початкової перевірки] (#adding-new-jettons-for-asset-processing-and-initial-verification). + +### Прийом джеттонів від користувачів через централізований гаманець + +:::info +Для того, щоб запобігти вузькому місцю у вхідних транзакціях на один гаманець, пропонується приймати депозити на декілька гаманців і розширювати кількість цих гаманців за потреби. +::: + +У цьому сценарії платіжний сервіс створює унікальний ідентифікатор мемо для кожного відправника, який розкриває +адресу централізованого гаманця та суми, що надсилаються. Відправник надсилає токени +на вказану централізовану адресу з обов'язковим мемо в коментарі. + +**Плюси цього методу:** цей метод дуже простий, оскільки немає додаткових комісій при прийомі токенів, і вони отримуються безпосередньо в гарячому гаманці. + +**Недоліки цього методу:** цей метод вимагає, щоб усі користувачі додавали коментар до переказу, що може призвести до більшої кількості помилок при переказі (забуті примітки, неправильні примітки тощо), а отже, до більшого навантаження на працівників служби підтримки. + +Приклади з Tonweb: + +1. [Прийом депозитів Jetton на індивідуальний гаманець HOT з коментарями (пам'ятка)] (https://github.com/toncenter/examples/blob/main/deposits-jettons.js) +2. [Приклад виведення коштів з Jettons](https://github.com/toncenter/examples/blob/main/withdrawals-jettons.js) + +#### Підготовка + +1. [Підготуйте список прийнятих джеттонів](/develop/dapps/asset-processing/jettons#adding-new-jettons-for-asset-processing-and-initial-verification) (основні адреси джеттонів). +2. Розгорніть гарячий гаманець (використовуючи v3R2, якщо не очікується виведення коштів через Jetton; highload v3 - якщо очікується виведення коштів через Jetton). [Розгортання гаманця](/develop/dapps/asset-processing/#wallet-deployment). +3. Виконайте тестовий переказ Jetton, використовуючи адресу гарячого гаманця для ініціалізації гаманця. + +#### Обробка вхідних джеттонів + +1. Завантажте список прийнятих джеттонів. +2. [Отримати адресу гаманця Jetton] (#retrieving-jetton-wallet-addresses-for-a-given-user) для вашого розгорнутого гарячого гаманця. +3. Отримайте головну адресу Jetton для кожного гаманця Jetton за допомогою [отримання даних гаманця](/develop/dapps/asset-processing/jettons#retrieving-data-for-a-specific-jetton-wallet). +4. Порівняйте адреси генеральних контрактів Jetton з кроку 1 та кроку 3 (безпосередньо вище). + Якщо адреси не збігаються, необхідно повідомити про помилку перевірки адреси Jetton. +5. Отримайте список останніх необроблених транзакцій за допомогою облікового запису гарячого гаманця та + ітераційно перегляньте його (сортуючи кожну транзакцію по черзі). Див: [Перевірка транзакцій за контрактом] (https://docs.ton.org/develop/dapps/asset-processing/#checking-contracts-transactions). +6. Перевірити вхідне повідомлення (in_msg) на наявність транзакцій і отримати адресу джерела з вхідного повідомлення. [Приклад Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L84) +7. Якщо адреса джерела збігається з адресою в гаманці Jetton, то необхідно продовжити обробку транзакції. + Якщо ні, то пропустіть обробку транзакції і перевірте наступну транзакцію. +8. Переконайтеся, що тіло повідомлення не порожнє і що перші 32 біти повідомлення збігаються з оперативним кодом `transfer notification` `0x7362d09c`. + [Приклад Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L91) + Якщо тіло повідомлення порожнє або операційний код невірний - пропустіть транзакцію. +9. Прочитайте інші дані тіла повідомлення, зокрема `query_id`, `amount`, `sender`, `forward_payload`. + [Макети повідомлень Jetton контрактів](#jetton-contract-message-layouts), [Приклад Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L105) +10. Спробуйте отримати текстові коментарі з даних `forward_payload`. Перші 32 біти мають збігатися з + опкодом текстового коментаря `0x00000000`, а решта - з текстом у кодуванні UTF-8. + [Приклад Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-jettons-single-wallet.js#L110) +11. Якщо дані `forward_payload` порожні або код операції невірний - пропустити транзакцію. +12. Порівняйте отриманий коментар зі збереженими нотатками. Якщо вони збігаються (ідентифікація користувача завжди можлива) - відправляйте переказ. +13. Почніть з кроку 5 і повторюйте процес, поки не пройдете весь список транзакцій. + +### Прийом джеттонів з депозитних адрес користувачів + +Для прийому джеттонів з депозитних адрес користувачів необхідно, щоб платіжний сервіс створив +власну індивідуальну адресу (депозит) для кожного учасника, який надсилає кошти. Надання послуги в цьому випадку передбачає +виконання декількох паралельних процесів, включаючи створення нових депозитів, сканування блоків на предмет транзакцій, +виведення коштів з депозитів на гарячий гаманець і так далі. + +Оскільки гарячий гаманець може використовувати один гаманець Jetton для кожного типу Jetton, необхідно створити декілька +гаманців для ініціювання депозитів. Для того, щоб створити велику кількість гаманців, але при цьому керувати ними за допомогою +однієї ключової фрази (або приватного ключа), необхідно при створенні гаманця вказувати різний "subwallet_id". +На TON функціонал, необхідний для створення субгаманця, підтримується гаманцями версії v3 і вище. + +#### Створення субгаманця в Tonweb + +```js +const WalletClass = tonweb.wallet.all['v3R2']; +const wallet = new WalletClass(tonweb.provider, { + publicKey: keyPair.publicKey, + wc: 0, + walletId: , +}); +``` + +#### Підготовка + +1. [Підготувати список прийнятих джеттонів] (#додавання нових джеттонів для обробки активів та початкової перевірки). +2. Розгорніть гарячий гаманець (використовуючи v3R2, якщо не очікується виведення коштів через Jetton; highload v3 - якщо очікується виведення коштів через Jetton). [Розгортання гаманця](/develop/dapps/asset-processing/#wallet-deployment). + +#### Створення депозитів + +1. Прийняти запит на створення нового депозиту для користувача. +2. Згенеруйте адресу нового субгаманця (v3R2) на основі seed'а гарячого гаманця. [Створення субгаманця в Tonweb] (#creating-a-subwallet-in-tonweb) +3. Адреса отримання може бути надана користувачеві як адреса, що використовується для депозитів Jetton (це адреса + власника депозитного гаманця Jetton). Ініціалізація гаманця не потрібна, це можна зробити + при знятті Джеттонів з депозиту. +4. Для цієї адреси необхідно обчислити адресу гаманця Jetton через майстер-контракт Jetton. + [Як отримати адресу гаманця Jetton для заданого користувача] (#retrieving-jetton-wallet-addresses-for-a-given-user). +5. Додайте адресу гаманця Jetton до пулу адрес для моніторингу транзакцій і збережіть адресу субгаманця. + +#### Обробка транзакцій + +:::info Підтвердження транзакції +Транзакції TON є незворотними після одного підтвердження. Для кращого користувацького досвіду рекомендується уникати очікування додаткових блоків після завершення транзакцій в блокчейні TON. Детальніше читайте в [Catchain.pdf] (https://docs.ton.org/catchain.pdf#page=3). +::: + +Не завжди можна визначити точну кількість отриманих джеттонів з повідомлення, оскільки гаманці Jetton +можуть не надсилати повідомлення про "повідомлення про переказ", "надлишки" та "внутрішній переказ". Вони не стандартизовані. Це означає, +що немає гарантії, що повідомлення про внутрішній переказ можна буде розшифрувати. + +Тому для визначення суми, що надійшла на гаманець, необхідно запитувати баланси за допомогою методу get. +Для отримання ключових даних при запиті балансів використовуються блоки відповідно до стану рахунку для конкретного блоку в ланцюжку. +[Підготовка до прийому блоків за допомогою Tonweb] (https://github.com/toncenter/tonweb/blob/master/src/test-block-subscribe.js). + +Цей процес відбувається наступним чином: + +1. Підготовка до приймання блоків (підготовка системи до приймання нових блоків). +2. Отримати новий блок і зберегти ідентифікатор попереднього блоку. +3. Отримуйте транзакції з блоків. +4. Фільтр транзакцій, що використовуються тільки з адресами з пулу депозитних гаманців Jetton. +5. Декодуйте повідомлення за допомогою тіла `transfer notification`, щоб отримати детальнішу інформацію, зокрема адресу + відправника, кількість джеттонів та коментар. (Дивіться: [Обробка вхідних джеттонів](#processing-incoming-jettons)) +6. Якщо на рахунку + є хоча б одна транзакція з нерозшифрованими вихідними повідомленнями (тіло повідомлення не містить операційних кодів для + `transfer notification` та операційних кодів для `excesses`) або без вихідних повідомлень, то баланс Jetton повинен бути запитаний методом get для поточного блоку, а для розрахунку різниці балансів використовується попередній блок + . Тепер загальна зміна балансу на рахунку відображається за допомогою + транзакцій, що проводяться в межах блоку. +7. Як ідентифікатор для неідентифікованої передачі джеттонів (без "повідомлення про передачу") можна використовувати дані транзакції + , якщо є одна така транзакція, або дані блоку (якщо в блоці присутні декілька). +8. Тепер необхідно перевірити, чи правильний баланс депозиту. Якщо баланс депозиту достатній для ініціювання переказу між гарячим гаманцем та існуючим гаманцем Jetton, необхідно зняти джеттони, щоб переконатися, що баланс гаманця зменшився. +9. Почніть з кроку 2 і повторіть весь процес. + +#### Зняття коштів з депозитів + +Не слід здійснювати перекази з депозиту на гарячий гаманець при кожному поповненні депозиту +, оскільки за операцію переказу стягується комісія в ТОНах (сплачується в тарифах на газ у мережі). +Важливо визначити певну мінімальну суму джеттонів, яка необхідна для того, щоб переказ на +був виправданим (і, відповідно, поповнення депозиту). + +За замовчуванням власники депозитних гаманців Jetton не ініціалізуються. Це пов'язано з тим, що не існує заздалегідь визначеної +вимоги сплачувати комісію за зберігання. Депозитні гаманці Jetton можуть бути розгорнуті при відправці повідомлень з тілом +`transfer`, яке потім може бути негайно знищене. Для цього інженер повинен використовувати спеціальний +механізм відправки повідомлень: [128 + 32](/develop/smart-contracts/messages#message-modes). + +1. Отримати список депозитів, позначених для виведення на гарячий гаманець +2. Отримати збережені адреси власників для кожного депозиту +3. Потім повідомлення надсилаються на адресу кожного власника (шляхом об'єднання декількох таких повідомлень в пакет) з високонавантаженого гаманця + з прикріпленою сумою TON Jetton. Вона визначається шляхом додавання комісій за ініціалізацію гаманця v3R2* комісій за відправку повідомлення з тілом `transfer` + довільної суми TON, пов'язаної з `forward_ton_amount` + (якщо необхідно). Приєднана сума TON визначається шляхом додавання комісії за ініціалізацію гаманця v3R2 (значення) + + комісії за відправлення повідомлення з тілом `transfer` (значення) + довільна сума TON + для `forward_ton_amount` (значення) (за необхідності). +4. Коли баланс за адресою стає ненульовим, статус акаунта змінюється. Зачекайте кілька секунд і перевірте статус + акаунта, незабаром він зміниться зі стану `nonexists` на `uninit`. +5. Для кожної адреси власника (зі статусом `uninit`) необхідно відправити зовнішнє повідомлення з гаманцем v3R2 + init і тіло з повідомленням `transfer` для поповнення гаманця Jetton = 128 + 32. Для `transfer`, + користувач повинен вказати адресу гарячого гаманця в якості `призначення` і `призначення відповіді`. + Для спрощення ідентифікації переказу можна додати текстовий коментар. +6. Перевірити доставку Джеттона можна за допомогою адреси депозиту на адресу гарячого гаманця за посиланням + , враховуючи [інформацію про обробку вхідних Джеттонів, яку можна знайти тут] (#processing-incoming-jettons). + +### Виведення коштів з Jetton + +:::info Важливо + +Нижче ви знайдете покрокову інструкцію, як обробляти виведення коштів з джеттона. +::: + +Щоб вивести джеттони, гаманець надсилає повідомлення з тілом "переказу" на відповідний гаманець Jetton. +Потім гаманець Jetton відправляє джеттони одержувачу. Для того, щоб сповіщення про переказ надійшло, важливо додати деяку кількість TON +в якості `forward_ton_amount` (і необов'язковий коментар до `forward_payload`). +Див: [Макети повідомлень джеттон-контрактів](#jetton-contract-message-layouts) + +#### Підготовка + +1. Підготуйте список джеттонів для виведення коштів: [Додавання нових джеттонів для обробки та початкової верифікації] (#adding-new-jettons-for-asset-processing-and-initial-verification) +2. Розгортання гарячого гаманця розпочато. Рекомендується Highload v3. [Розгортання гаманця](/develop/dapps/asset-processing/#wallet-deployment) +3. Здійсніть переказ Jetton, використовуючи адресу гарячого гаманця, щоб ініціалізувати гаманець Jetton і поповнити його баланс. + +#### Обробка зняття коштів + +1. Завантажити список оброблених джеттонів +2. Отримати адреси гаманців Jetton для розгорнутого гарячого гаманця: [Як отримати адреси гаманців Jetton для даного користувача] (#retrieving-jetton-wallet-addresses-for-a-given-user) +3. Отримати головні адреси Jetton для кожного гаманця Jetton: [Як отримати дані для гаманців Jetton](#retrieving-data-for-a-specific-jetton-wallet). + Необхідно ввести параметр `jetton` (який фактично є адресою головного контракту Jetton). +4. Порівняйте адреси з генеральних контрактів Jetton з кроку 1 та кроку 3. Якщо адреси не збігаються, слід повідомити про помилку перевірки адреси Jetton. +5. Отримуються запити на виведення коштів, в яких фактично вказується тип Jetton, сума, що переказується, та адреса гаманця отримувача. +6. Перевірте баланс гаманця Jetton, щоб переконатися, що на ньому достатньо коштів для виведення коштів. +7. Згенеруйте [повідомлення](/develop/dapps/asset-processing/jettons#message-0). +8. При використанні гаманця з високим навантаженням рекомендується збирати пакети повідомлень і відправляти їх по одному за раз для оптимізації комісійної винагороди. +9. Збережіть час закінчення терміну дії для вихідних зовнішніх повідомлень (це час, доки гаманець успішно + обробить повідомлення, після цього гаманець більше не буде приймати повідомлення) +10. Надішліть одне або кілька повідомлень (пакетна розсилка). +11. Отримайте список останніх необроблених транзакцій в обліковому записі гарячого гаманця та повторіть його. + Дізнайтеся більше тут: [Перевірка транзакцій контракту](/develop/dapps/asset-processing/#checking-contracts-transactions), + [Приклад Tonweb](https://github.com/toncenter/examples/blob/9f20f7104411771793dfbbdf07f0ca4860f12de2/deposits-single-wallet.js#L43) або + використовуйте метод API Toncenter `/getTransactions`. +12. Подивіться вихідні повідомлення в акаунті. +13. Якщо існує повідомлення з операторним кодом `transfer`, то його слід декодувати, щоб отримати значення `query_id`. + Отриманий `query_id` потрібно позначити як успішно відправлений. +14. Якщо час, необхідний для обробки поточної відсканованої транзакції, перевищує + час закінчення терміну дії, а вихідне повідомлення з заданим `query_id` + не знайдено, то запит слід (це необов'язково) позначити як прострочений і безпечно відправити його повторно. +15. Шукайте вхідні повідомлення в акаунті. +16. Якщо існує повідомлення, яке використовує операційний код `excesses`, його слід розшифрувати і отримати значення `query_id` + . Знайдений `query_id` слід позначити як успішно доставлений. +17. Перейдіть до кроку 5. Прострочені запити, які не були успішно відправлені, слід повернути до списку відкликання. + +## Обробка в ланцюжку Jetton + +Зазвичай, щоб приймати та обробляти джеттони, обробник повідомлень, відповідальний за внутрішні повідомлення, використовує операційний код `op=0x7362d09c`. + +:::info Підтвердження транзакції +Транзакції TON є незворотними після одного підтвердження. Для кращого користувацького досвіду рекомендується уникати очікування додаткових блоків після завершення транзакцій в блокчейні TON. Детальніше читайте в [Catchain.pdf] (https://docs.ton.org/catchain.pdf#page=3). +::: + +### Рекомендації щодо обробки в ланцюжку + +Нижче наведено "список рекомендацій", які необхідно враховувати при **проведенні обробки джеттону в ланцюжку**: + +1. **Ідентифікувати вхідні джеттони** за типом гаманця, а не за основним контрактом Jetton. Іншими словами, ваш контракт повинен взаємодіяти (отримувати і відправляти повідомлення) з конкретним гаманцем джеттона (а не з якимось невідомим гаманцем, що використовує конкретний основний контракт Jetton). +2. Під час зв'язування гаманця Jetton та головного контракту Jetton переконайтеся, що цей зв'язок є двонаправленим, тобто гаманець розпізнає головний контракт і навпаки. Наприклад, якщо ваша контрактна система отримує повідомлення від гаманця Jetton (який вважає свій MySuperJetton головним контрактом), інформація про переказ повинна відображатися користувачеві, перш ніж показати символ, ім'я та зображення + контракту MySuperJetton, переконайтеся, що гаманець MySuperJetton використовує правильну контрактну систему. У свою чергу, якщо ваша контрактна система з якихось причин повинна відправляти джеттони з використанням майстер-контрактів MySuperJetton або MySuperJetton, перевірте, що гаманець X використовує ті ж параметри контракту, що і гаманець MySuperJetton. + Крім того, перед тим, як надсилати запит на переказ на X, переконайтеся, що він визнає MySuperJetton своїм головним. +3. Справжня сила децентралізованих фінансів (DeFi) базується на можливості накладати протоколи один на одного, як кубики лего. Наприклад, скажімо, джеттон А обмінюється на джеттон Б, який, в свою чергу, використовується як кредитне плече в рамках протоколу кредитування (коли користувач надає ліквідність), який потім використовується для купівлі NFT .... і так далі. Таким чином, розглянемо, як контракт може обслуговувати не тільки позамережевих користувачів, але й мережевих суб'єктів, прикріплюючи токенізовану вартість до повідомлення про переказ, додаючи користувацьке корисне навантаження, яке може бути надіслане разом із повідомленням про переказ. +4. \*\*Майте на увазі, що не всі контракти дотримуються однакових стандартів. На жаль, деякі джеттони можуть бути ворожими (з використанням векторів атак) і створюватися з єдиною метою - атакувати користувачів, які нічого не підозрюють. З метою безпеки, якщо протокол, про який йде мова, складається з багатьох контрактів, не створюйте велику кількість однотипних джеттон-гаманців. Зокрема, не надсилайте джеттони всередині протоколу між депозитним контрактом, контрактом на зберігання, контрактом на обліковий запис користувача тощо. Зловмисники можуть навмисно втрутитися в логіку контракту, підробивши повідомлення про переказ, суми джеттонів або параметри корисного навантаження. Зменшіть ймовірність атак, використовуючи лише один гаманець у системі на один джеттон (для всіх депозитів і зняття коштів). +5. Також **часто корисно** створювати субконтракти для кожного окремого джеттона, щоб зменшити ймовірність підміни адреси (наприклад, коли повідомлення про переказ надсилається на джеттон B з використанням контракту, призначеного для джеттона A). +6. Наполегливо рекомендується працювати з неподільними одиницями джеттон на рівні контрактів. Логіка, пов'язана з десятковою системою числення, зазвичай використовується для покращення користувацького інтерфейсу (UI) diplay і не пов'язана з числовим веденням записів у ланцюжку. + +Щоб дізнатися більше про [Безпечне програмування смарт-контрактів у FunC від CertiK] (https://blog.ton.org/secure-smart-contract-programming-in-func), ознайомтеся з цим ресурсом. Рекомендується, щоб розробники **обробляли всі винятки смарт-контрактів**, щоб вони ніколи не були пропущені під час розробки програми. + +## Рекомендації щодо обробки гаманця Jetton + +Як правило, всі процедури верифікації, що використовуються для обробки джеттонів, підходять і для гаманців. Для обробки джеттон-гаманців наші найважливіші рекомендації наступні: + +1. Коли гаманець отримує повідомлення про переказ з невідомого джеттон-гаманця, дуже важливо довіряти джеттон-гаманцю та його головній адресі, оскільки він може бути зловмисною підробкою. Щоб захистити себе, перевірте Jetton Master (основний договір), використовуючи надану адресу, щоб переконатися, що ваші процеси верифікації визнають джеттон-гаманець легітимним. Після того, як ви довіритеся гаманцю і він буде підтверджений як легітимний, ви можете дозволити йому доступ до залишків на ваших рахунках та інших даних у гаманці. Якщо Jetton Master не розпізнає цей гаманець, рекомендується взагалі не ініціювати і не розкривати свої джеттон-перекази, а показувати тільки вхідні перекази TON (Toncoin, прикріплені до повідомлень про перекази). +2. На практиці, якщо користувач хоче взаємодіяти з джеттоном, а не з джеттон-гаманцем. Іншими словами, користувачі відправляють wTON/oUSDT/jUSDT, jUSDC, jDAI замість `EQAjN...`/`EQBLE...` + тощо. Часто це означає, що коли користувач ініціює джеттон-переказ, гаманець запитує відповідного джеттон-майстра, який джеттон-гаманець (що належить користувачеві) повинен ініціювати запит на переказ. Важливо ніколи не довіряти сліпо\*\* цим даним від майстра (майстер-контракту). Перш ніж надсилати запит на переказ на джеттон-гаманець, завжди переконайтеся, що джеттон-гаманець дійсно належить тому майстру джеттонів, на якого він посилається. +3. \*\*Майте на увазі, що ворожі Jetton-майстри/jetton-гаманці з часом можуть змінювати свої гаманці/майстри. Тому вкрай важливо, щоб користувачі проявляли належну обачність і перевіряли легітимність будь-яких гаманців, з якими вони взаємодіють, перед кожним використанням. +4. \*\*Завжди переконайтеся, що ви відображаєте джеттони в інтерфейсі таким чином, щоб вони не змішувалися з TON-переказами, системними сповіщеннями тощо. Навіть параметри "символ", "ім'я" та "зображення" + можуть бути створені таким чином, щоб вводити в оману користувачів, роблячи їх потенційними жертвами шахрайства. Було зафіксовано кілька випадків, коли шкідливі джеттони використовувалися для імітації TON-переказів, помилок у сповіщеннях, нарахування винагороди або оголошень про заморожування активів. +5. **Завжди слідкуйте за потенційними зловмисниками**, які створюють підроблені джеттони, тому завжди корисно надати користувачам функціонал, необхідний для усунення небажаних джеттонів в їхньому основному інтерфейсі користувача. + +Автори: [kosrk](https://github.com/kosrk), [krigga](https://github.com/krigga), [EmelyanenkoK](https://github.com/EmelyanenkoK/) та [tolya-yanot](https://github.com/tolya-yanot/). + +## Найкращі практики + +Якщо вам потрібні готові приклади для тестування, перевірте [SDKs](/develop/dapps/asset-processing/jettons#sdks) і спробуйте їх запустити. Нижче наведено фрагменти коду, які допоможуть вам зрозуміти обробку джеттонів на прикладах коду. + +### Надсилайте джеттони з коментарями + + + + +
+ +Source code + + +```js +// first 4 bytes are tag of text comment +const comment = new Uint8Array([... new Uint8Array(4), ... new TextEncoder().encode('text comment')]); + +await wallet.methods.transfer({ + secretKey: keyPair.secretKey, + toAddress: JETTON_WALLET_ADDRESS, // address of Jetton wallet of Jetton sender + amount: TonWeb.utils.toNano('0.05'), // total amount of TONs attached to the transfer message + seqno: seqno, + payload: await jettonWallet.createTransferBody({ + jettonAmount: TonWeb.utils.toNano('500'), // Jetton amount (in basic indivisible units) + toAddress: new TonWeb.utils.Address(WALLET2_ADDRESS), // recepient user's wallet address (not Jetton wallet) + forwardAmount: TonWeb.utils.toNano('0.01'), // some amount of TONs to invoke Transfer notification message + forwardPayload: comment, // text comment for Transfer notification message + responseAddress: walletAddress // return the TONs after deducting commissions back to the sender's wallet address + }), + sendMode: 3, +}).send() +``` + +
+ +
+ + +
+ +Source code + + +```go +client := liteclient.NewConnectionPool() + +// connect to testnet lite server +err := client.AddConnectionsFromConfigUrl(context.Background(), "https://ton.org/global.config.json") +if err != nil { + panic(err) +} + +ctx := client.StickyContext(context.Background()) + +// initialize ton api lite connection wrapper +api := ton.NewAPIClient(client) + +// seed words of account, you can generate them with any wallet or using wallet.NewSeed() method +words := strings.Split("birth pattern then forest walnut then phrase walnut fan pumpkin pattern then cluster blossom verify then forest velvet pond fiction pattern collect then then", " ") + +w, err := wallet.FromSeed(api, words, wallet.V3R2) +if err != nil { + log.Fatalln("FromSeed err:", err.Error()) + return +} + +token := jetton.NewJettonMasterClient(api, address.MustParseAddr("EQD0vdSA_NedR9uvbgN9EikRX-suesDxGeFg69XQMavfLqIw")) + +// find our jetton wallet +tokenWallet, err := token.GetJettonWallet(ctx, w.WalletAddress()) +if err != nil { + log.Fatal(err) +} + +amountTokens := tlb.MustFromDecimal("0.1", 9) + +comment, err := wallet.CreateCommentCell("Hello from tonutils-go!") +if err != nil { + log.Fatal(err) +} + +// address of receiver's wallet (not token wallet, just usual) +to := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N") +transferPayload, err := tokenWallet.BuildTransferPayload(to, amountTokens, tlb.ZeroCoins, comment) +if err != nil { + log.Fatal(err) +} + +// your TON balance must be > 0.05 to send +msg := wallet.SimpleMessage(tokenWallet.Address(), tlb.MustFromTON("0.05"), transferPayload) + +log.Println("sending transaction...") +tx, _, err := w.SendWaitTransaction(ctx, msg) +if err != nil { + panic(err) +} +log.Println("transaction confirmed, hash:", base64.StdEncoding.EncodeToString(tx.Hash)) +``` + +
+ +
+ + +
+ +Source code + + +```py +my_wallet = Wallet(provider=client, mnemonics=my_wallet_mnemonics, version='v4r2') + +# for TonCenterClient and LsClient +await my_wallet.transfer_jetton(destination_address='address', jetton_master_address=jetton.address, jettons_amount=1000, fee=0.15) + +# for all clients +await my_wallet.transfer_jetton_by_jetton_wallet(destination_address='address', jetton_wallet='your jetton wallet address', jettons_amount=1000, fee=0.1) +``` + +
+ +
+ + + +
+ +Source code + + +```py +from pytoniq import LiteBalancer, WalletV4R2, begin_cell +import asyncio + +mnemonics = ["your", "mnemonics", "here"] + +async def main(): + provider = LiteBalancer.from_mainnet_config(1) + await provider.start_up() + + wallet = await WalletV4R2.from_mnemonic(provider=provider, mnemonics=mnemonics) + USER_ADDRESS = wallet.address + JETTON_MASTER_ADDRESS = "EQBlqsm144Dq6SjbPI4jjZvA1hqTIP3CvHovbIfW_t-SCALE" + DESTINATION_ADDRESS = "EQAsl59qOy9C2XL5452lGbHU9bI3l4lhRaopeNZ82NRK8nlA" + + USER_JETTON_WALLET = (await provider.run_get_method(address=JETTON_MASTER_ADDRESS, + method="get_wallet_address", + stack=[begin_cell().store_address(USER_ADDRESS).end_cell().begin_parse()]))[0].load_address() + forward_payload = (begin_cell() + .store_uint(0, 32) # TextComment op-code + .store_snake_string("Comment") + .end_cell()) + transfer_cell = (begin_cell() + .store_uint(0xf8a7ea5, 32) # Jetton Transfer op-code + .store_uint(0, 64) # query_id + .store_coins(1 * 10**9) # Jetton amount to transfer in nanojetton + .store_address(DESTINATION_ADDRESS) # Destination address + .store_address(USER_ADDRESS) # Response address + .store_bit(0) # Custom payload is None + .store_coins(1) # Ton forward amount in nanoton + .store_bit(1) # Store forward_payload as a reference + .store_ref(forward_payload) # Forward payload + .end_cell()) + + await wallet.transfer(destination=USER_JETTON_WALLET, amount=int(0.05*1e9), body=transfer_cell) + await provider.close_all() + +asyncio.run(main()) +``` + +
+ +
+
+ +### Прийняти Jetton Transfer з розбором коментарів + + + + +
+ +Source code + + +```ts +import { + Address, + TonClient, + Cell, + beginCell, + storeMessage, + JettonMaster, + OpenedContract, + JettonWallet, + Transaction +} from '@ton/ton'; + + +export async function retry(fn: () => Promise, options: { retries: number, delay: number }): Promise { + let lastError: Error | undefined; + for (let i = 0; i < options.retries; i++) { + try { + return await fn(); + } catch (e) { + if (e instanceof Error) { + lastError = e; + } + await new Promise(resolve => setTimeout(resolve, options.delay)); + } + } + throw lastError; +} + +export async function tryProcessJetton(orderId: string) : Promise { + + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + apiKey: 'TONCENTER-API-KEY', // https://t.me/tonapibot + }); + + interface JettonInfo { + address: string; + decimals: number; + } + + interface Jettons { + jettonMinter : OpenedContract, + jettonWalletAddress: Address, + jettonWallet: OpenedContract + } + + const MY_WALLET_ADDRESS = 'INSERT-YOUR-HOT-WALLET-ADDRESS'; // your HOT wallet + + const JETTONS_INFO : Record = { + 'jUSDC': { + address: 'EQB-MPwrd1G6WKNkLz_VnV6WqBDd142KMQv-g1O-8QUA3728', // + decimals: 6 + }, + 'jUSDT': { + address: 'EQBynBO23ywHy_CgarY9NK9FTz0yDsG82PtcbSTQgGoXwiuA', + decimals: 6 + }, + } + const jettons: Record = {}; + + const prepare = async () => { + for (const name in JETTONS_INFO) { + const info = JETTONS_INFO[name]; + const jettonMaster = client.open(JettonMaster.create(Address.parse(info.address))); + const userAddress = Address.parse(MY_WALLET_ADDRESS); + + const jettonUserAddress = await jettonMaster.getWalletAddress(userAddress); + + console.log('My jetton wallet for ' + name + ' is ' + jettonUserAddress.toString()); + + const jettonWallet = client.open(JettonWallet.create(jettonUserAddress)); + + //const jettonData = await jettonWallet; + const jettonData = await client.runMethod(jettonUserAddress, "get_wallet_data") + + jettonData.stack.pop(); //skip balance + jettonData.stack.pop(); //skip owneer address + const adminAddress = jettonData.stack.readAddress(); + + + if (adminAddress.toString() !== (Address.parse(info.address)).toString()) { + throw new Error('jetton minter address from jetton wallet doesnt match config'); + } + + jettons[name] = { + jettonMinter: jettonMaster, + jettonWalletAddress: jettonUserAddress, + jettonWallet: jettonWallet + }; + } + } + + const jettonWalletAddressToJettonName = (jettonWalletAddress : Address) => { + const jettonWalletAddressString = jettonWalletAddress.toString(); + for (const name in jettons) { + const jetton = jettons[name]; + + if (jetton.jettonWallet.address.toString() === jettonWalletAddressString) { + return name; + } + } + return null; + } + + // Subscribe + const Subscription = async ():Promise =>{ + + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + apiKey: 'TONCENTER-API-KEY', // https://t.me/tonapibot + }); + + const myAddress = Address.parse('INSERT-YOUR-HOT-WALLET'); // Address of receiver TON wallet + const transactions = await client.getTransactions(myAddress, { + limit: 5, + }); + return transactions; + } + + return retry(async () => { + + await prepare(); + const Transactions = await Subscription(); + + for (const tx of Transactions) { + + const sourceAddress = tx.inMessage?.info.src; + if (!sourceAddress) { + // external message - not related to jettons + continue; + } + + if (!(sourceAddress instanceof Address)) { + continue; + } + + const in_msg = tx.inMessage; + + if (in_msg?.info.type !== 'internal') { + // external message - not related to jettons + continue; + } + + // jetton master contract address check + const jettonName = jettonWalletAddressToJettonName(sourceAddress); + if (!jettonName) { + // unknown or fake jetton transfer + continue; + } + + if (tx.inMessage === undefined || tx.inMessage?.body.hash().equals(new Cell().hash())) { + // no in_msg or in_msg body + continue; + } + + const msgBody = tx.inMessage; + const sender = tx.inMessage?.info.src; + const originalBody = tx.inMessage?.body.beginParse(); + let body = originalBody?.clone(); + const op = body?.loadUint(32); + if (!(op == 0x7362d09c)) { + continue; // op != transfer_notification + } + + console.log('op code check passed', tx.hash().toString('hex')); + + const queryId = body?.loadUint(64); + const amount = body?.loadCoins(); + const from = body?.loadAddress(); + const maybeRef = body?.loadBit(); + const payload = maybeRef ? body?.loadRef().beginParse() : body; + const payloadOp = payload?.loadUint(32); + if (!(payloadOp == 0)) { + console.log('no text comment in transfer_notification'); + continue; + } + + const comment = payload?.loadStringTail(); + if (!(comment == orderId)) { + continue; + } + + console.log('Got ' + jettonName + ' jetton deposit ' + amount?.toString() + ' units with text comment "' + comment + '"'); + const txHash = tx.hash().toString('hex'); + return (txHash); + } + throw new Error('Transaction not found'); + }, {retries: 30, delay: 1000}); +} +``` + +
+ +
+ + +
+ +Source code + + +```go +import ( + "context" + "fmt" + "log" + + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/liteclient" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/ton" + "github.com/xssnick/tonutils-go/ton/jetton" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +const ( + MainnetConfig = "https://ton.org/global.config.json" + TestnetConfig = "https://ton.org/global.config.json" + MyWalletAddress = "INSERT-YOUR-HOT-WALLET-ADDRESS" +) + +type JettonInfo struct { + address string + decimals int +} + +type Jettons struct { + jettonMinter *jetton.Client + jettonWalletAddress string + jettonWallet *jetton.WalletClient +} + +func prepare(api ton.APIClientWrapped, jettonsInfo map[string]JettonInfo) (map[string]Jettons, error) { + userAddress := address.MustParseAddr(MyWalletAddress) + block, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + return nil, err + } + + jettons := make(map[string]Jettons) + + for name, info := range jettonsInfo { + jettonMaster := jetton.NewJettonMasterClient(api, address.MustParseAddr(info.address)) + jettonWallet, err := jettonMaster.GetJettonWallet(context.Background(), userAddress) + if err != nil { + return nil, err + } + + jettonUserAddress := jettonWallet.Address() + + jettonData, err := api.RunGetMethod(context.Background(), block, jettonUserAddress, "get_wallet_data") + if err != nil { + return nil, err + } + + slice := jettonData.MustCell(0).BeginParse() + slice.MustLoadCoins() // skip balance + slice.MustLoadAddr() // skip owneer address + adminAddress := slice.MustLoadAddr() + + if adminAddress.String() != info.address { + return nil, fmt.Errorf("jetton minter address from jetton wallet doesnt match config") + } + + jettons[name] = Jettons{ + jettonMinter: jettonMaster, + jettonWalletAddress: jettonUserAddress.String(), + jettonWallet: jettonWallet, + } + } + + return jettons, nil +} + +func jettonWalletAddressToJettonName(jettons map[string]Jettons, jettonWalletAddress string) string { + for name, info := range jettons { + if info.jettonWallet.Address().String() == jettonWalletAddress { + return name + } + } + return "" +} + +func GetTransferTransactions(orderId string, foundTransfer chan<- *tlb.Transaction) { + jettonsInfo := map[string]JettonInfo{ + "jUSDC": {address: "EQB-MPwrd1G6WKNkLz_VnV6WqBDd142KMQv-g1O-8QUA3728", decimals: 6}, + "jUSDT": {address: "EQBynBO23ywHy_CgarY9NK9FTz0yDsG82PtcbSTQgGoXwiuA", decimals: 6}, + } + + client := liteclient.NewConnectionPool() + + cfg, err := liteclient.GetConfigFromUrl(context.Background(), MainnetConfig) + if err != nil { + log.Fatalln("get config err: ", err.Error()) + } + + // connect to lite servers + err = client.AddConnectionsFromConfig(context.Background(), cfg) + if err != nil { + log.Fatalln("connection err: ", err.Error()) + } + + // initialize ton api lite connection wrapper + api := ton.NewAPIClient(client, ton.ProofCheckPolicySecure).WithRetry() + master, err := api.CurrentMasterchainInfo(context.Background()) + if err != nil { + log.Fatalln("get masterchain info err: ", err.Error()) + } + + // address on which we are accepting payments + treasuryAddress := address.MustParseAddr("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N") + + acc, err := api.GetAccount(context.Background(), master, treasuryAddress) + if err != nil { + log.Fatalln("get masterchain info err: ", err.Error()) + } + + jettons, err := prepare(api, jettonsInfo) + if err != nil { + log.Fatalln("can't prepare jettons data: ", err.Error()) + } + + lastProcessedLT := acc.LastTxLT + + transactions := make(chan *tlb.Transaction) + + go api.SubscribeOnTransactions(context.Background(), treasuryAddress, lastProcessedLT, transactions) + + log.Println("waiting for transfers...") + + // listen for new transactions from channel + for tx := range transactions { + if tx.IO.In == nil || tx.IO.In.MsgType != tlb.MsgTypeInternal { + // external message - not related to jettons + continue + } + + msg := tx.IO.In.Msg + sourceAddress := msg.SenderAddr() + + // jetton master contract address check + jettonName := jettonWalletAddressToJettonName(jettons, sourceAddress.String()) + if len(jettonName) == 0 { + // unknown or fake jetton transfer + continue + } + + if msg.Payload() == nil || msg.Payload() == cell.BeginCell().EndCell() { + // no in_msg body + continue + } + + msgBodySlice := msg.Payload().BeginParse() + + op := msgBodySlice.MustLoadUInt(32) + if op != 0x7362d09c { + continue // op != transfer_notification + } + + // just skip bits + msgBodySlice.MustLoadUInt(64) + amount := msgBodySlice.MustLoadCoins() + msgBodySlice.MustLoadAddr() + + payload := msgBodySlice.MustLoadMaybeRef() + payloadOp := payload.MustLoadUInt(32) + if payloadOp == 0 { + log.Println("no text comment in transfer_notification") + continue + } + + comment := payload.MustLoadStringSnake() + if comment != orderId { + continue + } + + // process transaction + log.Printf("Got %s jetton deposit %d units with text comment %s\n", jettonName, amount, comment) + foundTransfer <- tx + } +} +``` + +
+
+ + + +
+ +Source code + + +```py +import asyncio + +from pytoniq import LiteBalancer, begin_cell + +MY_WALLET_ADDRESS = "EQAsl59qOy9C2XL5452lGbHU9bI3l4lhRaopeNZ82NRK8nlA" + + +async def parse_transactions(provider: LiteBalancer, transactions): + for transaction in transactions: + if not transaction.in_msg.is_internal: + continue + if transaction.in_msg.info.dest.to_str(1, 1, 1) != MY_WALLET_ADDRESS: + continue + + sender = transaction.in_msg.info.src.to_str(1, 1, 1) + value = transaction.in_msg.info.value_coins + if value != 0: + value = value / 1e9 + + if len(transaction.in_msg.body.bits) < 32: + print(f"TON transfer from {sender} with value {value} TON") + continue + + body_slice = transaction.in_msg.body.begin_parse() + op_code = body_slice.load_uint(32) + if op_code != 0x7362D09C: + continue + + body_slice.load_bits(64) # skip query_id + jetton_amount = body_slice.load_coins() / 1e9 + jetton_sender = body_slice.load_address().to_str(1, 1, 1) + if body_slice.load_bit(): + forward_payload = body_slice.load_ref().begin_parse() + else: + forward_payload = body_slice + + jetton_master = ( + await provider.run_get_method( + address=sender, method="get_wallet_data", stack=[] + ) + )[2].load_address() + jetton_wallet = ( + ( + await provider.run_get_method( + address=jetton_master, + method="get_wallet_address", + stack=[ + begin_cell() + .store_address(MY_WALLET_ADDRESS) + .end_cell() + .begin_parse() + ], + ) + )[0] + .load_address() + .to_str(1, 1, 1) + ) + + if jetton_wallet != sender: + print("FAKE Jetton Transfer") + continue + + if len(forward_payload.bits) < 32: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton" + ) + else: + forward_payload_op_code = forward_payload.load_uint(32) + if forward_payload_op_code == 0: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton and comment: {forward_payload.load_snake_string()}" + ) + else: + print( + f"Jetton transfer from {jetton_sender} with value {jetton_amount} Jetton and unknown payload: {forward_payload} " + ) + + print(f"Transaction hash: {transaction.cell.hash.hex()}") + print(f"Transaction lt: {transaction.lt}") + + +async def main(): + provider = LiteBalancer.from_mainnet_config(1) + await provider.start_up() + transactions = await provider.get_transactions(address=MY_WALLET_ADDRESS, count=5) + await parse_transactions(provider, transactions) + await provider.close_all() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +
+
+
+ +## SDK + +Список SDK для різних мов (js, python, golang, C#, Rust і т.д.) можна знайти [тут](/develop/dapps/apis/sdk). + +## Дивіться також + +- [Обробка платежів](/develop/dapps/asset-processing/) +- [Обробка NFT на TON](/develop/dapps/asset-processing/nfts) +- [Парсинг метаданих на TON](/develop/dapps/asset-processing/metadata) diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md b/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md new file mode 100644 index 0000000000..1ed365f656 --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/asset-processing/overview.md @@ -0,0 +1,62 @@ +import Button from '@site/src/components/button' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Огляд процесу обробки активів + +Тут ви можете знайти **короткий огляд** про те, [як працюють перекази TON] (/develop/dapps/asset-processing/overview#overview-on-messages-and-transactions), які [типи активів](/develop/dapps/asset-processing/overview#digital-asset-types-on-ton) можна знайти в TON (і про що ви прочитаєте [далі](/develop/dapps/asset-processing/overview#read-next)) і як [взаємодіяти з ton](/develop/dapps/asset-processing/overview#interaction-with-ton-blockchain) за допомогою вашої мови програмування, рекомендується зрозуміти всю інформацію, викладену нижче, перш ніж переходити до наступних сторінок. + +## Огляд повідомлень і транзакцій + +Втілюючи повністю асинхронний підхід, TON Blockchain включає в себе кілька концепцій, які є незвичними для традиційних блокчейнів. Зокрема, кожна взаємодія будь-якого актора з блокчейном складається з графа асинхронно переданих [повідомлень] (/develop/smart-contracts/guidelines/message-delivery-guarantees) між смарт-контрактами та/або зовнішнім світом. Кожна транзакція складається з одного вхідного повідомлення і до 512 вихідних повідомлень. + +Існує 3 типи повідомлень, які повністю описані [тут] (/develop/smart-contracts/messages#типи повідомлень). Якщо говорити коротко: + +- [зовнішнє повідомлення](/develop/smart-contracts/guidelines/external-messages): + - "Зовнішнє повідомлення" (іноді його називають просто "зовнішнє повідомлення") - це повідомлення, яке надсилається з *зовні* блокчейну до смарт-контракту *всередині* блокчейну. + - "Зовнішнє вихідне повідомлення" (зазвичай його називають "повідомленням журналу") надсилається від *суб'єкта блокчейну* до *зовнішнього світу*. +- [внутрішнє повідомлення] (/develop/smart-contracts/guidelines/internal-messages) надсилається від одного *суб'єкта блокчейну* до *іншого*, може містити певну кількість цифрових активів і довільну частину даних. + +Загальний шлях будь-якої взаємодії починається із зовнішнього повідомлення, надісланого до смарт-контракту "гаманця", який аутентифікує відправника повідомлення за допомогою криптографії з відкритим ключем, бере на себе оплату комісії та надсилає внутрішні блокчейн-повідомлення. Ця черга повідомлень утворює орієнтований ациклічний граф, або дерево. + +Наприклад: + +![](/img/docs/asset-processing/alicemsgDAG.svg) + +- "Аліса" використовує, наприклад, [Tonkeeper] (https://tonkeeper.com/), щоб відправити "зовнішнє повідомлення" на свій гаманець. +- зовнішнє повідомлення" - вхідне повідомлення для контракту "гаманець A v4" з порожнім судом (повідомлення з нізвідки, наприклад, [Tonkeeper](https://tonkeeper.com/)). +- вихідне повідомлення" - це вихідне повідомлення для контракту "гаманець A v4" і вхідне повідомлення для контракту "гаманець B v4" з джерелом "гаманець A v4" і призначенням "гаманець B v4". + +В результаті маємо 2 транзакції з їх набором вхідних та вихідних повідомлень. + +Кожна дія, коли контракт отримує повідомлення на вхід (запускається ним), обробляє його і генерує або не генерує вихідні повідомлення на виході, називається "транзакцією". Дізнайтеся більше про транзакції [тут] (/develop/smart-contracts/guidelines/message-delivery-guarantees#what-is-transaction). + +Ці "транзакції" можуть охоплювати **тривалий період часу**. Технічно, транзакції з чергами повідомлень агрегуються в блоки, які обробляються валідаторами. Асинхронна природа TON Blockchain **не дозволяє передбачити хеш і lt (логічний час) транзакції** на етапі відправлення повідомлення. + +Прийнята до блоку "транзакція" є остаточною і не може бути змінена. + +:::info Підтвердження транзакції +Транзакції TON є незворотними після одного підтвердження. Для кращого користувацького досвіду рекомендується уникати очікування додаткових блоків після завершення транзакцій в блокчейні TON. Детальніше читайте в [Catchain.pdf] (https://docs.ton.org/catchain.pdf#page=3). +::: + +Смарт-контракти сплачують кілька типів [комісій](/develop/smart-contracts/fees) за транзакції (зазвичай від балансу вхідного повідомлення, поведінка залежить від [режиму повідомлення](/develop/smart-contracts/messages#message-modes)). Розмір комісії залежить від конфігурації робочого ланцюга: максимальна комісія на `masterchain` і значно нижча на `basechain`. + +## Типи цифрових активів на TON + +ТОН має три типи цифрових активів. + +- Toncoin, основний токен мережі. Він використовується для всіх базових операцій в блокчейні, наприклад, для оплати за газ або стейкінгу для валідації. +- Контрактні активи, такі як токени і NFT, які є аналогом стандартів ERC-20/ERC-721 і управляються довільними контрактами, а тому можуть вимагати кастомних правил для обробки. Ви можете знайти більше інформації про їх обробку в статтях [обробка NFT](/develop/dapps/asset-processing/nfts) і [обробка джеттонів](/develop/dapps/asset-processing/jettons). +- Нативні токени (Native token) - особливий вид активів, які можуть бути прикріплені до будь-якого повідомлення в мережі. Але наразі ці активи не використовуються, оскільки функціонал для випуску нових нативних токенів закритий. + +## Взаємодія з блокчейном TON + +Базові операції з блокчейном TON можна здійснювати за допомогою TonLib. Це спільна бібліотека, яка може бути скомпільована разом з вузлом TON і надавати API для взаємодії з блокчейном через так звані lite-сервери (сервери для lite-клієнтів). TonLib дотримується підходу без довіри, перевіряючи докази для всіх вхідних даних; таким чином, немає необхідності в надійному постачальнику даних. Методи, доступні для TonLib, перелічено [у схемі TL](https://github.com/ton-blockchain/ton/blob/master/tl/generate/scheme/tonlib_api.tl#L234). Вони можуть бути використані як спільна бібліотека за допомогою [wrappers](/develop/dapps/asset-processing/#repositories). + +## Читати далі + +Прочитавши цю статтю, ви зможете перевірити: + +1. [Обробка платежів](/develop/dapps/asset-processing/), щоб дізнатися, як працювати з `TON coins`. +2. [Обробка джеттонів](/develop/dapps/asset-processing/jettons), щоб дізнатися, як працювати з `джеттонами` (іноді їх називають `токенами`) +3. [Обробка NFT](/develop/dapps/asset-processing/nfts), щоб дізнатися, як працювати з `NFT` (це спеціальний тип `jetton`) diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx b/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx new file mode 100644 index 0000000000..0c4ba0c9ce --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/develop/dapps/ton-connect/overview.mdx @@ -0,0 +1,113 @@ +import Button from '@site/src/components/button' + +# Про TON Connect + +TON Connect - це потужний інструментарій з відкритим вихідним кодом, який слугує універсальним стандартом авторизації додатків в екосистемі [TON](/learn/introduction), дозволяючи користувачам безпечно та зручно входити в додатки та сервіси за допомогою своїх гаманців TON замість традиційних логінів та паролів. + +![](/img/docs/ton-connect/ton-connect-overview.png?raw=true) + +Не соромтеся використовувати один з наступних потоків для інтеграції вашого додатку: + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Варіанти використання для вашого DApp + +Ознайомтеся з цими результатами, які надає екосистема TON для чудової DApplication-інтеграції. + +- **Трафік**. Залучайте додаткові відвідування користувачів через криптогаманці, які підтримують TON Connect. +- **Автентичність**. Використовуйте гаманці користувачів TON як готові акаунти, усуваючи необхідність додаткових кроків автентифікації і, таким чином, покращуючи користувацький досвід. +- **Платежі**. Обробляйте транзакції швидко і безпечно через TON Blockchain, використовуючи Toncoin або загорнуті стабільні монети (jUSDC/jUSDT). +- **Утримання**. Покращуйте утримання користувачів за допомогою функції збереження списків у додатку, яка дозволяє користувачам відстежувати нещодавно відкриті та улюблені програми. + +## Для розробників гаманців + +Якщо ви розробник гаманців, ви можете підключити свій гаманець до TON Connect і надати своїм користувачам можливість взаємодіяти з додатками TON у безпечний та зручний спосіб, прочитайте, як [інтегрувати TON Connect у ваш гаманець](/develop/dapps/ton-connect/wallet/). + +## Історії успіху + +- [GetGems - Відкритий мережевий ринок] (https://getgems.io/) +- [STON.fi - AMM DEX для блокчейну TON] (https://ston.fi/) +- [Tonstarter](http://tonstarter.com/) + +
+ Показати весь список + +- [getgems.io](https://getgems.io/) +- [fragment.com](https://fragment.com/) (Ton Connect v.1) +- [ston.fi](https://ston.fi/) +- [ton.diamonds](https://ton.diamonds/) +- [beta.disintar.io](https://beta.disintar.io/) +- [tegro.finance](https://tegro.finance/liquidity) +- [minter.ton.org](https://minter.ton.org/) +- [libermall.com](https://libermall.com/) +- [dedust.io](https://dedust.io/swap) +- [toncap.net](https://toncap.net/) +- [cryptomus.com](https://cryptomus.com/) +- [avanchange.com](https://avanchange.com/) +- [wton.dev](https://wton.dev/) +- [mint.spiroverse.io/shop](https://mint.spiroverse.io/shop) +- [vk.com/vk_nft_hub](https://vk.com/vk_nft_hub) +- [tonverifier.live](https://verifier.ton.org/) +- [stickerface.io/member](https://stickerface.io/member) +- [tonstarter.com](https://tonstarter.com/) +- [cryptogas.shop/ton](https://cryptogas.shop/ton) +- [megaton.fi](https://megaton.fi/) +- [dns.ton.org](https://dns.ton.org/) +- [coinpaymaster.com](https://coinpaymaster.com/) +- [ton.gagarin.world/app/](https://ton.gagarin.world/app) +- [daolama.co](https://daolama.co/) +- [marketplace.playmuse.org](http://marketplace.playmuse.org/) +- [ton.vote](https://ton.vote/) +- [plane.tonfancy.io](https://plane.tonfancy.io/) +- [pi.oberton.io](https://pi.oberton.io/) +- [business.thetonpay.app](https://business.thetonpay.app/) +- [bridge.orbitchain.io](https://bridge.orbitchain.io/) +- [connecton-web-new.vercel.app](https://connecton-web-new.vercel.app/) +- [app.fanz.ee/staking](https://app.fanz.ee/staking) +- [testnet.pton.fi](https://testnet.pton.fi/) +- [tonft.app](https://tonft.app/) +- [cardify.casino](https://cardify.casino/) +- [4riends.org](https://4riends.org/#/) +- [tonflex.fi](https://tonflex.fi/swap) +- [soquest.xyz](https://soquest.xyz/) +- [app.evaa.finance](https://app.evaa.finance/) + +
+ +## Приєднуйтесь до екосистеми ТОН + +Щоб підключити свій сервіс до екосистеми TON, вам потрібно виконати наступне: + +- \*\*TON Connect. Включіть протокол TON Connect у свій додаток. +- **Транзакції**. Створюйте визначені повідомлення транзакцій за допомогою бібліотек TON. Пориньте у процес [надсилання повідомлень] (/develop/dapps/ton-connect/message-builders) за допомогою нашого вичерпного керівництва. +- **Платежі**. Обробляйте платежі через публічний API ([tonapi](https://tonapi.io/)) або власний індексатор, наприклад, [gobycicle](http://github.com/gobicycle/bicycle). Дізнайтеся більше з нашого докладного посібника з [обробки активів] (/develop/dapps/asset-processing). diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/develop/fift/overview.mdx b/i18n/uk/docusaurus-plugin-content-docs/current/develop/fift/overview.mdx new file mode 100644 index 0000000000..411d1a4949 --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/develop/fift/overview.mdx @@ -0,0 +1,57 @@ +import Button from '@site/src/components/button' + +# Огляд + +Fift - це стекова мова програмування загального призначення, оптимізована для створення, налагодження та управління смарт-контрактами TON Blockchain. +Fift була спеціально розроблена для взаємодії з віртуальною машиною TON (TON VM або TVM) та блокчейном TON. + +```fift +{ ."hello " } execute ."world" +hello world ok +``` + +:::info +Зазвичай використання Fift не є обов'язковим для програмування смарт-контрактів в TON. Однак, іноді вам може знадобитися використання мови Fift для вирішення нестандартних технічних проблем в рамках вашого завдання. +::: + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +



+ +## Документація + +- [П'ятірка: короткий вступ] (https://ton.org/fiftbase.pdf) +- [Віртуальна машина TON](/learn/tvm-instructions/tvm-overview) + +## Приклади + +- [Приклади п'яти смарт-контрактів](/develop/smart-contracts/examples#fift-smart-contracts) + +## Навчальні посібники + +- [Вступ до Fift] (https://blog.ton.org/introduction-to-fift) +- [\[YouTube\]Його величність П'ятірка](https://www.youtube.com/watch?v=HVsveTmVowc&list=PLtUBO1QNEKwttRsAs9eacL2oCMOhWaOZs) \[[RU версія](https://www.youtube.com/playlist?list=PLyDBPwv9EPsCYG-hR4N5FRTKUkfM8POgh)] by **@MarcoDaTr0p0je** & **@Wikimar**. + +## Джерела + +- [П'ять скриптів для стандартних смарт-контрактів] (https://github.com/ton-blockchain/ton/tree/master/crypto/smartcont) diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/develop/func/overview.mdx b/i18n/uk/docusaurus-plugin-content-docs/current/develop/func/overview.mdx new file mode 100644 index 0000000000..2be052ec27 --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/develop/func/overview.mdx @@ -0,0 +1,157 @@ +import Button from '@site/src/components/button' + +# Огляд + +Для програмування смарт-контрактів на TON використовується мова високого рівня FunC. + +FunC - це специфічна для домену C-подібна мова зі статичною типізацією. +Ось простий приклад методу для переказу грошей, написаний на FunC: + +```func +() send_money(slice address, int amount) impure inline { + var msg = begin_cell() + .store_uint(0x10, 6) ;; nobounce + .store_slice(address) + .store_coins(amount) + .end_cell(); + + send_raw_message(msg, 64); +} +``` + +FunC програми компілюються в асемблерний код Fift, який генерує відповідний байт-код для [TON Virtual Machine] (/learn/tvm-instructions/tvm-overview). + +Далі цей байт-код (фактично [дерево комірок] (/learn/overviews/cells), як і будь-які інші дані в TON Blockchain) може бути використаний для створення смарт-контрактів в блокчейні або може бути запущений на локальному екземплярі TVM. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Компілятор + +### Компіляція з JS + +Найзручніший і найшвидший спосіб почати розробляти і компілювати смарт-контракти - це використовувати фреймворк Blueprint. Детальніше читайте в розділі [Blueprint](/develop/smart-contracts/sdk/javascript). + +```bash +npm create ton@latest +``` + +### Компіляція з оригінальними двійковими файлами + +Якщо ви хочете використовувати рідний TON-компілятор FunC локально, вам потрібно встановити двійкові файли на вашому комп'ютері. Двійкові файли компілятора FunC для Windows, MacOS (Intel/M1) та Ubuntu можна завантажити за посиланням: + +- [Сторінка налаштування середовища](/develop/smart-contracts/environment/installation) + +:::info +У той же час, ви завжди можете створити двійкові файли з таких джерел, як:\ +[Вихідний код компілятора FunC](https://github.com/ton-blockchain/ton/tree/master/crypto/func) (читайте [як скомпілювати](/develop/howto/compile#func) компілятор FunC з вихідних текстів). +::: + +## Курс TON: FunC + +Курс [TON Blockchain Course] (https://stepik.org/course/176754/) - це вичерпний посібник з розробки TON Blockchain. + +Модуль 4 повністю присвячений мові FunC та розробці смарт-контрактів. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Навчальні посібники + +:::tip наконечник стартера +Найкраще почати розробку з використанням FunC: [ВСТУП](/develop/smart-contracts/) +::: + +Інші матеріали люб'язно надані експертами спільноти: + +- [Серія TON Speed Run](https://tonspeedrun.com/) + - [🚩 Виклик 1: Просте розгортання NFT] (https://github.com/romanovichim/TONQuest1) + - [🚩 Виклик 2: Контракт з чат-ботом] (https://github.com/romanovichim/TONQuest2) + - [🚩 Виклик 3: Торговий автомат Jetton] (https://github.com/romanovichim/TONQuest3) + - [🚩 Виклик 4: Лотерея/розіграш] (https://github.com/romanovichim/TONQuest4) + - [🚩 Виклик 5: Створіть UI для взаємодії з договором за 5 хвилин] (https://github.com/romanovichim/TONQuest5) + - [🚩 Виклик 6: Аналіз продажів NFT на маркетплейсі Getgems] (https://github.com/romanovichim/TONQuest6) + + + +- [Func & Blueprint](https://www.youtube.com/watch?v=7omBDfSqGfA&list=PLtUBO1QNEKwtO_zSyLj-axPzc9O9rkmYa) by **@MarcoDaTr0p0je** +- [Learn FunC in Y Minutes](https://learnxinyminutes.com/docs/func/) by **@romanovichim** +- [TON Hello World: Покрокове керівництво для написання вашого першого смарт-контракту] (https://ton-community.github.io/tutorials/02-contract/) +- [TON Hello World: Покрокове керівництво для тестування вашого першого смарт-контракту] (https://ton-community.github.io/tutorials/04-testing/) +- [10 FunC уроків](https://github.com/romanovichim/TonFunClessons_Eng) від **@romanovichim**, з використанням blueprint +- [10 уроків FunC (RU)](https://github.com/romanovichim/TonFunClessons_ru) by **@romanovichim**, using blueprint +- [FunC Quiz](https://t.me/toncontests/60) від **Vadim** - добре підходить для самоперевірки. Займе 10-15 хвилин. Питання переважно про FunС з кількома загальними питаннями про TON +- [FunC Quiz (RU)](https://t.me/toncontests/58?comment=14888) by **Vadim**-FunC Quiz російською мовою + +## Конкурси + +Участь у [конкурсах](https://t.me/toncontests) - чудовий спосіб вивчити FunC. + +Ви також можете вивчити попередні конкурси з навчальною метою. + +#### Конкурси Спадщина + +| Опис конкурсу | Завдання | Рішення | +| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| TSC #5 (грудень, 2023) | [Завдання](https://github.com/ton-community/tsc5) | | +| TSC #4 (вересень, 2023) | [Завдання](https://github.com/ton-community/tsc4) | [Рішення](/develop/smart-contracts/examples#ton-smart-challenge-4) | +| TSC #3 (грудень, 2022) | [Завдання](https://github.com/ton-blockchain/func-contest3) | [Рішення] (https://github.com/nns2009/TON-FunC-contest-3) | +| TSC #2 (липень, 2022) | [Завдання](https://github.com/ton-blockchain/func-contest2) | [Рішення] (https://github.com/ton-blockchain/func-contest2-solutions) | +| TSC #1 (березень, 2022) | [Завдання](https://github.com/ton-blockchain/func-contest1) | [Рішення] (https://github.com/ton-blockchain/func-contest1-solutions) | + +## Приклади смарт-контрактів + +Стандартні базові смарт-контракти, такі як гаманці, електорат (управляє валідацією на TON), гаманці з декількома підписами і т.д., можуть бути орієнтиром при вивченні. + +- [Приклади смарт-контрактів](/develop/smart-contracts/examples) + +## Журнал змін + +[Історія оновлень funC](/develop/func/changelog). diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/develop/overview.mdx b/i18n/uk/docusaurus-plugin-content-docs/current/develop/overview.mdx new file mode 100644 index 0000000000..f0268944bb --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/develop/overview.mdx @@ -0,0 +1,207 @@ +import Button from '@site/src/components/button' +import Player from '@site/src/components/player' + +# Документація TON + +Ласкаво просимо до офіційної документації з розробки TON Blockchain! + +Цей ресурс має на меті надати вам всю необхідну інформацію, яка знадобиться вам для створення, тестування та розгортання додатків на блокчейні TON. + +Це спільна ініціатива з відкритим вихідним кодом, і внески завжди вітаються. Вся документація може бути відредагована через GitHub, просто [дотримуйтесь цих інструкцій](/contribute). + +- Серія _TON Hello World_ містить детальні покрокові інструкції щодо гаманців, смарт-контрактів, міні-додатків, а також тестування та налагодження смарт-контрактів на TON. +- Початок роботи з TON - це покрокове керівництво по взаємодії з блокчейном TON. (відеоурок додається) + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +### Основи блокчейну з TON + +Цей курс знайомить з основами блокчейну, з особливим акцентом на практичні навички роботи в екосистемі TON. Ви зрозумієте, як функціонує блокчейн та його різноманітні застосування. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +### Курс TON + +Ми з гордістю представляємо курс **TON Blockchain Course**, який є вичерпним посібником з блокчейну TON. Курс призначений для розробників, які хочуть навчитися створювати смарт-контракти та децентралізовані додатки на блокчейні TON в цікавій та інтерактивній формі. + +Він складається з **9 модулів** і охоплює основи блокчейну TON, мови програмування FunC та віртуальної машини TON (TVM). + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Модулі розробки + +Якщо ви новачок у розробці TON Blockchain, рекомендується почати з самого початку і пропрацювати ці теми. + +### Фундаментальні концепції + +- [The Open Network] (/learn/introduction) - Огляд блокчейну TON на високому рівні. +- [Блокчейн з блокчейнів] (/learn/overviews/ton-blockchain) - доступне пояснення TON Blockchain. +- [Адреси смарт-контрактів](/learn/overviews/addresses) - детальне пояснення адрес. +- [Клітинки як структура даних](/learn/overviews/cells) - високорівневе пояснення структур даних. +- [TON Networking](/learn/networking/oview) - огляд високорівневих однорангових протоколів TON. +- [TON Virtual Machine (TVM)](/learn/tvm-instructions/tvm-oview) - Огляд віртуальної машини TON високого рівня. +- [Транзакції та фази](/learn/tvm-instructions/tvm-overview#transactions-and-phases) - Детальне пояснення транзакцій та фаз. +- [Транзакційні збори](/develop/smart-contracts/fees) - Пояснення на високому рівні щодо транзакційних зборів. + +### Інфраструктура + +- [Типи вузлів](/participate/nodes/node-types) - Детальне пояснення типів вузлів. +- [Запустити повний вузол](/participate/run-nodes/full-node) - детальне пояснення, як запустити вузол. +- [TON DNS & Sites](/participate/web3/dns) - детальне пояснення TON DNS & Sites. +- [TON Storage](/participate/ton-storage/storage-daemon) - Детальне пояснення про TON Storage. + +### Додаткові ресурси + +- [**FAQ**](/develop/howto/faq) - Часті запитання +- [Документація FunC](/develop/func/overview) +- [Документація Fift](/develop/fift/overview) + +## Розробка смарт-контрактів + +Смарт-контракти - це будівельні блоки децентралізованих додатків (DApps) на блокчейні TON. Якщо ви хочете розробити власний DApp, важливо розуміти, як працюють смарт-контракти. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +



+ +Наступні ресурси надають цінну інформацію для розробки смарт-контрактів TON: + +- [TON Hello World: Покрокове керівництво для написання вашого першого смарт-контракту] (https://ton-community.github.io/tutorials/02-contract/) - Доступне і стисле пояснення основ роботи з JS. +- [Як працювати зі смарт-контрактами гаманця](/develop/smart-contracts/tutorials/wallet) - Детальне та ретельне пояснення основ смарт-контрактів з використанням JS та GO. +- [Вивчаємо смарт-контракти на прикладах](/develop/smart-contracts/examples) (FunC, Fift) +- [Speed Run TON](/develop/smart-contracts/examples) - 6 інтерактивних завдань та покрокових інструкцій для навчання розробці смарт-контрактів. + +## Розробка DApp + +Децентралізовані додатки (DApps) - це додатки, які працюють на одноранговій мережі комп'ютерів, а не на одному комп'ютері (TON Blockchain). Вони схожі на традиційні веб-додатки, але побудовані поверх мережі блокчейн. Це означає, що DApps децентралізовані, тобто жодна організація не контролює їх. + +```mdx-code-block + +``` + +### Розробка DeFi + +- [TON Connect](/develop/dapps/ton-connect/overview) - інтеграція та автентифікація для DApps. +- [Off-chain Payments Processing](/develop/dapps/asset-processing) - приклади та концепції обробки платежів. +- [TON обробка джеттонів](/develop/dapps/asset-processing/jettons) - приклади та концепції для обробки джеттонів. +- [Взаємозамінні (crwd)lbracket/dwrc(FT) Не взаємозамінні crwdlbracketdwrcNFT токени] (/develop/dapps/defi/tokens) - смарт-контракти, приклади, інструменти + +Зробіть перші кроки у розробці DApps за допомогою вичерпного посібника зі створення DApps: + +- [TON Hello World: Покрокове керівництво для створення вашого першого веб-клієнта] (https://ton-community.github.io/tutorials/03-client/) +- [Інтеграція Telegram-бота через TON Connect](/develop/dapps/ton-connect/tg-bot-integration) + +### API та SDK + +- [API](/develop/dapps/apis) +- [SDK](/develop/dapps/apis/sdk) + +## Поширені запитання + +Перейдіть до розділу [Часті запитання] (/develop/howto/faq). diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/develop/smart-contracts/testing/overview.mdx b/i18n/uk/docusaurus-plugin-content-docs/current/develop/smart-contracts/testing/overview.mdx new file mode 100644 index 0000000000..e77b991b73 --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/develop/smart-contracts/testing/overview.mdx @@ -0,0 +1,141 @@ +# Написання тестів за допомогою Blueprint + +## Огляд + +Інструментарій для тестування (зазвичай пісочниця) вже включено до TypeScript SDK під назвою [Blueprint](/develop/smart-contracts/sdk/javascript). Ви можете створити демонстраційний проект і запустити тест за замовчуванням у два кроки: + +1. Створіть новий проєкт Blueprint: + +```bash +npm create ton@latest MyProject +``` + +2. Проведіть тест: + +```bash +cd MyProject +npx blueprint test +``` + +В результаті ви побачите відповідний вивід у вікні терміналу: + +```bash +% npx blueprint test + +> MyProject@0.0.1 test +> jest + + PASS tests/Main.spec.ts + Main + ✓ should deploy (127 ms) + +Test Suites: 1 passed, 1 total +Tests: 1 passed, 1 total +Snapshots: 0 total +Time: 1.224 s, estimated 2 s +Ran all test suites. +``` + +## Основне використання + +Тестування смарт-контрактів дозволяє перевірити безпеку, оптимізувати витрати газу та дослідити крайні випадки. +Написання тестів у Blueprint (на основі [Sandbox](https://github.com/ton-org/sandbox)) працює через визначення довільних дій з контрактом і порівняння результатів тесту з очікуваним результатом, наприклад: + +```typescript +it('should execute with success', async () => { // description of the test case + const res = await main.sendMessage(sender.getSender(), toNano('0.05')); // performing an action with contract main and saving result in res + + expect(res.transactions).toHaveTransaction({ // configure the expected result with expect() function + from: main.address, // set expected sender for transaction we want to test matcher properties from + success: true // set the desirable result using matcher property success + }); + + printTransactionFees(res.transactions); // print table with details on spent fees +}); +``` + +### Написання тестів на складне твердження + +Основний робочий процес створення тесту виглядає наступним чином: + +1. Створіть спеціальну обгорнуту сутність `Contract` за допомогою `blockchain.openContract()`. +2. Опишіть дії, які повинен виконати ваш `Contract`, і збережіть результат виконання у змінній `res`. +3. Перевірте властивості за допомогою функції `expect()` та відповідника `toHaveTransaction()`. + +Відповідник `toHaveTransaction` очікує об'єкт з будь-якою комбінацією полів типу `FlatTransaction`, визначених з наступними властивостями + +| Ім'я | Тип | Опис | +| -------------------------------------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| від | Адреса? | Контрактна адреса відправника повідомлення | +| на | Адреса | Контрактна адреса призначення повідомлення (Альтернативна назва властивості `to`). | +| значення | Біґінт? | Кількість Toncoins у повідомленні в нанотонах | +| тіло | Cell | Тіло повідомлення визначено як комірка | +| op | номер? | Код операції - це номер ідентифікатора операції (зазвичай crc32 у TL-B). Очікується у перших 32 бітах тіла повідомлення. | +| успіх | булевий? | Прапорець користувацької пісочниці, який визначає результуючий статус певної транзакції. True - якщо і обчислення, і фаза дії пройшли успішно. В іншому випадку - False. | + +Ви можете опустити поля, які вас не цікавлять, і передати функції, які приймають типи, що повертають булеві значення ("істина" означає "добре") для перевірки, наприклад, діапазонів чисел, опкодів повідомлень тощо. Зверніть увагу, що якщо поле є необов'язковим (наприклад, `from?: Address`), то функція також повинна приймати необов'язковий тип. + +:::tip +Повний список полів-відповідників ви можете знайти в [Документації пісочниці](https://github.com/ton-org/sandbox#test-a-transaction-with-matcher). +::: + +### Спеціальний набір тестів + +#### Витягнути SendMode + +Щоб витягти режим відправлення надісланого повідомлення, ви можете скористатися наступним кодом: + +```ts + +const smc = await blockchain.getContract(addr); + +const re = blockchain.executor.runTransaction({ + config: blockchain.configBase64, libs: null, verbosity: 'full', + now: Math. floor (Date.now) / 1000), + lt: BigInt(Date.now()), + randomSeed: null, + ignoreChksig: false, + debugEnabled: true, + shardAccount: beginCell() + .store (storeShardAccount (smc.account)) + .endCell() + .toBoc() + .toString('base64'), + message: beginCell() + .store (storeMessageRelaxed (...)) + .endCell(), +}); + +if (!re.result. success || !re.result.actions) { + throw new Error('fail'); +} +const actions = loadoutList(Cell.fromBase64(re.result.actions).beginParse()); +actions[0].type === 'sendMsg' && actions[0].mode; + +``` + +## Навчальні посібники + +Дізнайтеся більше про тестування з найцінніших підручників спільноти на TON: + +- [Урок 2: Тестування FunC для смарт-контракту] (https://github.com/romanovichim/TonFunClessons_Eng/blob/main/lessons/smartcontract/2lesson/secondlesson.md) +- [TON Hello World частина 4: Покрокове керівництво для тестування вашого першого смарт-контракту] (https://ton-community.github.io/tutorials/04-testing/) +- [TON Smart Contract Pipeline](https://dev.to/roma_i_m/ton-smart-contract-pipeline-write-simple-contract-and-compile-it-4pnh) +- \[[YouTube]Шостий урок FunC & Blueprint. Газ, збори, тести]] (https://youtu.be/3XIpKZ6wNcg) + +## Приклади + +Ознайомтеся з наборами тестів, які використовуються для контрактів TON Ecosystem, і навчіться на прикладах. + +- [випробування в пісочниці з рідинно-контрактним підрядом](https://github.com/ton-blockchain/liquid-staking-contract/tree/main/tests) +- [governance_tests](https://github.com/Trinketer22/governance_tests/blob/master/config_tests/tests/) +- [JettonWallet.spec.ts](https://github.com/EmelyanenkoK/modern_jetton/blob/master/tests/JettonWallet.spec.ts) +- [governance_tests](https://github.com/Trinketer22/governance_tests/blob/master/elector_tests/tests/complaint-test.fc) +- [MassSender.spec.ts](https://github.com/Gusarich/ton-mass-sender/blob/main/tests/MassSender.spec.ts) +- [TonForwarder.spec.ts](https://github.com/TrueCarry/ton-contract-forwarder/blob/main/src/contracts/ton-forwarder/TonForwarder.spec.ts) +- [Assurer.spec.ts](https://github.com/aSpite/dominant-assurance-contract/blob/main/tests/Assurer.spec.ts) + +## Дивіться також + +- [Blueprint](/develop/smart-contracts/sdk/javascript) +- [toncli](/develop/smart-contracts/testing/toncli) diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/learn/academy/academy-overview.md b/i18n/uk/docusaurus-plugin-content-docs/current/learn/academy/academy-overview.md new file mode 100644 index 0000000000..3c8a893907 --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/learn/academy/academy-overview.md @@ -0,0 +1,16 @@ +# Освітні ресурси + +### TON Speedrun + +- [TON Speedrun](https://tonspeedrun.com/) - спеціалізована платформа, призначена для практичного підходу до навчання в розробці TON. + +### Курси + +- [Blockchain Basics with TON](https://stepik.org/course/201294/promo) ([RU версія](https://stepik.org/course/202221/), [CHN версія](https://stepik.org/course/200976/)) - + Цей курс знайомить з основами блокчейну, з особливим акцентом на практичні навички в екосистемі TON. Ви зрозумієте, як функціонує блокчейн та його різноманітні застосування. + +## Дивіться також + +- [Speedrun TON](https://tonspeedrun.com/) +- [TON Hello World] (https://tonhelloworld.com/01-wallet/) +- [[YouTube] TON Dev Study EN] (https://www.youtube.com/@TONDevStudy) [[RU]] (https://www.youtube.com/results?search_query=tondevstudy) diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/learn/introduction.mdx b/i18n/uk/docusaurus-plugin-content-docs/current/learn/introduction.mdx new file mode 100644 index 0000000000..e1f842e25b --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/learn/introduction.mdx @@ -0,0 +1,81 @@ +import Player from '@site/src/components/player' +import Button from '@site/src/components/button' + +# Відкрита мережа + +Відкрита мережа (TON) - це децентралізована і відкрита інтернет-платформа, що складається з декількох компонентів. До них відносяться: Блокчейн TON, DNS TON, сховище TON і сайти TON. Блокчейн TON - це основний протокол, який з'єднує базову інфраструктуру TON разом, щоб сформувати велику екосистему TON. + +TON орієнтований на досягнення широкої міжмережевої інтероперабельності, працюючи у високомасштабованій безпечній платформі. TON призначена для обробки мільйонів транзакцій в секунду (TPS), з метою охоплення сотень мільйонів користувачів, які рухаються вперед. + +Блокчейн розроблений як розподілений суперкомп'ютер, або "суперсервер", призначений для надання різноманітних продуктів і послуг, що сприятимуть розвитку децентралізованого бачення нового інтернету. + +- Дізнайтеся, які послуги ТОН надає своїм користувачам, переглянувши цей розділ: [Взяти участь у TON] (/участі/) +- Щоб дізнатися більше про технічні аспекти TON Blockchain, перегляньте [Блокчейн з блокчейнів] (/learn/overviews/ton-blockchain) +- Дізнайтеся більше про розробку всього, що стосується TON, переглянувши цей розділ: [Початок роботи] (/develop/oview) + +## Огляд з висоти пташиного польоту + +Щоб зрозуміти справжнє бачення децентралізованого інтернету і те, як TON сприяє цій неминучості, подивіться відео нижче: + + + +## Основи блокчейну з TON + +Цей курс знайомить з основами блокчейну, з особливим акцентом на практичні навички роботи в екосистемі TON. Ви зрозумієте, як функціонує блокчейн та його різноманітні застосування. Ви також отримаєте важливі навички, пов'язані з TON, включаючи налаштування гаманця, торгівлю NFT, створення Jetton і транзакції з монетами TON на децентралізованих біржах (DEX). Курс також забезпечить вас критично важливими знаннями про криптовалютні загрози та шахрайство і дасть практичні поради, як захистити свої криптовалютні активи. + +- [Blockchain Basics with TON](https://stepik.org/course/201294/) ([RU версія](https://stepik.org/course/202221/), [CHN версія](https://stepik.org/course/200976/)) + +## Курс TON Blockchain + +Ми з гордістю представляємо вам курс **TON Blockchain Course**, який є вичерпним посібником з блокчейну TON. Курс призначений для розробників, які хочуть навчитися створювати смарт-контракти та децентралізовані додатки на блокчейні TON. + +Він складається з **9 модулів** і охоплює основи блокчейну TON, мови програмування FunC та віртуальної машини TON (TVM). + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Новачок в блокчейні? + +Якщо ви не знайомі з блокчейном і не розумієте, що робить цю технологію такою революційною, подумайте про те, щоб глибоко зануритися в ці важливі ресурси: + +- [Що таке блокчейн? Що таке смарт-контракт? Що таке газ?] (https://blog.ton.org/what_is_blockchain) +- [Як блокчейн може допомогти вам на безлюдному острові] (https://talkol.medium.com/why-decentralized-consensus-blockchain-is-good-for-business-5ff263468210) +- [\[YouTube\] Криптографічні мережі і чому вони важливі] (https://youtu.be/2wxtiNgXBaU) + +## Відносини TON з Ethereum + +Для тих, хто знайомий з розробкою Ethereum, ми написали дві вступні статті, які допоможуть вам зрозуміти, що відрізняє TON в цьому відношенні: + +- [Шість унікальних аспектів блокчейну TON, які здивують розробників Solidity] (https://blog.ton.org/six-unique-aspects-of-ton-blockchain-that-will-surprise-solidity-developers) +- [Час спробувати щось нове: Асинхронні смарт-контракти] (https://telegra.ph/Its-time-to-try-something-new-Asynchronous-smart-contracts-03-25) +- [Порівняння блокчейнів] (https://ton.org/comparison_of_blockchains.pdf) diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/learn/networking/overview.md b/i18n/uk/docusaurus-plugin-content-docs/current/learn/networking/overview.md new file mode 100644 index 0000000000..0b8b537b61 --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/learn/networking/overview.md @@ -0,0 +1,19 @@ +# TON Networking + +Проект TON використовує власні пірингові мережеві протоколи. + +- **Блокчейн використовує ці протоколи** для розповсюдження нових блоків, надсилання та отримання кандидатів на транзакції тощо. + + У той час як мережеві вимоги одноблочних проектів, таких як Bitcoin або Ethereum, можна задовольнити досить легко (потрібно лише побудувати + однорангову оверлейну мережу, а потім поширювати всі нові блоки і + кандидатів на транзакції за допомогою протоколу [gossip](https://en.wikipedia.org/wiki/Gossip_protocol)), багатоблочні проекти, такі + як TON, набагато вимогливіші (наприклад, потрібно мати можливість + підписатися на оновлення лише деяких шардчейнів, а не обов'язково на всі). + +- **Екосистемні послуги TON (наприклад, TON Proxy, TON Sites, TON Storage) працюють на основі цих протоколів.**. + + Як тільки більш складні мережеві протоколи, необхідні + для підтримки блокчейну TON, будуть створені, виявиться, що їх можна легко + використовувати для цілей, не обов'язково пов'язаних з безпосередніми потребами самого + блокчейну, таким чином надаючи більше можливостей і гнучкості для створення + нових послуг в екосистемі TON. diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/learn/overviews/addresses.md b/i18n/uk/docusaurus-plugin-content-docs/current/learn/overviews/addresses.md new file mode 100644 index 0000000000..946eb904d7 --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/learn/overviews/addresses.md @@ -0,0 +1,220 @@ +# Адреси смарт-контрактів + +У цьому розділі буде описано специфіку адрес смарт-контрактів у блокчейні TON. Він також пояснить, як актори є синонімами смарт-контрактів на TON. + +## Все - це смарт-контракт + +На TON смарт-контракти будуються за допомогою [моделі актора] (/learn/overviews/ton-blockchain#single-actor). Фактично, актори в TON технічно представлені як смарт-контракти. Це означає, що навіть ваш гаманець є простим актором (і смарт-контрактом). + +Зазвичай актори обробляють вхідні повідомлення, змінюють свій внутрішній стан і в результаті генерують вихідні повідомлення. Ось чому кожен актор (тобто смарт-контракт) в блокчейні TON повинен мати адресу, щоб мати можливість отримувати повідомлення від інших акторів. + +:::info ДОСВІД EVM +У віртуальній машині Ethereum (EVM) адреси повністю відокремлені від смарт-контрактів. Ви можете дізнатися більше про відмінності, прочитавши нашу статтю ["Шість унікальних аспектів TON Blockchain, які здивують розробників Solidity"] (https://blog.ton.org/six-unique-aspects-of-ton-blockchain-that-will-surprise-solidity-developers), автор - Тал Кол. +::: + +## Адреса смарт-контракту + +Адреси смарт-контрактів, що працюють на TON, зазвичай складаються з двох основних компонентів: + +- **(workchain_id)**: позначає ідентифікатор робочого ланцюжка (знакове 32-бітне ціле число) + +- **(account_id)** позначає адресу облікового запису (64-512 біт, залежно від ланцюжка) + +У розділі огляду сирих адрес цієї документації ми обговоримо, як виглядають пари **(workchain_id, account_id)**. + +### Ідентифікатор ланцюжка та ідентифікатор облікового запису + +#### Ідентифікатор ланцюжка + +[Як ми бачили раніше (/learn/overviews/ton-blockchain#workchain-blockchain-with-your-own-rules), можна створити цілих `2^32` робочих ланцюжків, що працюють на TON Blockchain. Ми також звернули увагу на те, як 32-розрядні префіксні адреси смарт-контрактів ідентифікуються і пов'язуються з адресами смарт-контрактів в різних ланцюжках. Це дозволяє смарт-контрактам відправляти і отримувати повідомлення до і від різних ланцюжків в TON Blockchain. + +На сьогоднішній день в блокчейні TON працює лише майстер-ланцюг (workchain_id=-1) та іноді основний ланцюг (workchain_id=0). + +Обидва вони мають 256-бітові адреси, тому ми припускаємо, що ідентифікатор workchain_id дорівнює або 0, або -1, а адреса всередині ланцюжка має точно 256 біт. + +#### Ідентифікатор облікового запису + +Всі ідентифікатори облікових записів на TON використовують 256-бітові адреси в Masterchain і Basechain (або базовому ланцюжку). + +Фактично, ідентифікатор облікового запису **(account_id)** визначається як хеш-функція для об'єктів смарт-контракту (зокрема, SHA-256). Кожен смарт-контракт, що працює на блокчейні TON, зберігає два основних компоненти. До них відносяться: + +1. Скомпільований код. Логіка смарт-контракту, скомпільована у вигляді байт-коду. +2. Початковий стан. Значення контракту на момент його розгортання в ланцюжку. + +Нарешті, щоб точно отримати адресу контракту, необхідно обчислити хеш, що відповідає парі **(Початковий код, Початковий стан)** об'єкта. Наразі ми не будемо заглиблюватися в те, як працює [TVM](/learn/tvm-instructions/tvm-overview), але важливо розуміти, що ідентифікатори облікових записів на TON визначаються за такою формулою: +: +**account_id = hash(початковий код, початковий стан)**. + +Згодом, в цій документації, ми зануримося глибше в технічні характеристики і огляд схеми TVM і TL-B. Тепер, коли ми ознайомилися з генерацією **account_id** і їх взаємодією з адресами смарт-контрактів на TON, давайте пояснимо, що таке Raw і User-Friendly адреси. + +## Стан адреси + +Кожна адреса може перебувати в одному з можливих станів: + +- `неіснуючий` - за цією адресою не було жодної прийнятої транзакції, тому вона не має жодних даних (або договір було видалено). Можна сказати, що спочатку всі2256 адрес знаходяться в цьому стані. +- `uninit` - адреса має деякі дані, які містять баланс і метаінформацію. У цьому стані адреса ще не має коду смарт-контракту/постійних даних. Адреса переходить в цей стан, наприклад, коли її не існувало, а якась інша адреса надіслала на неї токени. +- `активний` - адреса має код смарт-контракту, постійні дані та баланс. У цьому стані вона може виконувати певну логіку під час транзакції та змінювати свої постійні дані. Адреса переходить в цей стан, коли вона була `uninit` і було вхідне повідомлення з параметром state_init (зверніть увагу, що для розгортання цієї адреси хеш `state_init` і `code` повинен бути рівним адресі). +- `frozen` - адреса не може виконувати жодних операцій, цей стан містить лише два хеші попереднього стану (комірку коду та комірку стану відповідно). Коли витрати на зберігання адреси перевищують її баланс, вона переходить у цей стан. Щоб розморозити його, ви можете відправити внутрішнє повідомлення з `state_init` і `code`, які зберігають хеші, описані раніше, і трохи Toncoin. Відновити його може бути складно, тому не варто допускати такої ситуації. Існує проект для розморожування адреси, який ви можете знайти [тут] (https://unfreezer.ton.org/). + +## Сирі та зручні для користувача адреси + +Після короткого огляду того, як адреси смарт-контрактів в ланцюжках ланцюжків і ідентифікаторів облікових записів TON (зокрема, для Masterchain і Basechain), важливо розуміти, що ці адреси виражаються в двох основних форматах: + +- **Сирі адреси**: Оригінальне повне представлення адрес смарт-контрактів. +- **Зручні адреси**: Зручні для користувача адреси - це покращений формат сирої адреси, який забезпечує кращу безпеку та простоту використання. + +Нижче ми пояснимо відмінності між цими двома типами адрес і зануримося глибше в те, чому в TON використовуються зручні для користувача адреси. + +### Сира адреса + +Сирі адреси смарт-контрактів складаються з ідентифікатора ланцюжка і ідентифікатора облікового запису *(workchain_id, account_id)* і відображаються в наступному форматі: + +- [десятковий ідентифікатор_ланцюга\]:[64 шістнадцяткових цифри з ідентифікатором_рахунку\] + +Нижче наведено приклад необробленої адреси смарт-контракту з використанням ідентифікатора ланцюжка і ідентифікатора облікового запису разом (у вигляді **workchain_id** і **account_id**): + +`-1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260` + +Зверніть увагу на `-1` на початку адресного рядка, який позначає ідентифікатор *workchain_id*, що належить до майстер-ланцюга. + +:::note +В адресних рядках можна використовувати великі літери (наприклад, 'A', 'B', 'C', 'D' і т.д.) замість малих (наприклад, 'a', 'b', 'c', 'd' і т.д.). +::: + +#### Проблеми з необробленими адресами + +Використання форми Raw Address пов'язане з двома основними проблемами: + +1. При використанні формату "сирої" адреси неможливо перевірити адреси для усунення помилок перед відправленням транзакції. + Це означає, що якщо ви випадково додасте або видалите символи в адресному рядку перед відправленням транзакції, ваша транзакція буде відправлена не за адресою призначення, що призведе до втрати коштів. +2. При використанні формату сирої адреси неможливо додати спеціальні прапори, подібні до тих, що використовуються при надсиланні транзакцій, які використовують зручні для користувача адреси. + Щоб допомогти вам краще зрозуміти цю концепцію, нижче ми пояснимо, які прапори можна використовувати. + +### Зручна для користувача адреса + +Зручні адреси були розроблені для того, щоб убезпечити і спростити роботу користувачів TON, які обмінюються адресами в Інтернеті (наприклад, на платформах обміну повідомленнями або через своїх постачальників послуг електронної пошти), а також в реальному світі. + +#### Зручна для користувача адресна структура + +Зручні для користувача адреси складаються загалом з 36 байт і отримуються шляхом генерації наступних компонентів по порядку: + +1. *[прапори - 1 байт]* - Прапори, які прив'язуються до адрес, змінюють спосіб реагування смарт-контрактів на отримане повідомлення. + Типи прапорів, які використовують зручний для користувача формат адреси, включають наступні: + + - isBounceable. Позначає тип адреси, що підлягає або не підлягає поверненню. (*0x11* для "bounceable", *0x51* для "non-bounceable") + - isTestnetOnly. Позначає тип адреси, який використовується лише для цілей тестової мережі. Адреси, що починаються з *0x80*, не повинні прийматися програмним забезпеченням, що працює у виробничій мережі + - isUrlSafe. Позначає застарілий прапорець, який визначає адресу як URL-безпечну. Після цього всі адреси вважаються URL-безпечними. +2. *\[workchain_id - 1 байт]* - Ідентифікатор ланцюжка (*workchain_id*) визначається знаковим 8-бітним цілим числом *workchain_id*.\ + (*0x00* для BaseChain, *0xff* для MasterChain) +3. *\[account_id - 32 byte]* - Ідентифікатор облікового запису складається з ([big-endian](https://www.freecodecamp.org/news/what-is-endianness-big-endian-vs-little-endian/)) 256-бітної адреси в робочому ланцюжку. +4. *\[перевірка адреси - 2 байти]* - У зручних для користувача адресах перевірка адреси складається з підпису CRC16-CCITT з попередніх 34 байт. ([Приклад](https://github.com/andreypfau/ton-kotlin/blob/ce9595ec9e2ad0eb311351c8a270ef1bd2f4363e/ton-kotlin-crypto/common/src/crc32.kt)) + Насправді, ідея перевірки для зручних для користувача адрес дуже схожа на [алгоритм Луна](https://en.wikipedia.org/wiki/Luhn_algorithm), який використовується на всіх кредитних картках, щоб запобігти помилковому введенню користувачами неіснуючих номерів карток. + +Додавання цих 4 основних компонентів означає, що `1 + 1 + 32 + 2 = 36` байт загалом (на одну зручну для користувача адресу). + +Щоб згенерувати зручну для користувача адресу, розробник повинен закодувати всі 36 байт, використовуючи будь-яку з них: + +- *base64* (тобто з цифрами, великими та малими латинськими літерами, символами '/' та '+') +- *base64url* (з '_' та '-' замість '/' та '+') + +Після завершення цього процесу завершується генерація зручної для користувача адреси довжиною 48 символів без пробілів. + +:::info ПРАПОРИ DNS-АДРЕС +У домені TON DNS-адреси, такі як mywallet.ton, іноді використовуються замість сирих і зручних для користувача адрес. Насправді DNS-адреси складаються зі зручних для користувача адрес і включають всі необхідні прапори, які дозволяють розробникам отримати доступ до всіх прапорів з DNS-запису в домені TON. +::: + +#### Зручні для користувача приклади кодування адрес + +Наприклад, смарт-контракт "test giver" (спеціальний смарт-контракт, що знаходиться в майстер-ланцюжку testnet і надсилає 2 тестових токени кожному, хто їх запитує) використовує наступну сиру адресу: + +`-1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260` + +Наведена вище сира адреса "постачальника тесту" має бути перетворена у зручну для користувача адресну форму. Це можна зробити за допомогою форм base64 або base64url (які ми розглядали раніше) наступним чином: + +- `kf/8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15+KsQHFLbKSMiYIny` (base64) +- `kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny` (base64url) + +:::info +Зверніть увагу, що обидві форми (*base64* і *base64url*) є дійсними і повинні бути прийняті! +::: + +#### Відновлювані та невідновлювані адреси + +Основна ідея прапорця bounceable address - це безпека коштів відправника. + +Наприклад, якщо смарт-контракт призначення не існує, або якщо під час транзакції виникне якась проблема, повідомлення буде "повернуто" відправнику і становитиме залишок початкової вартості транзакції (за вирахуванням всіх комісій за переказ і газ). Це гарантує, що відправник не втратить свої кошти, які були випадково надіслані на адресу, яка не може прийняти транзакцію. + +Зокрема, це стосується адрес, які можуть бути ретрансльованими: + +1. Прапор **bounceable=false** зазвичай означає, що отримувач є гаманцем. +2. Прапорець **bounceable=true** зазвичай позначає кастомний смарт-контракт з власною прикладною логікою (наприклад, DEX). У цьому прикладі з міркувань безпеки не слід надсилати повідомлення, що не відбиваються. + +Не соромтеся читати більше на цю тему в нашій документації, щоб краще зрозуміти [повідомлення, що не відскакують] (/develop/smart-contracts/guidelines/non-bouncable-messages). + +#### Броньовані представлення base64 + +Додаткові двійкові дані, пов'язані з блокчейном TON, використовують подібні "броньовані" зручні для користувача представлення адрес у форматі Base64. Вони відрізняються один від одного в залежності від перших 4 символів їх байтового тегу. Наприклад, 256-бітові публічні ключі Ed25519 представляються шляхом створення 36-байтової послідовності, використовуючи описаний нижче процес: + +- Однобайтовий тег у форматі *0x3E* позначає відкритий ключ +- Однобайтовий тег у форматі *0xE6* позначає відкритий ключ Ed25519 +- 32 байти, що містять стандартне двійкове представлення відкритого ключа Ed25519 +- 2 байти, що містять представлення CRC16-CCITT у великій системі числення попередніх 34 байт + +Отримана 36-байтна послідовність перетворюється в 48-символьний рядок base64 або base64url стандартним способом. Наприклад, відкритий ключ Ed25519 `E39ECDA0A7B0C60A7107EC43967829DBE8BC356A49B9DFC6186B3EAC74B5477D` (зазвичай представлений послідовністю з 32 байт, наприклад `0xE3, 0x9E, ..., 0x7D`) через "броньоване" представлення виглядає наступним чином: + +`Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2`. + +### Перетворення зручних для користувача адрес і сирих адрес + +Найпростіший спосіб перетворення зручних для користувача та необроблених адрес - це використання одного з декількох API TON та інших інструментів, зокрема: + +- [ton.org/address](https://ton.org/address) +- [dton.io API method](https://dton.io/api/address/0:867ac2b47d1955de6c8e23f57994fad507ea3bcfe2a7d76ff38f29ec46729627) +- [методи API toncenter у mainnet](https://toncenter.com/api/v2/#/accounts/pack_address_packAddress_get) +- [методи API toncenter у testnet](https://testnet.toncenter.com/api/v2/#/accounts/pack_address_packAddress_get) + +Крім того, існує два способи перетворення зручних і необроблених адрес гаманців за допомогою JavaScript: + +- [Перетворення адреси з/в зручну для користувача або необроблену форму за допомогою ton.js](https://github.com/ton-org/ton-core/blob/main/src/address/Address.spec.ts) +- [Перетворення адреси з/в зручну для користувача або необроблену форму за допомогою tonweb](https://github.com/toncenter/tonweb/tree/master/src/utils#address-class) + +Також можна скористатися подібними механізмами за допомогою [SDK] (/develop/dapps/apis/sdk). + +### Приклади адрес + +Дізнайтеся більше прикладів про адреси TON у [Кулінарній книзі TON] (/develop/dapps/cookbook#working-with-contracts-addresses). + +## Можливі проблеми + +При взаємодії з блокчейном TON дуже важливо розуміти наслідки переказу монет TON на адреси гаманців "uninit". У цьому розділі описані різні сценарії та їх результати, щоб забезпечити ясність щодо того, як обробляються такі транзакції. + +### Що відбувається, коли ви переводите Toncoin на адресу юніта? + +#### Транзакція з включеним \`state_init + +Якщо ви додаєте `state_init` (який складається з коду і даних гаманця або смарт-контракту) до своєї транзакції. Смарт-контракт спочатку розгортається з використанням наданого `state_init`. Після розгортання, вхідне повідомлення обробляється, подібно до відправки на вже ініціалізований акаунт. + +#### Транзакція без встановлених прапорів `state_init` та `bounce` + +Повідомлення не може бути доставлене до смарт-контракту `uninit`, і воно буде повернуте назад відправнику. Після вирахування плати за спожитий газ сума, що залишилася, повертається на адресу відправника. + +#### Транзакція без встановлених прапорів `state_init` та `bounce` + +Повідомлення не може бути доставлене, але воно не повернеться до відправника. Замість цього відправлена сума буде зарахована на адресу одержувача, збільшуючи його баланс, навіть якщо гаманець ще не ініціалізований. Вони зберігатимуться там доти, доки власник адреси не розгорне контракт смарт-гаманця, і тоді він зможе отримати доступ до балансу. + +#### Як це зробити правильно + +Найкращий спосіб розгорнути гаманець - це надіслати на його адресу (яка ще не ініціалізована) TON зі скинутим прапорцем `bounce`. Після цього кроку власник може розгорнути та ініціалізувати гаманець, використовуючи кошти за поточною неініціалізованою адресою. Цей крок зазвичай відбувається при першій операції з гаманцем. + +### У блокчейні TON реалізовано захист від помилкових транзакцій + +У блокчейні TON стандартні гаманці та додатки автоматично керують складнощами транзакцій на неініціалізовані адреси, використовуючи bounceable і non-bounceable адреси, які описані [тут] (#bounceable-vs-non-bounceable-addresses). Загальноприйнятою практикою для гаманців при відправці монет на неініціалізовані адреси є відправка монет як на bounceable, так і на non-bounceable адреси без повернення. + +Якщо є потреба швидко отримати адресу в bounceable/non-bounceable формі, це можна зробити [тут](https://ton.org/address/). + +### Відповідальність за кастомні продукти + +Якщо ви розробляєте власний продукт на блокчейні TON, важливо реалізувати подібні перевірки та логіку: + +Переконайтеся, що ваш додаток перевіряє, чи ініціалізовано адресу одержувача перед відправленням коштів. +На основі стану адреси використовуйте адреси з можливістю повернення для користувацьких смарт-контрактів зі спеціальною логікою додатку, щоб гарантувати повернення коштів. Для гаманців використовуйте адреси, що не повертаються. diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/learn/overviews/cells.md b/i18n/uk/docusaurus-plugin-content-docs/current/learn/overviews/cells.md new file mode 100644 index 0000000000..fd0e0db909 --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/learn/overviews/cells.md @@ -0,0 +1,52 @@ +# Клітини як сховище даних + +Все в TON зберігається в комірках. Комірка - це структура даних, що містить: + +- до **1023 біт** даних (не байт!) +- до **4 посилань** на інші комірки + +Біти та посилання не змішуються (вони зберігаються окремо). Циклічні посилання заборонені: для будь-якої комірки жодна з її нащадків не може мати цю початкову комірку як посилання. + +Таким чином, всі клітинки утворюють орієнтовний ациклічний граф (ОАГ). Ось гарний малюнок для ілюстрації: + +![Спрямований ациклічний графік](/img/docs/dag.png) + +## Типи клітин + +Наразі існує 5 типів клітин: *звичайні* та 4 *екзотичні*. +До екзотичних відносяться наступні типи: + +- Обрізана комірка гілки +- Комірка посилання на бібліотеку +- Комірка Меркле, стійка до впливу вологи +- Комірка оновлення Merkle + +:::tip +Детальніше про екзотичні клітини див: [**ТВМ Whitepaper, розділ 3**] (https://ton.org/tvm.pdf). +::: + +## Клітинні ароматизатори + +Комірка - це непрозорий об'єкт, оптимізований для компактного зберігання. + +Зокрема, вона дедублює дані: якщо є кілька еквівалентних підкомірок, на які є посилання в різних гілках, їхній вміст зберігається лише один раз. Однак, непрозорість означає, що комірку не можна змінювати або читати безпосередньо. Таким чином, з'являється 2 додаткових смаки комірок: + +- *Builder* для частково сконструйованих комірок, для яких можна визначити швидкі операції додавання бітових рядків, цілих чисел, інших комірок та посилань на інші комірки. +- *Slice* для "розрізаних" комірок, що представляють або залишок частково розібраної комірки, або значення (підкомірку), що знаходиться всередині такої комірки і витягнуте з неї за допомогою інструкції синтаксичного аналізу. + +Ще один особливий клітинний аромат використовується в TVM: + +- Продовження_ для комірок, що містять операційні коди (інструкції) для віртуальної машини TON, див. [Огляд TVM з висоти пташиного польоту](/learn/tvm-instructions/tvm-oview). + +## Серіалізація даних у комірки + +Будь-який об'єкт в TON (повідомлення, черга повідомлень, блок, стан всього блокчейну, код контракту і дані) серіалізується в комірку. + +Процес серіалізації описується схемою TL-B: формальним описом того, як цей об'єкт можна серіалізувати у *Builder* або як розібрати об'єкт заданого типу з *Slice*. +TL-B для комірок - це те саме, що TL або ProtoBuf для байтових потоків. + +Якщо ви хочете дізнатися більше про (де)серіалізацію комірок, ви можете прочитати статтю [Cell & Bag of Cells](/develop/data-formats/cell-boc). + +## Дивіться також + +- [Мова TL-B](/develop/data-formats/tl-b-language) diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/learn/overviews/ton-blockchain.md b/i18n/uk/docusaurus-plugin-content-docs/current/learn/overviews/ton-blockchain.md new file mode 100644 index 0000000000..2351cace2b --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/learn/overviews/ton-blockchain.md @@ -0,0 +1,72 @@ +# Блокчейн з блокчейнів + +:::tip +Терміни "**розумний контракт**", "**рахунок**" і "**актор**" використовуються в цьому документі як взаємозамінні для опису об'єкта блокчейну. +::: + +## Один актор + +Розглянемо один смарт-контракт. + +У ТОН це *речовина* з такими властивостями, як *адреса*, *код*, *дані*, *баланс* та інші. Іншими словами, це об'єкт, який має певне *зберігання* та *поведінку*. +Ця поведінка має наступний шаблон: + +- щось трапляється (найпоширеніша ситуація - коли контракт отримує повідомлення) +- контракт обробляє цю подію відповідно до своїх властивостей, виконуючи її "код" у віртуальній машині TON. +- контракт змінює власні властивості (`код`, `дані` та інші) +- контракт опціонально генерує вихідні повідомлення +- контракт переходить у режим очікування до наступної події + +Комбінація цих кроків називається **транзакцією**. Важливо, що події обробляються одна за одною, тому *транзакції* суворо впорядковані і не можуть переривати одна одну. + +Ця модель поведінки добре відома і називається "актор". + +### Найнижчий рівень: Ланцюжок рахунків + +Послідовність *транзакцій* `Tx1 -> Tx2 -> Tx3 -> ....` можна назвати **ланцюжком**. А в розглянутому випадку вона називається **AccountChain**, щоб підкреслити, що це *ланцюжок* одного облікового запису транзакцій. + +Тепер, оскільки вузлам, які обробляють транзакції, потрібно час від часу координувати стан смарт-контракту (досягати *консенсусу* щодо стану), ці *транзакції* пакетуються: +`[Tx1 -> Tx2] -> [Tx3 -> Tx4 -> Tx5] -> [] -> [Tx6]`. +Пакетна передача не втручається у послідовність, кожна транзакція все ще має лише один 'prev tx' і максимум один 'next tx', але тепер ця послідовність розрізана на **блоки**. + +Доцільно також включити до *блоків* черги вхідних та вихідних повідомлень. В такому випадку *блок* буде містити повний набір інформації, яка визначає і описує, що відбувалося зі смарт-контрактом протягом цього блоку. + +## Багато ланцюжків акаунтів: Осколки + +Тепер розглянемо багато акаунтів. Ми можемо отримати декілька *AccountChains* і зберігати їх разом, такий набір *AccountChains* називається **ShardChain**. Так само ми можемо розрізати **ShardChain** на **ShardBlocks**, які є сукупністю окремих *AccountBlocks*. + +### Динамічне розділення та злиття ShardChains + +Зауважте, що оскільки *ShardChain* складається з *AccountChains*, які легко розрізнити, ми можемо легко його розділити. Таким чином, якщо у нас є 1 *ShardChain*, який описує події, що відбуваються з 1 мільйоном акаунтів, і кількість транзакцій в секунду занадто велика, щоб обробляти і зберігати їх в одному вузлі, ми просто розділимо (або **розщепимо**) цей ланцюжок на два менших *ShardChains*, кожен з яких відповідає за півмільйона акаунтів, і кожен ланцюжок обробляється на окремій підмножині вузлів. + +Аналогічно, якщо деякі осколки стали занадто вільними, їх можна "об'єднати" в один більший осколок. + +Очевидно, що існує два граничних випадки: коли шард містить лише один обліковий запис (і тому не може бути розділений далі) і коли шард містить всі облікові записи. + +Акаунти можуть взаємодіяти один з одним, надсилаючи повідомлення. Існує спеціальний механізм маршрутизації, який переміщує повідомлення з вихідних черг до відповідних вхідних черг і гарантує, що 1) всі повідомлення будуть доставлені 2) повідомлення будуть доставлені послідовно (повідомлення, відправлене раніше, досягне адресата раніше). + +:::info ПРИМІТКА +Щоб зробити розділення та злиття детермінованим, агрегація ланцюжків облікових записів у шарди базується на бітовому представленні адрес облікових записів. Наприклад, адреса має вигляд `(префікс шарда, адреса)`. Таким чином, всі акаунти в шардчейні матимуть однаковий двійковий префікс (наприклад, всі адреси починаються з `0b00101`). +::: + +## Блокчейн + +Сукупність всіх шардів, яка містить всі облікові записи, що діють за одним набором правил, називається **Блокчейном**. + +У TON може бути багато наборів правил і, відповідно, багато блокчейнів, які працюють одночасно і можуть взаємодіяти один з одним, надсилаючи повідомлення між ланцюжками так само, як акаунти одного ланцюжка можуть взаємодіяти один з одним. + +### Workchain: Блокчейн з власними правилами + +Якщо ви хочете налаштувати правила групи шардчейнів, ви можете створити **Workchain**. Хорошим прикладом є створення ланцюжка, який працює на базі EVM, щоб запускати на ньому смарт-контракти Solidity. + +Теоретично, кожен учасник спільноти може створити власний воркчейн. Насправді, це досить складне завдання - побудувати його, потім заплатити (дорогу) ціну за створення і отримати 2/3 голосів від валідаторів, щоб схвалити створення вашого ланцюжка. + +TON дозволяє створювати до `2^32` робочих ланцюжків, кожен з яких розбивається на `2^60` осколків. + +На сьогоднішній день в TON існує лише 2 робочі ланцюги: MasterChain та BaseChain. + +BaseChain використовується для повсякденних транзакцій між учасниками, оскільки він досить дешевий, в той час як MasterChain виконує важливу функцію для TON, тому давайте розглянемо, що він робить! + +### Masterchain: Блокчейн з блокчейнів + +Існує необхідність синхронізації маршрутизації повідомлень і виконання транзакцій. Іншими словами, вузлам мережі потрібен спосіб зафіксувати певну "точку" в багатоланцюговому стані і досягти консенсусу щодо цього стану. У TON для цього використовується спеціальний ланцюжок, який називається **MasterChain**. Блоки *masterchain* містять додаткову інформацію (останні хеші блоків) про всі інші ланцюжки в системі, таким чином, будь-який спостерігач однозначно визначає стан всіх мультиланцюжкових систем за одним блоком майстер-ланцюга. diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/learn/tvm-instructions/tvm-overview.mdx b/i18n/uk/docusaurus-plugin-content-docs/current/learn/tvm-instructions/tvm-overview.mdx new file mode 100644 index 0000000000..00d76d5b3e --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/learn/tvm-instructions/tvm-overview.mdx @@ -0,0 +1,133 @@ +import Button from '@site/src/components/button' + +# Огляд TVM + +Всі смарт-контракти TON виконуються на власній віртуальній машині TON (TVM). TVM побудована за принципом "стека", що робить її ефективною і простою в реалізації. + +Цей документ дає уявлення про те, як TVM виконує транзакції з висоти пташиного польоту. + +:::tip + +- TVM Source - [**TVM C++ реалізація**](https://github.com/ton-blockchain/ton/tree/master/crypto/vm) + ::: + +## Курс TON: TVM + +:::tip +Перед початком курсу переконайтеся, що ви добре розумієте основи технології блокчейн. Якщо у вас є прогалини в знаннях, рекомендуємо пройти курс [Blockchain Basics with TON](https://stepik.org/course/201294/promo) ([RU версія](https://stepik.org/course/202221/), [CHN версія](https://stepik.org/course/200976/)). +::: + +Курс [TON Blockchain Course] (https://stepik.org/course/176754/) - це вичерпний посібник з розробки TON Blockchain. + +Модуль 2 повністю охоплює **TVM**, транзакції, масштабування та бізнес-кейси. + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +```mdx-code-block + +``` + +## Транзакції та етапи + +Коли на акаунті в одному з ланцюжків TON відбувається якась подія, вона викликає **транзакцію**. Найпоширенішою подією є "надходження якогось повідомлення", але, взагалі кажучи, це можуть бути "тик-так", "злиття", "розщеплення" та інші події. + +Кожна транзакція складається з 5 етапів: + +1. **Фаза зберігання** - на цій фазі розраховується плата за зберігання, накопичена контрактом через зайняття певного місця в стані ланцюжка. Детальніше в [Плата за зберігання] (/develop/smart-contracts/fees#storage-fee). +2. **Фаза кредитування** - на цій фазі розраховується баланс контракту щодо (можливої) вартості вхідного повідомлення і стягнутої плати за зберігання. +3. **Фаза обчислення** - на цій фазі TVM виконує контракт (див. нижче) і результатом виконання контракту є сукупність реквізитів `exit_code`, `actions` (серіалізований список дій), `gas_details`, `new_storage` та деяких інших. +4. **Фаза дій** - якщо фаза обчислень пройшла успішно, в цій фазі обробляються "дії" з фази обчислень. Зокрема, дії можуть включати відправку повідомлень, оновлення коду смарт-контракту, оновлення бібліотек тощо. Зауважте, що деякі дії можуть зазнати невдачі під час обробки (наприклад, якщо ми спробуємо відправити повідомлення з більшим TON, ніж є в контракті), в такому випадку вся транзакція може повернутися назад або ця дія може бути пропущена (це залежить від режиму дій, іншими словами, контракт може відправити повідомлення типу "відправити або повернути" або "спробувати відправити, якщо не буде ігноруватися"). +5. **Фаза відмов** - якщо фаза обчислення завершилася невдало (повернуто `код_виходу >= 2`), у цій фазі формується _повідомлення про відмову_ для транзакцій, ініційованих вхідним повідомленням. + +## Обчислювальна фаза + +На цій фазі відбувається виконання TVM. + +### Стан ТВМ + +У будь-який момент часу стан ТВМ повністю визначається 6 властивостями: + +- Стек (див. нижче) +- Керуючі регістри - (див. нижче), простіше кажучи, це означає до 16 змінних, які можуть бути безпосередньо встановлені та прочитані під час виконання +- Поточне продовження - об'єкт, який описує поточну виконувану послідовність інструкцій +- Поточна кодова сторінка - простими словами, це означає версію TVM, яка запущена в даний момент +- Ліміти газу - набір з 4 цілих значень: поточний ліміт газуgl, максимальний ліміт газу gm, залишок газуgr та кредит газу gc +- Контекст бібліотеки - хеш-мапа бібліотек, які може викликати TVM + +### ТВМ - це штабелеукладальна машина + +TVM - це стекова машина з останнім входом і першим виходом. Всього існує 7 типів змінних, які можна зберігати в стеку, три з яких не є комірками: + +- Ціле - знакові 257-розрядні цілі числа +- Кортеж - впорядкована колекція до 255 елементів з довільними типами значень, які можуть бути різними. +- Нуль. + +І чотири різних смаки клітин: + +- Комірка - базова (можливо, вкладена) непрозора структура, що використовується TON Blockchain для зберігання всіх даних +- Зріз - спеціальний об'єкт, який дозволяє читати з комірки +- Конструктор - спеціальний об'єкт, який дозволяє створювати нові комірки +- Продовження - спеціальний об'єкт, який дозволяє використовувати комірку як джерело інструкцій TVM + +### Регістри управління + +- `c0` - Містить наступне продовження або продовження повернення (подібно до адреси повернення підпрограми у звичайному дизайні). Це значення має бути продовженням. +- `c1` - Містить альтернативне продовження (повернення); це значення має бути Продовженням. +- `c2` - Містить обробник виключення. Це значення є продовженням, яке викликається щоразу, коли виникає виняток. +- `c3` - допоміжний регістр, містить поточний словник, по суті хеш-мапу, що містить код усіх функцій, які використовуються у програмі. Це значення повинно бути продовженням. +- `c4` - Містить корінь постійних даних, або просто розділ контракту `data`. Це значення є коміркою. +- `c5` - Містить дії виведення. Це значення є коміркою. +- `c7` - Містить корінь тимчасових даних. Це кортеж. + +### Ініціалізація TVM + +TVM ініціалізується, коли виконання транзакції доходить до фази обчислень, а потім виконує команди (опкоди) з _Поточного продовження_, поки не залишиться більше команд для виконання (і не буде продовження для переходів назад). + +Детальний опис процесу ініціалізації можна знайти тут: [TVM Ініціалізація](/learn/tvm-instructions/tvm-initialization.md) + +## Інструкція з експлуатації TVM + +Список інструкцій TVM можна знайти тут: [TVM-інструкції](/learn/tvm-instructions/instructions). + +### Результат виконання TVM + +Окрім коду виходу та даних про спожитий газ, TVM опосередковано виводить наступні дані: + +- Регістр c4 - комірка, яка буде збережена як нові "дані" смарт-контракту (якщо виконання не буде повернуто на цій або наступних фазах) +- c5 register - (список вихідних дій) комірка з останньою дією у списку та посилання на комірку з попередньою дією (рекурсивно) + +Всі інші значення регістрів ігноруються. + +Зауважте, що оскільки існує обмеження на максимальну глибину комірок `<1024`, і особливо обмеження на глибину c4 і c5 `<=512`, то буде обмеження на кількість вихідних дій в одному tx `<=255`. Якщо контракту потрібно відправити більше, він може відправити повідомлення із запитом `continue_sending` самому собі і відправити всі необхідні повідомлення у наступних транзакціях. + +## Дивіться також + +- [Інструкції TVM](/learn/tvm-instructions/instructions) +- [TON TVM](https://ton.org/tvm.pdf) Концепції TVM (може містити застарілу інформацію) diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/participate/README.md b/i18n/uk/docusaurus-plugin-content-docs/current/participate/README.md new file mode 100644 index 0000000000..76435705ee --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/participate/README.md @@ -0,0 +1,38 @@ +# Огляд + +Розділ "Участь" нашої документації розроблений таким чином, щоб дозволити користувачам відкрити для себе можливості роботи з TON +Він також має на меті запропонувати основні фреймворки (дослідники, гаманці, TEP), необхідні для участі в екосистемі TON і створення бачення TON для Всесвітньої павутини TON (TWWW). + +## Долучайтеся до екосистеми ТОН + +- [TON Explorers](/учасники/дослідники) +- [Додатки для гаманців (для розробників)] (/participate/wallets/apps) +- [Типи контрактів на гаманці] (/participate/wallets/contracts) + +### Приєднуйтесь до спільноти TON + +- [Пропозиції щодо посилення ТОН (TEPs)] (https://github.com/ton-blockchain/TEPs) +- [Відкрийте для себе інновації TON на сайті TON Research] (https://tonresear.ch/) +- [Ставка з номінаторами TON](/participate/network-maintenance/nominators) + +### Мости + +- [Огляд мостів] (/participate/crosschain/oview) +- [Адреси мостів](/participate/crosschain/bridge-addresses) + +### Запустити вузол + +- [Дізнатися про типи вузлів у TON](/participate/nodes/node-types) +- [Запустити ваш повний вузол або валідатор](/participate/run-nodes/full-node) +- [TON Validator maintenance & security](/participate/nodes/node-maintenance-and-security) + +## Беріть участь у TON Web3 + +- [Огляд TON Web3](/participate/web3/oview) +- [Використовуйте TON DNS для своїх доменів](/participate/web3/dns) +- [Управління сайтом та доменом](/participate/web3/site-management) +- [\[Навчальний посібник\] Як запустити власний TON-сайт?](/develop/dapps/tutorials/how-to-run-ton-site) + +### TON Proxy + +- [Як відкрити будь-який сайт TON?] (/participate/web3/how-to-open-any-ton-site) diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/participate/crosschain/overview.md b/i18n/uk/docusaurus-plugin-content-docs/current/participate/crosschain/overview.md new file mode 100644 index 0000000000..849e77704e --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/participate/crosschain/overview.md @@ -0,0 +1,57 @@ +# Перехресні ланцюгові мости + +Децентралізовані крос-ланцюгові мости працюють на TON Blockchain, дозволяючи переносити активи з TON Blockchain в інші блокчейни і навпаки. + +## Toncoin Bridge + +Міст Toncoin дозволяє переказувати Toncoin між блокчейном TON і блокчейном Ethereum, а також між блокчейном TON і смарт-ланцюжком BNB. + +Мостом керують [децентралізовані оракули](/учасники/кросчейн/адреси мосту). + +### Як ним користуватися? + +Фронтенд мосту розміщений на https://ton.org/bridge. + +:::info +[Вихідний код інтерфейсу мосту](https://github.com/ton-blockchain/bridge) +::: + +### Вихідні коди смарт-контрактів TON-Ethereum + +- [FunC (сторона TON)](https://github.com/ton-blockchain/bridge-func) +- [Solidity (сторона Ethereum)] (https://github.com/ton-blockchain/bridge-solidity/tree/eth_mainnet) + +### Вихідні коди смарт-контрактів TON-BNB Smart Chain + +- [FunC (сторона TON)](https://github.com/ton-blockchain/bridge-func/tree/bsc) +- [Солідність (сторона BSC)] (https://github.com/ton-blockchain/bridge-solidity/tree/bsc_mainnet) + +### Налаштування блокчейну + +Ви можете отримати фактичні адреси мостових смарт-контрактів та адреси оракулів, переглянувши відповідний конфіг: + +TON-Ethereum: [#71](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L738). + +TON-BSC: [#72](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L739). + +ТОН-Полігон: [#73](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L740). + +### Документація + +- [Як працює міст] (https://github.com/ton-blockchain/TIPs/issues/24) + +### Дорожня карта перехресного ланцюга + +- https://t.me/tonblockchain/146 + +## Міст Тонана + +### Як взяти участь? + +:::caution проект\ +Це концептуальна стаття. Ми все ще шукаємо когось досвідченого для її написання. +::: + +Ви можете знайти фронтенд тут: https://tonana.org/ + +Вихідний код знаходиться тут: https://github.com/tonanadao diff --git a/i18n/uk/docusaurus-plugin-content-docs/current/participate/web3/overview.mdx b/i18n/uk/docusaurus-plugin-content-docs/current/participate/web3/overview.mdx new file mode 100644 index 0000000000..4f644f6eef --- /dev/null +++ b/i18n/uk/docusaurus-plugin-content-docs/current/participate/web3/overview.mdx @@ -0,0 +1,17 @@ +# Огляд + +## Концепції + +Більше про ідеї читайте в статті: + +- [Платежі на ТОН] (https://blog.ton.org/ton-payments) +- [TON DNS & Domains](/participate/web3/dns) +- [Сайти TON, TON WWW та TON Proxy](https://blog.ton.org/ton-sites) + +## Варіанти використання + +- [\*.ton зручні домени для будь-якого смарт-контракту](/participate/web3/dns) +- [Підключення до сайтів TON за допомогою проксі-сервера TON](/participate/web3/setting-proxy) +- [Запустіть власний проксі-сервер TON для підключення до сайтів TON](/participate/web3/sites-and-proxy) +- [Прив'яжіть свій гаманець TON або сайт TON до домену] (/participate/web3/site-management) +- [Як створити субдомен за допомогою смарт-контрактів TON DNS](/participate/web3/site-management#how-to-setup-subdomains) diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/develop/companies/auditors.mdx b/i18n/zh-CN/docusaurus-plugin-content-docs/current/develop/companies/auditors.mdx index 3affce3f37..965b5e6b16 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/develop/companies/auditors.mdx +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/develop/companies/auditors.mdx @@ -2,21 +2,29 @@ import Button from '@site/src/components/button' # 安全保障提供商(SAP) -## TON SAP 列表 +:::info +使用以下质量保证提供商测试您的软件。 +::: -请使用以下质量保证提供商测试您的软件: +## 主要 TON 区块链 SAP - [skynet.certik.com](https://skynet.certik.com/) - [quantstamp.com](https://quantstamp.com/) -- [softstack.io formerly Chainsulting](https://softstack.io/) -- [slowmist.com](https://slowmist.com/) + +## 添加新的 SAP + +- [hackenproof.com](https://hackenproof.com/) - [hexens.io](https://hexens.io/) -- [vidma.io](https://vidma.io/) - [scalebit](https://www.scalebit.xyz/) +- [skynet.certik.com](https://skynet.certik.com/) +- [slowmist.com](https://slowmist.com/) +- [softstack.io formerly Chainsulting](https://softstack.io/) +- [trailofbits.com](https://www.trailofbits.com/) +- [vidma.io](https://vidma.io/) ## 添加新的 SAP -如果您是TON的新安全提供商并希望被列入名单,请填写表格。 +添加新的SAP ```mdx-code-block ``` -## 验证者节点 - -当**验证者节点**持有足够数量的Toncoin作为质押代币时,它将被激活。验证者节点对网络的运行至关重要,参与新网络区块的验证。 +## 归档节点 TON基于权益证明机制运行,其中验证者在维护网络功能方面发挥着关键作用。验证者会因其贡献而[以Toncoin获得奖励](/participate/network-maintenance/staking-incentives),激励网络参与并确保网络安全。 [作为验证者运行全节点](/participate/run-nodes/full-node#become-a-validator) -## 全节点 + Liteserver +\ -当在全节点上激活端点时,节点将承担**Liteserver**的角色。这种节点类型可以处理并响应来自轻客户端的请求,允许与TON区块链无缝互动。 +## 验证者节点 -### 轻客户端:与 TON 交互的SDK +TON operates on a **Proof-of-Stake** mechanism, where `validators` are pivotal in maintaining network functionality. `Validators` are [rewarded in Toncoin](/participate/network-maintenance/staking-incentives) for their contributions, incentivizing network participation and ensuring network security. Liteservers使与轻客户端的快速通信成为可能,便于执行检索余额或提交交易等任务,而不需要完整的区块历史。 每个支持ADNL协议的SDK都可以使用`config.json`文件作为轻客户端。`config.json`文件包含了可以用来连接TON区块链的端点列表。 -[选择TON SDK](/develop/dapps/apis/sdk) +## Liteserver 每个不支持ADNL的SDK通常使用HTTP中间件来连接TON区块链。它的安全性和速度不如ADNL,但使用起来更简单。 -### 与 TON 的互动:公共Liteservers(端点) +`Liteservers` enable swift communication with Lite Clients, facilitating tasks like retrieving balance or submitting transactions without necessitating the full block history. TON基金会提供了几个公共Liteservers,集成到全局配置中,可供普遍使用。这些端点,如标准钱包使用的端点,确保即使不设置个人liteserver,也能与TON区块链进行交互。 @@ -52,32 +54,34 @@ TON基金会提供了几个公共Liteservers,集成到全局配置中,可供 在您的应用程序中使用下载的`config.json`文件与TON SDK。 -#### 故障排除 +If you want to have more stable *connection*, you can run your own `Liteserver`. To run a `full node` as a `Liteserver`, simply enable the `Liteserver` mode in your node's configuration file. -##### 故障排除 +\ -如果您看到此错误,这意味着您尝试连接的liteserver不可用。解决公共liteservers问题的正确方法如下: +## 轻客户端:与 TON 交互的SDK -1. 从tontech链接下载config.json文件: +Each SDK which supports ADNL protocol can be used as a `Lite Client` with `config.json` file (find how to download it [here](/participate/nodes/node-types#troubleshooting)). The `config.json` file contains a list of endpoints that can be used to connect to the TON Blockchain. -```bash -wget https://api.tontech.io/ton/wallet-mainnet.autoconf.json -O /usr/bin/ton/global.config.json -``` +每个不支持ADNL的SDK通常使用HTTP中间件来连接TON区块链。它的安全性和速度不如ADNL,但使用起来更简单。 它会从配置文件中移除响应慢的liteservers。 -2. 在您的应用程序中使用下载的`config.json`文件与TON SDK(/participate/nodes/node-types#lite-clients-the-sdks-to-interact-with-ton)。 +### 故障排除 -### 作为 Liteserver 运行全节点 +Below you can find approaches how to fix common nowed issues with `light clients` -如果你的项目需要高度_安全_,你可以运行自己的 Liteserver。要将完整节点作为 Liteserver 运行,只需在节点配置文件中启用 Liteserver 模式即可: +### 故障排除 [在节点中启用 Liteserver](/participate/run-nodes/full-node#enable-liteserver-mode) -## 归档节点 +1. 从tontech链接下载config.json文件: -[在节点中启用Liteserver](/participate/run-nodes/full-node#enable-liteserver-mode) +```bash +wget https://api.tontech.io/ton/wallet-mainnet.autoconf.json -O /usr/bin/ton/global.config.json +``` 这种节点对于创建需要完整区块链历史的区块链浏览器或其他工具至关重要。 -**归档节点**本质上是存档整个区块历史的全节点。 +2. Use the downloaded config.json file in your application with [TON SDK](/develop/dapps/apis/sdk). diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/run-nodes/archive-node.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/run-nodes/archive-node.md index 09303fd619..668f9aeb78 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/run-nodes/archive-node.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/run-nodes/archive-node.md @@ -1,11 +1,11 @@ # 运行归档节点 -## 概述 - -:::caution 需要系统管理员 -运行节点需要具备 Linux/Ubuntu 系统管理的基本知识。 +:::info +Read about [Full Node](/participate/run-nodes/full-node) before this article ::: +## 概述 + 存档节点是一种[完整节点](/participate/run-nodes/fullnode)类型,存储区块链的扩展历史数据。 如果您正在创建一个需要访问历史数据的 blockchain 浏览器或类似的应用程序, 建议使用归档节点作为索引器。 ## 先决条件 @@ -16,8 +16,6 @@ - Ubuntu 22.04 - Debian 11 -请使用 [具有 sudo 权限的非 root 用户](/participate/run-nodes/full-node#prerequisites-1) 安装和运行 mytonctrl。 - ## 硬件要求 - 16 x 内核 CPU @@ -31,17 +29,9 @@ __Note__注意:4 TB 假定使用启用压缩的 zfs 卷 ## 安装 -一般来说,运行存档节点需要以下步骤: - -1. 安装 ZFS 并准备卷 -2. 安装 MyTonCtrl -3. 在服务器上运行完整节点并停止验证器进程 -4. 从 https://archival-dump.ton.org 下载和恢复转储数据 -5. 运行完整节点,为存档节点配置数据库规格 - -### 安装 ZFS 并准备卷 +### 安装 -通常,为您的节点在_专用SSD驱动器_上创建一个单独的ZFS池是个好主意,这将使您更容易管理存储空间并备份您的节点。 +一般来说,运行存档节点需要以下步骤: 通常,在专用 SSD 驱动器上为节点创建一个单独的 ZFS 池是个好主意,这样可以方便管理存储空间和备份节点。 @@ -65,11 +55,11 @@ sudo zfs set compression=lz4 data ### 安装 MyTonCtrl -请使用 [Running Full Node](/participate/run-nodes/full-node) 安装 mytonctrl。 +Please, use a [Running Full Node](/participate/run-nodes/full-node) to **install** and **run** mytonctrl. ### 准备节点 -#### 准备节点 +#### 安装 MyTonCtrl 1. 执行还原之前,必须使用 root 账户停止验证器: @@ -86,7 +76,7 @@ mv /var/ton-work /var/ton-work.bak #### 下载转储 -1. 在 [@TONBaseChatEn](https://t.me/TONBaseChatEn) Telegram 聊天中请求`user`和`password`凭证以获得下载转储的访问权限。 +1. 备份 `ton-work` 配置文件(我们需要 `/var/ton-work/db/config.json`、`/var/ton-work/keys` 和 `/var/ton-work/db/keyring`)。 2. 下面是一个从 ton.org 服务器下载和恢复转储的命令示例: ```shell @@ -95,7 +85,7 @@ wget --user --password -c https://archival-dump.ton.org/dumps/latest 转储大小为__~1.5TB__,因此下载和恢复需要一些时间。 -准备并运行命令: +转储大小为__~1.5TB__,因此下载和恢复需要一些时间。 1. 必要时安装工具(`pv`, `plzip`) 2. 将 `` 和 `` 替换为您的凭据 @@ -119,7 +109,7 @@ cp -r /var/ton-work.bak/db/keyring /var/ton-work/db/keyring 3. 请确保`/var/ton-work`和`/var/ton-work/keys`目录的权限提升正确: -- /var/ton-work/db "目录的所有者应为 "validator "用户: +- 请确保`/var/ton-work`和`/var/ton-work/keys`目录的权限提升正确: ```shell chown -R validator:validator /var/ton-work/db @@ -194,7 +184,7 @@ systemctl start validator.service 如果由于某种原因,某些程序无法运行或发生故障,你可以随时 [roll back](https://docs.oracle.com/cd/E23824_01/html/821-1448/gbciq.html#gbcxk) 到 ZFS 文件系统上的 @archstate 快照,这是转储的原始状态。 -1. 停止验证程序(切勿跳过!)。 +1. Stop validator process (**Never skip this!**) ```shell sudo -s diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/wallets/apps.mdx b/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/wallets/apps.mdx index 0a068a293f..f3a6c067e3 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/wallets/apps.mdx +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/wallets/apps.mdx @@ -96,21 +96,21 @@ TON Wallet是面向普通用户的大规模采用区块链技术的第一步。 [Tonhub](https://tonhub.com/) - 是另一个完整的TON钱包,支持基本的最新功能。Ton Whales正在迅速提升钱包的能力。 -| | -| -------------------------------------------------------------------------------------------------- | -|               ![Tonhub](/img/docs/wallet-apps/Tonhub.png?raw=true)                                 | +| | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|               ![Tonhub](/img/docs/wallet-apps/Tonhub.png?raw=true)                                 | #### 优点和缺点 -- ✅ 拥有自己定制的[Ton Nominator](https://github.com/tonwhales/ton-nominators)合约,由Tonhub UI支持。 -- ✅ 从一开始就是开源钱包。 -- ✅ [漏洞赏金计划](https://tonwhales.com/bounty)。 +- [GitHub](https://github.com/tonwhales/wallet) +- [Sandbox iOS](https://apps.apple.com/app/ton-development-wallet/id1607857373) +- [Sandbox Android](https://play.google.com/store/apps/details?id=com.tonhub.wallet.testnet) - ❌ 没有任何桌面平台的支持。 - ❌ 要为其源代码做出贡献需要高级技能。 -#### Tonhub测试环境 +#### OpenMask -您需要下载单独的应用程序才能连接到Testnet。 +[OpenMask](https://www.openmask.app/) - 作为浏览器扩展,是一款开创性的工具,使用户在Web3中的交互和体验成为可能。 #### 链接 @@ -122,20 +122,20 @@ TON Wallet是面向普通用户的大规模采用区块链技术的第一步。 [OpenMask](https://www.openmask.app/) - 作为浏览器扩展,是一款开创性的工具,使用户在Web3中的交互和体验成为可能。 -| | -| ------------------------------------------------------------------------------------------------------ | -|               ![OpenMask](/img/docs/wallet-apps/OpenMask.png?raw=true)                                 | +| | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +|               ![OpenMask](/img/docs/wallet-apps/OpenMask.png?raw=true)                                 | #### 优点和缺点 -- ✅ 对开发者来说,通过桌面学习和创建dApps而无需移动设备很方便。 -- ✅ 独特的功能,如多钱包,以及其文档中的详细描述和示例。 +- [GitHub](https://github.com/OpenProduct/openmask-extension) +- [文档](https://www.openmask.app/docs/introduction) - ❌ 目前几乎没有与dApps的集成。 - ❌ 仅支持浏览器扩展平台。 -#### OpenMask测试环境 +#### MyTonWallet -要在Mainnet和Testnet之间切换OpenMask:您需要点击OpenMask主屏幕顶部的“mainnet/testnet”按钮,然后选择您需要的网络。 +[MyTonWallet](https://mytonwallet.io/) - 是TON最功能丰富的Web钱包和浏览器扩展 - 支持代币、NFT、TON DNS、TON站点、TON代理和TON魔法。 #### 链接 @@ -146,18 +146,18 @@ TON Wallet是面向普通用户的大规模采用区块链技术的第一步。 [MyTonWallet](https://mytonwallet.io/) - 是TON最功能丰富的Web钱包和浏览器扩展 - 支持代币、NFT、TON DNS、TON站点、TON代理和TON魔法。 -| | -| ------------------------------------------------------------------------------------------------------------ | -|               ![MyTonWallet](/img/docs/wallet-apps/MyTonWallet.png?raw=true)                                 | +| | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +|               ![MyTonWallet](/img/docs/wallet-apps/MyTonWallet.png?raw=true)                                 | #### 优点和缺点 -- ✅ 已实现所有基本功能。 -- ✅ 独特功能 - 从钱包UI管理官方[Nominator Pool合约](https://github.com/ton-blockchain/nominator-pool)。 +- [GitHub](https://github.com/mytonwalletorg/mytonwallet) +- [MyTonWallet Telegram](https://t.me/MyTonWalletRu) - ✅ 支持所有主要平台(如macOS、Linux和Windows),也可以作为Chrome扩展运行。 - ❌ 不支持Firefox作为扩展。 -#### MyTonWallet测试环境 +#### 非托管硬件(冷)钱包 要将MyTonWallet切换到Testnet:打开设置,点击应用版本5次,打开网络切换器。 @@ -166,22 +166,22 @@ TON Wallet是面向普通用户的大规模采用区块链技术的第一步。 - [GitHub](https://github.com/mytonwalletorg/mytonwallet) - [MyTonWallet Telegram](https://t.me/MyTonWalletRu) -## 非托管硬件(冷)钱包 +## 链接 :::info 硬件钱包是一种物理设备,它将您的加密货币资金的私钥存储在远离互联网的地方。即使您使用它进行交易,钱包也会在离线环境中确认交易。这个过程有助于始终将您的私钥远离互联网的风险。 ::: -### Ledger +### SafePal -[Ledger](https://www.ledger.com/)硬件钱包与Ledger Live应用程序。 +[SafePal](https://www.safepal.com/en/)是您进入快速扩张的去中心化应用程序银河系的门户。 #### 链接 -- [Ledger TON博客文章](https://blog.ton.org/ton-is-coming-to-ledger-hardware-wallets) Ledger钱包中TON的用户手册。 +- [SafePal](https://www.safepal.com/en/)官方网站 - [Ledger](https://www.ledger.com/)官方网站。 -### SafePal +### 托管钱包 [SafePal](https://www.safepal.com/en/)是您进入快速扩张的去中心化应用程序银河系的门户。 @@ -199,17 +199,17 @@ TON Wallet是面向普通用户的大规模采用区块链技术的第一步。 [@wallet](https://t.me/wallet) — 一个用于在Telegram中发送、接收或使用P2P交易TON换取真钱的机器人。支持Telegram Mini App UI。 -| | -| -------------------------------------------------------------------------------------------------- | -|               ![wallet](/img/docs/wallet-apps/Wallet.png?raw=true)                                 | +| | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|               ![wallet](/img/docs/wallet-apps/Wallet.png?raw=true)                                 | ### @cryptobot [@cryptobot](https://t.me/cryptobot) — 一个用于存储、发送和交换TON的Telegram机器人钱包。 -| | -| -------------------------------------------------------------------------------------------------------- | -|               ![CryptoBot](/img/docs/wallet-apps/CryptoBot.png?raw=true)                                 | +| | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|               ![CryptoBot](/img/docs/wallet-apps/CryptoBot.png?raw=true)                                 | #### 第三方集成链接 @@ -219,9 +219,9 @@ TON Wallet是面向普通用户的大规模采用区块链技术的第一步。 [@tonRocketBot](https://t.me/tonRocketBot) - 一个用于存储、发送和交换TON的Telegram机器人钱包。支持Jetton交易。 -| | -| -------------------------------------------------------------------------------------------------------------- | -|               ![tonrocketbot](/img/docs/wallet-apps/tonrocketbot.png?raw=true)                                 | +| | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|               ![tonrocketbot](/img/docs/wallet-apps/tonrocketbot.png?raw=true)                                 | #### 第三方集成链接 @@ -230,7 +230,7 @@ TON Wallet是面向普通用户的大规模采用区块链技术的第一步。 ## 多签名钱包 -### Tonkey +### 参阅 Tonkey是一个先进的项目,为TON区块链引入了多重签名功能。 diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/web3/how-to-open-any-ton-site.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/web3/how-to-open-any-ton-site.md index cc2b4cecc1..998e562bee 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/web3/how-to-open-any-ton-site.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/web3/how-to-open-any-ton-site.md @@ -34,13 +34,13 @@ - [通过TON代理连接](/participate/web3/setting-proxy/) -## 🤓 高级方法 +## 连接到公共代理 ### 使用Tonutils-Proxy -这是访问TON网站最安全的方式。 +此方法在此处描述: -1. 从[这里](https://github.com/xssnick/Tonutils-Proxy#download-precompiled-version)下载最新版本 +1. [通过TON代理连接](/participate/web3/setting-proxy/) 2. 启动它并按“启动网关” diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/web3/setting-proxy.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/web3/setting-proxy.md index c9e1b260d1..d4a0f2d6a5 100644 --- a/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/web3/setting-proxy.md +++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/participate/web3/setting-proxy.md @@ -18,7 +18,7 @@ TON代理与常规HTTP代理兼容,因此您可以直接在浏览器或操作 设置 -> 常规 -> 网络设置 -> 配置 -> 手动代理设置 -> HTTP代理 -在“HTTP代理”字段中,输入其中一个公共入口代理的地址,在“端口”字段中,输入“8080”(不带引号)。 +根据您的操作系统,遵循Windows、macOS、Linux、iOS或Android的说明。 点击“确定”。 @@ -30,42 +30,42 @@ TON代理与常规HTTP代理兼容,因此您可以直接在浏览器或操作 设置 -> WiFi -> 点击当前连接的网络 -> 代理设置 -> 手动 -在“服务器”字段中,输入其中一个公共入口代理的地址,在“端口”字段中,输入“8080”(不带引号)。 +根据您的操作系统,遵循Windows、macOS、Linux、iOS或Android的说明。 点击“保存”。 ## Android -设置 -> WiFi -> 长按Wi-Fi网络名称 -> 修改网络 -> 高级选项 -> 手动 - 在“服务器”字段中,输入其中一个公共入口代理的地址,在“端口”字段中,输入“8080”(不带引号)。 +根据您的操作系统,遵循Windows、macOS、Linux、iOS或Android的说明。 + 点击“保存”。 ## Windows -点击“开始”按钮,然后选择设置 > 网络和互联网 > 代理。 +在“服务器”字段中,输入其中一个公共入口代理的地址,在“端口”字段中,输入“8080”(不带引号)。 -在“手动代理设置”下,旁边的“使用代理服务器”选择“设置”。 +点击“保存”。 在“编辑代理服务器对话框”中,执行以下操作: -打开“使用代理服务器”。 +点击“开始”按钮,然后选择设置 > 网络和互联网 > 代理。 -输入其中一个公共入口代理的地址,在“端口”字段中,输入“8080”(不带引号)。 +在“手动代理设置”下,旁边的“使用代理服务器”选择“设置”。 点击“保存”。 ## MacOS -设置 -> 网络 -> 高级 -> 代理 -> 网络代理(HTTP)。 +输入其中一个公共入口代理的地址,在“端口”字段中,输入“8080”(不带引号)。 -在“网络代理服务器”字段中,输入其中一个公共入口代理的地址,冒号后面输入“8080”(不带引号)。 +点击“保存”。 点击“确定”。 ## Ubuntu -设置 -> 网络 -> 网络代理按钮 -> 手动 +在“网络代理服务器”字段中,输入其中一个公共入口代理的地址,冒号后面输入“8080”(不带引号)。 -在“HTTP代理”字段中,输入其中一个公共入口代理的地址,对于端口,输入“8080”(不带引号)。 +点击“确定”。