fix(admin): resolve incorrect crypto balance calculation fallback displaying fiat amount
This commit is contained in:
@@ -257,18 +257,7 @@ export default function MerchantsPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{m.balance_breakdown && m.balance_breakdown.length > 0 && (
|
|
||||||
<div className="flex flex-wrap gap-2 pt-2 border-t border-emerald-100/50">
|
|
||||||
{m.balance_breakdown.map((b: any, i: number) => (
|
|
||||||
<div key={i} className="px-2 py-1 bg-white/60 rounded-lg border border-emerald-100/50 flex items-center gap-1.5 shadow-sm">
|
|
||||||
<div className={`w-1.5 h-1.5 rounded-full ${b.network === 'SOLANA' ? 'bg-emerald-400' : b.network === 'POLYGON' ? 'bg-purple-400' : b.network === 'TRON' ? 'bg-red-400' : 'bg-orange-400'}`}></div>
|
|
||||||
<span className="text-[9px] font-black text-emerald-800 uppercase tabular-nums">
|
|
||||||
{Number(b.amount).toFixed(4)} {b.token}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => handlePayoutClick(m)}
|
onClick={() => handlePayoutClick(m)}
|
||||||
|
|||||||
@@ -57,9 +57,9 @@ export async function GET() {
|
|||||||
merchant_id,
|
merchant_id,
|
||||||
COALESCE(paid_network, 'SİSTEM') as network,
|
COALESCE(paid_network, 'SİSTEM') as network,
|
||||||
COALESCE(paid_token, 'TRY') as token,
|
COALESCE(paid_token, 'TRY') as token,
|
||||||
SUM(COALESCE(paid_amount_crypto, amount)) as amount
|
SUM(CAST(COALESCE(paid_amount_crypto, '0') AS numeric)) as amount
|
||||||
FROM transactions
|
FROM transactions
|
||||||
WHERE status = 'succeeded'
|
WHERE status = 'succeeded' AND paid_network IS NOT NULL
|
||||||
GROUP BY merchant_id, paid_network, paid_token
|
GROUP BY merchant_id, paid_network, paid_token
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|||||||
9
checkMainnet.ts
Normal file
9
checkMainnet.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { Connection, PublicKey } from '@solana/web3.js';
|
||||||
|
|
||||||
|
async function checkMainnet() {
|
||||||
|
const connection = new Connection('https://api.mainnet-beta.solana.com', 'confirmed');
|
||||||
|
const pubkey = new PublicKey("HvfSWWepPGnb1JSAuqEogq3mTvm9pTXKQZD4WKFCHKYe");
|
||||||
|
const bal = await connection.getBalance(pubkey);
|
||||||
|
console.log("Mainnet Balance:", bal / 1e9);
|
||||||
|
}
|
||||||
|
checkMainnet().catch(console.log);
|
||||||
75
debug_address.js
Normal file
75
debug_address.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
const { Client } = require('pg');
|
||||||
|
const { Connection, PublicKey } = require('@solana/web3.js');
|
||||||
|
|
||||||
|
async function debugSpecificPayment() {
|
||||||
|
const client = new Client({ connectionString: process.env.DATABASE_URL });
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
const targetAddress = "DZrWQ3Li3AogniRhgyGjNVmG1b3hLe7rR3tgeaKRcy63";
|
||||||
|
|
||||||
|
// Find the transaction by address
|
||||||
|
const res = await client.query(`
|
||||||
|
SELECT id, source_ref_id, amount, currency, metadata, status, created_at
|
||||||
|
FROM transactions
|
||||||
|
WHERE metadata->'wallets'->'SOLANA'->>'address' = $1
|
||||||
|
`, [targetAddress]);
|
||||||
|
|
||||||
|
if (res.rows.length === 0) {
|
||||||
|
console.log(`❌ No transaction found in DB with Solana address: ${targetAddress}`);
|
||||||
|
await client.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tx = res.rows[0];
|
||||||
|
console.log(`\n--- Transaction Found: ${tx.id} ---`);
|
||||||
|
console.log(`Source Ref: ${tx.source_ref_id}`);
|
||||||
|
console.log(`Status: ${tx.status}`);
|
||||||
|
console.log(`Created: ${tx.created_at}`);
|
||||||
|
console.log(`Fiat Amount: ${tx.amount} ${tx.currency}`);
|
||||||
|
console.log(`Intent Network/Token: ${tx.metadata?.intent_network} / ${tx.metadata?.intent_token}`);
|
||||||
|
|
||||||
|
// Check Balance on devnet
|
||||||
|
const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
|
||||||
|
|
||||||
|
let actualSol = 0;
|
||||||
|
try {
|
||||||
|
const pubKey = new PublicKey(targetAddress);
|
||||||
|
const balance = await connection.getBalance(pubKey);
|
||||||
|
actualSol = balance / 1e9;
|
||||||
|
console.log(`\nActual Devnet Balance: ${actualSol} SOL`);
|
||||||
|
|
||||||
|
const signatures = await connection.getSignaturesForAddress(pubKey, { limit: 5 });
|
||||||
|
console.log(`Recent Txs: ${signatures.length}`);
|
||||||
|
} catch(e) {
|
||||||
|
console.log("Error fetching balance:", e.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try calculation
|
||||||
|
let expectedSolAmount = 0;
|
||||||
|
try {
|
||||||
|
const tryRes = await fetch(`https://api.binance.com/api/v3/ticker/price?symbol=USDTTRY`);
|
||||||
|
const tryData = await tryRes.json();
|
||||||
|
const usdTryPrice = parseFloat(tryData.price);
|
||||||
|
|
||||||
|
const solRes = await fetch(`https://api.binance.com/api/v3/ticker/price?symbol=SOLUSDT`);
|
||||||
|
const solData = await solRes.json();
|
||||||
|
const solUsdPrice = parseFloat(solData.price);
|
||||||
|
|
||||||
|
const priceInTry = solUsdPrice * usdTryPrice;
|
||||||
|
const rawExpected = parseFloat(tx.amount) / priceInTry;
|
||||||
|
expectedSolAmount = parseFloat((rawExpected * 0.98).toFixed(6));
|
||||||
|
console.log(`\nExpected Amount: ~${expectedSolAmount} SOL (based on current price)`);
|
||||||
|
} catch(e) {
|
||||||
|
console.log("Failed to fetch price");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualSol >= expectedSolAmount && expectedSolAmount > 0) {
|
||||||
|
console.log("✅ Balance covers expectation");
|
||||||
|
} else {
|
||||||
|
console.log("❌ Balance is less than expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
debugSpecificPayment();
|
||||||
43
debug_latest_5.js
Normal file
43
debug_latest_5.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
const { Client } = require('pg');
|
||||||
|
const { Connection, PublicKey } = require('@solana/web3.js');
|
||||||
|
|
||||||
|
async function debugLatest() {
|
||||||
|
const client = new Client({ connectionString: process.env.DATABASE_URL });
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
const res = await client.query(`
|
||||||
|
SELECT id, source_ref_id, amount, currency, metadata, status, created_at
|
||||||
|
FROM transactions
|
||||||
|
ORDER BY created_at DESC LIMIT 5
|
||||||
|
`);
|
||||||
|
|
||||||
|
console.log("=== LAST 5 TRANSACTIONS ===");
|
||||||
|
|
||||||
|
for (const tx of res.rows) {
|
||||||
|
console.log(`\n--- TX: ${tx.id} ---`);
|
||||||
|
console.log(`Status: ${tx.status} | Amount: ${tx.amount} ${tx.currency} | Created: ${tx.created_at}`);
|
||||||
|
|
||||||
|
const wallets = tx.metadata?.wallets || {};
|
||||||
|
const solWallet = wallets['SOLANA'];
|
||||||
|
|
||||||
|
if (solWallet) {
|
||||||
|
console.log(`Checking SOL Address: ${solWallet.address}`);
|
||||||
|
try {
|
||||||
|
const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
|
||||||
|
const pubKey = new PublicKey(solWallet.address);
|
||||||
|
const balance = await connection.getBalance(pubKey);
|
||||||
|
console.log(`Devnet Balance: ${balance / 1e9} SOL`);
|
||||||
|
|
||||||
|
const connectionMain = new Connection('https://api.mainnet-beta.solana.com', 'confirmed');
|
||||||
|
const balanceMain = await connectionMain.getBalance(pubKey);
|
||||||
|
console.log(`Mainnet Balance: ${balanceMain / 1e9} SOL`);
|
||||||
|
} catch(e) {
|
||||||
|
console.log("Error fetching balance:", e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
debugLatest().catch(console.error);
|
||||||
26
reset_db.js
Normal file
26
reset_db.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
const { Client } = require('pg');
|
||||||
|
|
||||||
|
async function resetDatabase() {
|
||||||
|
const client = new Client({ connectionString: process.env.DATABASE_URL });
|
||||||
|
try {
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
console.log("Bağlantı başarılı. Sadece işlemleri (transactions) siliyorum...");
|
||||||
|
|
||||||
|
// Sadece işlemleri sil, merchant verilerini vb. tut
|
||||||
|
const res = await client.query('DELETE FROM transactions RETURNING id');
|
||||||
|
console.log(`Başarıyla ${res.rowCount} işlem (transaction) silindi.`);
|
||||||
|
|
||||||
|
// Eğer bekleyen bakiye eşitlemeleri vb varsa (merchant_balances) onları da sıfırlayabilirsiniz:
|
||||||
|
// const res2 = await client.query('DELETE FROM merchant_balances RETURNING id');
|
||||||
|
// console.log(`${res2.rowCount} cüzdan bakiyesi sıfırlandı.`);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Hata oluştu:", err);
|
||||||
|
} finally {
|
||||||
|
await client.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetDatabase();
|
||||||
25
reset_merchants.js
Normal file
25
reset_merchants.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
const { Client } = require('pg');
|
||||||
|
|
||||||
|
async function resetMerchants() {
|
||||||
|
const client = new Client({ connectionString: process.env.DATABASE_URL });
|
||||||
|
try {
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
console.log("Bağlantı başarılı. Firmaları ve ilişkili verieri siliyorum...");
|
||||||
|
|
||||||
|
// Önce merchant bakiyelerini silelim (foreign key hatası almamak için)
|
||||||
|
await client.query('DELETE FROM merchant_balances');
|
||||||
|
console.log("Firma kripto bakiyeleri (merchant_balances) sıfırlandı.");
|
||||||
|
|
||||||
|
// Firmaları sil
|
||||||
|
const res = await client.query('DELETE FROM merchants');
|
||||||
|
console.log(`Başarıyla ${res.rowCount} firma (merchant) silindi.`);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Hata oluştu:", err);
|
||||||
|
} finally {
|
||||||
|
await client.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetMerchants();
|
||||||
39
testE2E_Solana.js
Normal file
39
testE2E_Solana.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// testE2E_Solana.js
|
||||||
|
import { Client } from 'pg';
|
||||||
|
import fetch from 'node-fetch';
|
||||||
|
|
||||||
|
async function testE2E() {
|
||||||
|
const client = new Client({ connectionString: process.env.DATABASE_URL });
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
// 1. Get Merchant
|
||||||
|
let res = await client.query('SELECT * FROM merchants LIMIT 1');
|
||||||
|
let merchantId = res.rows[0]?.id;
|
||||||
|
|
||||||
|
// 2. Create Transaction
|
||||||
|
const createRes = await fetch('http://localhost:3000/api/create-payment-intent', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify({ amount: 5, currency: 'TRY', merchant_id: merchantId })
|
||||||
|
});
|
||||||
|
const createData = await createRes.json();
|
||||||
|
console.log("Create Data ID:", createData.id);
|
||||||
|
|
||||||
|
const txId = createData.id;
|
||||||
|
const solAddress = createData.wallets.SOLANA;
|
||||||
|
console.log("Deposit Address:", solAddress);
|
||||||
|
|
||||||
|
// 3. Let's see how much it expects
|
||||||
|
// Assuming 5 TRY is ~0.001 SOL
|
||||||
|
console.log("Sending sweep request with NO FUNDS FIRST...");
|
||||||
|
const sweepRes = await fetch('http://localhost:3000/api/crypto-sweep', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify({ txId, network: 'SOLANA', token: 'SOL' })
|
||||||
|
});
|
||||||
|
const sweepData = await sweepRes.json();
|
||||||
|
console.log("Sweep Data:", sweepData);
|
||||||
|
|
||||||
|
await client.end();
|
||||||
|
}
|
||||||
|
testE2E().catch(console.error);
|
||||||
27
testPending.ts
Normal file
27
testPending.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { Client } from 'pg';
|
||||||
|
import { Connection, PublicKey } from '@solana/web3.js';
|
||||||
|
|
||||||
|
async function checkAllPending() {
|
||||||
|
const client = new Client({ connectionString: process.env.DATABASE_URL });
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
const res = await client.query("SELECT * FROM transactions WHERE status = 'pending'");
|
||||||
|
console.log(`Found ${res.rows.length} pending transactions`);
|
||||||
|
|
||||||
|
const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
|
||||||
|
|
||||||
|
for (const tx of res.rows) {
|
||||||
|
const wallets = tx.metadata?.wallets || {};
|
||||||
|
const solWallet = wallets['SOLANA'];
|
||||||
|
if (solWallet && solWallet.address) {
|
||||||
|
try {
|
||||||
|
const b = await connection.getBalance(new PublicKey(solWallet.address));
|
||||||
|
console.log(`TX ${tx.id} | Amount: ${tx.amount} TRY | Address: ${solWallet.address} | SOL Balance: ${b / 1e9}`);
|
||||||
|
} catch(e) {
|
||||||
|
console.log(`Error on TX ${tx.id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await client.end();
|
||||||
|
}
|
||||||
|
checkAllPending().catch(console.error);
|
||||||
17
testSweepResp.ts
Normal file
17
testSweepResp.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import fetch from 'node-fetch';
|
||||||
|
|
||||||
|
async function verifySweepResponse() {
|
||||||
|
const res = await fetch('http://localhost:3000/api/crypto-sweep', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
txId: '5fda5442-23ea-4130-8646-d0a882ed2517',
|
||||||
|
network: 'SOLANA',
|
||||||
|
token: 'SOL'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
console.log("Sweep API returns:", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
verifySweepResponse().catch(console.error);
|
||||||
43
test_e2e.js
Normal file
43
test_e2e.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
const { Client } = require('pg');
|
||||||
|
const { CryptoEngine } = require('./lib/crypto-engine');
|
||||||
|
|
||||||
|
async function testE2E() {
|
||||||
|
const fetch = require('node-fetch');
|
||||||
|
|
||||||
|
// 1. Create a mock merchant if none
|
||||||
|
const client = new Client({ connectionString: process.env.DATABASE_URL });
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
let res = await client.query('SELECT * FROM merchants LIMIT 1');
|
||||||
|
let merchantId = res.rows[0]?.id;
|
||||||
|
if(!merchantId) {
|
||||||
|
res = await client.query(`INSERT INTO merchants (name, payment_provider) VALUES ('Test', 'stripe') RETURNING id`);
|
||||||
|
merchantId = res.rows[0].id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Call create-payment-intent API
|
||||||
|
const createRes = await fetch('http://localhost:3000/api/create-payment-intent', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify({ amount: 5, currency: 'TRY', merchant_id: merchantId })
|
||||||
|
});
|
||||||
|
const createData = await createRes.json();
|
||||||
|
console.log("Create Data:", createData);
|
||||||
|
|
||||||
|
const txId = createData.id;
|
||||||
|
const solAddress = createData.wallets.SOLANA;
|
||||||
|
console.log("SOL Adresi:", solAddress);
|
||||||
|
|
||||||
|
// 3. Fund it! (I don't have SOL right now in memory, but I will simulate it by querying the DB to get the privatekey and sweeping? No, wait, I can just mock the balance in the CryptoEngine but it's Devnet so I can just fund it via Solana faucet or direct transfer from my gas tank).
|
||||||
|
// Let's actually just call /api/crypto-sweep with a wait, but we know it will fail because 0 balance. Let's see if 0 balance returns 200 with waiting!
|
||||||
|
const sweepRes = await fetch('http://localhost:3000/api/crypto-sweep', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify({ txId, network: 'SOLANA', token: 'SOL' })
|
||||||
|
});
|
||||||
|
const sweepData = await sweepRes.json();
|
||||||
|
console.log("Sweep Data:", sweepData);
|
||||||
|
|
||||||
|
await client.end();
|
||||||
|
}
|
||||||
|
testE2E().catch(console.error);
|
||||||
68
test_sweep_db.ts
Normal file
68
test_sweep_db.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { db } from './lib/db';
|
||||||
|
|
||||||
|
async function testSweepDB() {
|
||||||
|
const txId = "5fda5442-23ea-4130-8646-d0a882ed2517";
|
||||||
|
const selectedNetwork = "SOLANA";
|
||||||
|
const selectedToken = "SOL";
|
||||||
|
const expectedCryptoAmount = "0.164824";
|
||||||
|
const txHash = "mocked-txhash-123";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await db.query('SELECT * FROM transactions WHERE id = $1', [txId]);
|
||||||
|
const transaction = result.rows[0];
|
||||||
|
|
||||||
|
const settings = await (async () => {
|
||||||
|
const result = await db.query('SELECT key, value FROM system_settings WHERE key IN (\'sol_platform_address\', \'evm_platform_address\', \'tron_platform_address\', \'btc_platform_address\', \'default_fee_percent\')');
|
||||||
|
const map: Record<string, string> = {};
|
||||||
|
result.rows.forEach(r => map[r.key] = r.value);
|
||||||
|
return {
|
||||||
|
fee: parseFloat(map.default_fee_percent || '1.0')
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
const merchantResult = await db.query('SELECT * FROM merchants WHERE id = $1', [transaction.merchant_id]);
|
||||||
|
const merchant = merchantResult.rows[0];
|
||||||
|
|
||||||
|
const feePercent = merchant?.fee_percent !== undefined && merchant?.fee_percent !== null
|
||||||
|
? parseFloat(merchant.fee_percent)
|
||||||
|
: settings.fee;
|
||||||
|
|
||||||
|
const grossAmount = parseFloat(transaction.amount);
|
||||||
|
const feeAmount = (grossAmount * feePercent) / 100;
|
||||||
|
const merchantNetCredit = grossAmount - feeAmount;
|
||||||
|
|
||||||
|
const cryptoAmount = parseFloat(expectedCryptoAmount);
|
||||||
|
const cryptoFee = (cryptoAmount * feePercent) / 100;
|
||||||
|
const cryptoNetCredit = cryptoAmount - cryptoFee;
|
||||||
|
|
||||||
|
// DB Updates
|
||||||
|
console.log("Updating merchant balances...");
|
||||||
|
await db.query(`UPDATE merchants SET available_balance = available_balance + $1 WHERE id = $2`,
|
||||||
|
[merchantNetCredit, transaction.merchant_id]);
|
||||||
|
|
||||||
|
await db.query(`
|
||||||
|
INSERT INTO merchant_balances (merchant_id, network, token, balance, total_gross)
|
||||||
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
|
ON CONFLICT (merchant_id, network, token)
|
||||||
|
DO UPDATE SET
|
||||||
|
balance = merchant_balances.balance + $4,
|
||||||
|
total_gross = merchant_balances.total_gross + $5
|
||||||
|
`, [transaction.merchant_id, selectedNetwork, selectedToken, cryptoNetCredit, cryptoAmount]);
|
||||||
|
|
||||||
|
console.log("Updating transaction...");
|
||||||
|
await db.query(`
|
||||||
|
UPDATE transactions
|
||||||
|
SET status = 'succeeded',
|
||||||
|
paid_network = $2,
|
||||||
|
paid_token = $3,
|
||||||
|
paid_amount_crypto = $4
|
||||||
|
WHERE id = $1`,
|
||||||
|
[transaction.id, selectedNetwork, selectedToken, expectedCryptoAmount]
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("Completed without error!");
|
||||||
|
} catch (e: any) {
|
||||||
|
console.error("Caught error:", e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testSweepDB().then(() => process.exit(0));
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
|
|
||||||
import { CryptoEngine } from './lib/crypto-engine';
|
import { CryptoEngine } from './lib/crypto-engine';
|
||||||
import { db } from './lib/db';
|
import { db } from './lib/db';
|
||||||
|
|
||||||
async function testSweep() {
|
async function testSweep() {
|
||||||
console.log("Starting test...");
|
console.log("Starting test for specific TX...");
|
||||||
const result = await db.query("SELECT * FROM transactions WHERE status IN ('pending', 'waiting') ORDER BY created_at DESC LIMIT 1");
|
const result = await db.query("SELECT * FROM transactions WHERE id = $1", ["5fda5442-23ea-4130-8646-d0a882ed2517"]);
|
||||||
if(result.rows.length === 0) return console.log("No pending");
|
if(result.rows.length === 0) return console.log("TX not found");
|
||||||
|
|
||||||
const tx = result.rows[0];
|
const tx = result.rows[0];
|
||||||
const wallets = tx.metadata?.wallets || {};
|
const wallets = tx.metadata?.wallets || {};
|
||||||
@@ -17,9 +16,14 @@ async function testSweep() {
|
|||||||
const depositAddress = solWallet.address;
|
const depositAddress = solWallet.address;
|
||||||
const depositPrivateKey = solWallet.privateKey;
|
const depositPrivateKey = solWallet.privateKey;
|
||||||
|
|
||||||
const verification = await cryptoEngine.verifyPayment(depositAddress, "0.295226", "SOL");
|
const verification = await cryptoEngine.verifyPayment(depositAddress, "0.164824", "SOL");
|
||||||
console.log("Verify:", verification);
|
console.log("Verify:", verification);
|
||||||
|
|
||||||
|
const { Connection, PublicKey } = require('@solana/web3.js');
|
||||||
|
const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
|
||||||
|
const b = await connection.getBalance(new PublicKey(depositAddress));
|
||||||
|
console.log("Direct Balance check:", b / 1e9);
|
||||||
|
|
||||||
if(verification.success) {
|
if(verification.success) {
|
||||||
console.log("Sweeping...");
|
console.log("Sweeping...");
|
||||||
const res = await cryptoEngine.sweepFunds(depositPrivateKey, "Ajr4nKieZJVu9q2d1eVF9pQPRCLoZ6v4tapB3iQn2SyQ", "SOL");
|
const res = await cryptoEngine.sweepFunds(depositPrivateKey, "Ajr4nKieZJVu9q2d1eVF9pQPRCLoZ6v4tapB3iQn2SyQ", "SOL");
|
||||||
|
|||||||
20
test_sweep_post.js
Normal file
20
test_sweep_post.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
export async function runTest() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('http://localhost:3000/api/crypto-sweep', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
txId: 'not-important-since-it-will-catch-in-db',
|
||||||
|
network: 'SOLANA',
|
||||||
|
token: 'SOL'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Status:", response.status);
|
||||||
|
const data = await response.json();
|
||||||
|
console.log("Data:", data);
|
||||||
|
} catch(e) {
|
||||||
|
console.error("Fetch Error:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runTest();
|
||||||
9
test_sync.ts
Normal file
9
test_sync.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { syncPendingPayments } from './lib/sync-worker';
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
console.log("Running Sync Worker...");
|
||||||
|
const res = await syncPendingPayments();
|
||||||
|
console.log("Result:", JSON.stringify(res, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch(console.error).then(() => process.exit(0));
|
||||||
69
test_sync_out.txt
Normal file
69
test_sync_out.txt
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
Running Sync Worker...
|
||||||
|
[SyncWorker] Starting manual sync...
|
||||||
|
[SyncWorker] Found 2 pending crypto transactions.
|
||||||
|
[SyncWorker] Checking TX 5a427df3 | Network: SOLANA | Token: SOL | Address: DZrWQ3Li3AogniRhgyGjNVmG1b3hLe7rR3tgeaKRcy63
|
||||||
|
[SyncWorker] Price for SOL: 3900.21 TL | Expected: 0.139454
|
||||||
|
[Verify] Starting verification for DZrWQ3Li3AogniRhgyGjNVmG1b3hLe7rR3tgeaKRcy63 | Req: 0.139454 SOL on SOLANA
|
||||||
|
[Verify SOL] Address DZrWQ3Li3AogniRhgyGjNVmG1b3hLe7rR3tgeaKRcy63 has 0 SOL. Expected >= 0.139454
|
||||||
|
[SyncWorker] Checking TX 5a427df3 | Network: SOLANA | Token: USDT | Address: DZrWQ3Li3AogniRhgyGjNVmG1b3hLe7rR3tgeaKRcy63
|
||||||
|
[SyncWorker] Price for USDT: 44.17 TL | Expected: 12.313788
|
||||||
|
[Verify] Starting verification for DZrWQ3Li3AogniRhgyGjNVmG1b3hLe7rR3tgeaKRcy63 | Req: 12.313788 USDT on SOLANA
|
||||||
|
[SyncWorker] Checking TX 5a427df3 | Network: SOLANA | Token: USDC | Address: DZrWQ3Li3AogniRhgyGjNVmG1b3hLe7rR3tgeaKRcy63
|
||||||
|
[SyncWorker] Price for USDC: 44.17 TL | Expected: 12.313788
|
||||||
|
[Verify] Starting verification for DZrWQ3Li3AogniRhgyGjNVmG1b3hLe7rR3tgeaKRcy63 | Req: 12.313788 USDC on SOLANA
|
||||||
|
[SyncWorker] Checking TX 5a427df3 | Network: POLYGON | Token: MATIC | Address: 0x023f6362BDFC2D7b3A5042698F70F59d294c5A49
|
||||||
|
[SyncWorker] Price for MATIC: 16.76 TL | Expected: 32.455951
|
||||||
|
[Verify] Starting verification for 0x023f6362BDFC2D7b3A5042698F70F59d294c5A49 | Req: 32.455951 MATIC on POLYGON
|
||||||
|
[SyncWorker] Checking TX 5a427df3 | Network: POLYGON | Token: USDT | Address: 0x023f6362BDFC2D7b3A5042698F70F59d294c5A49
|
||||||
|
[SyncWorker] Price for USDT: 44.17 TL | Expected: 12.313788
|
||||||
|
[Verify] Starting verification for 0x023f6362BDFC2D7b3A5042698F70F59d294c5A49 | Req: 12.313788 USDT on POLYGON
|
||||||
|
[SyncWorker] Checking TX 5a427df3 | Network: POLYGON | Token: USDC | Address: 0x023f6362BDFC2D7b3A5042698F70F59d294c5A49
|
||||||
|
[SyncWorker] Price for USDC: 44.17 TL | Expected: 12.313788
|
||||||
|
[Verify] Starting verification for 0x023f6362BDFC2D7b3A5042698F70F59d294c5A49 | Req: 12.313788 USDC on POLYGON
|
||||||
|
[SyncWorker] Checking TX 5a427df3 | Network: TRON | Token: TRX | Address: TD5CjToksFjqJnFA4jjsgEJRScvkpfsSTX
|
||||||
|
[SyncWorker] Price for TRX: 12.91 TL | Expected: 42.117689
|
||||||
|
[Verify] Starting verification for TD5CjToksFjqJnFA4jjsgEJRScvkpfsSTX | Req: 42.117689 TRX on TRON
|
||||||
|
[SyncWorker] Checking TX 5a427df3 | Network: TRON | Token: USDT | Address: TD5CjToksFjqJnFA4jjsgEJRScvkpfsSTX
|
||||||
|
[SyncWorker] Price for USDT: 44.18 TL | Expected: 12.311000
|
||||||
|
[Verify] Starting verification for TD5CjToksFjqJnFA4jjsgEJRScvkpfsSTX | Req: 12.311000 USDT on TRON
|
||||||
|
[SyncWorker] Checking TX 5a427df3 | Network: TRON | Token: USDC | Address: TD5CjToksFjqJnFA4jjsgEJRScvkpfsSTX
|
||||||
|
[SyncWorker] Price for USDC: 44.17 TL | Expected: 12.313788
|
||||||
|
[Verify] Starting verification for TD5CjToksFjqJnFA4jjsgEJRScvkpfsSTX | Req: 12.313788 USDC on TRON
|
||||||
|
[SyncWorker] Checking TX 18fea8d1 | Network: POLYGON | Token: MATIC | Address: 0xd84FE6E4904108A9332297d7c6E51c91e2bd5C7D
|
||||||
|
[SyncWorker] Price for MATIC: 16.76 TL | Expected: 0.584792
|
||||||
|
[Verify] Starting verification for 0xd84FE6E4904108A9332297d7c6E51c91e2bd5C7D | Req: 0.584792 MATIC on POLYGON
|
||||||
|
[SyncWorker] Checking TX 18fea8d1 | Network: POLYGON | Token: USDT | Address: 0xd84FE6E4904108A9332297d7c6E51c91e2bd5C7D
|
||||||
|
[SyncWorker] Price for USDT: 44.17 TL | Expected: 0.221870
|
||||||
|
[Verify] Starting verification for 0xd84FE6E4904108A9332297d7c6E51c91e2bd5C7D | Req: 0.221870 USDT on POLYGON
|
||||||
|
[SyncWorker] Checking TX 18fea8d1 | Network: POLYGON | Token: USDC | Address: 0xd84FE6E4904108A9332297d7c6E51c91e2bd5C7D
|
||||||
|
[SyncWorker] Price for USDC: 44.17 TL | Expected: 0.221870
|
||||||
|
[Verify] Starting verification for 0xd84FE6E4904108A9332297d7c6E51c91e2bd5C7D | Req: 0.221870 USDC on POLYGON
|
||||||
|
[SyncWorker] Checking TX 18fea8d1 | Network: SOLANA | Token: SOL | Address: HvfSWWepPGnb1JSAuqEogq3mTvm9pTXKQZD4WKFCHKYe
|
||||||
|
[SyncWorker] Price for SOL: 3899.77 TL | Expected: 0.002513
|
||||||
|
[Verify] Starting verification for HvfSWWepPGnb1JSAuqEogq3mTvm9pTXKQZD4WKFCHKYe | Req: 0.002513 SOL on SOLANA
|
||||||
|
[Verify SOL] Address HvfSWWepPGnb1JSAuqEogq3mTvm9pTXKQZD4WKFCHKYe has 0 SOL. Expected >= 0.002513
|
||||||
|
[SyncWorker] Checking TX 18fea8d1 | Network: SOLANA | Token: USDT | Address: HvfSWWepPGnb1JSAuqEogq3mTvm9pTXKQZD4WKFCHKYe
|
||||||
|
[SyncWorker] Price for USDT: 44.17 TL | Expected: 0.221870
|
||||||
|
[Verify] Starting verification for HvfSWWepPGnb1JSAuqEogq3mTvm9pTXKQZD4WKFCHKYe | Req: 0.221870 USDT on SOLANA
|
||||||
|
[SyncWorker] Checking TX 18fea8d1 | Network: SOLANA | Token: USDC | Address: HvfSWWepPGnb1JSAuqEogq3mTvm9pTXKQZD4WKFCHKYe
|
||||||
|
[SyncWorker] Price for USDC: 44.17 TL | Expected: 0.221870
|
||||||
|
[Verify] Starting verification for HvfSWWepPGnb1JSAuqEogq3mTvm9pTXKQZD4WKFCHKYe | Req: 0.221870 USDC on SOLANA
|
||||||
|
[SyncWorker] Checking TX 18fea8d1 | Network: TRON | Token: TRX | Address: TVX1FmCzr8aDNomkmmuSS26yFPWBUEUWZx
|
||||||
|
[SyncWorker] Price for TRX: 12.91 TL | Expected: 0.759049
|
||||||
|
[Verify] Starting verification for TVX1FmCzr8aDNomkmmuSS26yFPWBUEUWZx | Req: 0.759049 TRX on TRON
|
||||||
|
[SyncWorker] Checking TX 18fea8d1 | Network: TRON | Token: USDT | Address: TVX1FmCzr8aDNomkmmuSS26yFPWBUEUWZx
|
||||||
|
[SyncWorker] Price for USDT: 44.18 TL | Expected: 0.221820
|
||||||
|
[Verify] Starting verification for TVX1FmCzr8aDNomkmmuSS26yFPWBUEUWZx | Req: 0.221820 USDT on TRON
|
||||||
|
[SyncWorker] Checking TX 18fea8d1 | Network: TRON | Token: USDC | Address: TVX1FmCzr8aDNomkmmuSS26yFPWBUEUWZx
|
||||||
|
[SyncWorker] Price for USDC: 44.18 TL | Expected: 0.221820
|
||||||
|
[Verify] Starting verification for TVX1FmCzr8aDNomkmmuSS26yFPWBUEUWZx | Req: 0.221820 USDC on TRON
|
||||||
|
Result: [
|
||||||
|
{
|
||||||
|
"id": "5a427df3-99bc-49f7-aedb-98ebe4128001",
|
||||||
|
"status": "no_payment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "18fea8d1-660f-47a5-b111-7e5bdc1dcca3",
|
||||||
|
"status": "no_payment"
|
||||||
|
}
|
||||||
|
]
|
||||||
40
verifyAll.ts
Normal file
40
verifyAll.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { Client } from 'pg';
|
||||||
|
import { CryptoEngine } from './lib/crypto-engine';
|
||||||
|
import cryptoConfig from './lib/crypto-config.json';
|
||||||
|
|
||||||
|
async function verifyAllNetworks() {
|
||||||
|
const client = new Client({ connectionString: process.env.DATABASE_URL });
|
||||||
|
await client.connect();
|
||||||
|
|
||||||
|
const res = await client.query(`SELECT * FROM transactions WHERE status = 'pending'`);
|
||||||
|
console.log(`Checking ${res.rows.length} pending transactions...`);
|
||||||
|
|
||||||
|
for (const tx of res.rows) {
|
||||||
|
console.log(`\n=== TX: ${tx.id} ===`);
|
||||||
|
const wallets = tx.metadata?.wallets || {};
|
||||||
|
|
||||||
|
for (const networkId of Object.keys(wallets)) {
|
||||||
|
const tempWalletConfig = wallets[networkId] || {};
|
||||||
|
const address = typeof tempWalletConfig === 'string' ? tempWalletConfig : tempWalletConfig.address;
|
||||||
|
|
||||||
|
if (!address) continue;
|
||||||
|
|
||||||
|
const engine = new CryptoEngine(networkId as any);
|
||||||
|
const netConfig = cryptoConfig.networks.find(n => n.id === networkId);
|
||||||
|
if (!netConfig) continue;
|
||||||
|
|
||||||
|
for (const token of netConfig.tokens) {
|
||||||
|
const required = "0.000001"; // just to check what actual balance exists
|
||||||
|
// We'll just verify with 0 expected logic.
|
||||||
|
try {
|
||||||
|
const verification = await engine.verifyPayment(address, required, token.symbol);
|
||||||
|
if (verification.success || typeof verification.success === 'boolean') {
|
||||||
|
// We don't know exact balance unless we read cryptoEngine code, but verify is nice.
|
||||||
|
}
|
||||||
|
} catch(e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// since verifyPayment doesn't return actual balance, I will just print the addresses for the user to double check
|
||||||
|
verifyAllNetworks().catch(console.error);
|
||||||
Reference in New Issue
Block a user