diff --git a/changelogs/3.0.13.txt b/changelogs/3.0.13.txt
new file mode 100644
index 00000000..619f4cd5
--- /dev/null
+++ b/changelogs/3.0.13.txt
@@ -0,0 +1 @@
+Bug fixes and performance improvements
diff --git a/package-lock.json b/package-lock.json
index 5fd2f4fd..f66633ec 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "mytonwallet",
- "version": "3.0.12",
+ "version": "3.0.13",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mytonwallet",
- "version": "3.0.12",
+ "version": "3.0.13",
"license": "GPL-3.0-or-later",
"dependencies": {
"@awesome-cordova-plugins/core": "^6.6.0",
diff --git a/package.json b/package.json
index 383cc9e5..e371af4a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "mytonwallet",
- "version": "3.0.12",
+ "version": "3.0.13",
"description": "The most feature-rich web wallet and browser extension for TON – with support of multi-accounts, tokens (jettons), NFT, TON DNS, TON Sites, TON Proxy, and TON Magic.",
"main": "index.js",
"scripts": {
diff --git a/public/static-sites/go/index.html b/public/static-sites/go/index.html
index 4b6595a5..47dcd0a5 100644
--- a/public/static-sites/go/index.html
+++ b/public/static-sites/go/index.html
@@ -34,11 +34,12 @@
diff --git a/src/components/explore/hooks/useDappBridge.ts b/src/components/explore/hooks/useDappBridge.ts
index e7162e1d..d26f3fe6 100644
--- a/src/components/explore/hooks/useDappBridge.ts
+++ b/src/components/explore/hooks/useDappBridge.ts
@@ -1,11 +1,16 @@
import type {
- AppRequest, ConnectEvent,
- ConnectEventError, ConnectRequest, DeviceInfo, RpcMethod, WalletEvent,
+ AppRequest,
+ ConnectEvent,
+ ConnectEventError,
+ ConnectRequest,
+ DeviceInfo,
+ RpcMethod,
+ WalletEvent,
WalletResponse,
} from '@tonconnect/protocol';
import { BottomSheet } from 'native-bottom-sheet';
import { useMemo, useRef, useState } from '../../../lib/teact/teact';
-import { getGlobal } from '../../../global';
+import { getActions, getGlobal } from '../../../global';
import type { CustomInAppBrowserObject } from './useWebViewBridge';
import { CONNECT_EVENT_ERROR_CODES, SEND_TRANSACTION_ERROR_CODES } from '../../../api/tonConnect/types';
@@ -36,6 +41,8 @@ interface OwnProps {
export function useDappBridge({
endpoint,
}: OwnProps) {
+ const { openLoadingOverlay, closeLoadingOverlay } = getActions();
+
// eslint-disable-next-line no-null/no-null
const inAppBrowserRef = useRef(null);
const [requestId, setRequestId] = useState(0);
@@ -67,12 +74,17 @@ export function useDappBridge({
await BottomSheet.enable();
}
+ openLoadingOverlay();
+
const response = await callApi(
'tonConnect_connect',
buildDappRequest(origin),
request,
requestId,
);
+
+ closeLoadingOverlay();
+
if (IS_DELEGATING_BOTTOM_SHEET) {
await BottomSheet.disable();
}
diff --git a/src/components/main/sections/Content/Token.module.scss b/src/components/main/sections/Content/Token.module.scss
index 42013fd0..b91abb1c 100644
--- a/src/components/main/sections/Content/Token.module.scss
+++ b/src/components/main/sections/Content/Token.module.scss
@@ -260,6 +260,6 @@
-webkit-text-fill-color: transparent;
:global(.theme-dark) & {
- background-image: linear-gradient(81.88deg, #44B5ED 19.42%, #2CD36F 71.55%);
+ background-image: linear-gradient(81.88deg, #58AFFF 19.42%, #2CD36F 71.55%);
}
}
diff --git a/src/components/settings/Settings.module.scss b/src/components/settings/Settings.module.scss
index b5c0ba13..bb01bae1 100644
--- a/src/components/settings/Settings.module.scss
+++ b/src/components/settings/Settings.module.scss
@@ -837,6 +837,10 @@ a.item:hover {
color: var(--color-black);
}
+.walletVersionAddress {
+ white-space: nowrap;
+}
+
.walletVersionAddress,
.walletVersionAmount {
font-size: 0.75rem;
diff --git a/src/components/settings/Settings.tsx b/src/components/settings/Settings.tsx
index c11846f6..7194a726 100644
--- a/src/components/settings/Settings.tsx
+++ b/src/components/settings/Settings.tsx
@@ -549,7 +549,7 @@ function Settings({
)}
- {!!versions?.length && !isHardwareAccount && (
+ {!!versions?.length && (
{lang('Wallet Versions')}
diff --git a/src/components/transfer/TransferComplete.tsx b/src/components/transfer/TransferComplete.tsx
index 1d296950..f96f0182 100644
--- a/src/components/transfer/TransferComplete.tsx
+++ b/src/components/transfer/TransferComplete.tsx
@@ -1,10 +1,11 @@
-import React, { memo } from '../../lib/teact/teact';
+import React, { memo, useEffect } from '../../lib/teact/teact';
import { getActions } from '../../global';
import type { ApiNft } from '../../api/types';
import { TONCOIN_SLUG } from '../../config';
import buildClassName from '../../util/buildClassName';
+import captureKeyboardListeners from '../../util/captureKeyboardListeners';
import { ANIMATED_STICKERS_PATHS } from '../ui/helpers/animatedAssets';
import { useDeviceScreen } from '../../hooks/useDeviceScreen';
@@ -68,6 +69,12 @@ function TransferComplete({
onBack: onClose,
});
+ useEffect(() => {
+ return isActive
+ ? captureKeyboardListeners({ onEnter: onClose })
+ : undefined;
+ }, [isActive, onClose]);
+
const handleTransactionRepeatClick = useLastCallback(() => {
startTransfer({
isPortrait,
diff --git a/src/components/ui/PasswordForm.tsx b/src/components/ui/PasswordForm.tsx
index 6e7275fb..112cc23b 100644
--- a/src/components/ui/PasswordForm.tsx
+++ b/src/components/ui/PasswordForm.tsx
@@ -142,12 +142,10 @@ function PasswordForm({
});
useEffect(() => {
- return isSubmitDisabled
+ return isSubmitDisabled || isLoading
? undefined
- : captureKeyboardListeners({
- onEnter: handleSubmit,
- });
- }, [handleSubmit, isSubmitDisabled]);
+ : captureKeyboardListeners({ onEnter: handleSubmit });
+ }, [handleSubmit, isLoading, isSubmitDisabled]);
function getPinPadTitle() {
switch (operationType) {
diff --git a/src/components/vesting/VestingModal.module.scss b/src/components/vesting/VestingModal.module.scss
index 8bba593e..bccd96d9 100644
--- a/src/components/vesting/VestingModal.module.scss
+++ b/src/components/vesting/VestingModal.module.scss
@@ -84,7 +84,7 @@
-webkit-text-fill-color: transparent;
:global(.theme-dark) & {
- background: linear-gradient(81.88deg, #44B5ED 19.42%, #2CD36F 71.55%);
+ background: linear-gradient(81.88deg, #58AFFF 19.42%, #2CD36F 71.55%);
background-clip: text;
-webkit-text-fill-color: transparent;
@@ -294,7 +294,7 @@
background-size: 100%;
:global(.theme-dark) & {
- background-image: linear-gradient(81.88deg, #0C9EE8 19.42%, #2CD36F 71.55%);
+ background-image: linear-gradient(81.88deg, #469CEC 19.42%, #2CD36F 71.55%);
}
}
}
@@ -326,7 +326,7 @@
background-size: 100%;
:global(.theme-dark) & {
- background-image: linear-gradient(81.88deg, #0C9EE8 19.42%, #2CD36F 71.55%);
+ background-image: linear-gradient(81.88deg, #469CEC 19.42%, #2CD36F 71.55%);
}
}
}
diff --git a/src/config.ts b/src/config.ts
index 02bd7e5c..64ad2fb4 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -291,6 +291,7 @@ export const BURN_ADDRESS = 'UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ';
export const DEFAULT_WALLET_VERSION: ApiWalletVersion = 'W5';
export const POPULAR_WALLET_VERSIONS: ApiWalletVersion[] = ['v3R1', 'v3R2', 'v4R2', 'W5'];
+export const LEDGER_WALLET_VERSIONS: ApiWalletVersion[] = ['v3R2', 'v4R2'];
export const DEFAULT_TIMEOUT = 10000;
export const DEFAULT_RETRIES = 3;
diff --git a/src/global/actions/api/auth.ts b/src/global/actions/api/auth.ts
index 3aac1937..b446b656 100644
--- a/src/global/actions/api/auth.ts
+++ b/src/global/actions/api/auth.ts
@@ -1016,7 +1016,16 @@ addActionHandler('importAccountByVersion', async (global, actions, { version })
const { title: currentWalletTitle } = (global.accounts?.byId ?? {})[accountId];
global = updateCurrentAccountId(global, wallet!.accountId);
- global = createAccount(global, wallet!.accountId, wallet!.address, { title: currentWalletTitle }, version);
+
+ const ledgerInfo = wallet!.ledger ? {
+ isHardware: true,
+ ledger: wallet?.ledger,
+ } : undefined;
+
+ global = createAccount(global, wallet!.accountId, wallet!.address, {
+ title: currentWalletTitle,
+ ...ledgerInfo,
+ }, version);
setGlobal(global);
});
diff --git a/src/global/actions/api/swap.ts b/src/global/actions/api/swap.ts
index ae61e94d..18711302 100644
--- a/src/global/actions/api/swap.ts
+++ b/src/global/actions/api/swap.ts
@@ -183,7 +183,9 @@ addActionHandler('cancelSwap', (global, actions, { shouldReset } = {}) => {
swapFee: '0',
networkFee: 0,
realNetworkFee: 0,
+ amountIn: '0',
amountOutMin: '0',
+ amountOut: '0',
inputSource: SwapInputSource.In,
swapType,
pairs,
diff --git a/src/hooks/useVesting.ts b/src/hooks/useVesting.ts
index 092d6138..1a577a9d 100644
--- a/src/hooks/useVesting.ts
+++ b/src/hooks/useVesting.ts
@@ -43,7 +43,7 @@ export default function useVesting({ vesting, userMycoin }: { vesting?: ApiVesti
const {
shouldRender,
transitionClassNames,
- } = useShowTransition(Boolean(hasVesting && isMycoinLoaded && userMycoin));
+ } = useShowTransition(Boolean(hasVesting && isMycoinLoaded && userMycoin && amount !== '0'));
const onVestingTokenClick = useLastCallback(() => {
openVestingModal();
diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss
index 9d0370cb..8e6f90a4 100644
--- a/src/styles/_variables.scss
+++ b/src/styles/_variables.scss
@@ -209,7 +209,7 @@
&:global(.theme-dark),
:global(.component-theme-dark) {
- --color-blue: #0C9EE8;
+ --color-blue: #469CEC;
--color-black: #DCEEFF;
--color-gray-1: #A3B8CA;
--color-gray-2: #8799B3;
@@ -219,7 +219,7 @@
--color-green-2: #79A28B;
--color-purple-1: #95A0FE;
--color-purple-2: #7986F7;
- --color-blue-10o: #0C9EE81A;
+ --color-blue-10o: #469CEC1A;
--color-background-first: #1E2732;
--color-background-first-disabled: #1A2129;
@@ -236,8 +236,8 @@
--color-input-hint: #435362;
- --color-blue-button-background: #0C9EE8;
- --color-blue-button-background-hover: #39BAFB;
+ --color-blue-button-background: #469CEC;
+ --color-blue-button-background-hover: #51A7F7;
--color-red-button-background: #D74A4A;
--color-red-button-background-hover: #F35B5B;
@@ -317,9 +317,9 @@
--color-background-blue-second: #133950;
--color-vesting-close-background: #124B6B;
--color-vesting-close-background-hover: #105F89;
- --color-vesting-blue: #0C9EE8;
- --color-vesting-blue-hover: #28AAEA;
- --color-vesting-text: #34B5F6;
+ --color-vesting-blue: #469CEC;
+ --color-vesting-blue-hover: #51A7F7;
+ --color-vesting-text: #58AFFF;
--color-vesting-background: #115073;
}
}
diff --git a/src/util/deeplink/index.ts b/src/util/deeplink/index.ts
index 9db67c0f..b7a526e5 100644
--- a/src/util/deeplink/index.ts
+++ b/src/util/deeplink/index.ts
@@ -37,6 +37,7 @@ enum DeeplinkCommand {
BuyWithCrypto = 'buy-with-crypto',
BuyWithCard = 'buy-with-card',
Stake = 'stake',
+ Transfer = 'transfer',
}
let urlAfterSignIn: string | undefined;
@@ -286,6 +287,18 @@ export function processSelfDeeplink(deeplink: string) {
}
break;
}
+
+ case DeeplinkCommand.Transfer: {
+ let tonDeeplink = deeplink;
+ SELF_UNIVERSAL_URLS.forEach((prefix) => {
+ if (tonDeeplink.startsWith(prefix)) {
+ tonDeeplink = tonDeeplink.replace(prefix, TON_PROTOCOL);
+ }
+ });
+
+ processTonDeeplink(tonDeeplink);
+ break;
+ }
}
} catch (err) {
logDebugError('processSelfDeeplink', err);
diff --git a/src/util/ledger/index.ts b/src/util/ledger/index.ts
index 5e7b38e8..d9814f46 100644
--- a/src/util/ledger/index.ts
+++ b/src/util/ledger/index.ts
@@ -73,9 +73,15 @@ type TransactionParams = {
};
};
+export type PossibleWalletVersion = 'v3R2' | 'v4R2';
+
+enum LedgerWalletVersion {
+ v3R2 = 'v3r2',
+ v4R2 = 'v4',
+}
+
const CHAIN = 0; // workchain === -1 ? 255 : 0;
-const WALLET_VERSION = 'v4R2';
-const INTERNAL_WALLET_VERSION = 'v4';
+const DEFAULT_WALLET_VERSION = 'v3R2';
const ATTEMPTS = 10;
const PAUSE = 125;
const IS_BOUNCEABLE = false;
@@ -90,6 +96,10 @@ const knownJettonAddresses = KNOWN_JETTONS.map(
let transport: TransportWebHID | TransportWebUSB | undefined;
let tonTransport: TonTransport | undefined;
+function getInternalWalletVersion(version: PossibleWalletVersion) {
+ return LedgerWalletVersion[version];
+}
+
export async function importLedgerWallet(network: ApiNetwork, accountIndex: number) {
const walletInfo = await getLedgerWalletInfo(network, accountIndex);
return callApi('importLedgerWallet', network, walletInfo);
@@ -142,7 +152,7 @@ export async function checkTonApp() {
// Workaround for Ledger S, this is a way to check if it is unlocked.
// There will be an error with code 0x530c
await tonTransport?.getAddress(getLedgerAccountPathByIndex(0), {
- walletVersion: INTERNAL_WALLET_VERSION,
+ walletVersion: LedgerWalletVersion.v3R2,
});
return true;
@@ -318,10 +328,11 @@ export async function submitLedgerTransfer(
const fromAddress = await callApi('fetchAddress', accountId);
- const [path, walletInfo, appInfo] = await Promise.all([
+ const [path, walletInfo, appInfo, accountInfo] = await Promise.all([
getLedgerAccountPath(accountId),
callApi('getWalletInfo', network, fromAddress!),
getTonAppInfo(),
+ callApi('fetchAccount', accountId),
]);
const { seqno, balance } = walletInfo!;
@@ -361,6 +372,8 @@ export async function submitLedgerTransfer(
? SendMode.CARRY_ALL_REMAINING_BALANCE
: SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS;
+ const walletSpecifiers = accountInfo!.version === 'v3R2' ? { includeWalletOp: false } : undefined;
+
try {
const signedCell = await tonTransport!.signTransaction(path, {
to: Address.parse(toAddress),
@@ -370,6 +383,7 @@ export async function submitLedgerTransfer(
bounce: isBounceable,
amount: BigInt(amount),
payload,
+ walletSpecifiers,
});
const message: ApiSignedTransfer = {
@@ -413,10 +427,11 @@ export async function submitLedgerNftTransfer(options: {
const fromAddress = await callApi('fetchAddress', accountId);
- const [path, walletInfo, appInfo] = await Promise.all([
+ const [path, walletInfo, appInfo, accountInfo] = await Promise.all([
getLedgerAccountPath(accountId),
callApi('getWalletInfo', network, fromAddress!),
getTonAppInfo(),
+ callApi('fetchAccount', accountId),
]);
if (!appInfo.isUnsafeSupported) {
@@ -440,6 +455,8 @@ export async function submitLedgerNftTransfer(options: {
forwardPayload = buildCommentPayload(comment);
}
+ const walletSpecifiers = accountInfo!.version === 'v3R2' ? { includeWalletOp: false } : undefined;
+
try {
const signedCell = await tonTransport!.signTransaction(path, {
to: Address.parse(nftAddress),
@@ -458,6 +475,7 @@ export async function submitLedgerNftTransfer(options: {
forwardAmount,
forwardPayload,
},
+ walletSpecifiers,
});
const message: ApiSignedTransfer = {
@@ -556,11 +574,12 @@ export async function signLedgerTransactions(accountId: string, messages: ApiDap
await callApi('waitLastTransfer', accountId);
- const [path, fromAddress, appInfo] = await Promise.all([
+ const [path, appInfo, accountInfo] = await Promise.all([
getLedgerAccountPath(accountId),
- callApi('fetchAddress', accountId),
getTonAppInfo(),
+ callApi('fetchAccount', accountId),
]);
+ const fromAddress = accountInfo!.address;
const { isUnsafeSupported, isJettonIdSupported } = appInfo;
@@ -569,9 +588,13 @@ export async function signLedgerTransactions(accountId: string, messages: ApiDap
}
const seqno = await callApi('getWalletSeqno', accountId, vestingAddress);
- const walletSpecifiers: TransactionParams['walletSpecifiers'] = vestingAddress
- ? { subwalletId: VESTING_SUBWALLET_ID, includeWalletOp: false }
- : undefined;
+ let walletSpecifiers: TransactionParams['walletSpecifiers'];
+ if (accountInfo!.version === 'v3R2') {
+ walletSpecifiers = { includeWalletOp: false };
+ }
+ if (vestingAddress) {
+ walletSpecifiers = { subwalletId: VESTING_SUBWALLET_ID, includeWalletOp: false };
+ }
const preparedParams: TransactionParams[] = await Promise.all(messages.map(async (message, index) => {
const {
@@ -706,7 +729,7 @@ export async function getLedgerWalletInfo(network: ApiNetwork, accountIndex: num
address,
publicKey: publicKey!.toString('hex'),
balance,
- version: WALLET_VERSION,
+ version: DEFAULT_WALLET_VERSION,
driver: 'HID',
deviceId: transport!.deviceModel?.id,
deviceName: transport!.deviceModel?.productName,
@@ -719,16 +742,19 @@ export function getLedgerWalletAddress(index: number, isTestnet?: boolean) {
return tonTransport!.getAddress(path, {
chain: CHAIN,
bounceable: WALLET_IS_BOUNCEABLE,
- walletVersion: INTERNAL_WALLET_VERSION,
+ walletVersion: LedgerWalletVersion.v3R2,
});
}
export async function verifyAddress(accountId: string) {
- const path = await getLedgerAccountPath(accountId);
+ const [accountInfo, path] = await Promise.all([
+ callApi('fetchAccount', accountId),
+ getLedgerAccountPath(accountId),
+ ]);
await tonTransport!.validateAddress(path, {
bounceable: IS_BOUNCEABLE,
- walletVersion: INTERNAL_WALLET_VERSION,
+ walletVersion: getInternalWalletVersion(accountInfo!.version as PossibleWalletVersion),
});
}