Skip to content
Draft
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
70 changes: 68 additions & 2 deletions apps/namadillo/src/App/Masp/MaspUnshield.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Panel } from "@namada/components";
import { Alert, Panel } from "@namada/components";
import { AccountType } from "@namada/types";
import { MaspSyncCover } from "App/Common/MaspSyncCover";
import { NamadaTransferTopHeader } from "App/NamadaTransfer/NamadaTransferTopHeader";
Expand All @@ -10,6 +10,7 @@ import {
import { allDefaultAccountsAtom } from "atoms/accounts";
import {
lastCompletedShieldedSyncAtom,
maspNotesAtom,
namadaShieldedAssetsAtom,
} from "atoms/balance/atoms";
import { chainParametersAtom } from "atoms/chain/atoms";
Expand All @@ -25,7 +26,8 @@ import { wallets } from "integrations";
import invariant from "invariant";
import { useAtom, useAtomValue } from "jotai";
import { createTransferDataFromNamada } from "lib/transactions";
import { useState } from "react";
import { useEffect, useState } from "react";
import { toDisplayAmount } from "utils";

export const MaspUnshield: React.FC = () => {
const [displayAmount, setDisplayAmount] = useState<BigNumber | undefined>();
Expand Down Expand Up @@ -54,6 +56,9 @@ export const MaspUnshield: React.FC = () => {
const account = defaultAccounts.data?.find(
(account) => account.type === AccountType.ShieldedKeys
);
const isLedgerAccount = defaultAccounts.data?.some(
(account) => account.type === AccountType.Ledger
);
const sourceAddress = account?.address;
const destinationAddress = defaultAccounts.data?.find(
(account) => account.type !== AccountType.ShieldedKeys
Expand All @@ -66,6 +71,10 @@ export const MaspUnshield: React.FC = () => {
const selectedAsset =
selectedAssetAddress ? availableAssets?.[selectedAssetAddress] : undefined;

const notesAtom = useAtomValue(maspNotesAtom);
const [notes, setNotes] = useState<[string, BigNumber][] | null>();
const [availableToSpend, setAvailableToSpend] = useState<BigNumber | null>();

const {
execute: performTransfer,
isPending: isPerformingTransfer,
Expand Down Expand Up @@ -140,6 +149,49 @@ export const MaspUnshield: React.FC = () => {
}
}
};

useEffect(() => {
if (
// !isLedgerAccount ||
!selectedAsset ||
!notesAtom.isSuccess ||
!feeProps
) {
// notes !== null && setNotes(null);
return;
}
const notes = notesAtom.data.filter(
([token]) => token === selectedAsset.asset.address
);
// const conversions = notesAtom.data[1].filter(
// ([token]) => token === selectedAsset.asset.address
// );
console.log("notes", notes);
// console.log("conversions", conversions);

const www = notesAtom.data
.filter(([token]) => token === selectedAsset.asset.address)
.map(
([token, balance]) =>
[token, toDisplayAmount(selectedAsset.asset, BigNumber(balance))] as [
string,
BigNumber,
]
)
.sort((a, b) => b[1].minus(a[1]).toNumber());

const kappa = www.slice(0, 4).reduce((acc, [_, amount]) => {
return acc.plus(amount);
}, BigNumber(0));
const gas = feeProps.gasConfig.gasLimit.times(
feeProps.gasConfig.gasPriceInMinDenom
);

// setNotes(www);
// setAvailableToSpend(kappa.minus(gas));
// TODO: Check if not called to often
}, [selectedAsset, notesAtom.data, account, feeProps]);

// We stop the ledger status check when the transfer is in progress
setLedgerStatusStop(isPerformingTransfer);

Expand All @@ -151,6 +203,20 @@ export const MaspUnshield: React.FC = () => {
isDestinationShielded={false}
/>
</header>
{notes && notes.length > 4 && (
<Alert
type="warning"
title="Info!"
className="max-w-[480px] mx-auto mb-4"
>
<p>
Due to ledger BS we have to limit the amount that you can unshield
at this time to <b>{availableToSpend?.toString()}</b>
<br />
After tx is successful, you will be able to unshield more
</p>
</Alert>
)}
<TransferModule
source={{
isLoadingAssets: isLoadingAssets,
Expand Down
21 changes: 21 additions & 0 deletions apps/namadillo/src/atoms/balance/atoms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
mapNamadaAssetsToTokenBalances,
} from "./functions";
import {
fetchNotes,
fetchShieldedBalance,
fetchShieldedRewards,
fetchShieldedRewardsPerToken,
Expand Down Expand Up @@ -123,6 +124,26 @@ export const isShieldedSyncCompleteAtom = atom((get) => {
return get(shieldedSyncProgress) === 1;
});

export const maspNotesAtom = atomWithQuery((get) => {
const viewingKeysQuery = get(viewingKeysAtom);
const chainTokensQuery = get(chainTokensAtom);
const chainParametersQuery = get(chainParametersAtom);

const [viewingKey] = viewingKeysQuery.data ?? [];
const chainTokens = chainTokensQuery.data?.map((t) => t.address);
const chainId = chainParametersQuery.data?.chainId;

return {
queryKey: ["masp-notes", viewingKey, chainTokens, chainId],
...queryDependentFn(async () => {
if (!viewingKey || !chainTokens || !chainId) {
return [];
}
return await fetchNotes(viewingKey, chainTokens, chainId);
}, [viewingKeysQuery, chainTokensQuery, chainParametersQuery]),
};
});

export const shieldedBalanceAtom = atomWithQuery((get) => {
const enablePolling = get(shouldUpdateBalanceAtom);
const viewingKeysQuery = get(viewingKeysAtom);
Expand Down
9 changes: 9 additions & 0 deletions apps/namadillo/src/atoms/balance/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ export const fetchShieldedBalance = async (
return await sdk.rpc.queryBalance(viewingKey.key, addresses, chainId);
};

export const fetchNotes = async (
viewingKey: DatedViewingKey,
addresses: string[],
chainId: string
): Promise<Balance> => {
const sdk = await getSdkInstance();
return await sdk.rpc.queryMASPNotes(viewingKey.key, addresses, chainId);
};

export const fetchShieldedRewards = async (
viewingKey: DatedViewingKey,
chainId: string,
Expand Down
16 changes: 16 additions & 0 deletions packages/sdk/src/rpc/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,22 @@ export class Rpc {
return await this.query.query_balance(owner, tokens, chainId);
}

/**
* Query MASP notes
* @async
* @param owner - Owner address
* @param tokens - Array of token addresses
* @param chainId - Chain id needed to load specific context
* @returns [[tokenAddress, amount]]
*/
async queryMASPNotes(
owner: string,
tokens: string[],
chainId: string
): Promise<Balance> {
return await this.query.query_notes_to_spend(owner, tokens, chainId);
}

/**
* Query native token from chain
* @async
Expand Down
Loading
Loading