Skip to content

Commit

Permalink
Ana/emoney sendmodal multiple denoms (#3370)
Browse files Browse the repository at this point in the history
* first changes

* working for first balance in array

* allow selecting token. add selected balance.

* fix validation selectedToken

* make compatible with the one token networks

* make compatible for all networks. styling

* simplify code

* fix validations

* update snapshot

* sendmodal fix test and update snapshot

* add tests

* change position. set amount to 0 in each selection

* fix first load. styling

* update snapshot

* remove ellipsis from form

* bust dep cache

* added vue-jest

* update snapshot

* changelog

Co-authored-by: Fabian <frznhope@gmail.com>
  • Loading branch information
Bitcoinera and faboweb committed Jan 14, 2020
1 parent 32c83c4 commit 82df018
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 41 deletions.
1 change: 1 addition & 0 deletions changes/ana_emoney-sendmodal-multiple-denoms
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[Added] [#3370](https://github.com/cosmos/lunie/pull/3370) Now it is possible to select different tokens to send in the SendModal for networks with multiple tokens @Bitcoinera
116 changes: 91 additions & 25 deletions src/ActionModal/components/SendModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,36 @@
/>
</TmFormGroup>
<TmFormGroup
v-if="getDenoms.length > 1"
:error="$v.selectedToken.$error"
class="action-modal-form-group"
field-id="selected-token"
field-label="Token"
>
<TmField
id="token"
v-model="selectedToken"
:title="`Select the token you wish to operate with`"
:options="getDenoms"
placeholder="Select the token"
type="select"
/>
<TmFormMsg
v-if="$v.selectedToken.$error && !$v.selectedToken.required"
name="Token"
type="required"
/>
</TmFormGroup>
<TmFormGroup
id="form-group-amount"
:error="$v.amount.$error && $v.amount.$invalid"
class="action-modal-form-group"
field-id="amount"
field-label="Amount"
>
<span class="input-suffix max-button">{{ denom }}</span>
<span v-if="selectedToken" class="input-suffix max-button">{{
selectedToken
}}</span>
<TmFieldGroup>
<TmField
id="amount"
Expand All @@ -62,8 +86,8 @@
/>
</TmFieldGroup>
<TmFormMsg
v-if="balance.amount === 0"
:msg="`doesn't have any ${denom}s`"
v-if="selectedBalance.amount === 0"
:msg="`doesn't have any ${selectedToken}s`"
name="Wallet"
type="custom"
/>
Expand Down Expand Up @@ -149,8 +173,8 @@ export default {
TmBtn
},
props: {
denom: {
type: String,
denoms: {
type: Array,
required: true
}
},
Expand All @@ -160,22 +184,29 @@ export default {
memo: defaultMemo,
max_memo_characters: 256,
editMemo: false,
balance: {
amount: null,
denom: ``
}
isFirstLoad: true,
selectedToken: ``,
selectedBalance: ``,
balances: [
{
amount: null,
denom: ``
}
]
}),
computed: {
...mapGetters([`network`]),
...mapGetters({ userAddress: `address` }),
transactionData() {
// This is the best place I have found so far to call this function
this.setTokenAndBalance()
return {
type: transaction.SEND,
toAddress: this.address,
amounts: [
{
amount: uatoms(+this.amount),
denom: toMicroDenom(this.denom)
denom: toMicroDenom(this.selectedToken)
}
],
memo: this.memo
Expand All @@ -184,10 +215,24 @@ export default {
notifyMessage() {
return {
title: `Successful Send`,
body: `Successfully sent ${+this.amount} ${this.denom}s to ${
body: `Successfully sent ${+this.amount} ${this.selectedToken}s to ${
this.address
}`
}
},
getDenoms() {
return this.denoms.map(denom => (denom = { key: denom, value: denom }))
}
},
watch: {
// we set the amount in the input to zero every time the user selects another token so they
// realize they are dealing with a different balance each time
selectedToken: function() {
if (!this.isFirstLoad) {
this.amount = 0
} else {
this.isFirstLoad = false
}
}
},
mounted() {
Expand Down Expand Up @@ -215,15 +260,36 @@ export default {
this.sending = false
},
setMaxAmount() {
this.amount = this.balance.amount
this.amount = this.selectedBalance.amount
},
isMaxAmount() {
if (this.balance.amount === 0) {
if (this.selectedBalance.amount === 0) {
return false
} else {
return parseFloat(this.amount) === parseFloat(this.balance.amount)
return (
parseFloat(this.amount) === parseFloat(this.selectedBalance.amount)
)
}
},
setTokenAndBalance() {
// if it is single-token network, then we take the first and only value from the
// balances array
if (this.balances.length === 1) {
this.selectedToken = this.getDenoms[0].value
this.selectedBalance = this.balances[0]
// if it is a multiple-tokens network and we already have a selectedToken by the user
// then we search for the corresponding balance from the array
} else if (this.selectedToken) {
this.selectedBalance = this.balances.filter(
balance => balance.denom === this.selectedToken
)[0]
}
},
token() {
if (!this.selectedToken) return ``
return this.selectedToken
},
bech32Validate(param) {
try {
b32.decode(param)
Expand Down Expand Up @@ -252,23 +318,20 @@ export default {
amount: {
required: x => !!x && x !== `0`,
decimal,
between: between(SMALLEST, this.balance.amount)
between: between(SMALLEST, this.selectedBalance.amount)
},
denom: { required },
denoms: { required },
selectedToken: { required },
memo: {
maxLength: maxLength(this.max_memo_characters)
}
}
},
apollo: {
balance: {
balances: {
query: gql`
query BalanceSendModal(
$networkId: String!
$address: String!
$denom: String!
) {
balance(networkId: $networkId, address: $address, denom: $denom) {
query BalancesSendModal($networkId: String!, $address: String!) {
balances(networkId: $networkId, address: $address) {
amount
denom
}
Expand All @@ -280,8 +343,7 @@ export default {
variables() {
return {
networkId: this.network,
address: this.userAddress,
denom: this.denom
address: this.userAddress
}
}
},
Expand Down Expand Up @@ -314,4 +376,8 @@ export default {
font-size: 12px;
cursor: pointer;
}
#form-group-amount {
margin-bottom: 30px;
}
</style>
14 changes: 13 additions & 1 deletion src/components/common/TmBalance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
/>
</div>

<SendModal ref="SendModal" :denom="stakingDenom" />
<SendModal ref="SendModal" :denoms="getAllDenoms" />
<ModalWithdrawRewards ref="ModalWithdrawRewards" />
</div>
</div>
Expand Down Expand Up @@ -82,6 +82,14 @@ export default {
// the validator rewards are needed to filter the top 5 validators to withdraw from
readyToWithdraw() {
return this.overview.totalRewards > 0
},
getAllDenoms() {
if (this.overview.balances) {
const balances = this.overview.balances
return balances.map(({ denom }) => denom)
} else {
return [this.stakingDenom]
}
}
},
methods: {
Expand All @@ -99,6 +107,10 @@ export default {
overview(networkId: $networkId, address: $address) {
totalRewards
liquidStake
balances {
denom
amount
}
totalStake
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,18 @@ describe(`SendModal`, () => {
}
},
propsData: {
denom: "STAKE"
denoms: ["STAKE"]
},
sync: false
})

wrapper.setData({
balance: {
denom: `STAKE`,
amount: 10000
}
balances: [
{
denom: `STAKE`,
amount: 10000
}
]
})

wrapper.vm.$refs.actionModal = {
Expand Down Expand Up @@ -211,10 +213,12 @@ describe(`SendModal`, () => {
})
it(`should not show warning message if balance = 0`, async () => {
wrapper.setData({
balance: {
amount: 0,
denom: "STAKE"
}
balances: [
{
amount: 0,
denom: "STAKE"
}
]
})
wrapper.vm.setMaxAmount()
await wrapper.vm.$nextTick()
Expand All @@ -224,14 +228,49 @@ describe(`SendModal`, () => {
})
it(`isMaxAmount() should return false if balance = 0`, async () => {
wrapper.setData({
balance: {
amount: 0,
denom: "STAKE"
}
balances: [
{
amount: 0,
denom: "STAKE"
}
]
})
wrapper.vm.setMaxAmount()
await wrapper.vm.$nextTick()
expect(wrapper.vm.isMaxAmount()).toBe(false)
})
})

describe(`Set token and balance`, () => {
it(`it takes the corresponding balance from the balances array when
selectedToken has been chosen and balances has a length over 1`, async () => {
wrapper.setData({
selectedToken: `TOKEN1`,
balances: [
{
amount: 1,
denom: "TOKEN1"
},
{
amount: 2,
denom: "TOKEN2"
}
]
})
wrapper.vm.setTokenAndBalance()
expect(wrapper.vm.selectedBalance.amount).toBe(1)
})
// This one creates a lot of ugly errors
// it(`returns empty string if selectedToken hasn't been chosen yet`, () => {
// wrapper.setData({
// balances: []
// })
// const res = wrapper.vm.token()
// expect(res).toBe("")
// })
it(`returns selectedToken if selectedToken has been chosen`, () => {
const res = wrapper.vm.token()
expect(res).toBe("STAKE")
})
})
})
Loading

0 comments on commit 82df018

Please sign in to comment.