Skip to content

Commit

Permalink
feat: support testnet 4, closes LEA-1406
Browse files Browse the repository at this point in the history
  • Loading branch information
kyranjamie committed Oct 18, 2024
1 parent 1df5138 commit 28539a5
Show file tree
Hide file tree
Showing 29 changed files with 1,340 additions and 1,617 deletions.
22 changes: 11 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,15 @@
"@coinbase/cbpay-js": "2.1.0",
"@fungible-systems/zone-file": "2.0.0",
"@hirosystems/token-metadata-api-client": "1.2.0",
"@leather.io/bitcoin": "0.13.2",
"@leather.io/constants": "0.12.1",
"@leather.io/crypto": "1.6.2",
"@leather.io/models": "0.17.0",
"@leather.io/query": "2.14.1",
"@leather.io/stacks": "1.1.5",
"@leather.io/tokens": "0.9.0",
"@leather.io/ui": "1.27.1",
"@leather.io/utils": "0.15.0",
"@leather.io/bitcoin": "0.14.2",
"@leather.io/constants": "0.12.5",
"@leather.io/crypto": "1.6.6",
"@leather.io/models": "0.18.2",
"@leather.io/query": "2.15.2",
"@leather.io/stacks": "1.2.3",
"@leather.io/tokens": "0.9.1",
"@leather.io/ui": "1.30.0",
"@leather.io/utils": "0.16.6",
"@ledgerhq/hw-transport-webusb": "6.27.19",
"@noble/hashes": "1.5.0",
"@noble/secp256k1": "2.1.0",
Expand Down Expand Up @@ -261,9 +261,9 @@
"@btckit/types": "0.0.19",
"@chromatic-com/storybook": "1.2.23",
"@leather.io/eslint-config": "0.7.0",
"@leather.io/panda-preset": "0.4.0",
"@leather.io/panda-preset": "0.4.1",
"@leather.io/prettier-config": "0.6.0",
"@leather.io/rpc": "2.1.10",
"@leather.io/rpc": "2.1.13",
"@ls-lint/ls-lint": "2.2.3",
"@mdx-js/loader": "3.0.0",
"@pandacss/dev": "0.46.1",
Expand Down
2,762 changes: 1,228 additions & 1,534 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/app/common/persistence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ export const queryClient = new QueryClient({
});

export async function persistAndRenderApp(renderApp: () => void) {
if (!IS_TEST_ENV)
if (!IS_TEST_ENV) {
void persistQueryClient({
queryClient,
persister: chromeStorageLocalPersister,
buster: VERSION,
});
}
renderApp();
}
20 changes: 11 additions & 9 deletions src/app/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ function kebabCase(str: string) {
return str.replace(KEBAB_REGEX, match => '-' + match.toLowerCase());
}

interface MakeBitcoinTxExplorerLinkArgs {
txid: string;
bitcoin: BitcoinChainConfig;
}

interface MakeStacksTxExplorerLinkArgs {
mode: BitcoinNetworkModes;
searchParams?: URLSearchParams;
Expand Down Expand Up @@ -60,16 +55,23 @@ export function makeStacksAddressExplorerLink({
return `${HIRO_EXPLORER_URL}/address/${address}?${searchParams.toString()}`;
}

interface MakeBitcoinTxExplorerLinkArgs {
txid: string;
bitcoin: BitcoinChainConfig;
}
export function makeBitcoinTxExplorerLink({
txid,
bitcoin: { bitcoinUrl, bitcoinNetwork },
}: MakeBitcoinTxExplorerLinkArgs) {
switch (bitcoinNetwork) {
case 'mainnet':
case 'testnet':
return `https://mempool.space/${
bitcoinNetwork !== 'mainnet' ? bitcoinNetwork + '/' : ''
}tx/${txid}`;
return 'https://mempool.space/tx/' + txid;
case 'testnet3':
return 'https://mempool.space/testnet/tx/' + txid;
case 'testnet4':
return 'https://mempool.space/testnet4/tx/' + txid;
case 'signet':
return 'https://mempool.space/signet/tx/' + txid;
case 'regtest':
return `${bitcoinUrl}/tx/${txid}`;
default:
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/loaders/bitcoin-account-loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function BitcoinTaprootAccountLoader({ children, ...props }: BtcAccountLo

const properIndex = 'current' in props ? currentAccountIndex : props.index;

const signer = useTaprootSigner(properIndex, network.chain.bitcoin.bitcoinNetwork);
const signer = useTaprootSigner(properIndex, network.chain.bitcoin.mode);

if (!signer || !isBitcoinEnabled) return null;
return children(signer(0));
Expand Down
25 changes: 18 additions & 7 deletions src/app/features/add-network/network-form-fields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { HStack, styled } from 'leather-styles/jsx';

import {
BITCOIN_API_BASE_URL_MAINNET,
BITCOIN_API_BASE_URL_TESTNET,
BITCOIN_API_BASE_URL_TESTNET3,
BITCOIN_API_BASE_URL_TESTNET4,
type BitcoinNetwork,
type BitcoinNetworkModes,
} from '@leather.io/models';
import {
Expand All @@ -24,15 +26,19 @@ import { type AddNetworkFormValues } from './use-add-network';

const networks: {
label: string;
value: BitcoinNetworkModes;
value: BitcoinNetwork;
}[] = [
{
label: 'Mainnet',
value: 'mainnet',
},
{
label: 'Testnet',
value: 'testnet',
label: 'Testnet3',
value: 'testnet3',
},
{
label: 'Testnet4',
value: 'testnet4',
},
{
label: 'Signet',
Expand Down Expand Up @@ -66,15 +72,20 @@ export function NetworkFormFields({ isEditNetworkMode }: NetworkFormFieldsProps)
[setFieldValue]
);

function setNetworkUrls(value: BitcoinNetworkModes) {
function setNetworkUrls(value: BitcoinNetwork | BitcoinNetworkModes) {
switch (value) {
case 'mainnet':
setStacksUrl('https://api.hiro.so');
setBitcoinUrl(BITCOIN_API_BASE_URL_MAINNET);
break;
case 'testnet':
case 'testnet3':
setStacksUrl('https://api.testnet.hiro.so');
setBitcoinUrl(BITCOIN_API_BASE_URL_TESTNET3);
break;
case 'testnet4':
setStacksUrl('https://api.testnet.hiro.so');
setBitcoinUrl(BITCOIN_API_BASE_URL_TESTNET);
setBitcoinUrl(BITCOIN_API_BASE_URL_TESTNET4);
break;
case 'signet':
setStacksUrl('https://api.testnet.hiro.so');
Expand Down Expand Up @@ -112,7 +123,7 @@ export function NetworkFormFields({ isEditNetworkMode }: NetworkFormFieldsProps)

<Select.Root
defaultValue={initialValues.bitcoinNetwork || networks[0].value}
onValueChange={(value: BitcoinNetworkModes) => {
onValueChange={(value: BitcoinNetwork) => {
setNetworkUrls(value);
void setFieldValue('bitcoinNetwork', value);
}}
Expand Down
8 changes: 6 additions & 2 deletions src/app/features/add-network/use-add-network.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { useLocation, useNavigate } from 'react-router-dom';
import { ChainID } from '@stacks/transactions';

import {
type BitcoinNetworkModes,
type BitcoinNetwork,
type DefaultNetworkConfigurations,
type NetworkConfiguration,
bitcoinNetworkToNetworkMode,
networkConfigurationSchema,
} from '@leather.io/models';

Expand All @@ -33,7 +34,7 @@ export interface AddNetworkFormValues {
name: string;
stacksUrl: string;
bitcoinUrl: string;
bitcoinNetwork: BitcoinNetworkModes;
bitcoinNetwork: BitcoinNetwork;
}

const initialFormValues: AddNetworkFormValues = {
Expand Down Expand Up @@ -72,6 +73,7 @@ function useInitialValues() {
stacksUrl: network.chain.stacks.url,
bitcoinUrl: network.chain.bitcoin.bitcoinUrl,
bitcoinNetwork: network.chain.bitcoin.bitcoinNetwork,
mode: network.chain.bitcoin.mode,
};
}

Expand Down Expand Up @@ -169,6 +171,7 @@ export function useAddNetwork() {
subnetChainId: chainId, // Used for signing transactions (via the network object, not to be confused with the NetworkConfigurations)
url: stacksPath,
bitcoinNetwork,
mode: bitcoinNetworkToNetworkMode(bitcoinNetwork),
bitcoinUrl: bitcoinPath,
});
navigate(RouteUrls.Home);
Expand All @@ -180,6 +183,7 @@ export function useAddNetwork() {
chainId: chainId,
url: stacksPath,
bitcoinNetwork,
mode: bitcoinNetworkToNetworkMode(bitcoinNetwork),
bitcoinUrl: bitcoinPath,
});
navigate(RouteUrls.Home);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ function LedgerSignBitcoinTxContainer() {
const { signTransaction, latestDeviceResponse, awaitingDeviceConnection } =
useLedgerSignTx<BitcoinApp>({
chain,
isAppOpen: isBitcoinAppOpen({ network: network.chain.bitcoin.bitcoinNetwork }),
isAppOpen: isBitcoinAppOpen({ network: network.chain.bitcoin.mode }),
getAppVersion: getBitcoinAppVersion,
connectApp: connectLedgerBitcoinApp(network.chain.bitcoin.bitcoinNetwork),
connectApp: connectLedgerBitcoinApp(network.chain.bitcoin.mode),
async signTransactionWithDevice(bitcoinApp) {
if (!inputsToSign) {
ledgerNavigate.cancelLedgerAction();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ function LedgerRequestBitcoinKeys() {
const { requestKeys, latestDeviceResponse, awaitingDeviceConnection } =
useRequestLedgerKeys<BitcoinApp>({
chain,
connectApp: connectLedgerBitcoinApp(network.chain.bitcoin.bitcoinNetwork),
connectApp: connectLedgerBitcoinApp(network.chain.bitcoin.mode),
getAppVersion: getBitcoinAppVersion,
isAppOpen: isBitcoinAppOpen({ network: network.chain.bitcoin.bitcoinNetwork }),
isAppOpen: isBitcoinAppOpen({ network: network.chain.bitcoin.mode }),
onSuccess() {
navigate('/', { replace: true });
},
async pullKeysFromDevice(app) {
const { keys } = await pullBitcoinKeysFromLedgerDevice(app)({
network: bitcoinNetworkModeToCoreNetworkMode(network.chain.bitcoin.bitcoinNetwork),
network: bitcoinNetworkModeToCoreNetworkMode(network.chain.bitcoin.mode),
onRequestKey(index) {
const keyGroupFinalIndex = defaultNumberOfKeysToPullFromLedgerDevice - 1;
const isNativeSegwitkey = index <= keyGroupFinalIndex;
Expand Down
2 changes: 1 addition & 1 deletion src/app/features/psbt-signer/hooks/use-parsed-inputs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ interface UseParsedInputsArgs {
}
export function useParsedInputs({ inputs, indexesToSign }: UseParsedInputsArgs) {
const network = useCurrentNetwork();
const bitcoinNetwork = getBtcSignerLibNetworkConfigByMode(network.chain.bitcoin.bitcoinNetwork);
const bitcoinNetwork = getBtcSignerLibNetworkConfigByMode(network.chain.bitcoin.mode);
const bitcoinAddressNativeSegwit = useCurrentAccountNativeSegwitIndexZeroSigner().address;
const { address: bitcoinAddressTaproot } = useCurrentAccountTaprootIndexZeroSigner();
const inscriptions = useInscriptionsByOutputs(inputs);
Expand Down
2 changes: 1 addition & 1 deletion src/app/features/psbt-signer/hooks/use-parsed-outputs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface UseParsedOutputsArgs {
export function useParsedOutputs({ isPsbtMutable, outputs, network }: UseParsedOutputsArgs) {
const bitcoinAddressNativeSegwit = useCurrentAccountNativeSegwitIndexZeroSigner().address;
const { address: bitcoinAddressTaproot } = useCurrentAccountTaprootIndexZeroSigner();
const bitcoinNetwork = getBtcSignerLibNetworkConfigByMode(network.chain.bitcoin.bitcoinNetwork);
const bitcoinNetwork = getBtcSignerLibNetworkConfigByMode(network.chain.bitcoin.mode);

return useMemo(
() =>
Expand Down
2 changes: 1 addition & 1 deletion src/app/pages/receive/components/receive-tokens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export function ReceiveTokens({
}}
title="SRC-20"
/>
{(network.chain.bitcoin.bitcoinNetwork === 'testnet' || runesEnabled) && (
{(network.chain.bitcoin.mode === 'testnet' || runesEnabled) && (
<ReceiveItem
address={btcAddressTaproot}
icon={<RunesAvatarIcon />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function useSignBip322MessageFactory({ address, signPsbt }: SignBip322MessageFac
message,
address,
signPsbt,
network: network.chain.bitcoin.bitcoinNetwork,
network: network.chain.bitcoin.mode,
});

await shortPauseBeforeToast();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function SendInscriptionContainer() {
setUtxo(
createUtxoFromInscription({
inscription: routeState.inscription,
network: network.chain.bitcoin.bitcoinNetwork,
network: network.chain.bitcoin.mode,
accountIndex: currentAccountIndex,
inscriptionAddressIdx: addressesMap[routeState.inscription.address],
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ export function useSendInscriptionForm() {
.concat(
complianceValidator(
btcAddressValidator(),
bitcoinNetworkModeToCoreNetworkMode(currentNetwork.chain.bitcoin.bitcoinNetwork)
bitcoinNetworkModeToCoreNetworkMode(currentNetwork.chain.bitcoin.mode)
)
)
.concat(btcAddressNetworkValidator(currentNetwork.chain.bitcoin.bitcoinNetwork)),
.concat(btcAddressNetworkValidator(currentNetwork.chain.bitcoin.mode)),
}),
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export function BtcSendForm() {
/>
<SelectedAssetField icon={<BtcAvatarIcon />} name="Bitcoin" symbol={symbol} />
<TransferRecipientField />
{currentNetwork.chain.bitcoin.bitcoinNetwork === 'testnet' && (
{currentNetwork.chain.bitcoin.mode === 'testnet' && (
<Callout variant="warning" title="Funds have no value" mt="space.04">
This is a Bitcoin testnet transaction.
<Link
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ export function useBtcSendForm() {
.string()
.defined(FormErrorMessages.AddressRequired)
.concat(btcAddressValidator())
.concat(btcAddressNetworkValidator(currentNetwork.chain.bitcoin.bitcoinNetwork))
.concat(btcAddressNetworkValidator(currentNetwork.chain.bitcoin.mode))
.concat(notCurrentAddressValidator(nativeSegwitSigner.address || ''))
.concat(
complianceValidator(
btcAddressValidator(),
bitcoinNetworkModeToCoreNetworkMode(currentNetwork.chain.bitcoin.bitcoinNetwork)
bitcoinNetworkModeToCoreNetworkMode(currentNetwork.chain.bitcoin.mode)
)
),
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type UseQueryOptions, useQueries } from '@tanstack/react-query';
import axios from 'axios';

import type { BitcoinNetworkModes } from '@leather.io/models';
import { type BitcoinNetworkModes } from '@leather.io/models';
import { ensureArray, isEmptyString } from '@leather.io/utils';

import { analytics } from '@shared/utils/analytics';
Expand Down Expand Up @@ -69,7 +69,7 @@ function useCheckAddressComplianceQueries(addresses: string[]) {
return useQueries({
queries: addresses
.filter(address => !isEmptyString(address))
.map(address => makeComplianceQuery(address, network.chain.bitcoin.bitcoinNetwork)),
.map(address => makeComplianceQuery(address, network.chain.bitcoin.mode)),
});
}

Expand Down
4 changes: 2 additions & 2 deletions src/app/store/accounts/blockchain/bitcoin/bitcoin-keychain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export function bitcoinAccountBuilderFactory(

export function useBitcoinScureLibNetworkConfig() {
const network = useCurrentNetwork();
return getBtcSignerLibNetworkConfigByMode(network.chain.bitcoin.bitcoinNetwork);
return getBtcSignerLibNetworkConfigByMode(network.chain.bitcoin.mode);
}

export function useBitcoinExtendedPublicKeyVersions(): Versions | undefined {
Expand All @@ -72,7 +72,7 @@ export function useBitcoinExtendedPublicKeyVersions(): Versions | undefined {
return whenWallet({
software: undefined,
ledger: getHdKeyVersionsFromNetwork(
bitcoinNetworkModeToCoreNetworkMode(network.chain.bitcoin.bitcoinNetwork)
bitcoinNetworkModeToCoreNetworkMode(network.chain.bitcoin.mode)
),
});
} catch (e) {
Expand Down
Loading

0 comments on commit 28539a5

Please sign in to comment.