Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fedekunze/1548 mocked submit deposit #1549

Merged
merged 12 commits into from
Nov 13, 2018
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* [\#1472](https://github.com/cosmos/voyager/issues/1472) Added mock functionality for redelegation @fedekunze + @faboweb
* [\#1501](https://github.com/cosmos/voyager/issues/1501) Vote on proposals through modal @fedekunze + @jbibla
* [\1502](https://github.com/cosmos/voyager/issues/1502) A page for each proposal. @jbibla
* [\1548](https://github.com/cosmos/voyager/issues/1548) Add mocked deposit for testing @fedekunze

### Changed

Expand Down
2 changes: 1 addition & 1 deletion app/src/renderer/connectors/lcdClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ const Client = (axios, localLcdURL, remoteLcdURL) => {
submitProposalVote: function(proposalId, data) {
return req(`POST`, `/gov/proposals/${proposalId}/votes`, true)(data)
},
submitDeposit: function(proposalId, data) {
submitProposalDeposit: function(proposalId, data) {
return req(`POST`, `/gov/proposals/${proposalId}/deposits`, true)(data)
}
}
Expand Down
203 changes: 182 additions & 21 deletions app/src/renderer/connectors/lcdClientMock.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
"use strict"

const moment = require(`moment`)
const b32 = require(`../scripts/b32.js`)
const { getHeight } = require(`./rpcWrapperMock.js`)

Expand Down Expand Up @@ -353,13 +355,13 @@ let state = {
description: `custom text proposal description`,
initial_deposit: [
{
denom: `stake`,
denom: `steak`,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't we want to move towards stake?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah but it's not going to be used until GoS and the denom for governance is still steak

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, but this is just the mock implementation and not the real network. does it conflict with settings for the real network?

Copy link
Contributor Author

@fedekunze fedekunze Nov 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really, but I'd have to add another proposal or refactor it to change that, bc it'll probably break other unit tests that use the mocked proposals. Can I do that on the scope of #1378 ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I just did that PR. Let's see afterwards what breaks. 💥

amount: `200`
}
],
total_deposit: [
{
denom: `stake`,
denom: `steak`,
amount: `200`
}
],
Expand All @@ -381,13 +383,13 @@ let state = {
initial_deposit: [
{
denom: `stake`,
amount: `15`
amount: `20`
}
],
total_deposit: [
{
denom: `stake`,
amount: `15`
amount: `170`
}
],
submit_block: `10`,
Expand Down Expand Up @@ -433,37 +435,60 @@ let state = {
{
proposal_id: `1`,
depositer: validators[0],
amount: {
denom: `stake`,
amount: `15`
}
amount: [
{
denom: `stake`,
amount: `15`
},
{
denom: `stake`,
amount: `5`
}
]
},
{
proposal_id: `1`,
depositer: validators[1],
amount: {
denom: `stake`,
amount: `5`
}
amount: [
{
denom: `stake`,
amount: `5`
}
]
}
],
2: [
{
proposal_id: `2`,
depositer: validators[0],
amount: [
{
denom: `steak`,
amount: `200`
}
]
}
],
2: [],
5: [
{
proposal_id: `5`,
depositer: validators[0],
amount: {
denom: `stake`,
amount: `11`
}
amount: [
{
denom: `stake`,
amount: `20`
}
]
},
{
proposal_id: `5`,
depositer: validators[1],
amount: {
denom: `stake`,
amount: `150`
}
amount: [
{
denom: `stake`,
amount: `150`
}
]
}
]
}
Expand Down Expand Up @@ -891,6 +916,142 @@ module.exports = {
deposit => deposit.depositer === address
)
},
async submitProposalDeposit({
proposal_id,
base_req: { name, sequence },
depositer,
amount
}) {
let results = []
let fromKey = state.keys.find(a => a.name === name)
let fromAccount = state.accounts[fromKey.address]
if (fromAccount == null) {
results.push(txResult(1, `Nonexistent account`))
return results
}
// check nonce
if (parseInt(fromAccount.sequence) !== parseInt(sequence)) {
results.push(
txResult(
2,
`Expected sequence "${fromAccount.sequence}", got "${sequence}"`
)
)
return results
}

let proposal = state.proposals.find(
proposal => proposal.proposal_id === proposal_id
)
if (!proposal) {
results.push(txResult(3, `Nonexistent proposal`))
return results
} else if (
proposal.proposal_status != `Pending` &&
proposal.proposal_status != `Active`
) {
results.push(txResult(3, `Proposal #${proposal_id} already finished`))
return results
}

// update depositer's balance
let coin
let submittedDeposit = {
proposal_id,
depositer,
amount
}

// javascript's forEach doesn't support break, so using classic for loop...
for (let i = 0; i < amount.length; i++) {
coin = amount[i]
let depositCoinAmt = parseInt(coin.amount)
let coinBalance = fromAccount.coins.find(c => c.denom === coin.denom)

if (depositCoinAmt < 0) {
results.push(txResult(1, `Amount of ${coin.denom}s cannot be negative`))
return results
} else if (!coinBalance || coinBalance.amount < depositCoinAmt) {
results.push(txResult(1, `Not enough ${coin.denom}s in your account`))
return results
}

coinBalance.amount -= depositCoinAmt

// ============= TOTAL PROPOSAL's DEPOSIT =============
// Increment total deposit of the proposal
let depositIndex = proposal.total_deposit.findIndex(
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
deposit => deposit.denom === coin.denom
)
if (depositIndex === -1) {
// if there's no previous deposit in that denom we just append it to the total deposit
proposal.total_deposit.push(coin)
} else {
// if there's an existing deposit with that denom we add the submited deposit amount to it
let newAmt = String(
parseInt(proposal.total_deposit[depositIndex].amount) +
parseInt(coin.amount)
)
proposal.total_deposit[depositIndex].amount = newAmt
}

// ============= USER'S DEPOSITS =============
// check if there's an existing deposit by the depositer
let prevDepositIndex = state.deposits[proposal_id].findIndex(
deposit => deposit.depositer === depositer
)

if (prevDepositIndex === -1) {
// if no previous deposit by the depositer, we add it to the existing deposits
state.deposits[proposal_id].push(submittedDeposit)
break // break since no need to iterate over other coins
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
} else {
// ============= USER'S DEPOSITS WITH SAME COIN DENOM =============
// if there's a prev deposit, add the new amount to the corresponding coin
let prevDepCoinIdx = state.deposits[proposal_id][
prevDepositIndex
].amount.findIndex(prevDepCoin => {
return prevDepCoin.denom === coin.denom
})
if (prevDepCoinIdx === -1) {
state.deposits[proposal_id][prevDepositIndex].amount.push(coin)
} else {
// there's a previous deposit from the depositer with the same coin
let newAmt =
parseInt(
state.deposits[proposal_id][prevDepositIndex].amount[
prevDepCoinIdx
].amount
) + parseInt(coin.amount)

state.deposits[proposal_id][prevDepositIndex].amount[
prevDepCoinIdx
].amount = String(newAmt)
}
}
}
// TODO: double check if we need to update it inside the loop
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
incrementSequence(fromAccount)

// check if the propoposal is now active
if (proposal.proposal_status === `Pending`) {
// TODO: get min deposit coin from gov params instead of stake params
let depositCoinAmt = proposal.total_deposit.find(coin => {
return coin.denom === `steak`
}).amount
if (parseInt(depositCoinAmt) >= 10) {
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
proposal.proposal_status = `Active`
// TODO: get voting time from gov params
proposal.voting_start_block = Date.now()
proposal.voting_end_block = moment(proposal.voting_start_block)
.add(86400000, `ms`)
.toDate()
}
}
storeTx(`cosmos-sdk/MsgDeposit`, submittedDeposit)
results.push(txResult(0))
return results
},
async getProposalVotes(proposalId) {
return state.votes[proposalId] || []
},
Expand Down
5 changes: 4 additions & 1 deletion test/unit/specs/lcdClient.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,10 @@ describe(`LCD Client`, () => {

it(`submits a new deposit to a proposal`, async () => {
axios.post = jest.fn().mockReturnValue({})
await client.submitDeposit(proposals[0].proposal_id, deposits[0])
await client.submitProposalDeposit(
proposals[0].proposal_id,
deposits[0]
)
expect(axios.post.mock.calls[0]).toEqual([
`${remoteLcdURL}/gov/proposals/${proposals[0].proposal_id}/deposits`,
deposits[0]
Expand Down
Loading