CW-1273: Implement USDT0 Bridge (#2855)

* feat: Implement USDT0 Bridging using OFT Standard by Layer Zero. POC available in apps menu.

* feat: Implement USDT0 Bridging using OFT Standard by Layer Zero. POC available in apps menu.

* feat: Implement USDT0 Bridging using OFT Standard by Layer Zero. POC available in apps menu.

* Add transaction history and status polling for USDT0 bridging

* Add  Transaction history and status polling for USDT0 Bridging

* USDT0 Bridging Implementation

* Update Arbitrum USDT token symbol

* fix: Merge conflicts

* fix: Merge conflicts

* chore: Rever formatting

* feat: Implement new flow

* feat: Implement new ui flow

* Add currency to configure

* feat: new ui flow

* Update USDT0 implementation
- Switch to sqlite for storage instead of hive
- Switch bridge history and details to modals
- Switch bridge transfer details page to new tx details ui

* refactor: rearrange modal action buttons

* enhance usdt0 bridge flows

* Update lib/entities/wallet_manager.dart [skip ci]

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
David Adegoke
2026-04-15 05:06:05 +02:00
committed by GitHub
co-authored by Omar Hatem
parent 162e0a5300
commit 586a040e4a
45 changed files with 3958 additions and 43 deletions
+110
View File
@@ -226,6 +226,22 @@ class CWEVM extends EVM {
@override
Web3Client? getWeb3Client(WalletBase wallet) => (wallet as EVMChainWallet).getWeb3Client();
@override
Future<bool?> getTransactionReceipt(WalletBase wallet, String txHash) async {
final client = getWeb3Client(wallet);
if (client == null) return null;
try {
final receipt = await client.getTransactionReceipt(txHash);
if (receipt == null) return null;
return receipt.status;
} catch (_) {
return null;
}
}
@override
String getTokenAddress(CryptoCurrency asset) => (asset as Erc20Token).contractAddress;
@@ -492,10 +508,24 @@ class CWEVM extends EVM {
chainId: config.chainId,
name: config.name,
shortCode: config.shortCode,
currency: config.nativeCurrency,
))
.toList();
}
@override
ChainInfo? getChainInfoByChainId(int chainId) {
final config = _registry.getChainConfig(chainId);
if (config == null) return null;
return ChainInfo(
chainId: config.chainId,
name: config.name,
shortCode: config.shortCode,
currency: config.nativeCurrency,
);
}
@override
ChainInfo? getCurrentChain(WalletBase wallet) {
if (wallet is EVMChainWallet) {
@@ -505,6 +535,7 @@ class CWEVM extends EVM {
chainId: config.chainId,
name: config.name,
shortCode: config.shortCode,
currency: config.nativeCurrency,
);
}
return null;
@@ -542,6 +573,85 @@ class CWEVM extends EVM {
bool hasPriorityFee(int chainId) => EVMChainUtils.hasPriorityFee(chainId);
@override
bool isUSDT0Token(WalletBase wallet, CryptoCurrency token) {
if (token is! Erc20Token) return false;
final chainId = getSelectedChainId(wallet);
if (chainId == null) return false;
return USDT0Config.isUSDT0Token(token, chainId);
}
@override
List<ChainInfo> getUSDT0DestinationChains(WalletBase wallet) {
final currentChainId = getSelectedChainId(wallet);
if (currentChainId == null) return [];
final result = <ChainInfo>[];
for (final config in _registry.getAllChains()) {
if (USDT0Config.isChainSupported(config.chainId) && config.chainId != currentChainId) {
result.add(ChainInfo(
chainId: config.chainId,
name: config.name,
shortCode: config.shortCode,
currency: config.nativeCurrency,
));
}
}
return result;
}
@override
Future<USDT0Quote> quoteUSDT0Transfer({
required WalletBase wallet,
required int sourceChainId,
required int destinationChainId,
required BigInt amount,
required String recipientAddress,
}) {
final evmWallet = wallet as EVMChainWallet;
final client = evmWallet.getWeb3Client();
if (client == null) {
throw StateError('Wallet not connected');
}
return USDT0Service.quoteCrossChainTransfer(
client: client,
sourceChainId: sourceChainId,
destinationChainId: destinationChainId,
amount: amount,
recipientAddress: recipientAddress,
);
}
@override
Future<PendingTransaction> executeUSDT0Transfer({
required WalletBase wallet,
required CryptoCurrency token,
required int sourceChainId,
required int destinationChainId,
required BigInt amount,
required String recipientAddress,
required USDT0Quote quote,
required TransactionPriority priority,
bool useBlinkProtection = true,
}) {
final evmWallet = wallet as EVMChainWallet;
final tokenErc20 = token as Erc20Token;
return USDT0Service.executeCrossChainTransfer(
wallet: evmWallet,
sourceChainId: sourceChainId,
destinationChainId: destinationChainId,
amount: amount,
recipientAddress: recipientAddress,
quote: quote,
token: tokenErc20,
priority: priority as EVMChainTransactionPriority,
useBlinkProtection: useBlinkProtection,
);
}
Future<EvmWalletConnectFeeQuote?> getWCBufferedFeeQuote(
WalletBase wallet,
TransactionPriority priority,