Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions src/components/wallet/wallet-address-portfolio-from-provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { useMemo } from 'react'
import { WalletAddressPortfolioView, type WalletAddressPortfolioViewProps } from './wallet-address-portfolio-view'
import type { ChainType } from '@/stores'
import { ChainProviderGate, useChainProvider } from '@/contexts'
import type { TokenInfo } from '@/components/token/token-item'
import { toTransactionInfoList } from '@/components/transaction/adapters'

export interface WalletAddressPortfolioFromProviderProps {
chainId: ChainType
address: string
chainName?: string
onTokenClick?: WalletAddressPortfolioViewProps['onTokenClick']
onTransactionClick?: WalletAddressPortfolioViewProps['onTransactionClick']
className?: string
testId?: string
}

/**
* 从 Provider 获取地址资产组合(内部实现)
*
* 使用 ChainProvider 响应式 API 获取数据,复用 WalletAddressPortfolioView 展示。
*/
function WalletAddressPortfolioFromProviderInner({
chainId,
address,
chainName,
onTokenClick,
onTransactionClick,
className,
testId,
}: WalletAddressPortfolioFromProviderProps) {
const chainProvider = useChainProvider()

// 使用新的响应式 API
const { data: tokens = [], isLoading: tokensLoading } = chainProvider.allBalances.useState(
{ address },
{ enabled: !!address }
)

const { data: txResult, isLoading: transactionsLoading } = chainProvider.transactionHistory.useState(
{ address, limit: 50 },
{ enabled: !!address }
)

// 转换为 TokenInfo 格式
const tokenInfoList: TokenInfo[] = useMemo(() => {
return tokens.map((token) => ({
symbol: token.symbol,
name: token.name,
chain: chainId,
balance: token.amount.toFormatted(),
decimals: token.decimals,
fiatValue: undefined,
change24h: 0,
icon: token.icon,
}))
}, [tokens, chainId])

// 转换交易历史格式
const transactions = useMemo(() => {
if (!txResult) return []
return toTransactionInfoList(txResult, chainId)
}, [txResult, chainId])

return (
<WalletAddressPortfolioView
chainId={chainId}
chainName={chainName}
tokens={tokenInfoList}
transactions={transactions}
tokensLoading={tokensLoading}
transactionsLoading={transactionsLoading}
tokensRefreshing={false}
tokensSupported={chainProvider.supportsTokenBalances || chainProvider.supportsNativeBalance}
tokensFallbackReason={undefined}
transactionsSupported={chainProvider.supportsTransactionHistory}
transactionsFallbackReason={undefined}
onTokenClick={onTokenClick}
onTransactionClick={onTransactionClick}
className={className}
testId={testId}
/>
)
}

/**
* 从 Provider 获取地址资产组合
*
* 使用 ChainProviderGate 确保 ChainProvider 可用,再使用响应式 API 获取数据。
* 适用于 Stories 测试和任意地址查询场景。
*/
export function WalletAddressPortfolioFromProvider(props: WalletAddressPortfolioFromProviderProps) {
return (
<ChainProviderGate
chainId={props.chainId}
fallback={
<div className="flex h-96 items-center justify-center">
<div className="text-muted-foreground text-center">
<p>Chain not supported: {props.chainId}</p>
</div>
</div>
}
>
<WalletAddressPortfolioFromProviderInner {...props} />
</ChainProviderGate>
)
}
3 changes: 2 additions & 1 deletion src/i18n/locales/en/transaction.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@
"twoStepSecretDescription": "This address has a security password set. Please enter your security password to confirm the transfer.",
"twoStepSecretPlaceholder": "Enter security password",
"twoStepSecretError": "Incorrect security password",
"fee": "Fee"
"fee": "Fee",
"previewTitle": "Transaction Preview"
},
"destroyPage": {
"title": "Destroy",
Expand Down
3 changes: 2 additions & 1 deletion src/i18n/locales/zh-CN/transaction.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@
"twoStepSecretDescription": "该地址已设置安全密码,请输入安全密码确认转账。",
"twoStepSecretPlaceholder": "输入安全密码",
"twoStepSecretError": "安全密码错误",
"fee": "手续费"
"fee": "手续费",
"previewTitle": "交易预览"
},
"destroyPage": {
"title": "销毁",
Expand Down
12 changes: 8 additions & 4 deletions src/pages/send/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useMemo, useRef, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigation, useActivityParams, useFlow } from '@/stackflow';
import { setTransferConfirmCallback, setTransferWalletLockCallback, setScannerResultCallback } from '@/stackflow/activities/sheets';
import { setTransferPreviewCallback, setTransferWalletLockCallback, setScannerResultCallback } from '@/stackflow/activities/sheets';
import type { Contact, ContactAddress } from '@/stores';
import { addressBookStore, addressBookSelectors, preferencesActions } from '@/stores';
import { PageHeader } from '@/components/layout/page-header';
Expand Down Expand Up @@ -237,8 +237,8 @@ function SendPageContent() {

haptics.impact('light');

// Set up callback: TransferConfirm -> TransferWalletLock (合并的钱包锁+二次签名)
setTransferConfirmCallback(
// Set up callback: TransferPreview -> TransferWalletLock (合并的钱包锁+二次签名)
setTransferPreviewCallback(
async () => {
if (isWalletLockSheetOpen.current) return;
isWalletLockSheetOpen.current = true;
Expand Down Expand Up @@ -300,13 +300,17 @@ function SendPageContent() {
}
);

push('TransferConfirmJob', {
push('TransferPreviewJob', {
amount: state.amount?.toFormatted() ?? '0',
symbol,
decimals: String(state.asset?.decimals ?? chainConfig?.decimals ?? 8),
fromAddress: currentChainAddress?.address ?? '',
toAddress: state.toAddress,
feeAmount: state.feeAmount?.toFormatted() ?? '0',
feeSymbol: state.feeSymbol,
feeLoading: state.feeLoading ? 'true' : 'false',
chainId: selectedChain,
chainName: selectedChainName,
});
};

Expand Down
Loading