Skip to content

Commit

Permalink
feat: make withdrawals work properly in conway era
Browse files Browse the repository at this point in the history
  • Loading branch information
refi93 committed Jul 12, 2024
1 parent b56804d commit fa64bc4
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 38 deletions.
22 changes: 15 additions & 7 deletions app/frontend/actions/delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,16 @@ export default (store: Store) => {
}
await setPoolInfo(state)
const poolHash = state.shelleyDelegation.selectedPool.poolHash as string
const isStakingKeyRegistered = getSourceAccountInfo(state).shelleyAccountInfo.hasStakingKey
const stakingAddress = getSourceAccountInfo(state).stakingAddress
const {
shelleyAccountInfo: {hasStakingKey: isStakingKeyRegistered, hasVoteDelegation},
stakingAddress,
} = getSourceAccountInfo(state)
const txPlanResult = prepareTxPlan({
poolHash,
stakingAddress,
isStakingKeyRegistered,
txType: TxType.DELEGATE,
hasVoteDelegation,
})
const newState = getState()
if (hasPoolIdentifiersChanged(newState)) {
Expand Down Expand Up @@ -180,15 +183,20 @@ export default (store: Store) => {
}

state = getState()
const sourceAccount = getSourceAccountInfo(state)
const rewards = getSourceAccountInfo(state).shelleyBalances.rewardsAccountBalance as Lovelace
const balance = getSourceAccountInfo(state).balance as Lovelace
const {
accountIndex,
balance,
stakingAddress,
shelleyAccountInfo: {hasVoteDelegation},
shelleyBalances: {rewardsAccountBalance: rewards},
} = getSourceAccountInfo(state)

loadingAction(state, 'Preparing transaction...')
const txPlanResult = prepareTxPlan({
txType: TxType.DEREGISTER_STAKE_KEY,
rewards,
stakingAddress: sourceAccount.stakingAddress,
stakingAddress,
hasVoteDelegation,
})
if (txPlanResult.success === true) {
const summary = {
Expand All @@ -199,7 +207,7 @@ export default (store: Store) => {

setTransactionSummary(getState(), {plan: txPlanResult.txPlan, transactionSummary: summary})
await confirmTransaction(getState(), {
sourceAccountIndex: sourceAccount.accountIndex,
sourceAccountIndex: accountIndex,
txPlan: txPlanResult.txPlan,
txConfirmType: TxType.DEREGISTER_STAKE_KEY,
})
Expand Down
20 changes: 10 additions & 10 deletions app/frontend/actions/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ export default (store: Store) => {
let txAux
try {
if (txPlan) {
txAux = await getWallet()
.getAccount(sourceAccountIndex)
.prepareTxAux(txPlan)
txAux = await getWallet().getAccount(sourceAccountIndex).prepareTxAux(txPlan)
} else {
loadingAction(state, 'Preparing transaction plan...')
await sleep(1000) // wait for plan to be set in case of unfortunate timing
Expand Down Expand Up @@ -220,12 +218,8 @@ export default (store: Store) => {
let sendResponse
try {
assert(txSummary.plan != null)
const txAux = await getWallet()
.getAccount(sourceAccountIndex)
.prepareTxAux(txSummary.plan)
const signedTx = await getWallet()
.getAccount(sourceAccountIndex)
.signTxAux(txAux)
const txAux = await getWallet().getAccount(sourceAccountIndex).prepareTxAux(txSummary.plan)
const signedTx = await getWallet().getAccount(sourceAccountIndex).signTxAux(txAux)
if (isHwWallet(cryptoProviderType)) {
setState({waitingHwWalletOperation: null})
stopLoadingAction(state)
Expand Down Expand Up @@ -330,7 +324,13 @@ export default (store: Store) => {
// TODO: rewards should be of type Lovelace
const rewards = getSourceAccountInfo(state).shelleyBalances.rewardsAccountBalance as Lovelace
const stakingAddress = getSourceAccountInfo(state).stakingAddress
const txPlanResult = prepareTxPlan({rewards, stakingAddress, txType: TxType.WITHDRAW})
const hasVoteDelegation = getSourceAccountInfo(state).shelleyAccountInfo.hasVoteDelegation
const txPlanResult = prepareTxPlan({
rewards,
stakingAddress,
hasVoteDelegation,
txType: TxType.WITHDRAW,
})
// TODO: balance should be of type Lovelace
const balance = getSourceAccountInfo(state).balance as Lovelace

Expand Down
1 change: 1 addition & 0 deletions app/frontend/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ const initialState: State = {
currentEpoch: 0,
delegation: {},
hasStakingKey: false,
hasVoteDelegation: false,
rewards: '0',
rewardDetails: {
upcoming: null,
Expand Down
5 changes: 5 additions & 0 deletions app/frontend/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export enum CertificateType {
STAKING_KEY_DEREGISTRATION = 1,
DELEGATION = 2,
STAKEPOOL_REGISTRATION = 3,
VOTE_DELEGATION = 9,
}

export enum CryptoProviderFeature {
Expand Down Expand Up @@ -171,6 +172,7 @@ export type AccountInfo = {
currentEpoch: number
delegation: any
hasStakingKey: boolean
hasVoteDelegation: boolean
rewards: string
rewardDetails: {
upcoming: any
Expand Down Expand Up @@ -267,13 +269,15 @@ export type WithdrawRewardsTxPlanArgs = {
txType: TxType.WITHDRAW
rewards: Lovelace
stakingAddress: Address
hasVoteDelegation: boolean
}

export type DelegateAdaTxPlanArgs = {
txType: TxType.DELEGATE
poolHash: string
isStakingKeyRegistered: boolean
stakingAddress: Address
hasVoteDelegation: boolean
}

export type PoolOwnerTxPlanArgs = {
Expand All @@ -285,6 +289,7 @@ export type DeregisterStakingKeyTxPlanArgs = {
txType: TxType.DEREGISTER_STAKE_KEY
rewards: Lovelace
stakingAddress: Address
hasVoteDelegation: boolean
}

export type VotingRegistrationTxPlanArgs = {
Expand Down
18 changes: 7 additions & 11 deletions app/frontend/wallet/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,14 +394,10 @@ const Account = ({config, cryptoProvider, blockchainExplorer, accountIndex}: Acc

async function getBalance() {
const {legacy, base} = await myAddresses.discoverAllAddresses()
const {
coins: nonStakingBalance,
tokenBundle: nonStakingTokenBundle,
} = await blockchainExplorer.getBalance(legacy)
const {
coins: baseAddressBalance,
tokenBundle: stakingTokenBundle,
} = await blockchainExplorer.getBalance(base)
const {coins: nonStakingBalance, tokenBundle: nonStakingTokenBundle} =
await blockchainExplorer.getBalance(legacy)
const {coins: baseAddressBalance, tokenBundle: stakingTokenBundle} =
await blockchainExplorer.getBalance(base)
return {
tokenBalance: aggregateTokenBundles([nonStakingTokenBundle, stakingTokenBundle]),
baseAddressBalance,
Expand Down Expand Up @@ -436,9 +432,8 @@ const Account = ({config, cryptoProvider, blockchainExplorer, accountIndex}: Acc

async function getStakingInfo(validStakepoolDataProvider: StakepoolDataProvider) {
const stakingAddressHex = bechAddressToHex(await myAddresses.getStakingAddress())
const {nextRewardDetails, ...accountInfo} = await blockchainExplorer.getStakingInfo(
stakingAddressHex
)
const {nextRewardDetails, ...accountInfo} =
await blockchainExplorer.getStakingInfo(stakingAddressHex)
const rewardDetails = await blockchainExplorer.getRewardDetails(
nextRewardDetails,
accountInfo.delegation.poolHash,
Expand All @@ -448,6 +443,7 @@ const Account = ({config, cryptoProvider, blockchainExplorer, accountIndex}: Acc

return {
...accountInfo,
hasVoteDelegation: accountInfo.voteDelegation != null,
rewardDetails,
value: new BigNumber(accountInfo.rewards || 0) as Lovelace,
}
Expand Down
5 changes: 5 additions & 0 deletions app/frontend/wallet/backend-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ export type StakingInfoResponse = {
hasStakingKey: boolean
rewards: string
nextRewardDetails: Array<NextRewardDetail>
voteDelegation: {
dRepHash: string
isAlwaysAbstain: boolean
isAlwaysNoConfidence: boolean
} | null
}

export type BestSlotResponse = {
Expand Down
18 changes: 18 additions & 0 deletions app/frontend/wallet/shelley/shelley-transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
TxStakingKeyDeregistrationCert,
TxStakingKeyRegistrationCert,
TxWithdrawal,
TxVoteDelegationCert,
} from '../types'
import {
CborizedTxAmount,
Expand All @@ -40,6 +41,8 @@ import {
TxSigned,
CborizedCliWitness,
CborizedVotingRegistrationMetadata,
CborizedVoteDelegationCert,
DRepType,
} from './types'
import {CertificateType, HexString, TokenBundle} from '../../types'
import {UnexpectedError, UnexpectedErrorReason} from '../../errors'
Expand Down Expand Up @@ -239,6 +242,19 @@ function cborizeStakepoolRegistrationCert(
]
}

type SupportedDelegationCert = TxVoteDelegationCert & {dRep: 'alwaysAbstain'}
function cborizeVoteDelegationCert(
certificate: SupportedDelegationCert
): CborizedVoteDelegationCert {
const stakingKeyHash: Buffer = bech32.decode(certificate.stakingAddress).data.slice(1)
const stakeCredential: CborizedTxStakeCredential = [
TxStakeCredentialType.ADDR_KEYHASH,
stakingKeyHash,
]

return [TxCertificateKey.VOTE_DELEGATION, stakeCredential, DRepType.ALWAYS_ABSTAIN]
}

function cborizeTxCertificates(certificates: TxCertificate[]): CborizedTxCertificate[] {
const txCertificates = certificates.map((certificate) => {
switch (certificate.type) {
Expand All @@ -250,6 +266,8 @@ function cborizeTxCertificates(certificates: TxCertificate[]): CborizedTxCertifi
return cborizeDelegationCert(certificate)
case CertificateType.STAKEPOOL_REGISTRATION:
return cborizeStakepoolRegistrationCert(certificate)
case CertificateType.VOTE_DELEGATION:
return cborizeVoteDelegationCert(certificate)
default:
throw new UnexpectedError(UnexpectedErrorReason.InvalidCertificateType)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
TxStakingKeyRegistrationCert,
TxWithdrawal,
TxAuxiliaryDataTypes,
TxVoteDelegationCert,
} from '../../types'
import {computeTxPlan, validateTxPlan} from './computeTxPlan'
import {TxPlanDraft, TxPlanResult} from './types'
Expand Down Expand Up @@ -67,6 +68,14 @@ const prepareTxPlanDraft = (txPlanArgs: TxPlanArgs): TxPlanDraft => {
}
certificates.push(registrationCertificate)
}
if (!txPlanArgs.hasVoteDelegation) {
const voteDelegationCertificate: TxVoteDelegationCert = {
type: CertificateType.VOTE_DELEGATION,
stakingAddress: txPlanArgs.stakingAddress,
dRep: 'alwaysAbstain',
}
certificates.push(voteDelegationCertificate)
}
if (txPlanArgs.poolHash) {
const delegationCertificate: TxDelegationCert = {
type: CertificateType.DELEGATION,
Expand All @@ -86,9 +95,19 @@ const prepareTxPlanDraft = (txPlanArgs: TxPlanArgs): TxPlanDraft => {
const prepareWithdrawalTx = (txPlanArgs: WithdrawRewardsTxPlanArgs): TxPlanDraft => {
const withdrawals: TxWithdrawal[] = []
withdrawals.push({stakingAddress: txPlanArgs.stakingAddress, rewards: txPlanArgs.rewards})

const certificates: TxCertificate[] = []
if (!txPlanArgs.hasVoteDelegation) {
const voteDelegationCertificate: TxVoteDelegationCert = {
type: CertificateType.VOTE_DELEGATION,
stakingAddress: txPlanArgs.stakingAddress,
dRep: 'alwaysAbstain',
}
certificates.push(voteDelegationCertificate)
}
return {
outputs: [],
certificates: [],
certificates,
withdrawals,
auxiliaryData: null,
}
Expand All @@ -101,13 +120,22 @@ const prepareTxPlanDraft = (txPlanArgs: TxPlanArgs): TxPlanDraft => {
txType: TxType.WITHDRAW,
rewards: txPlanArgs.rewards,
stakingAddress: txPlanArgs.stakingAddress,
hasVoteDelegation: txPlanArgs.hasVoteDelegation,
})
const certificates: TxCertificate[] = [
{
type: CertificateType.STAKING_KEY_DEREGISTRATION,
stakingAddress: txPlanArgs.stakingAddress,
},
]
if (!txPlanArgs.hasVoteDelegation) {
const voteDelegationCertificate: TxVoteDelegationCert = {
type: CertificateType.VOTE_DELEGATION,
stakingAddress: txPlanArgs.stakingAddress,
dRep: 'alwaysAbstain',
}
certificates.push(voteDelegationCertificate)
}
return {
outputs,
certificates,
Expand Down
1 change: 1 addition & 0 deletions app/frontend/wallet/shelley/transaction/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export function computeRequiredDeposit(certificates: Array<TxCertificate>): Love
[CertificateType.STAKEPOOL_REGISTRATION]: 500000000,
[CertificateType.STAKING_KEY_REGISTRATION]: 2000000,
[CertificateType.STAKING_KEY_DEREGISTRATION]: -2000000,
[CertificateType.VOTE_DELEGATION]: 0,
}
return certificates.reduce(
(acc, {type}) => acc.plus(CertificateDeposit[type]),
Expand Down
22 changes: 17 additions & 5 deletions app/frontend/wallet/shelley/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ export const enum TxCertificateKey { // TODO: type would be a better name
STAKING_KEY_DEREGISTRATION = 1,
DELEGATION = 2,
STAKEPOOL_REGISTRATION = 3,
VOTE_DELEGATION = 9,
}

export const enum DRepType {
ALWAYS_ABSTAIN = 2,
}

export enum TxStakeCredentialType {
Expand All @@ -78,18 +83,24 @@ export type CborizedVotingRegistrationMetadata = [Map<number, Map<number, Buffer

export type CborizedTxStakingKeyRegistrationCert = [
TxCertificateKey.STAKING_KEY_REGISTRATION,
CborizedTxStakeCredential
CborizedTxStakeCredential,
]

export type CborizedTxStakingKeyDeregistrationCert = [
TxCertificateKey.STAKING_KEY_DEREGISTRATION,
CborizedTxStakeCredential
CborizedTxStakeCredential,
]

export type CborizedTxDelegationCert = [
TxCertificateKey.DELEGATION,
CborizedTxStakeCredential,
Buffer
Buffer,
]

export type CborizedVoteDelegationCert = [
TxCertificateKey.VOTE_DELEGATION,
CborizedTxStakeCredential,
DRepType,
]

// prettier-ignore
Expand Down Expand Up @@ -119,14 +130,15 @@ export type CborizedTxStakepoolRegistrationCert = [
Buffer,
Array<Buffer>,
any,
[string, Buffer] | null
[string, Buffer] | null,
]

export type CborizedTxCertificate =
| CborizedTxDelegationCert
| CborizedTxStakepoolRegistrationCert
| CborizedTxStakingKeyDeregistrationCert
| CborizedTxStakingKeyRegistrationCert
| CborizedVoteDelegationCert

export type CborizedTxWitnessByron = [Buffer, Buffer, Buffer, Buffer]

Expand All @@ -135,7 +147,7 @@ export type CborizedTxWitnessShelley = [Buffer, Buffer]
export type CborizedTxSigned = [
Map<TxBodyKey, any>,
Map<TxWitnessKey, Array<CborizedTxWitnessByron | CborizedTxWitnessShelley>>,
Buffer | null
Buffer | null,
]

export type CborizedTxUnsigned = [Map<TxBodyKey, any>, Buffer | null]
Expand Down
Loading

0 comments on commit fa64bc4

Please sign in to comment.