Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
yushih committed Apr 29, 2024
1 parent 9f28b29 commit b264948
Show file tree
Hide file tree
Showing 37 changed files with 744 additions and 825 deletions.
4 changes: 2 additions & 2 deletions packages/yoroi-extension/app/actions/ada/voting-actions.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// @flow
import { AsyncAction, Action } from '../lib/Action';
import { PublicDeriver } from '../../api/ada/lib/storage/models/PublicDeriver/index';
import type { WalletState } from '../../../chrome/extension/background/types';

export default class VotingActions {
generateCatalystKey: AsyncAction<void> = new AsyncAction();
createTransaction: AsyncAction<null | string> = new AsyncAction();
signTransaction: AsyncAction<{|
password?: string,
publicDeriver: PublicDeriver<>,
wallet: WalletState,
|}> = new AsyncAction();
cancel: Action<void> = new Action();
submitGenerate: Action<void> = new Action();
Expand Down
91 changes: 44 additions & 47 deletions packages/yoroi-extension/app/api/ada/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,10 @@ import type {
RestoreWalletResponse,
SendTokenList,
} from '../common/types';
import { getCardanoHaskellBaseConfig, } from './lib/storage/database/prepackaged/networks';
import {
getCardanoHaskellBaseConfig,
getNetworkById,
} from './lib/storage/database/prepackaged/networks';
import { toSenderUtxos, } from './transactions/transfer/utils';
import type { DefaultTokenEntry } from '../common/lib/MultiToken';
import { MultiToken } from '../common/lib/MultiToken';
Expand All @@ -152,6 +155,7 @@ import type { PersistedSubmittedTransaction } from '../localStorage';
import type { ForeignUtxoFetcher } from '../../connector/stores/ConnectorStore';
import type WalletTransaction from '../../domain/WalletTransaction';
import { derivePrivateByAddressing, derivePublicByAddressing } from './lib/cardanoCrypto/deriveByAddressing';
import type { WalletState } from '../../../chrome/extension/background/types';

// ADA specific Request / Response params

Expand Down Expand Up @@ -342,18 +346,15 @@ export type CreateUnsignedTxForUtxosFunc = (
// createDelegationTx

export type CreateDelegationTxRequest = {|
publicDeriver: (
IPublicDeriver<ConceptualWallet & IHasLevels> &
IGetPublic & IGetAllUtxos & IHasUtxoChains & IGetStakingKey
),
wallet: WalletState,
absSlotNumber: BigNumber,
registrationStatus: boolean,
poolRequest: void | string,
valueInAccount: MultiToken,
|};

type CreateVotingRegTxRequestCommon = {|
publicDeriver: IPublicDeriver<ConceptualWallet> & IGetAllUtxos & IHasUtxoChains,
wallet: WalletState,
absSlotNumber: BigNumber,
|};

Expand Down Expand Up @@ -387,7 +388,7 @@ export type CreateVotingRegTxFunc = (
// createWithdrawalTx

export type CreateWithdrawalTxRequest = {|
publicDeriver: IPublicDeriver<ConceptualWallet> & IGetAllUtxos & IHasUtxoChains,
wallet: WalletState,
absSlotNumber: BigNumber,
getAccountState: AccountStateFunc,
withdrawals: Array<{|
Expand Down Expand Up @@ -1314,8 +1315,8 @@ export default class AdaApi {
Logger.debug(`${nameof(AdaApi)}::${nameof(this.createDelegationTx)} called`);

try {
const { publicDeriver } = request;
const networkInfo = publicDeriver.getParent().getNetworkInfo();
const { wallet } = request;
const networkInfo = getNetworkById(wallet.networkId);
const config = getCardanoHaskellBaseConfig(networkInfo)
.reduce((acc, next) => Object.assign(acc, next), {});

Expand All @@ -1328,19 +1329,14 @@ export default class AdaApi {
networkId: networkInfo.NetworkId,
};

const publicKeyDbRow = await publicDeriver.getPublicKey();
if (publicKeyDbRow.IsEncrypted) {
throw new Error(`${nameof(AdaApi)}::${nameof(this.createDelegationTx)} public key is encrypted`);
}
const publicKey = RustModule.WalletV4.Bip32PublicKey.from_bytes(
Buffer.from(publicKeyDbRow.Hash, 'hex')
Buffer.from(wallet.publicKey, 'hex')
);

const stakingKeyDbRow = await publicDeriver.getStakingKey();
const stakingKey = derivePublicByAddressing({
addressing: stakingKeyDbRow.addressing,
addressing: wallet.stakingAddressing.addressing,
startingFrom: {
level: publicDeriver.getParent().getPublicDeriverLevel(),
level: wallet.publicDeriverLevel,
key: publicKey,
},
}).to_raw_key();
Expand All @@ -1351,12 +1347,10 @@ export default class AdaApi {
request.poolRequest
);

const allUtxo = await publicDeriver.getAllUtxos();
const allUtxo = wallet.utxos;
const addressedUtxo = asAddressedUtxo(allUtxo);
const changeAddr = await getReceiveAddress(publicDeriver);
if (changeAddr == null) {
throw new Error(`${nameof(this.createDelegationTx)} no internal addresses left. Should never happen`);
}
const changeAddr = await wallet.receiveAddress;

const unsignedTx = await shelleyNewAdaUnsignedTx(
[],
{
Expand All @@ -1377,23 +1371,28 @@ export default class AdaApi {
false,
);

const defaultToken = {
defaultNetworkId: wallet.networkId,
defaultIdentifier: wallet.defaultTokenId,
};

const utxoSum = allUtxosForKey.reduce(
(sum, utxo) => sum.joinAddMutable(new MultiToken(
utxo.output.tokens.map(token => ({
identifier: token.Token.Identifier,
amount: new BigNumber(token.TokenList.Amount),
networkId: token.Token.NetworkId,
})),
publicDeriver.getParent().getDefaultToken()
)),
publicDeriver.getParent().getDefaultMultiToken()
);
(sum, utxo) => sum.joinAddMutable(new MultiToken(
utxo.output.tokens.map(token => ({
identifier: token.Token.Identifier,
amount: new BigNumber(token.TokenList.Amount),
networkId: token.Token.NetworkId,
})),
defaultToken,
)),
new MultiToken([], defaultToken),
);

const differenceAfterTx = getDifferenceAfterTx(
unsignedTx,
allUtxo,
stakingKey,
publicDeriver.getParent().getDefaultToken(),
defaultToken,
);

const totalAmountToDelegate = utxoSum
Expand Down Expand Up @@ -1440,8 +1439,9 @@ export default class AdaApi {
): Promise<CreateWithdrawalTxResponse> {
Logger.debug(`${nameof(AdaApi)}::${nameof(this.createUnsignedTx)} called`);
try {
const network = getNetworkById(request.wallet.networkId);
const config = getCardanoHaskellBaseConfig(
request.publicDeriver.getParent().getNetworkInfo()
network,
).reduce((acc, next) => Object.assign(acc, next), {});

const protocolParams = {
Expand All @@ -1450,16 +1450,13 @@ export default class AdaApi {
linearFeeConstant: config.LinearFee.constant,
coinsPerUtxoWord: config.CoinsPerUtxoWord,
poolDeposit: config.PoolDeposit,
networkId: request.publicDeriver.getParent().networkInfo.NetworkId,
networkId: request.wallet.networkId,
};

const utxos = await request.publicDeriver.getAllUtxos();
const utxos = request.wallet.utxos;
const addressedUtxo = asAddressedUtxo(utxos);

const changeAddr = await getReceiveAddress(request.publicDeriver);
if (changeAddr == null) {
throw new Error(`${nameof(this.createWithdrawalTx)} no internal addresses left. Should never happen`);
}
const changeAddr = request.wallet.receiveAddress;

const certificates = [];
const neededKeys = {
Expand Down Expand Up @@ -1489,7 +1486,7 @@ export default class AdaApi {
}
}
const accountStates = await request.getAccountState({
network: request.publicDeriver.getParent().getNetworkInfo(),
network,
addresses: request.withdrawals.map(withdrawal => withdrawal.rewardAddress)
});
const finalWithdrawals = Object.keys(accountStates).reduce(
Expand Down Expand Up @@ -1581,7 +1578,7 @@ export default class AdaApi {
ChainNetworkId: Number.parseInt(config.ChainNetworkId, 10),
KeyDeposit: new BigNumber(config.KeyDeposit),
PoolDeposit: new BigNumber(config.PoolDeposit),
NetworkId: request.publicDeriver.getParent().getNetworkInfo().NetworkId,
NetworkId: request.wallet.networkId,
},
neededStakingKeyHashes: neededKeys,
});
Expand All @@ -1602,7 +1599,7 @@ export default class AdaApi {

try {
const config = getCardanoHaskellBaseConfig(
request.publicDeriver.getParent().getNetworkInfo()
getNetworkById(request.wallet.networkId)
).reduce((acc, next) => Object.assign(acc, next), {});

const protocolParams = {
Expand All @@ -1611,12 +1608,12 @@ export default class AdaApi {
linearFeeConstant: config.LinearFee.constant,
coinsPerUtxoWord: config.CoinsPerUtxoWord,
poolDeposit: config.PoolDeposit,
networkId: request.publicDeriver.getParent().networkInfo.NetworkId,
networkId: request.wallet.networkId,
};

const allUtxo = await request.publicDeriver.getAllUtxos();
const allUtxo = await request.wallet.utxos;
const addressedUtxo = asAddressedUtxo(allUtxo);
const changeAddr = await getReceiveAddress(request.publicDeriver);
const changeAddr = request.wallet.receiveAddress;
if (changeAddr == null) {
throw new Error(`${nameof(this.createVotingRegTx)} no internal addresses left. Should never happen`);
}
Expand Down Expand Up @@ -1663,7 +1660,7 @@ export default class AdaApi {
ChainNetworkId: Number.parseInt(config.ChainNetworkId, 10),
KeyDeposit: new BigNumber(config.KeyDeposit),
PoolDeposit: new BigNumber(config.PoolDeposit),
NetworkId: request.publicDeriver.getParent().getNetworkInfo().NetworkId,
NetworkId: request.wallet.networkId,
},
neededStakingKeyHashes: {
neededHashes: new Set(),
Expand Down
24 changes: 11 additions & 13 deletions packages/yoroi-extension/app/api/ada/lib/cardanoCrypto/utils.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// @flow

import { RustModule } from './rustLoader';
import { PublicDeriver } from '../storage/models/PublicDeriver';
import { generateWalletRootKey as cardanoGenerateWalletRootKey } from './cryptoWallet';
import { CoinTypes, WalletTypePurpose } from '../../../../config/numbersConfig';
import type { NetworkRow } from '../storage/database/primitives/tables';
import { asGetPublicKey } from '../storage/models/PublicDeriver/traits';
import type { WalletState } from '../../../../../chrome/extension/background/types';

export function v4PublicToV2(
v4Key: RustModule.WalletV4.Bip32PublicKey
Expand All @@ -14,11 +13,11 @@ export function v4PublicToV2(
}

export async function isWalletExist(
publicDerivers: Array<PublicDeriver<>>,
wallets: Array<WalletState>,
recoveryPhrase: string,
accountIndex: number,
selectedNetwork: $ReadOnly<NetworkRow>
): Promise<PublicDeriver<> | void> {
): Promise<WalletState | void> {
const rootPk = cardanoGenerateWalletRootKey(recoveryPhrase);
const accountPublicKey = rootPk
.derive(WalletTypePurpose.CIP1852)
Expand All @@ -27,19 +26,18 @@ export async function isWalletExist(
.to_public();
const publicKey = Buffer.from(accountPublicKey.as_bytes()).toString('hex');

for (const deriver of publicDerivers) {
const withPubKey = asGetPublicKey(deriver);
if (withPubKey == null) return;
const existedPublicKey = await withPubKey.getPublicKey();
const walletNetwork = deriver.getParent().getNetworkInfo();
for (const wallet of wallets) {
const existedPublicKey = wallet.publicKey;
const walletNetworkId = wallet.networkId
/**
* We will still allow to restore the wallet on a different networks even they are
* sharing the same recovery phrase but we are treating them differently
*/
if (
publicKey === existedPublicKey.Hash &&
walletNetwork.NetworkId === selectedNetwork.NetworkId
)
return deriver;
publicKey === existedPublicKey &&
walletNetworkId === selectedNetwork.NetworkId
) {
return wallet;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

import BigNumber from 'bignumber.js';
import { RustModule } from '../../cardanoCrypto/rustLoader';
import { asGetAllUtxos, } from '../models/PublicDeriver/traits';
import { PublicDeriver, } from '../models/PublicDeriver/index';
import { normalizeToAddress, unwrapStakingKey, } from './utils';
import type { IGetAllUtxosResponse, IGetStakingKey, } from '../models/PublicDeriver/interfaces';
import { MultiToken, } from '../../../../common/lib/MultiToken';
import type { WalletState } from '../../../../../../chrome/extension/background/types';

export type GetDelegatedBalanceRequest = {|
publicDeriver: PublicDeriver<> & IGetStakingKey,
wallet: WalletState,
rewardBalance: MultiToken,
stakingAddress: string,
delegation: string | null,
Expand Down Expand Up @@ -40,7 +39,7 @@ export async function getDelegatedBalance(
request: GetDelegatedBalanceRequest,
): Promise<GetDelegatedBalanceResponse> {
const utxoPart = await getUtxoDelegatedBalance(
request.publicDeriver,
request.wallet,
request.stakingAddress,
);

Expand Down Expand Up @@ -100,35 +99,35 @@ export function filterAddressesByStakingKey<T: { +address: string, ... }>(
}

export async function getUtxoDelegatedBalance(
publicDeriver: PublicDeriver<>,
wallet: WalletState,
stakingAddress: string,
): Promise<MultiToken> {
const withUtxos = asGetAllUtxos(publicDeriver);
if (withUtxos == null) {
return publicDeriver.getParent().getDefaultMultiToken();
}
const basePubDeriver = withUtxos;

// TODO: need to also deal with pointer address summing
// can get most recent pointer from getCurrentDelegation result

const stakingKey = unwrapStakingKey(stakingAddress);
const allUtxo = await basePubDeriver.getAllUtxos();
const stakingKey = unwrapStakingKey(wallet.stakingAddress);
const allUtxo = wallet.utxos;
const allUtxosForKey = filterAddressesByStakingKey<ElementOf<IGetAllUtxosResponse>>(
stakingKey,
allUtxo,
false,
);
const defaultToken = {
defaultNetworkId: wallet.networkId,
defaultIdentifier: wallet.defaultTokenId,
};
const defaultMultiToken = new MultiToken([], defaultToken);

const utxoSum = allUtxosForKey.reduce(
(sum, utxo) => sum.joinAddMutable(new MultiToken(
utxo.output.tokens.map(token => ({
identifier: token.Token.Identifier,
amount: new BigNumber(token.TokenList.Amount),
networkId: token.Token.NetworkId,
})),
publicDeriver.getParent().getDefaultToken()
defaultToken,
)),
publicDeriver.getParent().getDefaultMultiToken(),
defaultMultiToken,
);

return utxoSum;
Expand Down

0 comments on commit b264948

Please sign in to comment.