Skip to content

Commit 836b2f2

Browse files
authored
Merge pull request #5231 from EdgeApp/sam/kiln-ada-fix2
Sam/kiln ada fix2
2 parents 9544d16 + 09bab38 commit 836b2f2

File tree

10 files changed

+87
-29
lines changed

10 files changed

+87
-29
lines changed

src/components/scenes/Fio/FioDomainRegisterSelectWalletScene.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ class FioDomainRegisterSelectWallet extends React.PureComponent<Props, LocalStat
201201
const styles = getStyles(theme)
202202
const detailsText = sprintf(lstrings.fio_domain_wallet_selection_text, config.appName, loading ? '-' : activationCost)
203203

204-
let paymentWalletBody = lstrings.choose_your_wallet
204+
let paymentWalletBody: string = lstrings.choose_your_wallet
205205
if (paymentWallet != null && paymentWallet.id !== '') {
206206
const wallet = account.currencyWallets[paymentWallet.id]
207207
paymentWalletBody = `${getWalletName(wallet)} (${wallet.currencyInfo.currencyCode})`

src/components/scenes/SettingsScene.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export const SettingsScene = (props: Props) => {
7373
const [defaultLogLevel, setDefaultLogLevel] = React.useState<EdgeLogType | 'silent'>(logSettings.defaultLogLevel)
7474
const [disableAnim, setDisableAnim] = useState<boolean>(getDeviceSettings().disableAnimations)
7575
const [forceLightAccountCreate, setForceLightAccountCreate] = useState<boolean>(getDeviceSettings().forceLightAccountCreate)
76-
const [touchIdText, setTouchIdText] = React.useState(lstrings.settings_button_use_touchID)
76+
const [touchIdText, setTouchIdText] = React.useState<string>(lstrings.settings_button_use_touchID)
7777

7878
const iconSize = theme.rem(1.25)
7979
const isLightAccount = username == null

src/components/scenes/Staking/StakeModifyScene.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
StakePosition
1818
} from '../../../plugins/stake-plugins/types'
1919
import { getExchangeDenomByCurrencyCode } from '../../../selectors/DenominationSelectors'
20+
import { HumanFriendlyError } from '../../../types/HumanFriendlyError'
2021
import { useSelector } from '../../../types/reactRedux'
2122
import { EdgeSceneProps } from '../../../types/routerTypes'
2223
import { getCurrencyIconUris } from '../../../util/CdnUris'
@@ -169,6 +170,8 @@ const StakeModifySceneComponent = (props: Props) => {
169170
setErrorMessage(errMessage)
170171
} else if (err instanceof InsufficientFundsError) {
171172
setErrorMessage(lstrings.exchange_insufficient_funds_title)
173+
} else if (err instanceof HumanFriendlyError) {
174+
setErrorMessage(err.message)
172175
} else {
173176
showError(err)
174177
setErrorMessage(lstrings.unknown_error_occurred_fragment)

src/components/themed/FioRequestRow.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class FioRequestRowComponent extends React.PureComponent<Props> {
7474
const styles = getStyles(theme)
7575

7676
let statusStyle = styles.requestPartialConfirmation
77-
let label = lstrings.fragment_wallet_unconfirmed
77+
let label: string = lstrings.fragment_wallet_unconfirmed
7878
if (status === 'sent_to_blockchain') {
7979
statusStyle = styles.requestDetailsReceivedTx
8080
label = lstrings.fragment_request_subtitle

src/locales/en_US.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ const strings = {
100100
error_paymentprotocol_no_payment_option: 'No currencies available for this Payment Protocol invoice. Accepted currencies: %s',
101101
error_paymentprotocol_tx_verification_failed: 'Payment Protocol transaction verification mismatch',
102102
error_spend_amount_less_then_min_s: 'Spend amount is less than minimum of %s',
103+
error_amount_too_low_to_stake_s: 'The amount %s is too low to stake successfully',
103104

104105
// Warning messages:
105106
warning_low_fee_selected: 'Low Fee Selected',
@@ -1120,10 +1121,7 @@ const strings = {
11201121
price_change_buy_sell_trade: 'Would you like to buy, sell, or exchange %1$s?',
11211122
// Update notices
11221123
update_notice_deprecate_electrum_servers_title: 'Blockbook Upgrade',
1123-
update_notice_deprecate_electrum_servers_message:
1124-
'%s no longer uses Electrum Servers. If you would like to continue to use CUSTOM NODES, please input Blockbook compatible addresses.' +
1125-
'\n\n' +
1126-
'NOTE: If you had custom nodes enabled, those wallets will not sync until corrected.',
1124+
update_notice_deprecate_electrum_servers_message: `%s no longer uses Electrum Servers. If you would like to continue to use CUSTOM NODES, please input Blockbook compatible addresses.\n\nNOTE: If you had custom nodes enabled, those wallets will not sync until corrected.`,
11271125

11281126
error_boundary_title: 'Oops!',
11291127
error_boundary_message_s:
@@ -1221,9 +1219,7 @@ const strings = {
12211219
loan_breakdown_title: 'Loan Breakdown',
12221220
loan_close_swap_warning:
12231221
"Closing your loan will liquidate some of the deposited collateral if you do not have enough balance to repay the remaining principal and interest on your loan. The remaining collateral will be deposited back to your wallet.\n\nLiquidation most likely will incur a higer capital cost, if remaining principal isn't repaid.",
1224-
loan_close_loan_no_tx_needed_message:
1225-
`There appears to be no principal to repay nor collateral to withdraw.\n\n` +
1226-
`No transactions are required to close your account, however the account may re-appear after closing if there are pending on-chain transactions.`,
1222+
loan_close_loan_no_tx_needed_message: `There appears to be no principal to repay nor collateral to withdraw.\n\nNo transactions are required to close your account, however the account may re-appear after closing if there are pending on-chain transactions.`,
12271223
loan_close_loan_title: 'Close Loan',
12281224
loan_close_multiple_asset_error:
12291225
'Closing loans with multiple debt assets and/or deposited collateral assets is not supported.\n\nPlease specify funding sources to repay loans with using Repay.',
@@ -1859,7 +1855,7 @@ const strings = {
18591855

18601856
auto_log_off_failed_message_s: 'Failed to auto-logoff: %s',
18611857
contacts_load_failed_message_s: 'Failed to load contacts: %s'
1862-
}
1858+
} as const
18631859

18641860
// eslint-disable-next-line import/no-default-export
18651861
export default strings

src/locales/strings.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ import zh from './strings/zh.json'
1515

1616
const allLocales = { en, de, ru, es, esMX, it, pt, ja, fr, ko, vi, zh }
1717

18-
export const lstrings = { ...en }
18+
export const lstrings = { ...en } as const
19+
export type LStrings = typeof lstrings
20+
export type LStringsKey = keyof LStrings
21+
export type LStringsValues = LStrings[LStringsKey]
1922

2023
// Set the language at boot:
2124
const [firstLocale] = getLocales()

src/locales/strings/enUS.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"error_paymentprotocol_no_payment_option": "No currencies available for this Payment Protocol invoice. Accepted currencies: %s",
6464
"error_paymentprotocol_tx_verification_failed": "Payment Protocol transaction verification mismatch",
6565
"error_spend_amount_less_then_min_s": "Spend amount is less than minimum of %s",
66+
"error_amount_too_low_to_stake_s": "The amount %s is too low to stake successfully",
6667
"warning_low_fee_selected": "Low Fee Selected",
6768
"warning_custom_fee_selected": "Custom Fee Selected",
6869
"warning_low_or_custom_fee": "Using a low fee may increase the amount of time it takes for your transaction to confirm. In rare instances your transaction can fail.",

src/plugins/stake-plugins/generic/policyAdapters/CardanoKilnAdaptor.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { eq, gt, sub } from 'biggystring'
22
import { EdgeCurrencyWallet, EdgeTransaction } from 'edge-core-js'
33

4+
import { lstrings } from '../../../../locales/strings'
5+
import { HumanFriendlyError } from '../../../../types/HumanFriendlyError'
46
import { infoServerData } from '../../../../util/network'
57
import { AssetId, ChangeQuote, PositionAllocation, QuoteAllocation, StakePosition } from '../../types'
68
import { asInfoServerResponse } from '../../util/internalTypes'
79
import { StakePolicyConfig } from '../types'
8-
import { makeKilnApi } from '../util/kilnUtils'
10+
import { KilnError, makeKilnApi } from '../util/kilnUtils'
911
import { StakePolicyAdapter } from './types'
1012

1113
export interface CardanoPooledKilnAdapterConfig {
@@ -71,7 +73,21 @@ export const makeCardanoKilnAdapter = (policyConfig: StakePolicyConfig<CardanoPo
7173
throw new Error('Insufficient funds')
7274
}
7375

74-
const stakeTransaction = await kiln.adaStakeTransaction(walletAddress, adapterConfig.poolId, accountId)
76+
const result = await kiln.adaStakeTransaction(walletAddress, adapterConfig.poolId, accountId).catch(error => {
77+
if (error instanceof Error) return error
78+
throw error
79+
})
80+
if (result instanceof KilnError) {
81+
if (/Value \d+ less than the minimum UTXO value \d+/.test(result.error)) {
82+
const displayBalance = await wallet.nativeToDenomination(walletBalance, wallet.currencyInfo.currencyCode)
83+
throw new HumanFriendlyError(lstrings.error_amount_too_low_to_stake_s, `${displayBalance} ${wallet.currencyInfo.currencyCode}`)
84+
}
85+
}
86+
if (result instanceof Error) {
87+
throw result
88+
}
89+
90+
const stakeTransaction = result
7591
const edgeTx: EdgeTransaction = await wallet.otherMethods.decodeStakingTx(stakeTransaction.unsigned_tx_serialized)
7692

7793
const allocations: QuoteAllocation[] = [

src/plugins/stake-plugins/generic/util/kilnUtils.ts

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
1-
import { asArray, asEither, asMaybe, asObject, asString, asValue, Cleaner } from 'cleaners'
1+
import { asArray, asJSON, asMaybe, asObject, asString, asValue, Cleaner } from 'cleaners'
2+
3+
export class KilnError extends Error {
4+
name: string
5+
message: string
6+
error: string
7+
8+
constructor(message: string, error: string) {
9+
super(message)
10+
this.name = 'KilnError'
11+
this.message = message
12+
this.error = error
13+
}
14+
}
215

316
export interface KilnApi {
417
adaGetStakes: (params: {
@@ -28,6 +41,8 @@ export const makeKilnApi = (baseUrl: string, apiKey: string): KilnApi => {
2841
const res = await fetch(url, opts)
2942
if (!res.ok) {
3043
const message = await res.text()
44+
const errorResponse = asMaybe(asKilnErrorResponse)(message)
45+
if (errorResponse != null) throw new KilnError(errorResponse.message, errorResponse.error)
3146
throw new Error(`Kiln fetch error: ${message}`)
3247
}
3348
const json = await res.json()
@@ -62,7 +77,6 @@ export const makeKilnApi = (baseUrl: string, apiKey: string): KilnApi => {
6277
// eslint-disable-next-line @typescript-eslint/no-base-to-string
6378
const raw = await fetchKiln(`/v1/ada/stakes?${query.toString()}`)
6479
const response = asKilnResponse(asArray(asAdaStake))(raw)
65-
if ('message' in response) throw new Error('Kiln error: ' + response.message)
6680
return response.data
6781
},
6882

@@ -77,7 +91,6 @@ export const makeKilnApi = (baseUrl: string, apiKey: string): KilnApi => {
7791
})
7892
})
7993
const response = asKilnResponse(asAdaStakeTransaction)(raw)
80-
if ('message' in response) throw new Error('Kiln error: ' + response.message)
8194
return response.data
8295
},
8396

@@ -90,7 +103,6 @@ export const makeKilnApi = (baseUrl: string, apiKey: string): KilnApi => {
90103
})
91104
})
92105
const response = asKilnResponse(asAdaUnstakeTransaction)(raw)
93-
if ('message' in response) throw new Error('Kiln error: ' + response.message)
94106
return response.data
95107
},
96108

@@ -104,22 +116,19 @@ export const makeKilnApi = (baseUrl: string, apiKey: string): KilnApi => {
104116
})
105117
})
106118
const response = asKilnResponse(asAdaUnstakeTransaction)(raw)
107-
if ('message' in response) throw new Error('Kiln error: ' + response.message)
108119
return response.data
109120
},
110121

111122
// https://docs.api.kiln.fi/reference/getethonchainv2stakes
112123
async ethGetOnChainStakes(address) {
113124
const raw = await fetchKiln(`/v1/eth/onchain/v2/stakes?wallets=${address}`)
114125
const response = asKilnResponse(asArray(asEthOnChainStake))(raw)
115-
if ('message' in response) throw new Error('Kiln error: ' + response.message)
116126
return response.data
117127
},
118128
// https://docs.api.kiln.fi/reference/getethonchainv2operations
119129
async ethGetOnChainOperations(address) {
120130
const raw = await fetchKiln(`/v1/eth/onchain/v2/operations?wallets=${address}`)
121131
const response = asKilnResponse(asArray(asMaybe(asExitOperation)))(raw)
122-
if ('message' in response) throw new Error('Kiln error: ' + response.message)
123132
const filteredOps = response.data.filter((op): op is ExitOperation => op != null)
124133
return filteredOps
125134
}
@@ -135,15 +144,22 @@ export const makeKilnApi = (baseUrl: string, apiKey: string): KilnApi => {
135144
export interface KilnResponse<T> {
136145
data: T
137146
}
147+
138148
const asKilnResponse = <T>(asT: Cleaner<T>) =>
139-
asEither(
140-
asObject({
141-
data: asT
142-
}),
143-
asObject({
144-
message: asString
145-
})
146-
)
149+
asObject({
150+
data: asT
151+
})
152+
153+
export interface KilnErrorResponse {
154+
error: string
155+
message: string
156+
}
157+
const asKilnErrorResponse = asJSON(
158+
asObject<KilnErrorResponse>({
159+
error: asString,
160+
message: asString
161+
})
162+
)
147163

148164
//
149165
// Ada

src/types/HumanFriendlyError.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { sprintf } from 'sprintf-js'
2+
3+
import { LStringsValues } from '../locales/strings'
4+
5+
/**
6+
* Error class that is meant to be used for errors that are meant to be shown
7+
* to the user. The error message must be an lstrings value along with any
8+
* sprintf arguments.
9+
*
10+
* This error type is strictly a GUI error type because of it's dependency
11+
* on lstrings.
12+
*/
13+
export class HumanFriendlyError extends Error {
14+
name: string
15+
message: string
16+
17+
constructor(format: LStringsValues, ...args: any[]) {
18+
const message = sprintf(format, ...args)
19+
super(message)
20+
this.name = 'HumanFriendlyError'
21+
this.message = message
22+
}
23+
}

0 commit comments

Comments
 (0)