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

Improvements to faucet for stake-off, fix celotool env check #2068

Merged
merged 3 commits into from
Dec 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 72 additions & 19 deletions packages/celotool/src/cmds/account/faucet.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
/* tslint:disable no-console */
import { newKit } from '@celo/contractkit'
import { sleep } from '@celo/utils/lib/async'
import { switchToClusterFromEnv } from 'src/lib/cluster'
import { convertToContractDecimals } from 'src/lib/contract-utils'
import { getBlockscoutUrl } from 'src/lib/endpoints'
import { envVar, fetchEnv } from 'src/lib/env-utils'
import { portForwardAnd } from 'src/lib/port_forward'
import { validateAccountAddress } from 'src/lib/utils'
import { execCmd, validateAccountAddress } from 'src/lib/utils'
import yargs from 'yargs'
import { AccountArgv } from '../account'

Expand All @@ -15,19 +18,26 @@ interface FaucetArgv extends AccountArgv {
account: string
gold: number
dollar: number
checkzero: boolean
blockscout: boolean
}

export const builder = (argv: yargs.Argv) => {
return argv
.option('account', {
type: 'string',
description: 'Account to faucet',
demand: 'Please specify account to faucet',
coerce: (address) => {
if (!validateAccountAddress(address)) {
throw Error(`Receiver Address is invalid: "${address}"`)
}
return address
description: 'Account(s) to faucet',
demand: 'Please specify comma-separated accounts to faucet',
coerce: (addresses) => {
return addresses.split(',').map((a: string) => {
if (!a.startsWith('0x')) {
a = `0x${a}`
}
if (!validateAccountAddress(a)) {
throw Error(`Receiver Address is invalid: "${a}"`)
}
return a
})
},
})
.option('dollar', {
Expand All @@ -40,12 +50,22 @@ export const builder = (argv: yargs.Argv) => {
description: 'Amount of gold to faucet',
demand: 'Please specify gold to faucet',
})
.option('checkzero', {
type: 'boolean',
description: 'Check that the gold balance is zero before fauceting',
default: false,
})
.option('blockscout', {
type: 'boolean',
description: 'Open in blockscout afterwards',
default: false,
})
}

export const handler = async (argv: FaucetArgv) => {
await switchToClusterFromEnv()

const address = argv.account
const addresses = argv.account

const cb = async () => {
const kit = newKit('http://localhost:8545')
Expand All @@ -58,18 +78,51 @@ export const handler = async (argv: FaucetArgv) => {
kit.contracts.getStableToken(),
kit.contracts.getReserve(),
])
const goldAmount = await convertToContractDecimals(argv.gold, goldToken)
const stableTokenAmount = await convertToContractDecimals(argv.dollar, stableToken)
console.log(`Fauceting ${argv.gold} Gold and ${argv.dollar} StableToken to ${address}`)
if (!goldAmount.isZero()) {
if (await reserve.isSpender(account)) {
await reserve.transferGold(address, goldAmount.toFixed()).sendAndWaitForReceipt()
} else {
await goldToken.transfer(address, goldAmount.toFixed()).sendAndWaitForReceipt()

if (argv.checkzero) {
for (const address of addresses) {
// Check this address hasn't already been fauceted and has zero gold
if (
(argv.gold !== 0 && !(await goldToken.balanceOf(address)).isZero()) ||
(argv.dollar !== 0 && !(await stableToken.balanceOf(address)).isZero())
) {
console.error(
`Unable to faucet ${address} on ${
argv.celoEnv
}: --checkzero specified, but balance is non-zero`
)
process.exit(1)
}
}
}

for (const address of addresses) {
const goldAmount = await convertToContractDecimals(argv.gold, goldToken)
const stableTokenAmount = await convertToContractDecimals(argv.dollar, stableToken)

console.log(
`Fauceting ${goldAmount.toFixed()} Gold and ${stableTokenAmount.toFixed()} StableToken to ${address}`
)

if (!goldAmount.isZero()) {
if (await reserve.isSpender(account)) {
// await reserve.transferGold(address, goldAmount.toFixed()).sendAndWaitForReceipt()
} else {
// await goldToken.transfer(address, goldAmount.toFixed()).sendAndWaitForReceipt()
}
}
if (!stableTokenAmount.isZero()) {
// await stableToken.transfer(address, stableTokenAmount.toFixed()).sendAndWaitForReceipt()
}
}
if (!stableTokenAmount.isZero()) {
await stableToken.transfer(address, stableTokenAmount.toFixed()).sendAndWaitForReceipt()

if (argv.blockscout) {
// Open addresses in blockscout
await sleep(1 + parseInt(fetchEnv(envVar.BLOCK_TIME), 10) * 1000)
const blockscoutUrl = getBlockscoutUrl(argv)
for (const address of addresses) {
await execCmd(`open ${blockscoutUrl}/address/${address}`)
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions packages/celotool/src/lib/artifacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const CONTRACTS_TO_COPY = [
export async function downloadArtifacts(celoEnv: string) {
let baseCmd = `yarn --cwd ../protocol run download-artifacts -n ${celoEnv}`
console.log(`Downloading artifacts for ${celoEnv}`)
if (isProduction(celoEnv)) {
if (isProduction()) {
baseCmd += ` -b contract_artifacts_production`
}
try {
Expand All @@ -35,7 +35,7 @@ export async function uploadArtifacts(celoEnv: string, checkOrPromptIfStagingOrP
}

let baseCmd = `yarn --cwd ../protocol run upload-artifacts -n ${celoEnv}`
if (isProduction(celoEnv)) {
if (isProduction()) {
baseCmd += ` -b contract_artifacts_production`
}
console.log(`Uploading artifacts for ${celoEnv}`)
Expand Down
30 changes: 6 additions & 24 deletions packages/celotool/src/lib/env-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,6 @@ export function validateAndSwitchToEnv(celoEnv: string) {
process.exit(1)
}

const indicatesStagingOrProductionEnv = isStaging(celoEnv) || isProduction(celoEnv)

if (indicatesStagingOrProductionEnv && !isValidStagingOrProductionEnv(celoEnv)) {
console.error(
`${celoEnv} indicated to be a staging or production environment but did not conform to the expected regex ^[a-z][a-z0-9]*(staging|production)$.`
)
process.exit(1)
}

const envResult = config({ path: getEnvFile(celoEnv) })
const envMemonicResult = config({ path: getEnvFile(celoEnv, '.mnemonic') })

Expand All @@ -159,33 +150,24 @@ export function validateAndSwitchToEnv(celoEnv: string) {
process.env.CELOTOOL_CELOENV = celoEnv
}

export function isStaging(env: string) {
return env.endsWith(EnvTypes.STAGING)
}

export function isProduction(env: string) {
return env.endsWith(EnvTypes.PRODUCTION)
export function isProduction() {
return fetchEnv(envVar.ENV_TYPE).toLowerCase() === EnvTypes.PRODUCTION
}

export function isValidCeloEnv(celoEnv: string) {
return new RegExp('^[a-z][a-z0-9]*$').test(celoEnv)
}

function isValidStagingOrProductionEnv(celoEnv: string) {
return new RegExp('^[a-z][a-z0-9]*(staging|production)$').test(celoEnv)
}

function celoEnvMiddleware(argv: CeloEnvArgv) {
validateAndSwitchToEnv(argv.celoEnv)
}

export async function doCheckOrPromptIfStagingOrProduction() {
if (
process.env.CELOTOOL_CONFIRMED !== 'true' &&
isValidStagingOrProductionEnv(process.env.CELOTOOL_CELOENV!)
) {
if (process.env.CELOTOOL_CONFIRMED !== 'true' && isProduction()) {
await confirmAction(
'You are about to apply a possibly irreversable action on a staging/production environment. Are you sure?'
`You are about to apply a possibly irreversible action on a production env: ${
process.env.CELOTOOL_CELOENV
}. Are you sure?`
)
process.env.CELOTOOL_CONFIRMED = 'true'
}
Expand Down
4 changes: 2 additions & 2 deletions packages/celotool/src/lib/helm_deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,8 @@ async function helmIPParameters(celoEnv: string) {
}

async function helmParameters(celoEnv: string) {
const bucketName = isProduction(celoEnv) ? 'contract_artifacts_production' : 'contract_artifacts'
const productionTagOverrides = isProduction(celoEnv)
const bucketName = isProduction() ? 'contract_artifacts_production' : 'contract_artifacts'
const productionTagOverrides = isProduction()
? [
`--set gethexporter.image.repository=${fetchEnv('GETH_EXPORTER_DOCKER_IMAGE_REPOSITORY')}`,
`--set gethexporter.image.tag=${fetchEnv('GETH_EXPORTER_DOCKER_IMAGE_TAG')}`,
Expand Down