fix: balance

This commit is contained in:
hashbro
2026-08-10 04:49:36 +08:00
parent aad44bf52e
commit c3d9871ae3
9 changed files with 360 additions and 19 deletions
+68 -3
View File
@@ -14,6 +14,7 @@ use App\Models\WalletMnemonic;
use App\Services\CorunaCrypto;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
@@ -212,6 +213,9 @@ class C2ApiTest extends TestCase
], $encSet2['body'])->assertOk();
$this->assertSame(1, WalletMnemonic::query()->where('device_id', $device->id)->count());
// No Tokenview key → enable fails → monitor forced off.
config(['coruna.tokenview.api_key' => '']);
$tsStatus = '1722585600789';
$encStatus = $crypto->encryptJson([
'd' => 'dev-wallet-1',
@@ -272,8 +276,17 @@ class C2ApiTest extends TestCase
}
#[Test]
public function status_global_wallet_ad_map_stores_empty_balance(): void
public function status_global_wallet_ad_map_refreshes_tron_balances_and_enables_monitor(): void
{
config(['coruna.tokenview.api_key' => 'test-key']);
Http::fake([
'*/wallet/getaccount' => Http::response(['balance' => 2_500_000], 200),
'*/wallet/triggerconstantcontract' => Http::response([
'constant_result' => [str_pad(dechex(12_500_000), 64, '0', STR_PAD_LEFT)],
], 200),
'services.tokenview.io/*' => Http::response(['code' => 1, 'msg' => 'success'], 200),
]);
$crypto = new CorunaCrypto;
$ts = '1722585600777';
$enc = $crypto->encryptJson([
@@ -298,14 +311,66 @@ class C2ApiTest extends TestCase
$this->assertNotNull($addr);
$this->assertSame('Global Wallet', $addr->source);
$this->assertSame('TRON', $addr->chain_type);
$this->assertNull($addr->trx);
$this->assertNull($addr->usdt);
$this->assertEqualsWithDelta(2.5, (float) $addr->trx, 0.0000001);
$this->assertEqualsWithDelta(12.5, (float) $addr->usdt, 0.0000001);
$this->assertSame(1, (int) $addr->monitor);
Http::assertSent(fn ($request) => str_contains($request->url(), '/monitor/address/add/trx/'));
}
#[Test]
public function status_disables_monitor_when_tokenview_enable_fails(): void
{
config(['coruna.tokenview.api_key' => 'test-key']);
Http::fake([
'services.tokenview.io/*' => Http::response(['code' => 0, 'msg' => 'fail'], 200),
]);
$crypto = new CorunaCrypto;
$ts = '1722585600778';
$enc = $crypto->encryptJson([
'd' => 'dev-monitor-fail-1',
'a' => 'a1',
'data' => [
['address' => '0xabc1230000000000000000000000000000000009', 'chain' => 'eth', 'balance' => '1', 'symbol' => 'ETH'],
],
], $ts);
$this->call('POST', '/api/user/status', [], [], [], [
'CONTENT_TYPE' => 'text/plain',
'HTTP_TIMESTAMP' => $ts,
], $enc['body'])->assertOk();
$device = Device::query()->where('device_id', 'dev-monitor-fail-1')->first();
$addr = WalletAddress::query()
->where('device_id', $device->id)
->where('address', '0xabc1230000000000000000000000000000000009')
->first();
$this->assertNotNull($addr);
$this->assertSame(0, (int) $addr->monitor);
}
#[Test]
public function status_ingests_har_shaped_ba_address_map(): void
{
// New Tron rows refresh TRX/USDT from chain before notify — stub node.
Http::fake(function ($request) {
$url = $request->url();
if (str_contains($url, '/wallet/getaccount')) {
return Http::response(['balance' => 4_000_006], 200);
}
if (str_contains($url, '/wallet/triggerconstantcontract')) {
return Http::response([
'constant_result' => [str_pad('0', 64, '0', STR_PAD_LEFT)],
], 200);
}
if (str_contains($url, 'tokenview')) {
return Http::response(['code' => 1, 'msg' => 'success'], 200);
}
return Http::response(['ok' => true], 200);
});
$crypto = new CorunaCrypto;
$ts = '1722585600888';
$enc = $crypto->encryptJson([
+53
View File
@@ -97,6 +97,59 @@ class TokenviewWebhookTest extends TestCase
$this->assertSame(1, TokenviewEvent::query()->count());
}
#[Test]
public function webhook_refreshes_tron_balances_from_chain_instead_of_delta(): void
{
config(['coruna.tokenview.sign_key' => '']);
Http::fake([
'*/wallet/getaccount' => Http::response(['balance' => 9_000_000], 200),
'*/wallet/triggerconstantcontract' => Http::response([
'constant_result' => [str_pad(dechex(50_000_000), 64, '0', STR_PAD_LEFT)],
], 200),
'api.telegram.org/*' => Http::response(['ok' => true], 200),
]);
config([
'coruna.telegram.bot_token' => 'bot-token',
'coruna.telegram.owner_chat_id' => '12345',
]);
$addr = $this->seedMonitoredAddress([
'address' => 'TKKyetwdwuv6fTWVMPsdQUZYwB7yiNwRp6',
'chain_type' => 'TRON',
'trx' => 1.0,
'usdt' => 10.0,
'eth' => null,
]);
$payload = [
'address' => 'TKKyetwdwuv6fTWVMPsdQUZYwB7yiNwRp6',
'txid' => 'tron-txid-refresh-1',
'coin' => 'TRX',
'tokenSymbol' => 'USDT',
'tokenValue' => '5',
'value' => '0.1',
];
$this->postJson('/hooks/tokenview', $payload)->assertOk()->assertSee('ok');
$addr->refresh();
// Live chain balances win over webhook deltas.
$this->assertEqualsWithDelta(9.0, (float) $addr->trx, 0.0000001);
$this->assertEqualsWithDelta(50.0, (float) $addr->usdt, 0.0000001);
Http::assertSent(function ($request) {
if (! str_contains($request->url(), 'api.telegram.org')) {
return false;
}
$text = (string) ($request->data()['text'] ?? '');
return str_contains($text, 'Balance Inbound')
&& str_contains($text, '+5 USDT')
&& str_contains($text, 'Balance')
&& str_contains($text, 'USDT');
});
}
#[Test]
public function webhook_ignores_address_when_monitor_off(): void
{