Skip to content

Commit

Permalink
gabe's suggestion's
Browse files Browse the repository at this point in the history
  • Loading branch information
TalDerei committed Oct 17, 2024
1 parent e472dc6 commit 2a2f3c4
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 62 deletions.
13 changes: 3 additions & 10 deletions apps/minifront/src/components/send/send-form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useEffect, useMemo } from 'react';
import { penumbraAddrValidation } from '../helpers';
import InputToken from '../../shared/input-token';
import { GasFee } from '../../shared/gas-fee';
import { useBalancesResponses, useGasPrices, useStakingTokenMetadata } from '../../../state/shared';
import { useBalancesResponses, useStakingTokenMetadata } from '../../../state/shared';
import { NonNativeFeeWarning } from '../../shared/non-native-fee-warning';
import { transferableBalancesResponsesSelector } from '../../../state/send/helpers';
import { useRefreshFee } from '../../v2/transfer-layout/send-page/use-refresh-fee';
Expand All @@ -16,7 +16,6 @@ import { hasStakingToken } from '../../../fetchers/gas-prices';
export const SendForm = () => {
// Retrieve the staking token metadata and gas prices from the zustand
const stakingTokenMetadata = useStakingTokenMetadata();
const gasPrices = useGasPrices();

const transferableBalancesResponses = useBalancesResponses({
select: transferableBalancesResponsesSelector,
Expand All @@ -35,7 +34,6 @@ export const SendForm = () => {
setFeeTier,
setMemo,
sendTx,
setGasPrices,
setStakingToken,
txInProgress,
} = useStore(sendSelector);
Expand All @@ -52,22 +50,17 @@ export const SendForm = () => {
// useEffect here defers the state updates until after the rendering phase is complete,
// preventing direct state modifications during rendering.
useEffect(() => {
const updateStakingTokenAndGasPrices = () => {
const updateStakingToken = () => {
// Update the zustand store and local state
setStakingToken(isStakingToken);
if (gasPrices.data) {
setGasPrices(gasPrices.data);
}
};

updateStakingTokenAndGasPrices();
updateStakingToken();
}, [
transferableBalancesResponses,
stakingTokenMetadata,
selection,
gasPrices,
isStakingToken,
setGasPrices,
setStakingToken,
]);

Expand Down
32 changes: 16 additions & 16 deletions apps/minifront/src/state/send/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import { AllSlices, Middleware, SliceCreator, useStore } from '..';
import {
BalancesResponse,
TransactionPlannerRequest,
TransactionPlannerRequest_Output,
TransactionPlannerRequest_Spend,
} from '@penumbra-zone/protobuf/penumbra/view/v1/view_pb';
import { BigNumber } from 'bignumber.js';
import { MemoPlaintext } from '@penumbra-zone/protobuf/penumbra/core/transaction/v1/transaction_pb';
Expand All @@ -23,9 +21,10 @@ import { getAddress, getAddressIndex } from '@penumbra-zone/getters/address-view
import { toBaseUnit } from '@penumbra-zone/types/lo-hi';
import { isAddress } from '@penumbra-zone/bech32m/penumbra';
import { checkSendMaxInvariants, transferableBalancesResponsesSelector } from './helpers';
import { PartialMessage } from '@bufbuild/protobuf';
import { Metadata } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb';
import { Metadata, Value } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb';
import { getAssetTokenMetadata } from '../../fetchers/registry';
import { getGasPrices } from '../../fetchers/gas-prices';
import { Address } from '@penumbra-zone/protobuf/penumbra/core/keys/v1/keys_pb';

export interface SendSlice {
selection: BalancesResponse | undefined;
Expand All @@ -44,11 +43,15 @@ export interface SendSlice {
txInProgress: boolean;
assetFeeMetadata: Metadata | undefined;
gasPrices: GasPrices[] | undefined;
setGasPrices: (prices: GasPrices[]) => void;
stakingToken: boolean | undefined;
setStakingToken: (stakingToken: boolean) => void;
}

interface SpendOrOutput {
address: Address;
value: Value;
}

export const createSendSlice = (): SliceCreator<SendSlice> => (set, get) => {
return {
selection: undefined,
Expand Down Expand Up @@ -83,6 +86,10 @@ export const createSendSlice = (): SliceCreator<SendSlice> => (set, get) => {
},
refreshFee: async () => {
const { amount, recipient, selection } = get().send;
const prices = await getGasPrices();
set(state => {
state.send.gasPrices = prices;
});

if (!amount || !recipient || !selection) {
set(state => {
Expand Down Expand Up @@ -132,11 +139,6 @@ export const createSendSlice = (): SliceCreator<SendSlice> => (set, get) => {
});
}
},
setGasPrices: prices => {
set(state => {
state.send.gasPrices = prices;
});
},
setStakingToken: stakingToken => {
set(state => {
state.send.stakingToken = stakingToken;
Expand All @@ -154,17 +156,15 @@ const assembleRequest = ({
gasPrices,
stakingToken,
}: SendSlice) => {
const spendOrOutput:
| PartialMessage<TransactionPlannerRequest_Spend>
| PartialMessage<TransactionPlannerRequest_Output> = {
address: { altBech32m: recipient },
value: {
const spendOrOutput: SpendOrOutput = {
address: new Address({ altBech32m: recipient }),
value: new Value({
amount: toBaseUnit(
BigNumber(amount),
getDisplayDenomExponentFromValueView.optional(selection?.balanceView),
),
assetId: getAssetIdFromValueView(selection?.balanceView),
},
}),
};

const isSendingMax = checkSendMaxInvariants({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ export const assertSpendMax = async (
});

// Constraint: validate the requested spend amount is equal to the accumulated note balance.
const accumulatedBalance = await indexedDb.accumulateNoteBalance(
const totalNoteBalance = await indexedDb.totalNoteBalance(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- already asserted source existence
req.source!.account,
feeAssetId,
);
if (
accumulatedBalance.lo !== req.spends[0]?.value?.amount?.lo ||
accumulatedBalance.hi !== req.spends[0]?.value?.amount?.hi
totalNoteBalance.lo !== req.spends[0]?.value?.amount?.lo ||
totalNoteBalance.hi !== req.spends[0]?.value?.amount?.hi
) {
throw new ConnectError('Invalid transaction: Spend transaction was constructed improperly.');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { extractAltFee } from '../fees.js';
import { assertTransactionSource } from './assert-transaction-source.js';
import { TransactionPlan } from '@penumbra-zone/protobuf/penumbra/core/transaction/v1/transaction_pb';
import { assertSpendMax } from './assert-max-spends.js';
// import { AssetId } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb';
import { IndexedDbInterface } from '@penumbra-zone/types/indexed-db';

export const transactionPlanner: Impl['transactionPlanner'] = async (req, ctx) => {
Expand Down
56 changes: 25 additions & 31 deletions packages/storage/src/indexed-db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -959,44 +959,38 @@ export class IndexedDb implements IndexedDbInterface {
});
}

async accumulateNoteBalance(accountIndex: number, assetId: AssetId): Promise<Amount> {
async totalNoteBalance(accountIndex: number, assetId: AssetId): Promise<Amount> {
assertAssetId(assetId);
const spendableNotes = await this.db.getAllFromIndex(
'SPENDABLE_NOTES',
'assetId',
uint8ArrayToBase64(assetId.inner),
);

const spendableNotesSet: SpendableNoteRecord[] = [];

spendableNotes.forEach(note => {
const spendableNote = SpendableNoteRecord.fromJson(note);

// randomizer should be ignored
if (
spendableNote.heightSpent === 0n &&
!isZero(getAmountFromRecord(spendableNote)) &&
spendableNote.addressIndex?.account === accountIndex
) {
spendableNotesSet.push(spendableNote);
}
});

let accumulator = new Amount({ hi: 0n, lo: 0n });

// Accumulate the total value from the spendable note set
spendableNotesSet.forEach(noteRecord => {
if (noteRecord.note?.value?.amount) {
const noteAmount = noteRecord.note.value.amount;
const newAmount = addLoHi(
{ lo: accumulator.lo, hi: accumulator.hi },
{ lo: BigInt(noteAmount.lo), hi: BigInt(noteAmount.hi) },
return spendableNotes
.map(json => SpendableNoteRecord.fromJson(json))
.filter(note => {
return (
note.heightSpent === 0n &&
!isZero(getAmountFromRecord(note)) &&
// randomizer should be ignored
note.addressIndex?.account === accountIndex
);

accumulator = new Amount(newAmount);
}
});

return accumulator;
})
.reduce(
(acc, curr) => {
if (curr.note?.value?.amount) {
const noteAmount = curr.note.value.amount;
const newAmount = addLoHi(
{ lo: acc.lo, hi: acc.hi },
{ lo: BigInt(noteAmount.lo), hi: BigInt(noteAmount.hi) },
);
return new Amount(newAmount);
} else {
return acc;
}
},
new Amount({ hi: 0n, lo: 0n }),
);
}
}
2 changes: 1 addition & 1 deletion packages/types/src/indexed-db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export interface IndexedDbInterface {

hasTokenBalance(addressIndex: number, assetId: AssetId): Promise<boolean>;

accumulateNoteBalance(accountIndex: number, assetId: AssetId): Promise<Amount>;
totalNoteBalance(accountIndex: number, assetId: AssetId): Promise<Amount>;
}

export interface PenumbraDb extends DBSchema {
Expand Down

0 comments on commit 2a2f3c4

Please sign in to comment.