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
24 changes: 8 additions & 16 deletions apps/desktop/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1191,10 +1191,7 @@ app.on('child-process-gone', async (event, details) => {
app
.getGPUInfo('basic')
.then((gpuInfo) => {
logger.error(
'[GPU Crash] GPU Hardware Info:',
JSON.stringify(gpuInfo),
);
logger.error('[GPU Crash] GPU Hardware Info:', JSON.stringify(gpuInfo));
})
.catch(() => {
logger.error('[GPU Crash] Cannot retrieve GPU info after crash');
Expand Down Expand Up @@ -1418,15 +1415,12 @@ function startV8HeapMonitoring() {
).toFixed(1);

if (Number(usagePercent) > 70) {
logger.warn(
`[V8 Heap] ${usedMB}MB / ${limitMB}MB (${usagePercent}%)`,
{
totalHeapSize: heapStats.total_heap_size,
totalPhysicalSize: heapStats.total_physical_size,
allocatedMemory: heapStats.malloced_memory,
externalMemory: heapStats.external_memory,
},
);
logger.warn(`[V8 Heap] ${usedMB}MB / ${limitMB}MB (${usagePercent}%)`, {
totalHeapSize: heapStats.total_heap_size,
totalPhysicalSize: heapStats.total_physical_size,
allocatedMemory: heapStats.malloced_memory,
externalMemory: heapStats.external_memory,
});
}
}, MEMORY_CHECK_INTERVAL_MS);
}
Expand All @@ -1446,9 +1440,7 @@ function startWebviewMemoryMonitoring() {
const pid = wc.getOSProcessId();
const metric = metricsByPid.get(pid);
if (!metric) continue;
const memMB = Math.round(
(metric.memory?.workingSetSize ?? 0) / 1024,
);
const memMB = Math.round((metric.memory?.workingSetSize ?? 0) / 1024);
if (memMB > 300) {
logger.warn(
`[WebView Memory] pid=${pid} type=${wc.getType()} url=${wc.getURL().substring(0, 100)} memory=${memMB}MB`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,5 @@ function TabsDraggableFlatListImpl<T>(
export const TabsDraggableFlatList = React.forwardRef(
TabsDraggableFlatListImpl,
) as <T>(
props: DraggableFlatListProps<T> & { ref?: React.Ref<RNFlatList<T>> }
props: DraggableFlatListProps<T> & { ref?: React.Ref<RNFlatList<T>> },
) => React.ReactElement;
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ function BaseSortableListView<T>(
[onDragEnd],
);

const ListComponent = tabIntegrated ? TabsDraggableFlatList : DraggableFlatList;
const ListComponent = tabIntegrated
? TabsDraggableFlatList
: DraggableFlatList;

return (
<ListComponent<T>
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/chains/algo/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const NETWORK_REQUEST_ERROR_CODE = 40_005;
24 changes: 10 additions & 14 deletions packages/core/src/secret/__tests__/bip32-edge-cases.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -478,19 +478,15 @@ describe('BIP32 Edge Cases', () => {
secp256k1,
);

it(
'should handle deep derivation tree efficiently',
() => {
const seed = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex');
let key = deriver.generateMasterKeyFromSeed(seed);

for (let i = 0; i < 1000; i++) {
key = deriver.CKDPriv(key, i % 2 === 0 ? 0x80_00_00_00 : 0);
}

expect(key.key.length).toBe(32);
},
60_000,
);
it('should handle deep derivation tree efficiently', () => {
const seed = Buffer.from('000102030405060708090a0b0c0d0e0f', 'hex');
let key = deriver.generateMasterKeyFromSeed(seed);

for (let i = 0; i < 1000; i++) {
key = deriver.CKDPriv(key, i % 2 === 0 ? 0x80_00_00_00 : 0);
}

expect(key.key.length).toBe(32);
}, 60_000);
});
});
28 changes: 28 additions & 0 deletions packages/kit-bg/src/vaults/impls/algo/Vault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {
} from '@onekeyhq/core/src/types';
import {
ManageTokenInsufficientBalanceError,
type OneKeyError,
OneKeyInternalError,
OneKeyLocalError,
} from '@onekeyhq/shared/src/errors';
Expand Down Expand Up @@ -64,6 +65,7 @@ import type { IDBWalletType } from '../../../dbs/local/types';
import type { KeyringBase } from '../../base/KeyringBase';
import type {
IBroadcastTransactionByCustomRpcParams,
IBroadcastTransactionParams,
IBuildAccountAddressDetailParams,
IBuildDecodedTxParams,
IBuildEncodedTxParams,
Expand All @@ -75,6 +77,8 @@ import type {
IUpdateUnsignedTxParams,
IValidateGeneralInputParams,
} from '../../types';
import type { FailedAttemptError } from 'p-retry';
import { NETWORK_REQUEST_ERROR_CODE } from '@onekeyhq/core/src/chains/algo/constants';

export default class Vault extends VaultBase {
override coreApi = coreChainApi.algo.hd;
Expand Down Expand Up @@ -646,6 +650,14 @@ export default class Vault extends VaultBase {
};
}

override async broadcastTransaction(
params: IBroadcastTransactionParams,
): Promise<ISignedTxPro> {
const result = await super.broadcastTransaction(params);
await this._getSuggestedParams.clear();
return result;
}

override async broadcastTransactionFromCustomRpc(
params: IBroadcastTransactionByCustomRpcParams,
): Promise<ISignedTxPro> {
Expand All @@ -663,9 +675,25 @@ export default class Vault extends VaultBase {
txId,
rawTx: signedTx.rawTx,
});
await this._getSuggestedParams.clear();
return {
...params.signedTx,
txid: txId,
};
}

override async checkShouldRetryBroadcastTx(
error: FailedAttemptError,
): Promise<boolean> {
if (
(error as unknown as OneKeyError)?.code === NETWORK_REQUEST_ERROR_CODE &&
(error as unknown as OneKeyError)?.message?.includes(
'cannot broadcast txns in follower mode',
)
) {
await timerUtils.wait((error?.attemptNumber || 1) * 1000);
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,7 @@ function PasswordVerify({
<Input
selectTextOnFocus
size="large"
editable={
status.value !== EPasswordVerifyStatus.VERIFYING
}
editable={status.value !== EPasswordVerifyStatus.VERIFYING}
placeholder={intl.formatMessage({
id: ETranslations.auth_enter_your_passcode,
})}
Expand All @@ -317,7 +315,11 @@ function PasswordVerify({
// fix Keyboard Flickering on TextInput with secureTextEntry #39411
// https://github.com/facebook/react-native/issues/39411
textContentType="oneTimeCode"
onSubmitEditing={confirmBtnDisabled ? undefined : form.handleSubmit(onInputPasswordAuth)}
onSubmitEditing={
confirmBtnDisabled
? undefined
: form.handleSubmit(onInputPasswordAuth)
}
addOns={rightActions}
testID="password-input"
/>
Expand Down Expand Up @@ -356,9 +358,7 @@ function PasswordVerify({
onPasswordChange(pin);
}
}}
editable={
status.value !== EPasswordVerifyStatus.VERIFYING
}
editable={status.value !== EPasswordVerifyStatus.VERIFYING}
onComplete={onPassCodeComplete}
clearCode={passCodeClear}
disabledComplete={confirmBtnDisabled}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,12 +392,16 @@ function TokenListFooter(props: IProps) {
/>
) : null}
</XStack>
<Stack flexGrow={1} flexBasis={0} justifyContent="flex-end">
<Stack
flexGrow={1}
flexBasis={0}
justifyContent="center"
alignItems="flex-end"
>
<NumberSizeableText
size={tableLayout ? '$bodyMdMedium' : '$bodyLgMedium'}
formatter="value"
formatterOptions={{ currency: settings.currencyInfo.symbol }}
flex={1}
textAlign="right"
>
{smallBalanceTokensFiatValue}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -910,9 +910,7 @@ function BatchCreateAccountPreviewPage({
let advancedParams:
| IBatchBuildAccountsAdvancedFlowParams
| undefined;
let normalParams:
| IBatchBuildAccountsNormalFlowParams
| undefined;
let normalParams: IBatchBuildAccountsNormalFlowParams | undefined;
if (isAdvancedMode) {
advancedParams = {
walletId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ function AggregateTokenSelector() {

const processingTokenKey =
exchangeFilter && processingTokenState.isProcessing
? processingTokenState.token?.$key ?? null
? (processingTokenState.token?.$key ?? null)
: null;

const renderAggregateTokensList = useCallback(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,9 @@ function UploadCSVContent({ onUploaded }: IUploadCSVContentProps) {
return;
}

const filePath = localCopyResult.localUri.replace(/^file:\/\//, '');
const filePath = decodeURIComponent(
localCopyResult.localUri.replace(/^file:\/\//, ''),
);
// Read MAX_LINES + 1 to detect if file exceeds limit
const lines = await readFileStreamingLines(filePath, MAX_LINES);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type IUseBulkSendFeeEstimationParams = {
};

// Scale gasLimit for bulk transfer txs when batch estimation is not available.
// For transfer txs (non-approve), multiply gasLimit by (transfersInfo.length)
// For transfer txs (non-approve), multiply gasLimit by (transfersInfo.length + 1)
// to account for the higher gas consumption of multi-call contracts.
function scaleGasLimitForBulkTransfer(
feeInfo: IFeeInfoUnit,
Expand Down Expand Up @@ -275,7 +275,10 @@ export function useBulkSendFeeEstimation({
// Fallback mode: scale gasLimit for transfer txs
// Gas scales with the number of transfers in this tx, not the number of txs
const transferCount = unsignedTx.transfersInfo?.length ?? 1;
txFeeInfo = scaleGasLimitForBulkTransfer(txFeeInfo, transferCount);
txFeeInfo = scaleGasLimitForBulkTransfer(
txFeeInfo,
transferCount + 1,
);
}
const feeResult = calculateFeeForSend({
feeInfo: txFeeInfo,
Expand Down Expand Up @@ -412,7 +415,10 @@ export function useBulkSendFeeEstimation({
// Fallback mode: scale gasLimit for transfer txs
// Gas scales with the number of transfers in this tx, not the number of txs
const transferCount = unsignedTx.transfersInfo?.length ?? 1;
txFeeInfo = scaleGasLimitForBulkTransfer(txFeeInfo, transferCount);
txFeeInfo = scaleGasLimitForBulkTransfer(
txFeeInfo,
transferCount + 1,
);
}
const feeResult = calculateFeeForSend({
feeInfo: txFeeInfo,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import type { ComponentProps } from 'react';
import { memo, useCallback, useEffect, useState } from 'react';
import {
memo,
useCallback,
useContext,
useEffect,
useRef,
useState,
} from 'react';

import { isNil } from 'lodash';
import { useIntl } from 'react-intl';

import {
scrollTo,
useAnimatedReaction,
useSharedValue,
} from 'react-native-reanimated';

import {
Badge,
Button,
CollapsibleTabContext,
Form,
Icon,
Input,
Expand All @@ -17,6 +31,7 @@ import {
XStack,
YStack,
useForm,
useKeyboardEvent,
} from '@onekeyhq/components';
import backgroundApiProxy from '@onekeyhq/kit/src/background/instance/backgroundApiProxy';
import { useHelpLink } from '@onekeyhq/kit/src/hooks/useHelpLink';
Expand Down Expand Up @@ -181,6 +196,57 @@ function ReferralCodeBlock({
updateWalletStatus,
]);

// Keyboard avoidance: scroll collapsible tab header when input is covered
const inputWrapperRef = useRef<any>(null);
const isInputFocusedRef = useRef(false);
const tabsContext = useContext(CollapsibleTabContext);
const refMap = (tabsContext as any)?.refMap;
const focusedTabShared = (tabsContext as any)?.focusedTab;
const scrollYCurrent = (tabsContext as any)?.scrollYCurrent;
const tabContentInset = ((tabsContext as any)?.contentInset as number) ?? 0;

const scrollDelta = useSharedValue(0);

useAnimatedReaction(
() => scrollDelta.value,
(delta, prevDelta) => {
if (
delta > 0 &&
delta !== prevDelta &&
refMap &&
focusedTabShared &&
scrollYCurrent
) {
const ref = refMap[focusedTabShared.value];
if (ref) {
const targetScroll = scrollYCurrent.value + delta;
scrollTo(ref, 0, Math.max(0, targetScroll - tabContentInset), true);
}
scrollDelta.value = 0;
}
},
);

useKeyboardEvent(
{
keyboardWillShow: (e) => {
if (!isInputFocusedRef.current || !inputWrapperRef.current || !refMap) {
return;
}
inputWrapperRef.current.measureInWindow(
(_x: number, y: number, _width: number, height: number) => {
const inputBottom = y + height;
const keyboardTop = e.endCoordinates.screenY;
if (inputBottom > keyboardTop - 20) {
scrollDelta.value = inputBottom - keyboardTop + 60;
}
},
);
},
},
[],
);

const referralHelpLink = useHelpLink({ path: 'articles/11461266' });

const handleJoinReferral = useCallback(async () => {
Expand Down Expand Up @@ -229,7 +295,10 @@ function ReferralCodeBlock({

return shouldBoundReferralCode ? (
<XStack alignItems="center" gap="$2" alignSelf="stretch">
<Stack flex={platformEnv.isNative ? 1 : undefined}>
<Stack
flex={platformEnv.isNative ? 1 : undefined}
ref={inputWrapperRef}
>
<Form.Field
name="referralCode"
rules={{
Expand All @@ -252,6 +321,12 @@ function ReferralCodeBlock({
})}
backgroundColor="$bgApp"
maxLength={30}
onFocus={() => {
isInputFocusedRef.current = true;
}}
onBlur={() => {
isInputFocusedRef.current = false;
}}
/>
</Form.Field>
</Stack>
Expand Down
Loading