Skip to content

Commit

Permalink
feat(suite): add solana unstaking and claiming methods
Browse files Browse the repository at this point in the history
  • Loading branch information
dev-pvl committed Dec 23, 2024
1 parent 6249141 commit e58f97b
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 9 deletions.
30 changes: 28 additions & 2 deletions packages/suite/src/actions/wallet/stake/stakeFormSolanaActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,17 @@ import {
MIN_SOL_AMOUNT_FOR_STAKING,
MIN_SOL_BALANCE_FOR_STAKING,
MIN_SOL_FOR_WITHDRAWALS,
SOL_STAKING_OPERATION_FEE,
} from '@suite-common/wallet-constants';

import { Dispatch, GetState } from 'src/types/suite';
import { selectAddressDisplayType } from 'src/reducers/suite/suiteReducer';
import { getPubKeyFromAddress, prepareStakeSolTx } from 'src/utils/suite/solanaStaking';
import {
getPubKeyFromAddress,
prepareClaimSolTx,
prepareStakeSolTx,
prepareUnstakeSolTx,
} from 'src/utils/suite/solanaStaking';

import { calculate, composeStakingTransaction } from './stakeFormActions';

Expand All @@ -30,7 +36,8 @@ const calculateTransaction = (
compareWithAmount = true,
symbol: NetworkSymbol,
): PrecomposedTransaction => {
const feeInLamports = new BigNumber(feeLevel.feePerTx ?? '0').toString();
// TODO: change to the dynamic fee
const feeInLamports = new BigNumber(SOL_STAKING_OPERATION_FEE).toString();

const stakingParams = {
feeInBaseUnits: feeInLamports,
Expand Down Expand Up @@ -100,6 +107,25 @@ export const signTransaction =
});
}

if (stakeType === 'unstake') {
txData = await prepareUnstakeSolTx({
from: account.descriptor,
path: account.path,
amount: formValues.outputs[0].amount,
symbol: account.symbol,
selectedBlockchain,
});
}

if (stakeType === 'claim') {
txData = await prepareClaimSolTx({
from: account.descriptor,
path: account.path,
symbol: account.symbol,
selectedBlockchain,
});
}

if (!txData) {
dispatch(
notificationsActions.addToast({
Expand Down
68 changes: 63 additions & 5 deletions packages/suite/src/utils/suite/solanaStaking.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { VersionedTransaction, PublicKey } from '@solana/web3.js-version1';

import { NetworkSymbol } from '@suite-common/wallet-config';
import { LAMPORTS_PER_SOL, WALLET_SDK_SOURCE } from '@suite-common/wallet-constants';
import { selectSolanaWalletSdkNetwork } from '@suite-common/wallet-utils';
import { BigNumber } from '@trezor/utils';
import { WALLET_SDK_SOURCE } from '@suite-common/wallet-constants';
import {
networkAmountToSmallestUnit,
selectSolanaWalletSdkNetwork,
} from '@suite-common/wallet-utils';
import type { SolanaSignTransaction } from '@trezor/connect';
import { Blockchain } from '@suite-common/wallet-types';

Expand Down Expand Up @@ -65,8 +67,64 @@ export const prepareStakeSolTx = async ({
try {
const solanaClient = selectSolanaWalletSdkNetwork(symbol, selectedBlockchain.url);

const lamports = new BigNumber(LAMPORTS_PER_SOL).multipliedBy(amount).toNumber(); // stake method expects lamports as a number
const tx = await solanaClient.stake(from, lamports, WALLET_SDK_SOURCE);
const lamports = networkAmountToSmallestUnit(amount, symbol);
const tx = await solanaClient.stake(from, Number(lamports), WALLET_SDK_SOURCE);
const transformedTx = transformTx(tx.result, path);

return {
success: true,
tx: transformedTx,
};
} catch (e) {
console.error(e);

return {
success: false,
errorMessage: e.message,
};
}
};

export const prepareUnstakeSolTx = async ({
from,
path,
amount,
symbol,
selectedBlockchain,
}: PrepareStakeSolTxParams): Promise<PrepareStakeSolTxResponse> => {
try {
const solanaClient = selectSolanaWalletSdkNetwork(symbol, selectedBlockchain.url);

const lamports = networkAmountToSmallestUnit(amount, symbol);
const tx = await solanaClient.unstake(from, Number(lamports), WALLET_SDK_SOURCE);
const transformedTx = transformTx(tx.result, path);

return {
success: true,
tx: transformedTx,
};
} catch (e) {
console.error(e);

return {
success: false,
errorMessage: e.message,
};
}
};

type PrepareClaimSolTxParams = Omit<PrepareStakeSolTxParams, 'amount'>;

export const prepareClaimSolTx = async ({
from,
path,
symbol,
selectedBlockchain,
}: PrepareClaimSolTxParams): Promise<PrepareStakeSolTxResponse> => {
try {
const solanaClient = selectSolanaWalletSdkNetwork(symbol, selectedBlockchain.url);

const tx = await solanaClient.claim(from);
const transformedTx = transformTx(tx.result, path);

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export const MIN_SOL_AMOUNT_FOR_STAKING = new BigNumber(0.01);
export const MAX_SOL_AMOUNT_FOR_STAKING = new BigNumber(10_000_000);
export const MIN_SOL_FOR_WITHDRAWALS = new BigNumber(0.000005);
export const MIN_SOL_BALANCE_FOR_STAKING = MIN_SOL_AMOUNT_FOR_STAKING.plus(MIN_SOL_FOR_WITHDRAWALS);
export const SOL_STAKING_OPERATION_FEE = new BigNumber(70_000); // 0.00007 SOL

export const SOLANA_EPOCH_DAYS = 3;
4 changes: 2 additions & 2 deletions suite-common/wallet-core/src/stake/stakeSelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { StakeRootState } from './stakeReducer';

export const selectEverstakeData = (
state: StakeRootState,
networkSymbol: NetworkSymbol,
symbol: NetworkSymbol,
endpointType: 'poolStats' | 'validatorsQueue' | 'getAssets',
) => state.wallet.stake?.data?.[networkSymbol]?.[endpointType];
) => state.wallet.stake?.data?.[symbol]?.[endpointType];

export const selectPoolStatsApyData = (state: StakeRootState, symbol?: NetworkSymbol) => {
const { data } = state.wallet.stake ?? {};
Expand Down

0 comments on commit e58f97b

Please sign in to comment.