diff --git a/.changeset/tough-gorillas-invent.md b/.changeset/tough-gorillas-invent.md new file mode 100644 index 000000000..4b95c0c25 --- /dev/null +++ b/.changeset/tough-gorillas-invent.md @@ -0,0 +1,5 @@ +--- +'@celo/celocli': major +--- + +Remove Grandamento from CLI diff --git a/packages/cli/src/commands/grandamento/cancel.test.ts b/packages/cli/src/commands/grandamento/cancel.test.ts deleted file mode 100644 index 3d5b9cb21..000000000 --- a/packages/cli/src/commands/grandamento/cancel.test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Address } from '@celo/base/lib/address' -import { newKitFromWeb3 } from '@celo/contractkit' -import { assumeOwnership } from '@celo/contractkit/lib/test-utils/transferownership' -import { GrandaMentoWrapper } from '@celo/contractkit/lib/wrappers/GrandaMento' -import { testWithGanache } from '@celo/dev-utils/lib/ganache-test' -import BigNumber from 'bignumber.js' -import Web3 from 'web3' -import { testLocally } from '../../test-utils/cliUtils' -import Cancel from './cancel' -import Propose from './propose' - -testWithGanache('grandamento:cancel cmd', (web3: Web3) => { - const kit = newKitFromWeb3(web3) - let grandaMento: GrandaMentoWrapper - const newLimitMin = new BigNumber('1000') - const newLimitMax = new BigNumber('1000000000000') - let accounts: Address[] = [] - - const increaseLimits = async () => { - await grandaMento - .setStableTokenExchangeLimits('StableToken', newLimitMin.toString(), newLimitMax.toString()) - .sendAndWaitForReceipt() - } - - beforeAll(async () => { - accounts = await web3.eth.getAccounts() - kit.defaultAccount = accounts[0] - grandaMento = await kit.contracts.getGrandaMento() - }) - - beforeEach(async () => { - await assumeOwnership(web3, accounts[0]) - await increaseLimits() - // create mock proposal - await testLocally(Propose, [ - '--from', - accounts[0], - '--sellCelo', - 'true', - '--stableToken', - 'cUSD', - '--value', - '10000', - ]) - }) - - describe('cancel', () => { - it('left no proposal', async () => { - await testLocally(Cancel, ['--from', accounts[0], '--proposalID', '1']) - const activeProposals = await grandaMento.getActiveProposalIds() - expect(activeProposals).toEqual([]) - }) - }) -}) diff --git a/packages/cli/src/commands/grandamento/cancel.ts b/packages/cli/src/commands/grandamento/cancel.ts deleted file mode 100644 index 1f85857c8..000000000 --- a/packages/cli/src/commands/grandamento/cancel.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Flags } from '@oclif/core' -import { BaseCommand } from '../../base' -import { newCheckBuilder } from '../../utils/checks' -import { displaySendTx } from '../../utils/cli' -import { CustomFlags } from '../../utils/command' - -export default class Cancel extends BaseCommand { - static description = 'Cancels a Granda Mento exchange proposal' - - static flags = { - ...BaseCommand.flags, - from: CustomFlags.address({ - required: true, - description: 'The address allowed to cancel the proposal', - }), - proposalID: Flags.string({ - required: true, - exclusive: ['account', 'hotfix'], - description: 'UUID of proposal to view', - }), - } - - async run() { - const kit = await this.getKit() - const grandaMento = await kit.contracts.getGrandaMento() - - const res = await this.parse(Cancel) - const proposalID = res.flags.proposalID - - await newCheckBuilder(this).grandaMentoProposalExists(proposalID).runChecks() - - await displaySendTx( - 'cancelExchangeProposal', - grandaMento.cancelExchangeProposal(proposalID), - undefined, - 'ExchangeProposalCancelled' - ) - } -} diff --git a/packages/cli/src/commands/grandamento/execute.test.ts b/packages/cli/src/commands/grandamento/execute.test.ts deleted file mode 100644 index 184237a7c..000000000 --- a/packages/cli/src/commands/grandamento/execute.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { Address } from '@celo/base/lib/address' -import { newKitFromWeb3 } from '@celo/contractkit' -import { assumeOwnership } from '@celo/contractkit/lib/test-utils/transferownership' -import { GrandaMentoWrapper } from '@celo/contractkit/lib/wrappers/GrandaMento' -import { testWithGanache, timeTravel } from '@celo/dev-utils/lib/ganache-test' -import BigNumber from 'bignumber.js' -import Web3 from 'web3' -import { testLocally } from '../../test-utils/cliUtils' -import Execute from './execute' -import Propose from './propose' - -testWithGanache('grandamento:execute cmd', (web3: Web3) => { - const kit = newKitFromWeb3(web3) - let grandaMento: GrandaMentoWrapper - const newLimitMin = new BigNumber('1000') - const newLimitMax = new BigNumber('1000000000000') - let accounts: Address[] = [] - const dateNowOriginal = Date.now - let originalNoSyncCheck: string | undefined - - const increaseLimits = () => { - return grandaMento - .setStableTokenExchangeLimits('StableToken', newLimitMin.toString(), newLimitMax.toString()) - .sendAndWaitForReceipt() - } - - const createExchangeProposal = () => { - // create mock proposal - return testLocally(Propose, [ - '--from', - accounts[0], - '--sellCelo', - 'true', - '--stableToken', - 'cUSD', - '--value', - '10000', - ]) - } - - const approveExchangeProposal = async (proposalID: number | string) => { - await grandaMento.setApprover(accounts[0]).sendAndWaitForReceipt() - await grandaMento.approveExchangeProposal(proposalID).sendAndWaitForReceipt() - } - - const timeTravelDateAndChain = async (seconds: number) => { - await timeTravel(seconds, web3) - jest.useFakeTimers().setSystemTime(dateNowOriginal() + seconds * 1000) - // Otherwise contractkit complains there is a difference between Date.now() - // and the timestamp of the last block - process.env.NO_SYNCCHECK = 'true' - } - - beforeAll(async () => { - accounts = await web3.eth.getAccounts() - kit.defaultAccount = accounts[0] - grandaMento = await kit.contracts.getGrandaMento() - originalNoSyncCheck = process.env.NO_SYNCCHECK - }) - - afterEach(() => { - process.env.NO_SYNCCHECK = originalNoSyncCheck - }) - - beforeEach(async () => { - await assumeOwnership(web3, accounts[0]) - await increaseLimits() - await createExchangeProposal() - // Approve it - await approveExchangeProposal(1) - // Wait the veto period plus some extra time to be safe - await timeTravelDateAndChain((await grandaMento.vetoPeriodSeconds()).toNumber() + 1000) - }) - - describe('execute', () => { - it('executes the proposal', async () => { - await testLocally(Execute, ['--from', accounts[0], '--proposalID', '1']) - const activeProposals = await grandaMento.getActiveProposalIds() - expect(activeProposals).toEqual([]) - }) - - it('fails if the exchange proposal is not executable', async () => { - // Create a proposal with proposalID 2, but don't wait the veto period - await createExchangeProposal() - await approveExchangeProposal(2) - await expect( - testLocally(Execute, ['--from', accounts[0], '--proposalID', '2']) - ).rejects.toThrow() - }) - }) -}) diff --git a/packages/cli/src/commands/grandamento/execute.ts b/packages/cli/src/commands/grandamento/execute.ts deleted file mode 100644 index dd609e3ca..000000000 --- a/packages/cli/src/commands/grandamento/execute.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Flags } from '@oclif/core' -import { BaseCommand } from '../../base' -import { newCheckBuilder } from '../../utils/checks' -import { displaySendTx } from '../../utils/cli' -import { CustomFlags } from '../../utils/command' - -export default class Execute extends BaseCommand { - static description = 'Executes a Granda Mento exchange proposal' - - static flags = { - ...BaseCommand.flags, - from: CustomFlags.address({ - required: true, - description: 'The address to execute the exchange proposal', - }), - proposalID: Flags.string({ - required: true, - description: 'UUID of proposal to view', - }), - } - - async run() { - const kit = await this.getKit() - const grandaMento = await kit.contracts.getGrandaMento() - - const res = await this.parse(Execute) - const proposalID = res.flags.proposalID - - await newCheckBuilder(this) - .grandaMentoProposalExists(proposalID) - .grandaMentoProposalIsExecutable(proposalID) - .runChecks() - - await displaySendTx( - 'executeExchangeProposal', - grandaMento.executeExchangeProposal(proposalID), - undefined, - 'ExchangeProposalExecuted' - ) - } -} diff --git a/packages/cli/src/commands/grandamento/get-buy-amount.test.ts b/packages/cli/src/commands/grandamento/get-buy-amount.test.ts deleted file mode 100644 index d115d24df..000000000 --- a/packages/cli/src/commands/grandamento/get-buy-amount.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Address } from '@celo/base/lib/address' -import { newKitFromWeb3 } from '@celo/contractkit' -import { assumeOwnership } from '@celo/contractkit/lib/test-utils/transferownership' -import { testWithGanache } from '@celo/dev-utils/lib/ganache-test' -import Web3 from 'web3' -import { testLocally } from '../../test-utils/cliUtils' -import GetBuyAmount from './get-buy-amount' - -testWithGanache('grandamento:get-buy-amount cmd', (web3: Web3) => { - const kit = newKitFromWeb3(web3) - let accounts: Address[] = [] - - beforeAll(async () => { - accounts = await web3.eth.getAccounts() - kit.defaultAccount = accounts[0] - }) - - beforeEach(async () => { - await assumeOwnership(web3, accounts[0]) - }) - - it('gets the buy amount', async () => { - await testLocally(GetBuyAmount, [ - '--sellCelo', - 'true', - '--stableToken', - 'cusd', - '--value', - '100000000000000000000000', - ]) - }) -}) diff --git a/packages/cli/src/commands/grandamento/get-buy-amount.ts b/packages/cli/src/commands/grandamento/get-buy-amount.ts deleted file mode 100644 index eec180c40..000000000 --- a/packages/cli/src/commands/grandamento/get-buy-amount.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { StableToken } from '@celo/contractkit' -import { toFixed } from '@celo/utils/lib/fixidity' -import { Flags } from '@oclif/core' -import { BaseCommand } from '../../base' -import { printValueMap } from '../../utils/cli' -import { CustomFlags } from '../../utils/command' -import { enumEntriesDupWithLowercase } from '../../utils/helpers' - -const stableTokenOptions = enumEntriesDupWithLowercase(Object.entries(StableToken)) - -export default class GetBuyAmount extends BaseCommand { - static description = 'Gets the buy amount for a prospective Granda Mento exchange' - - static flags = { - ...BaseCommand.flags, - value: CustomFlags.wei({ - required: true, - description: 'The value of the tokens to exchange', - }), - stableToken: Flags.option({ - options: Object.keys(stableTokenOptions) as Array>, - description: 'Name of the stable to receive or send', - })({ required: true, default: 'cusd' }), - sellCelo: Flags.boolean({ - required: true, - description: 'Sell or buy CELO', - }), - } - - async run() { - const kit = await this.getKit() - const grandaMento = await kit.contracts.getGrandaMento() - - const res = await this.parse(GetBuyAmount) - const sellAmount = res.flags.value - const stableToken = stableTokenOptions[res.flags.stableToken] - const sellCelo = res.flags.sellCelo - - const stableTokenAddress = await kit.celoTokens.getAddress(stableToken) - const sortedOracles = await kit.contracts.getSortedOracles() - const celoStableTokenOracleRate = (await sortedOracles.medianRate(stableTokenAddress)).rate - - const buyAmount = await grandaMento.getBuyAmount( - toFixed(celoStableTokenOracleRate), - sellAmount, - sellCelo - ) - - printValueMap({ - buyAmount, - }) - } -} diff --git a/packages/cli/src/commands/grandamento/list.test.ts b/packages/cli/src/commands/grandamento/list.test.ts deleted file mode 100644 index 6a6bc9ad2..000000000 --- a/packages/cli/src/commands/grandamento/list.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Address } from '@celo/base/lib/address' -import { newKitFromWeb3 } from '@celo/contractkit' -import { StableToken } from '@celo/contractkit/lib/celo-tokens' -import { assumeOwnership } from '@celo/contractkit/lib/test-utils/transferownership' -import { GoldTokenWrapper } from '@celo/contractkit/lib/wrappers/GoldTokenWrapper' -import { GrandaMentoWrapper } from '@celo/contractkit/lib/wrappers/GrandaMento' -import { testWithGanache } from '@celo/dev-utils/lib/ganache-test' -import BigNumber from 'bignumber.js' -import Web3 from 'web3' -import { testLocally } from '../../test-utils/cliUtils' -import { setGrandaMentoLimits } from '../../test-utils/grandaMento' -import List from './list' - -testWithGanache('grandamento:list cmd', (web3: Web3) => { - const kit = newKitFromWeb3(web3) - let grandaMento: GrandaMentoWrapper - let accounts: Address[] = [] - let celoToken: GoldTokenWrapper - - beforeAll(async () => { - accounts = await web3.eth.getAccounts() - kit.defaultAccount = accounts[0] - grandaMento = await kit.contracts.getGrandaMento() - - celoToken = await kit.contracts.getGoldToken() - }) - - beforeEach(async () => { - await assumeOwnership(web3, accounts[0]) - await setGrandaMentoLimits(grandaMento) - }) - - it('shows an empty list of proposals', async () => { - await testLocally(List, []) - }) - - it('shows proposals', async () => { - // create mock proposal - const sellAmount = new BigNumber('100000000') - await celoToken.increaseAllowance(grandaMento.address, sellAmount).sendAndWaitForReceipt() - await ( - await grandaMento.createExchangeProposal( - kit.celoTokens.getContract(StableToken.cUSD), - sellAmount, - true - ) - ).sendAndWaitForReceipt() - - await testLocally(List, []) - }) -}) diff --git a/packages/cli/src/commands/grandamento/list.ts b/packages/cli/src/commands/grandamento/list.ts deleted file mode 100644 index c8da26df3..000000000 --- a/packages/cli/src/commands/grandamento/list.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { BaseCommand } from '../../base' -import { printValueMap } from '../../utils/cli' - -export default class List extends BaseCommand { - static description = 'List current active Granda Mento exchange proposals' - - static flags = { - ...BaseCommand.flags, - } - - async run() { - const kit = await this.getKit() - const grandaMento = await kit.contracts.getGrandaMento() - const proposals = await grandaMento.getActiveProposalIds() - - if (!proposals.length) { - console.log('No active Granda Mento proposals') - return - } - - console.log('Active proposals:') - - const proposalsDetails = proposals.map((id) => grandaMento.getHumanReadableExchangeProposal(id)) - - const res = await Promise.all(proposalsDetails) - - res.map((proposalJSON) => { - console.log('Proposal ID: ' + proposalJSON.id) - printValueMap(proposalJSON) - }) - } -} diff --git a/packages/cli/src/commands/grandamento/propose.test.ts b/packages/cli/src/commands/grandamento/propose.test.ts deleted file mode 100644 index 4654cde01..000000000 --- a/packages/cli/src/commands/grandamento/propose.test.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { Address } from '@celo/base/lib/address' -import { newKitFromWeb3 } from '@celo/contractkit' -import { assumeOwnership } from '@celo/contractkit/lib/test-utils/transferownership' -import { - ExchangeProposalState, - GrandaMentoWrapper, -} from '@celo/contractkit/lib/wrappers/GrandaMento' -import { testWithGanache } from '@celo/dev-utils/lib/ganache-test' -import BigNumber from 'bignumber.js' -import Web3 from 'web3' -import { testLocally } from '../../test-utils/cliUtils' -import { setGrandaMentoLimits } from '../../test-utils/grandaMento' -import Propose from './propose' - -testWithGanache('grandamento:propose cmd', (web3: Web3) => { - const kit = newKitFromWeb3(web3) - let grandaMento: GrandaMentoWrapper - let accounts: Address[] = [] - - beforeAll(async () => { - accounts = await web3.eth.getAccounts() - kit.defaultAccount = accounts[0] - grandaMento = await kit.contracts.getGrandaMento() - }) - - beforeEach(async () => { - await assumeOwnership(web3, accounts[0]) - await setGrandaMentoLimits(grandaMento) - }) - - describe('proposes', () => { - it('can sell Celo', async () => { - await testLocally(Propose, [ - '--from', - accounts[0], - '--sellCelo', - 'true', - '--stableToken', - 'cUSD', - '--value', - '10000', - ]) - - const activeProposals = await grandaMento.getActiveProposalIds() - - expect(activeProposals).not.toEqual([]) - - const proposal = await grandaMento.getExchangeProposal(activeProposals[0]) - expect(proposal.exchanger).toEqual(accounts[0]) - expect(proposal.stableToken).toEqual((await kit.contracts.getStableToken()).address) - expect(proposal.sellAmount).toEqBigNumber(10000) - expect(proposal.approvalTimestamp).toEqual(new BigNumber(0)) - expect(proposal.state).toEqual(ExchangeProposalState.Proposed) - expect(proposal.sellCelo).toEqual(true) - }) - - it('can buy Celo', async () => { - await testLocally(Propose, [ - '--from', - accounts[0], - '--sellCelo', - 'false', - '--stableToken', - 'cUSD', - '--value', - '10000', - ]) - const activeProposals = await grandaMento.getActiveProposalIds() - - expect(activeProposals).not.toEqual([]) - - const proposal = await grandaMento.getExchangeProposal(activeProposals[0]) - expect(proposal.exchanger).toEqual(accounts[0]) - expect(proposal.stableToken).toEqual((await kit.contracts.getStableToken()).address) - expect(proposal.sellAmount).toEqBigNumber(10000) - expect(proposal.approvalTimestamp).toEqual(new BigNumber(0)) - expect(proposal.state).toEqual(ExchangeProposalState.Proposed) - expect(proposal.sellCelo).toEqual(false) - }) - - it("doesn't work without explicitly setting the sellCelo flag", async () => { - let activeProposals - - await expect( - testLocally(Propose, [ - '--from', - accounts[0], - '--sellCelo', - '--stableToken', - 'cUSD', - '--value', - '10000', - ]) - ).rejects.toThrow() - - activeProposals = await grandaMento.getActiveProposalIds() - expect(activeProposals).toEqual([]) - - await expect( - testLocally(Propose, [ - '--from', - accounts[0], - '--sellCelo', - 'tru', // typo on propose - '--stableToken', - 'cUSD', - '--value', - '10000', - ]) - ).rejects.toThrow() - - activeProposals = await grandaMento.getActiveProposalIds() - expect(activeProposals).toEqual([]) - }) - }) -}) diff --git a/packages/cli/src/commands/grandamento/propose.ts b/packages/cli/src/commands/grandamento/propose.ts deleted file mode 100644 index 465a46f2d..000000000 --- a/packages/cli/src/commands/grandamento/propose.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { StableToken } from '@celo/contractkit' -import { Flags } from '@oclif/core' -import { BaseCommand } from '../../base' -import { newCheckBuilder } from '../../utils/checks' -import { displaySendTx } from '../../utils/cli' -import { CustomFlags } from '../../utils/command' -import { enumEntriesDupWithLowercase } from '../../utils/helpers' - -const stableTokenOptions = enumEntriesDupWithLowercase(Object.entries(StableToken)) - -export default class Propose extends BaseCommand { - static description = 'Proposes a Granda Mento exchange' - - static flags = { - ...BaseCommand.flags, - from: CustomFlags.address({ - required: true, - description: 'The address with tokens to exchange', - }), - value: CustomFlags.wei({ - required: true, - description: 'The value of the tokens to exchange', - }), - stableToken: Flags.option({ - options: Object.keys(stableTokenOptions) as Array>, - description: 'Name of the stable to receive or send', - })({ required: true, default: 'cusd' as const }), - sellCelo: Flags.boolean({ - required: true, - description: 'Sell or buy CELO', - }), - } - - async run() { - const kit = await this.getKit() - const celoToken = await kit.contracts.getGoldToken() - const grandaMento = await kit.contracts.getGrandaMento() - - const res = await this.parse(Propose) - const signer = res.flags.from - const sellAmount = res.flags.value - const stableToken = stableTokenOptions[res.flags.stableToken] - const sellCelo = res.flags.sellCelo - - kit.defaultAccount = signer - - const tokenToSell = sellCelo ? celoToken : await kit.contracts.getStableToken(stableToken) - - await newCheckBuilder(this, signer) - .hasEnoughErc20(signer, sellAmount, tokenToSell.address) - .runChecks() - - await displaySendTx( - 'increaseAllowance', - tokenToSell.increaseAllowance(grandaMento.address, sellAmount.toFixed()) - ) - - await displaySendTx( - 'createExchangeProposal', - await grandaMento.createExchangeProposal( - kit.celoTokens.getContract(stableToken), - sellAmount, - sellCelo - ), - undefined, - 'ExchangeProposalCreated' - ) - } -} diff --git a/packages/cli/src/commands/grandamento/show.test.ts b/packages/cli/src/commands/grandamento/show.test.ts deleted file mode 100644 index 044c82b0f..000000000 --- a/packages/cli/src/commands/grandamento/show.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Address } from '@celo/base/lib/address' -import { newKitFromWeb3 } from '@celo/contractkit' -import { StableToken } from '@celo/contractkit/lib/celo-tokens' -import { assumeOwnership } from '@celo/contractkit/lib/test-utils/transferownership' -import { GoldTokenWrapper } from '@celo/contractkit/lib/wrappers/GoldTokenWrapper' -import { GrandaMentoWrapper } from '@celo/contractkit/lib/wrappers/GrandaMento' -import { testWithGanache } from '@celo/dev-utils/lib/ganache-test' -import BigNumber from 'bignumber.js' -import Web3 from 'web3' -import { testLocally } from '../../test-utils/cliUtils' -import { setGrandaMentoLimits } from '../../test-utils/grandaMento' -import Show from './show' - -testWithGanache('grandamento:show cmd', (web3: Web3) => { - const kit = newKitFromWeb3(web3) - let grandaMento: GrandaMentoWrapper - let accounts: Address[] = [] - let celoToken: GoldTokenWrapper - - beforeAll(async () => { - accounts = await web3.eth.getAccounts() - kit.defaultAccount = accounts[0] - grandaMento = await kit.contracts.getGrandaMento() - - celoToken = await kit.contracts.getGoldToken() - }) - - beforeEach(async () => { - await assumeOwnership(web3, accounts[0]) - await setGrandaMentoLimits(grandaMento) - }) - - it('shows proposals', async () => { - // create mock proposal - const sellAmount = new BigNumber('100000000') - await celoToken.increaseAllowance(grandaMento.address, sellAmount).sendAndWaitForReceipt() - - await ( - await grandaMento.createExchangeProposal( - kit.celoTokens.getContract(StableToken.cUSD), - sellAmount, - true - ) - ).sendAndWaitForReceipt() - - await testLocally(Show, ['--proposalID', '1']) - }) -}) diff --git a/packages/cli/src/commands/grandamento/show.ts b/packages/cli/src/commands/grandamento/show.ts deleted file mode 100644 index de067898c..000000000 --- a/packages/cli/src/commands/grandamento/show.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Flags } from '@oclif/core' -import { BaseCommand } from '../../base' -import { newCheckBuilder } from '../../utils/checks' -import { printValueMap } from '../../utils/cli' - -export default class Show extends BaseCommand { - static description = 'Shows details of a Granda Mento exchange proposal' - - static flags = { - ...BaseCommand.flags, - proposalID: Flags.string({ - required: true, - description: 'UUID of proposal to view', - }), - } - - async run() { - const kit = await this.getKit() - const grandaMento = await kit.contracts.getGrandaMento() - - const res = await this.parse(Show) - const proposalID = res.flags.proposalID - - await newCheckBuilder(this).grandaMentoProposalExists(proposalID).runChecks() - - const proposal = await grandaMento.getHumanReadableExchangeProposal(proposalID) - - printValueMap(proposal) - } -}