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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@heroicons/react": "^1.0.6",
"@reduxjs/toolkit": "^2.8.2",
"@sidhujag/sysweb3-core": "^1.0.27",
"@sidhujag/sysweb3-keyring": "^1.0.531",
"@sidhujag/sysweb3-keyring": "^1.0.533",
"@sidhujag/sysweb3-network": "^1.0.105",
"@sidhujag/sysweb3-utils": "^1.1.256",
"@tippyjs/react": "^4.2.6",
Expand Down
4 changes: 3 additions & 1 deletion source/assets/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@
"walletLoggedOut": "Wallet ist abgemeldet",
"closeAndReopenPali": "Schließen Sie dieses Fenster und öffnen Sie Pali erneut, um sich zu authentifizieren und Ihre Hardware-Wallet zu verbinden",
"activeAccountNotFound": "Fehler: Aktives Konto nicht gefunden",
"paliWalletBrowserExtension": "Pali Wallet Browser-Erweiterung"
"paliWalletBrowserExtension": "Pali Wallet Browser-Erweiterung",
"addressType": "Adresstyp",
"taprootDisabled": "Taproot-Signierung bald verfügbar"
},
"components": {
"newPassword": "Neues Passwort (min. 8 Zeichen)",
Expand Down
4 changes: 3 additions & 1 deletion source/assets/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,9 @@
"walletLoggedOut": "Wallet is logged out",
"closeAndReopenPali": "Close this window and reopen Pali to authenticate and connect your hardware wallet",
"activeAccountNotFound": "Error: Active account not found",
"paliWalletBrowserExtension": "Pali Wallet Browser Extension"
"paliWalletBrowserExtension": "Pali Wallet Browser Extension",
"addressType": "Address type",
"taprootDisabled": "Taproot signing coming soon"
},
"start": {
"paliDoesnt": "Pali doesn't store your password. Regaining access requires a wallet reset with your Secret Recovery Phrase. This action erases the current wallet, created accounts, custom tokens, and imported accounts from your device, generating a new account tied to the reset phrase.",
Expand Down
4 changes: 3 additions & 1 deletion source/assets/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,9 @@
"walletLoggedOut": "La billetera está desconectada",
"closeAndReopenPali": "Cierre esta ventana y reabra Pali para autenticarse y conectar su billetera de hardware",
"activeAccountNotFound": "Error: Cuenta activa no encontrada",
"paliWalletBrowserExtension": "Extensión del Navegador Pali Wallet"
"paliWalletBrowserExtension": "Extensión del Navegador Pali Wallet",
"addressType": "Tipo de dirección",
"taprootDisabled": "La firma Taproot estará disponible pronto"
},
"start": {
"paliDoesnt": "Pali no guarda tu contraseña. Recuperar el acceso requiere un reinicio de la billetera con tu Frase Secreta de Recuperación. Esta acción borra la billetera actual, las cuentas creadas, tokens personalizados y cuentas importadas de tu dispositivo, generando una nueva cuenta vinculada a la frase de reinicio.",
Expand Down
4 changes: 3 additions & 1 deletion source/assets/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@
"walletLoggedOut": "Le portefeuille est déconnecté",
"closeAndReopenPali": "Fermez cette fenêtre et rouvrez Pali pour vous authentifier et connecter votre portefeuille matériel",
"activeAccountNotFound": "Erreur: Compte actif non trouvé",
"paliWalletBrowserExtension": "Extension de Navigateur Pali Wallet"
"paliWalletBrowserExtension": "Extension de Navigateur Pali Wallet",
"addressType": "Type d'adresse",
"taprootDisabled": "Signature Taproot bientôt disponible"
},
"components": {
"newPassword": "Nouveau mot de passe (8 caractères min.)",
Expand Down
4 changes: 3 additions & 1 deletion source/assets/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@
"walletLoggedOut": "ウォレットがログアウトしています",
"closeAndReopenPali": "このウィンドウを閉じてPaliを再度開き、認証してハードウェアウォレットを接続してください",
"activeAccountNotFound": "エラー:アクティブなアカウントが見つかりません",
"paliWalletBrowserExtension": "Pali Walletブラウザ拡張機能"
"paliWalletBrowserExtension": "Pali Walletブラウザ拡張機能",
"addressType": "アドレスタイプ",
"taprootDisabled": "Taproot 署名は近日対応"
},
"components": {
"newPassword": "新しいパスワード(最低8文字)",
Expand Down
4 changes: 3 additions & 1 deletion source/assets/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@
"walletLoggedOut": "지갑이 로그아웃되었습니다",
"closeAndReopenPali": "이 창을 닫고 Pali를 다시 열어서 인증하고 하드웨어 지갑을 연결하세요",
"activeAccountNotFound": "오류: 활성 계정을 찾을 수 없습니다",
"paliWalletBrowserExtension": "Pali Wallet 브라우저 확장"
"paliWalletBrowserExtension": "Pali Wallet 브라우저 확장",
"addressType": "주소 유형",
"taprootDisabled": "Taproot 서명은 곧 지원됩니다"
},
"components": {
"newPassword": "새 비밀번호 (최소 8자)",
Expand Down
4 changes: 3 additions & 1 deletion source/assets/locales/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,9 @@
"walletLoggedOut": "A carteira está desconectada",
"closeAndReopenPali": "Feche esta janela e reabra o Pali para autenticar e conectar sua carteira de hardware",
"activeAccountNotFound": "Erro: Conta ativa não encontrada",
"paliWalletBrowserExtension": "Extensão do Navegador Pali Wallet"
"paliWalletBrowserExtension": "Extensão do Navegador Pali Wallet",
"addressType": "Tipo de endereço",
"taprootDisabled": "Assinatura Taproot em breve"
},
"start": {
"paliDoesnt": "O Pali não armazena sua senha. Para recuperar o acesso, é necessário redefinir a carteira com sua Frase de Recuperação Secreta. Esta ação apaga a carteira atual, contas criadas, tokens personalizados e contas importadas do seu dispositivo, gerando uma nova conta vinculada à frase de redefinição.",
Expand Down
4 changes: 3 additions & 1 deletion source/assets/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@
"walletLoggedOut": "Кошелёк вышел из системы",
"closeAndReopenPali": "Закройте это окно и снова откройте Pali для аутентификации и подключения аппаратного кошелька",
"activeAccountNotFound": "Ошибка: Активный аккаунт не найден",
"paliWalletBrowserExtension": "Расширение для браузера Pali Wallet"
"paliWalletBrowserExtension": "Расширение для браузера Pali Wallet",
"addressType": "Тип адреса",
"taprootDisabled": "Подпись Taproot скоро будет доступна"
},
"components": {
"newPassword": "Новый пароль (мин. 8 символов)",
Expand Down
4 changes: 3 additions & 1 deletion source/assets/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@
"walletLoggedOut": "钱包已注销",
"closeAndReopenPali": "关闭此窗口并重新打开 Pali 以进行身份验证并连接您的硬件钱包",
"activeAccountNotFound": "错误:未找到活跃账户",
"paliWalletBrowserExtension": "Pali钱包浏览器扩展"
"paliWalletBrowserExtension": "Pali钱包浏览器扩展",
"addressType": "地址类型",
"taprootDisabled": "Taproot 签名即将推出"
},
"components": {
"newPassword": "新密码(至少8个字符)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,13 @@ const UtxoTransactionsListComponentBase = ({
const isSentByUs = anyVinOwn;
const signChar = isSentByUs ? '-' : '+';
const signClass = isSentByUs ? 'text-warning-error' : 'text-brand-green';
// Native SYS amount from first vout
// Native SYS amount: prefer output to our address for watch-only single-address accounts
// Fallback to first vout when no match (legacy behavior)
if (!intent && Array.isArray(tx?.vout) && tx.vout.length > 0) {
const value = Number(tx.vout[0]?.value || 0); // satoshis
const candidateVout =
tx.vout.find((v: any) => v?.isOwn === true) || tx.vout[0];

const value = Number(candidateVout?.value || 0); // satoshis
if (!isNaN(value) && value > 0) {
const baseSymbol = activeNetwork?.currency
? String(activeNetwork.currency).toUpperCase()
Expand Down
63 changes: 61 additions & 2 deletions source/pages/Settings/ImportAccount.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Input, Form } from 'antd';
import { useForm } from 'antd/es/form/Form';
import React, { useState } from 'react';
import React, { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom';
Expand All @@ -27,6 +27,9 @@ const ImportAccountView = () => {
const [isImporting, setIsImporting] = useState(false);
const [watchOnly, setWatchOnly] = useState(false);
const [validIdentifier, setValidIdentifier] = useState(false);
const [selectedUtxoAddressType, setSelectedUtxoAddressType] = useState<
'p2wpkh' | 'p2pkh'
>('p2wpkh');

const {
accounts,
Expand All @@ -47,7 +50,15 @@ const ImportAccountView = () => {
watchOnly
? ['wallet', 'importWatchOnlyFromController']
: ['wallet', 'importAccountFromPrivateKey'],
[form.getFieldValue('privKey'), form.getFieldValue('label')]
watchOnly
? [form.getFieldValue('privKey'), form.getFieldValue('label')]
: [
form.getFieldValue('privKey'),
form.getFieldValue('label'),
isBitcoinBased
? { utxoAddressType: selectedUtxoAddressType }
: undefined,
]
);

if (account) setIsAccountImported(true);
Expand All @@ -66,6 +77,20 @@ const ImportAccountView = () => {
}
};

// Simple WIF heuristic for showing the address-type selector: only on UTXO networks, not watch-only, not extended keys
const showAddressTypeSelector = useMemo(() => {
if (watchOnly || !isBitcoinBased) return false;
const value: string = form.getFieldValue('privKey') || '';
if (!value) return false;
const prefix = value.substring(0, 4);
const looksLikeExtended = ['zprv', 'vprv', 'xprv', 'tprv'].includes(prefix);
const looksLikeHex =
value.startsWith('0x') || /^[0-9a-fA-F]{64}$/.test(value);
if (looksLikeExtended || looksLikeHex) return false;
// If basic validation passed, treat as WIF and show selector
return validPrivateKey;
}, [watchOnly, isBitcoinBased, form, validPrivateKey]);

return (
<>
<ImportedWalletSuccessfully
Expand Down Expand Up @@ -106,6 +131,40 @@ const ImportAccountView = () => {
id="account-name-input"
/>
</Form.Item>
{showAddressTypeSelector && (
<div className="mb-2 text-left">
<label className="block text-white text-sm mb-2">
{t('settings.addressType')}
</label>
<div className="flex gap-3">
<label className="inline-flex items-center gap-2 cursor-pointer">
<input
type="radio"
name="utxoAddressType"
checked={selectedUtxoAddressType === 'p2wpkh'}
onChange={() => setSelectedUtxoAddressType('p2wpkh')}
/>
<span className="text-white text-sm">SegWit (P2WPKH)</span>
</label>
<label className="inline-flex items-center gap-2 cursor-pointer">
<input
type="radio"
name="utxoAddressType"
checked={selectedUtxoAddressType === 'p2pkh'}
onChange={() => setSelectedUtxoAddressType('p2pkh')}
/>
<span className="text-white text-sm">Legacy (P2PKH)</span>
</label>
<label
className="inline-flex items-center gap-2 opacity-50 cursor-not-allowed"
title={t('settings.taprootDisabled')}
>
<input type="radio" name="utxoAddressType" disabled />
<span className="text-white text-sm">Taproot (P2TR)</span>
</label>
</div>
</div>
)}
<div className="flex items-center justify-between mb-2">
<label className="text-white text-sm">Watch-only</label>
<input
Expand Down
33 changes: 27 additions & 6 deletions source/scripts/Background/controllers/MainController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
clearRpcCaches,
retryableFetch,
validateRpcBatchUniversal,
getNetworkConfig,
} from '@sidhujag/sysweb3-network';
import { txUtils, ITxid } from '@sidhujag/sysweb3-utils';
import {
Expand All @@ -26,6 +27,7 @@ import {
} from '@sidhujag/sysweb3-utils';
import isEmpty from 'lodash/isEmpty';
import isNil from 'lodash/isNil';
import * as syscoinjs from 'syscoinjs-lib';

import { getController, notificationManager } from '..';
import { clearNavigationState } from '../../../utils/navigationState';
Expand Down Expand Up @@ -2898,11 +2900,14 @@ class MainController {
}
}

public async importAccountFromPrivateKey(privKey: string, label?: string) {
const importedAccount = await this.getActiveKeyring().importAccount(
privKey,
label
);
public async importAccountFromPrivateKey(
privKey: string,
label?: string,
options?: { utxoAddressType?: 'p2wpkh' | 'p2pkh' }
) {
const importedAccount = await (
this.getActiveKeyring() as any
).importAccount(privKey, label, options);
store.dispatch(
createAccount({
account: importedAccount,
Expand Down Expand Up @@ -5249,7 +5254,23 @@ class MainController {
* Validate Syscoin address for the given network
*/
public validateSysAddress(address: string, chainId: number): boolean {
return isValidSYSAddress(address, chainId);
// Accept any valid UTXO address type for this network (bech32 and legacy base58)
if (isValidSYSAddress(address, chainId)) return true;

try {
const { activeNetwork: network } = store.getState().vault;
const { networks } = getNetworkConfig(network.slip44, network.currency);
const isTestnet = network.slip44 === 1;
const bitcoinjsNetwork = isTestnet ? networks.testnet : networks.mainnet;
// Try parsing as base58 legacy toOutputScript; will throw if invalid or wrong network
syscoinjs.utils.bitcoinjs.address.toOutputScript(
address,
bitcoinjsNetwork
);
return true;
} catch (_) {
return false;
}
}

/**
Expand Down
4 changes: 2 additions & 2 deletions source/utils/defaultNetworks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const getSyscoinUTXOMainnetNetwork = (): INetwork => ({
label: 'Syscoin Mainnet',
currency: 'sys',
url: 'https://blockbook.syscoin.org/',
explorer: 'https://blockbook.syscoin.org/',
explorer: 'https://explorer-blockbook.syscoin.org/',
default: true,
kind: INetworkType.Syscoin,
});
Expand All @@ -19,7 +19,7 @@ export const getSyscoinUTXOTestnetNetwork = (): INetwork => ({
label: 'Syscoin Testnet',
currency: 'tsys',
url: 'https://blockbook-dev.syscoin.org/',
explorer: 'https://blockbook-dev.syscoin.org/',
explorer: 'https://explorer-blockbook-dev.syscoin.org/',
default: false,
kind: INetworkType.Syscoin,
});
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3003,10 +3003,10 @@
resolved "https://registry.yarnpkg.com/@sidhujag/sysweb3-core/-/sysweb3-core-1.0.27.tgz#b7dd7d065c1845519e91ac470540ab94721eb33b"
integrity sha512-aeUJpk+DiziPJbD6HFnfixKZj0T4HYStshjk6+adziftLwamNc3MIp+MtIVZwtzvNpbzIXwAnuJM/QXQsc01NQ==

"@sidhujag/sysweb3-keyring@^1.0.531":
version "1.0.531"
resolved "https://registry.yarnpkg.com/@sidhujag/sysweb3-keyring/-/sysweb3-keyring-1.0.531.tgz#464678ed52114250f67ef25abbb22cd4c408fe64"
integrity sha512-iqMmAmJQlYiN++XnxaJ6FaudM37DNDWT19V9D9bCpr3Rf7WuxQ3PRoryC33aRbamD+mkrj9Sd0aJc50R4YDGpg==
"@sidhujag/sysweb3-keyring@^1.0.533":
version "1.0.533"
resolved "https://registry.yarnpkg.com/@sidhujag/sysweb3-keyring/-/sysweb3-keyring-1.0.533.tgz#392283e3f1b2eabb8a3ae513568296f23c82776e"
integrity sha512-podcWzQIpdGg5kuBFERHIQ5f+paonRVwu8xyiltg8AqP9aezzsLTWlcvuFIdUMdhl8jw/EsJmQAAO021ludjzg==
dependencies:
"@bitcoinerlab/descriptors" "^2.0.1"
"@bitcoinerlab/secp256k1" "^1.0.5"
Expand Down
Loading