feat: Solana chain
This commit is contained in:
@@ -13,7 +13,7 @@ use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* When a mnemonic has no linked addresses, derive BIP44 indexes 0..2 for
|
||||
* TRON/ETH/BTC and persist only activated addresses (after a balance query).
|
||||
* TRON/ETH/BTC/SOL and persist only activated addresses (after a balance query).
|
||||
* Fully inactive mnemonics stay out of the DB and are not monitored; the
|
||||
* wallets view previews one index-0 address per chain marked 未激活.
|
||||
* Activated rows are persisted with monitor on.
|
||||
@@ -27,6 +27,7 @@ class MnemonicWalletDiscovery
|
||||
['chain' => 'tron', 'chain_type' => 'TRON'],
|
||||
['chain' => 'eth', 'chain_type' => 'ETH'],
|
||||
['chain' => 'btc', 'chain_type' => 'BTC'],
|
||||
['chain' => 'sol', 'chain_type' => 'SOLANA'],
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
@@ -63,17 +64,23 @@ class MnemonicWalletDiscovery
|
||||
return 0;
|
||||
}
|
||||
|
||||
$existing = WalletAddress::query()
|
||||
$linkedChainTypes = WalletAddress::query()
|
||||
->where('mnemonic_id', $mnemonic->id)
|
||||
->exists();
|
||||
if ($existing) {
|
||||
return 0;
|
||||
}
|
||||
->pluck('chain_type')
|
||||
->map(fn ($c) => strtoupper(trim((string) $c)))
|
||||
->filter()
|
||||
->unique()
|
||||
->values()
|
||||
->all();
|
||||
|
||||
$source = trim((string) ($mnemonic->source ?: ''));
|
||||
$saved = [];
|
||||
|
||||
foreach (self::CHAINS as $spec) {
|
||||
if ($this->hasLinkedChain($linkedChainTypes, $spec['chain'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$rows = $this->discoverChain($mnemonic, $phrase, $source, $spec['chain'], $spec['chain_type']);
|
||||
foreach ($rows as $row) {
|
||||
@@ -94,6 +101,22 @@ class MnemonicWalletDiscovery
|
||||
return count($saved);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $linkedChainTypes uppercase chain_type values already linked
|
||||
*/
|
||||
private function hasLinkedChain(array $linkedChainTypes, string $chain): bool
|
||||
{
|
||||
$aliases = match ($chain) {
|
||||
'tron' => ['TRON', 'TRX'],
|
||||
'eth' => ['ETH', 'ETHEREUM', 'EVM', 'BNB', 'BSC', 'BINANCE'],
|
||||
'btc' => ['BTC', 'BITCOIN'],
|
||||
'sol' => ['SOL', 'SOLANA'],
|
||||
default => [strtoupper($chain)],
|
||||
};
|
||||
|
||||
return array_intersect($aliases, $linkedChainTypes) !== [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Persisted linked rows, or ephemeral index-0 previews when none exist.
|
||||
*
|
||||
@@ -121,6 +144,7 @@ class MnemonicWalletDiscovery
|
||||
'eth' => $coins['eth'],
|
||||
'btc' => $coins['btc'],
|
||||
'bnb' => $coins['bnb'],
|
||||
'sol' => $coins['sol'],
|
||||
'active' => true,
|
||||
'persisted' => true,
|
||||
];
|
||||
@@ -193,6 +217,7 @@ class MnemonicWalletDiscovery
|
||||
'tron' => $this->probeTron($driver, $address),
|
||||
'eth' => $this->probeEth($driver, $address),
|
||||
'btc' => $this->probeBtc($driver, $address),
|
||||
'sol' => $this->probeSol($driver, $address),
|
||||
default => ['activated' => false, 'coins' => []],
|
||||
};
|
||||
}
|
||||
@@ -262,6 +287,32 @@ class MnemonicWalletDiscovery
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{activated: bool, coins: array<string, string>}
|
||||
*/
|
||||
private function probeSol(ChainDriver $driver, string $address): array
|
||||
{
|
||||
try {
|
||||
$sol = $driver->getNativeBalance($address);
|
||||
} catch (\Throwable) {
|
||||
return ['activated' => false, 'coins' => $this->emptyCoins('sol')];
|
||||
}
|
||||
|
||||
$usdt = $this->tokenBalance($driver, $address, (string) config('coruna.sol.usdt_contract', ''));
|
||||
$activated = bccomp($sol, '0', 9) > 0 || bccomp($usdt, '0', 6) > 0;
|
||||
if (! $activated) {
|
||||
return ['activated' => false, 'coins' => $this->emptyCoins('sol')];
|
||||
}
|
||||
|
||||
return [
|
||||
'activated' => true,
|
||||
'coins' => [
|
||||
'sol' => $sol,
|
||||
'usdt' => $usdt,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $coins
|
||||
*/
|
||||
@@ -327,6 +378,7 @@ class MnemonicWalletDiscovery
|
||||
'eth' => null,
|
||||
'btc' => null,
|
||||
'bnb' => null,
|
||||
'sol' => null,
|
||||
'active' => false,
|
||||
'persisted' => false,
|
||||
];
|
||||
@@ -344,6 +396,7 @@ class MnemonicWalletDiscovery
|
||||
'tron' => ['trx' => '0', 'usdt' => '0'],
|
||||
'eth' => ['eth' => '0', 'usdt' => '0'],
|
||||
'btc' => ['btc' => '0'],
|
||||
'sol' => ['sol' => '0', 'usdt' => '0'],
|
||||
default => [],
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user