-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add toncoin processing #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a comprehensive payment processing guidebook for the TON blockchain, providing educational TypeScript examples that demonstrate various payment integration patterns using the @ton/ton, @ton/core, and @ton/crypto libraries.
Key Changes:
- Implements two deposit tracking approaches: invoice-based (single wallet with UUID comments) and unique address-based (individual wallets per user)
- Provides subscription classes for monitoring blockchain transactions via account polling and block streaming
- Includes utility functions for payment link generation, configuration management, and environment setup
Reviewed Changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
package.json |
Defines project dependencies and scripts for running examples |
tsconfig.json |
TypeScript configuration with strict mode and ES2020 target |
src/utils/payment-link.ts |
Utility for generating TON payment deeplinks with UUID tracking |
src/utils/config.ts |
Configuration loader with environment variable support |
src/subscription/BlockSubscription.ts |
Block-level transaction monitoring for the entire blockchain |
src/subscription/AccountSubscription.ts |
Account-specific transaction polling with cursor-based pagination |
src/deposits/invoices.ts |
Invoice-based deposit processing using comment-based UUID tracking |
src/deposits/unique-addresses.ts |
Multi-wallet deposit system with automatic forwarding to hot wallet |
README.md, .prettierrc, .prettierignore, .gitignore, .env.example |
Project documentation and configuration files |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
guidebook/payment-processing/src/subscription/BlockSubscription.ts
Outdated
Show resolved
Hide resolved
guidebook/payment-processing/src/subscription/AccountSubscription.ts
Outdated
Show resolved
Hide resolved
…n.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 13 out of 14 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (1)
guidebook/payment-processing/src/deposits/unique-addresses.ts:28
- Unused import toNano.
import { Address, internal, fromNano, toNano, SendMode } from '@ton/core';
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
guidebook/payment-processing/src/subscription/AccountSubscription.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
guidebook/payment-processing/src/deposits/jetton-unique-addresses.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 15 out of 16 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // not internal message check | ||
| if (!inMessage || inMessage.info.type !== 'internal') { | ||
| return; | ||
| } | ||
|
|
||
| // bounced check | ||
| if (tx.outMessages.size > 0) { |
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The bounced transaction check appears after the internal message check, but the comment on line 239 says 'bounced check'. This ordering is inconsistent with unique-addresses.ts where the outMessages check comes first (line 260). For consistency and clarity, consider reordering these checks to match the pattern in unique-addresses.ts, or update the comment to accurately reflect what is being checked.
| // not internal message check | |
| if (!inMessage || inMessage.info.type !== 'internal') { | |
| return; | |
| } | |
| // bounced check | |
| if (tx.outMessages.size > 0) { | |
| // outMessages check (internal message filter) | |
| if (tx.outMessages.size > 0) { | |
| return; | |
| } | |
| // not internal message check | |
| if (!inMessage || inMessage.info.type !== 'internal') { |
| async function main(): Promise<void> { | ||
| console.log('Starting deposit monitoring...'); | ||
| console.log(`Network: ${IS_MAINNET ? 'MAINNET' : 'TESTNET'}`); | ||
| console.log(`Wallet: ${MY_WALLET_ADDRESS}`); |
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This expression always evaluates to false.
| console.log(`Wallet: ${MY_WALLET_ADDRESS}`); | |
| console.log(`Wallet: ${MY_WALLET_ADDRESS}`); | |
| // In a real application, LAST_PROCESSED_LT and LAST_PROCESSED_HASH should be loaded from persistent storage (e.g., a database). |
verytactical
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Obviously a lot of work went into this PR. Thanks a lot!
To progress further on this PR, we'll have to
- Separate different demos into separate projects
- Put separate projects into separate PRs
- Fix styleguide issues, and feedback above
If there is any way we can help, let's hop into OO.
| @@ -0,0 +1,5 @@ | |||
| # TON Payment Processing Examples | |||
|
|
|||
| Educational TypeScript examples demonstrating payment processing on the TON blockchain using `@ton/ton`, `@ton/core`, and `@ton/crypto` libraries. | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add links to libraries
| # TON Payment Processing Examples | ||
|
|
||
| Educational TypeScript examples demonstrating payment processing on the TON blockchain using `@ton/ton`, `@ton/core`, and `@ton/crypto` libraries. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should include description of entrypoints.
Also should include description of dev processes: which scripts in package.json are for what purpose, especially
start:invoices- this should benpm startstart:unique- is thisnpm startscript, but for a separate project? probably, projects should be actually separated thenpayment-link- unclearbuild- should it be executed prior tonpm startor not? is it merely for checking types?
| * This example demonstrates how to accept TON coin deposits to a single wallet. | ||
| * | ||
| * Flow: | ||
| * 1. Generate a wallet address once (see wallet setup in separate example) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once in what period of time? For what purpose?
| * | ||
| * Flow: | ||
| * 1. Generate a wallet address once (see wallet setup in separate example) | ||
| * 2. For each payment, generate a unique UUID and save it in your database |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The script describes "how to accept Toncoin", but this description matches with "how to process a batch of payments".
If this code is supposed to show how to process payment batches, change file description.
If file description is correct, this should be "on each payment", and "generate a unique UUID and save it" should be a subitem.
| * 1. Generate a wallet address once (see wallet setup in separate example) | ||
| * 2. For each payment, generate a unique UUID and save it in your database | ||
| * 3. Provide the user with: | ||
| * - Your wallet address |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Your" - whose?
|
|
||
| let nextSeqno = this.lastProcessedBlock + 1; | ||
|
|
||
| while (nextSeqno <= targetSeqno) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
while loops must never be used in production.
This looks like a
for (
let nextSeqno = this.lastProcessedBlock + 1;
nextSeqno <= targetSeqno;
nextSeqno += 1
) { ... }
| export function loadConfig(): Config { | ||
| const isMainnet = process.env.IS_MAINNET === 'true'; | ||
| const apiKey = process.env.API_KEY || 'YOUR_API_KEY_HERE'; | ||
| const walletAddress = process.env.WALLET_ADDRESS || 'UQB7...5I'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not assume values in case config is missing. This must throw.
| const encodedComment = encodeURIComponent(comment); | ||
|
|
||
| // Build the deeplink | ||
| return `ton://transfer/${walletAddress}?amount=${amount}&text=${encodedComment}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| /** | ||
| * Generates a UUID for payment tracking | ||
| * Simple implementation - in production, use a proper UUID library |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proper UUID library is built into Node.
https://nodejs.org/api/crypto.html#cryptorandomuuidoptions
https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID
| * Example usage | ||
| */ | ||
| export function createPaymentExample(): void { | ||
| const walletAddress = 'UQB7...5I'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a valid address, and not a running example.
This repo contains code for running examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.
Files not reviewed (1)
- guidebook/toncoin-processing/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Other private editor folders | ||
| .nvim/ | ||
| .emacs/ | ||
| .helix/ |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The .gitignore file is missing the .env entry. While .env.example is provided for configuration, the actual .env file containing sensitive API keys and wallet addresses should be excluded from version control to prevent credential exposure.
| .helix/ | |
| .helix/ | |
| # Environment variable files | |
| .env |
| hotWalletAddress: string, | ||
| networkGlobalId: number, | ||
| ): Promise<void> { | ||
| // Skip outgoing transactions (bounced messages) |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check tx.outMessages.size > 0 filters out transactions with outgoing messages, but the inline comment on line 195 says 'Skip outgoing transactions (bounced messages)'. This is misleading because transactions with outgoing messages aren't necessarily 'outgoing transactions' - they could be incoming transactions that triggered contract execution. The comment should clarify that this filters out transactions that resulted in bounced messages or contract interactions, not just 'outgoing transactions'.
| // Skip outgoing transactions (bounced messages) | |
| // Skip transactions that resulted in outgoing messages (e.g., bounced messages or contract interactions) |
| console.log('Starting deposit monitoring...'); | ||
| console.log(`Network: ${config.isTestnet ? 'TESTNET' : 'MAINNET'}`); | ||
| console.log(`Wallet: ${config.walletAddress}`); | ||
| if (LAST_PROCESSED_LT && LAST_PROCESSED_HASH) { |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This expression always evaluates to false.
Linked to ton-org/docs#1101
Closes ton-org/docs#1258