mirror of
https://github.com/pezkuwichain/pezkuwi-telegram-miniapp.git
synced 2026-11-02 17:01:09 +00:00
fix(check-deposits): count only TON transfers sent to the deposit address (#38)
The TON check walked every jetton transfer in the deposit address's event feed, including the ones it sends. An outgoing transfer whose comment matched a user's deposit code would have been credited to that user; the 2026-02-13 sweep of 41.9 USDT was reported as an unknown-memo deposit on every run. Resolve the configured address to its raw form and skip any transfer whose recipient is not the deposit address.
This commit is contained in:
1 parent
2b255c56fc
commit
e0d56a5fb5
3 files changed
+47
No files matched your search
@@ -12,6 +12,7 @@ import { keccak_256 } from 'https://esm.sh/@noble/hashes@1.3.2/sha3';
|
||||
import { sha256 } from 'https://esm.sh/@noble/hashes@1.3.2/sha256';
|
||||
import { bytesToHex } from 'https://esm.sh/@noble/hashes@1.3.2/utils';
|
||||
import { secp256k1 } from 'https://esm.sh/@noble/curves@1.2.0/secp256k1';
|
||||
import { isIncomingTonTransfer } from './ton.ts';
|
||||
|
||||
const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://telegram.pezkiwi.app'];
|
||||
const MIN_DEPOSIT = 10; // Minimum 10 USDT
|
||||
@@ -138,6 +139,17 @@ async function checkTonDeposits(
|
||||
const result = { found: 0, processed: 0, errors: [] as string[] };
|
||||
|
||||
try {
|
||||
// tonapi reports recipients in raw form; the configured address may be
|
||||
// user-friendly, so resolve it before comparing.
|
||||
const parsed = await fetch(`${TON_API}/address/${depositAddress}/parse`, {
|
||||
headers: tonHeaders(),
|
||||
});
|
||||
if (!parsed.ok) {
|
||||
result.errors.push(await apiError('TON address parse error:', parsed));
|
||||
return result;
|
||||
}
|
||||
const depositRawAddress: string = (await parsed.json()).raw_form;
|
||||
|
||||
// Get recent transactions
|
||||
const response = await fetch(`${TON_API}/accounts/${depositAddress}/events?limit=50`, {
|
||||
headers: tonHeaders(),
|
||||
@@ -156,6 +168,7 @@ async function checkTonDeposits(
|
||||
for (const action of event.actions || []) {
|
||||
if (action.type !== 'JettonTransfer') continue;
|
||||
if (action.JettonTransfer?.jetton?.address !== TON_USDT_MASTER) continue;
|
||||
if (!isIncomingTonTransfer(action.JettonTransfer, depositRawAddress)) continue;
|
||||
|
||||
const txHash = event.event_id;
|
||||
const amount = parseInt(action.JettonTransfer.amount) / 1e6; // USDT has 6 decimals
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// A deposit address's event feed also carries the transfers it sends, such as
|
||||
// sweeps to the hot wallet. Only a transfer whose recipient is the deposit
|
||||
// address itself is a deposit.
|
||||
export interface TonJettonTransfer {
|
||||
recipient?: { address?: string };
|
||||
}
|
||||
|
||||
export function isIncomingTonTransfer(
|
||||
transfer: TonJettonTransfer | undefined,
|
||||
depositRawAddress: string
|
||||
): boolean {
|
||||
return transfer?.recipient?.address === depositRawAddress;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { assert, assertFalse } from 'jsr:@std/assert@1';
|
||||
import { isIncomingTonTransfer } from './ton.ts';
|
||||
|
||||
const DEPOSIT = '0:c35f028ad76a7003bcb164decaec61230a77ad05c724856409e9445014b0b7be';
|
||||
|
||||
Deno.test('a transfer to the deposit address is a deposit', () => {
|
||||
assert(isIncomingTonTransfer({ recipient: { address: DEPOSIT } }, DEPOSIT));
|
||||
});
|
||||
|
||||
Deno.test('a sweep out of the deposit address is not a deposit', () => {
|
||||
// 2026-02-13: 41.9 USDT sent from the deposit address, no memo.
|
||||
const sweep = {
|
||||
recipient: { address: '0:ef28248f185d0000000000000000000000000000000000000000000000000000' },
|
||||
};
|
||||
assertFalse(isIncomingTonTransfer(sweep, DEPOSIT));
|
||||
});
|
||||
|
||||
Deno.test('a transfer with no recipient is not a deposit', () => {
|
||||
assertFalse(isIncomingTonTransfer({}, DEPOSIT));
|
||||
assertFalse(isIncomingTonTransfer(undefined, DEPOSIT));
|
||||
});
|
||||
Reference in new issue
Block a user