Skip to content

Commit

Permalink
fix!: Move more helper functions to take network parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
janniks committed Sep 17, 2024
1 parent fac9843 commit d0a77fd
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 71 deletions.
32 changes: 12 additions & 20 deletions packages/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ import { CLI_NETWORK_OPTS, CLINetworkAdapter, getNetwork, NameInfoType } from '.

import { gaiaAuth, gaiaConnect, gaiaUploadProfileAll, getGaiaAddressFromProfile } from './data';

import { deriveDefaultUrl, STACKS_MAINNET, STACKS_TESTNET } from '@stacks/network';
import {
generateNewAccount,
generateWallet,
getAppPrivateKey,
restoreWalletAccounts,
} from '@stacks/wallet-sdk';
import { getMaxIDSearchIndex, getPrivateKeyAddress, setMaxIDSearchIndex } from './common';
import {
canonicalPrivateKey,
ClarityFunctionArg,
Expand All @@ -111,20 +119,6 @@ import {
subdomainOpToZFPieces,
} from './utils';

import {
deriveDefaultUrl,
STACKS_MAINNET,
STACKS_TESTNET,
TransactionVersion,
} from '@stacks/network';
import {
generateNewAccount,
generateWallet,
getAppPrivateKey,
restoreWalletAccounts,
} from '@stacks/wallet-sdk';
import { getMaxIDSearchIndex, getPrivateKeyAddress, setMaxIDSearchIndex } from './common';

// global CLI options
let txOnly = false;
let estimateOnly = false;
Expand Down Expand Up @@ -272,7 +266,7 @@ async function getAppKeys(network: CLINetworkAdapter, args: string[]): Promise<s
const privateKey = getAppPrivateKey({ account, appDomain });
const address = getAddressFromPrivateKey(
privateKey,
network.isMainnet() ? TransactionVersion.Mainnet : TransactionVersion.Testnet
network.isMainnet() ? STACKS_MAINNET : STACKS_TESTNET
);

return JSON.stringify({ keyInfo: { privateKey, address } });
Expand Down Expand Up @@ -360,10 +354,8 @@ async function migrateSubdomains(network: CLINetworkAdapter, args: string[]): Pr
for (const account of accounts) {
console.log('\nAccount:', account);

const txVersion = network.isMainnet() ? TransactionVersion.Mainnet : TransactionVersion.Testnet;

const dataKeyAddress = getAddressFromPrivateKey(account.dataPrivateKey, txVersion); // source
const walletKeyAddress = getAddressFromPrivateKey(account.stxPrivateKey, txVersion); // target
const dataKeyAddress = getAddressFromPrivateKey(account.dataPrivateKey, _network); // source
const walletKeyAddress = getAddressFromPrivateKey(account.stxPrivateKey, _network); // target

console.log(`Finding subdomains for data-key address '${dataKeyAddress}'`);
const namesResponse = await fetch(
Expand Down Expand Up @@ -1740,7 +1732,7 @@ async function stack(_network: CLINetworkAdapter, args: string[]): Promise<strin
});
const accounts = new AccountsApi(apiConfig);

const stxAddress = getAddressFromPrivateKey(privateKey, api.network.transactionVersion);
const stxAddress = getAddressFromPrivateKey(privateKey, network);

const balancePromise = accounts.getAccountBalance({
principal: stxAddress,
Expand Down
4 changes: 2 additions & 2 deletions packages/encryption/tests/messageSignature.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { bytesToHex, concatBytes, equals, utf8ToBytes } from '@stacks/common';
import { TransactionVersion } from '@stacks/network';
import { STACKS_TESTNET } from '@stacks/network';
import { getAddressFromPublicKey } from '@stacks/transactions';
import { verifyMessageSignatureRsv } from '../src/ec';
import { decodeMessage, encodeMessage, hashMessage } from '../src/messageSignature';
Expand Down Expand Up @@ -79,5 +79,5 @@ test('message signing complete flow', () => {
})
).toBe(true);

expect(getAddressFromPublicKey(publicKey, TransactionVersion.Testnet)).toBe(address);
expect(getAddressFromPublicKey(publicKey, STACKS_TESTNET)).toBe(address);
});
22 changes: 14 additions & 8 deletions packages/transactions/src/address.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { TransactionVersion } from '@stacks/network';
import {
STACKS_MAINNET,
StacksNetwork,
StacksNetworkName,
TransactionVersion,
networkFrom,
} from '@stacks/network';
import { AddressHashMode, AddressVersion } from './constants';

/**
Expand All @@ -7,37 +13,37 @@ import { AddressHashMode, AddressVersion } from './constants';
*/
export function addressHashModeToVersion(
hashMode: AddressHashMode,
txVersion: TransactionVersion
network?: StacksNetworkName | StacksNetwork
): AddressVersion {
// todo: `next` refacto with network param
network = networkFrom(network ?? STACKS_MAINNET);
switch (hashMode) {
case AddressHashMode.SerializeP2PKH:
switch (txVersion) {
switch (network.transactionVersion) {
case TransactionVersion.Mainnet:
return AddressVersion.MainnetSingleSig;
case TransactionVersion.Testnet:
return AddressVersion.TestnetSingleSig;
default:
throw new Error(
`Unexpected txVersion ${JSON.stringify(txVersion)} for hashMode ${hashMode}`
`Unexpected transactionVersion ${network.transactionVersion} for hashMode ${hashMode}`
);
}
case AddressHashMode.SerializeP2SH:
case AddressHashMode.SerializeP2SHNonSequential:
case AddressHashMode.SerializeP2WPKH:
case AddressHashMode.SerializeP2WSH:
case AddressHashMode.SerializeP2WSHNonSequential:
switch (txVersion) {
switch (network.transactionVersion) {
case TransactionVersion.Mainnet:
return AddressVersion.MainnetMultiSig;
case TransactionVersion.Testnet:
return AddressVersion.TestnetMultiSig;
default:
throw new Error(
`Unexpected txVersion ${JSON.stringify(txVersion)} for hashMode ${hashMode}`
`Unexpected transactionVersion ${network.transactionVersion} for hashMode ${hashMode}`
);
}
default:
throw new Error(`Unexpected hashMode ${JSON.stringify(hashMode)}`);
throw new Error(`Unexpected hashMode ${hashMode}`);
}
}
19 changes: 7 additions & 12 deletions packages/transactions/src/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,7 @@ import {
signatureRsvToVrs,
signatureVrsToRsv,
} from '@stacks/common';
import {
networkFrom,
STACKS_MAINNET,
StacksNetwork,
StacksNetworkName,
TransactionVersion,
} from '@stacks/network';
import { networkFrom, STACKS_MAINNET, StacksNetwork, StacksNetworkName } from '@stacks/network';
import { c32address } from 'c32check';
import { addressHashModeToVersion } from './address';
import { AddressHashMode, AddressVersion, PubKeyEncoding } from './constants';
Expand Down Expand Up @@ -58,21 +52,22 @@ utils.hmacSha256Sync = (key: Uint8Array, ...msgs: Uint8Array[]) => {
export function getAddressFromPrivateKey(
/** Private key bytes or hex string */
privateKey: PrivateKey,
transactionVersion = TransactionVersion.Mainnet
network?: StacksNetworkName | StacksNetwork
): string {
network = networkFrom(network ?? STACKS_MAINNET);
const publicKey = privateKeyToPublic(privateKey);
return getAddressFromPublicKey(publicKey, transactionVersion);
return getAddressFromPublicKey(publicKey, network);
}

// todo: use network as last parameter instead of txversion param. next refactor
/** Creates a P2PKH address string from the given public key and tx version. */
export function getAddressFromPublicKey(
/** Public key bytes or hex string */
publicKey: PublicKey,
transactionVersion = TransactionVersion.Mainnet
network?: StacksNetworkName | StacksNetwork
): string {
network = networkFrom(network ?? STACKS_MAINNET);
publicKey = typeof publicKey === 'string' ? hexToBytes(publicKey) : publicKey;
const addrVer = addressHashModeToVersion(AddressHashMode.SerializeP2PKH, transactionVersion);
const addrVer = addressHashModeToVersion(AddressHashMode.SerializeP2PKH, network);
const addr = addressFromVersionHash(addrVer, hashP2PKH(publicKey));
const addrString = addressToString(addr);
return addrString;
Expand Down
2 changes: 2 additions & 0 deletions packages/transactions/src/namespaces/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,5 @@ export const fromPrivateKey = privateKeyToAddress;
* ```
*/
export const fromPublicKey = publicKeyToAddressSingleSig;

// todo: add `fromPublicKeys` for multi-sig
11 changes: 0 additions & 11 deletions packages/transactions/src/wire/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { TransactionVersion } from '@stacks/network';
import { c32address } from 'c32check';
import { addressHashModeToVersion } from '../address';
import { AddressHashMode, AddressVersion, PayloadType } from '../constants';
import { publicKeyIsCompressed } from '../keys';
import { AssetString } from '../types';
Expand All @@ -22,15 +20,6 @@ import {
TokenTransferPayloadWire,
} from './types';

export function addressFromHashMode(
hashMode: AddressHashMode,
txVersion: TransactionVersion,
data: string
): AddressWire {
const version = addressHashModeToVersion(hashMode, txVersion);
return addressFromVersionHash(version, data);
}

export function addressFromPublicKeys(
version: AddressVersion,
hashMode: AddressHashMode,
Expand Down
10 changes: 5 additions & 5 deletions packages/transactions/tests/keys.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
signatureRsvToVrs,
utf8ToBytes,
} from '@stacks/common';
import { AddressVersion, STACKS_TESTNET, TransactionVersion } from '@stacks/network';
import { AddressVersion, STACKS_TESTNET } from '@stacks/network';
import { ec as EC } from 'elliptic';
import {
PubKeyEncoding,
Expand Down Expand Up @@ -75,10 +75,10 @@ test('Stacks public key and private keys', () => {
'SPZG6BAY4JVR9RNAB1HY92B7Q208ZYY4HZEA9PX5'
);

expect(getAddressFromPrivateKey(privKey, TransactionVersion.Testnet)).toBe(
expect(getAddressFromPrivateKey(privKey, STACKS_TESTNET)).toBe(
'STZG6BAY4JVR9RNAB1HY92B7Q208ZYY4HZG8ZXFM'
);
expect(getAddressFromPrivateKey(hexToBytes(privKey), TransactionVersion.Testnet)).toBe(
expect(getAddressFromPrivateKey(hexToBytes(privKey), STACKS_TESTNET)).toBe(
'STZG6BAY4JVR9RNAB1HY92B7Q208ZYY4HZG8ZXFM'
);

Expand All @@ -87,10 +87,10 @@ test('Stacks public key and private keys', () => {
'SPZG6BAY4JVR9RNAB1HY92B7Q208ZYY4HZEA9PX5'
);

expect(getAddressFromPublicKey(pubKeyString, TransactionVersion.Testnet)).toBe(
expect(getAddressFromPublicKey(pubKeyString, STACKS_TESTNET)).toBe(
'STZG6BAY4JVR9RNAB1HY92B7Q208ZYY4HZG8ZXFM'
);
expect(getAddressFromPublicKey(hexToBytes(pubKeyString), TransactionVersion.Testnet)).toBe(
expect(getAddressFromPublicKey(hexToBytes(pubKeyString), STACKS_TESTNET)).toBe(
'STZG6BAY4JVR9RNAB1HY92B7Q208ZYY4HZG8ZXFM'
);

Expand Down
29 changes: 21 additions & 8 deletions packages/transactions/tests/types.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { TransactionVersion } from '@stacks/network';
import { STACKS_MAINNET, STACKS_TESTNET, StacksNetwork } from '@stacks/network';
import {
AddressWire,
AssetWire,
LengthPrefixedList,
LengthPrefixedStringWire,
StacksWireType,
addressFromHashMode,
addressFromPublicKeys,
addressFromVersionHash,
addressHashModeToVersion,
addressToString,
createAddress,
createAsset,
Expand Down Expand Up @@ -63,7 +64,7 @@ test('C32 address hash mode - testnet P2PKH', () => {
const address = addressToString(
addressFromHashMode(
AddressHashMode.SerializeP2PKH,
TransactionVersion.Testnet,
STACKS_TESTNET,
'c22d24fec5d06e539c551e732a5ba88997761ba0'
)
);
Expand All @@ -75,7 +76,7 @@ test('C32 address hash mode - mainnet P2PKH', () => {
const address = addressToString(
addressFromHashMode(
AddressHashMode.SerializeP2PKH,
TransactionVersion.Mainnet,
STACKS_MAINNET,
'b976e9f5d6181e40bed7fa589142dfcf2fb28d8e'
)
);
Expand All @@ -87,7 +88,7 @@ test('C32 address hash mode - mainnet P2SH', () => {
const address = addressToString(
addressFromHashMode(
AddressHashMode.SerializeP2SH,
TransactionVersion.Mainnet,
STACKS_MAINNET,
'55011fc38a7e12f7d00496aef7a1c4b6dfeba81b'
)
);
Expand All @@ -99,7 +100,7 @@ test('C32 address hash mode - testnet P2SH', () => {
const address = addressToString(
addressFromHashMode(
AddressHashMode.SerializeP2SH,
TransactionVersion.Testnet,
STACKS_TESTNET,
'55011fc38a7e12f7d00496aef7a1c4b6dfeba81b'
)
);
Expand All @@ -111,7 +112,7 @@ test('C32 address hash mode - mainnet P2WSH', () => {
const address = addressToString(
addressFromHashMode(
AddressHashMode.SerializeP2WSH,
TransactionVersion.Mainnet,
STACKS_MAINNET,
'55011fc38a7e12f7d00496aef7a1c4b6dfeba81b'
)
);
Expand All @@ -123,7 +124,7 @@ test('C32 address hash mode - testnet P2WSH', () => {
const address = addressToString(
addressFromHashMode(
AddressHashMode.SerializeP2WSH,
TransactionVersion.Testnet,
STACKS_TESTNET,
'55011fc38a7e12f7d00496aef7a1c4b6dfeba81b'
)
);
Expand Down Expand Up @@ -214,3 +215,15 @@ test('Public keys to address hash', () => {
expect(address.hash160).toBe(fixture.result);
}
});

// helpers

/** @internal */
function addressFromHashMode(
hashMode: AddressHashMode,
network: StacksNetwork,
data: string
): AddressWire {
const version = addressHashModeToVersion(hashMode, network);
return addressFromVersionHash(version, data);
}
6 changes: 3 additions & 3 deletions packages/wallet-sdk/src/derive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,14 @@ const selectUsernameForAccount = async (
// try to find existing usernames owned by stx derivation path
if (opts.network) {
const stxPrivateKey = deriveStxPrivateKey(opts);
const address = getAddressFromPrivateKey(stxPrivateKey, opts.network.transactionVersion);
const address = getAddressFromPrivateKey(stxPrivateKey, opts.network);
let username = await fetchFirstName({ address, api });
if (username) {
return { username, derivationType: DerivationType.Wallet };
} else {
// try to find existing usernames owned by data derivation path
const dataPrivateKey = deriveDataPrivateKey(opts);
const address = getAddressFromPrivateKey(dataPrivateKey, opts.network.transactionVersion);
const address = getAddressFromPrivateKey(dataPrivateKey, opts.network);
username = await fetchFirstName({ address, api });
if (username) {
return { username, derivationType: DerivationType.Data };
Expand All @@ -220,7 +220,7 @@ export const fetchUsernameForAccountByDerivationType = async (
// try to find existing usernames owned by given derivation path
const selectedNetwork = opts.network ? networkFrom(opts.network) : STACKS_MAINNET;
const privateKey = derivePrivateKeyByType(opts);
const address = getAddressFromPrivateKey(privateKey, selectedNetwork.transactionVersion);
const address = getAddressFromPrivateKey(privateKey, selectedNetwork);
const username = await fetchFirstName({ address, api });
return { username };
};
Expand Down
7 changes: 5 additions & 2 deletions packages/wallet-sdk/src/models/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
fetchProfileFromUrl,
signAndUploadProfile,
} from './profile';
import { TransactionVersion } from '@stacks/network';
import { STACKS_MAINNET, STACKS_TESTNET, TransactionVersion } from '@stacks/network';

export const getStxAddress = ({
account,
Expand All @@ -29,7 +29,10 @@ export const getStxAddress = ({
account: Account;
transactionVersion?: TransactionVersion;
}): string => {
return getAddressFromPrivateKey(account.stxPrivateKey, transactionVersion);
return getAddressFromPrivateKey(
account.stxPrivateKey,
transactionVersion == TransactionVersion.Mainnet ? STACKS_MAINNET : STACKS_TESTNET // todo: refactor for `next` wallet update
);
};

/**
Expand Down

0 comments on commit d0a77fd

Please sign in to comment.