Skip to content

Commit

Permalink
Add makeRawTransaction() for DeployLink, fix WrappedCommand, formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
reductionista committed Feb 16, 2022
1 parent f97ec19 commit f7891ab
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 84 deletions.
30 changes: 16 additions & 14 deletions packages-ts/gauntlet-terra-contracts/src/commands/abstract/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Result } from '@chainlink/gauntlet-core'
import { logger, prompt } from '@chainlink/gauntlet-core/dist/utils'
import { TransactionResponse, TerraCommand } from '@chainlink/gauntlet-terra'
import { TransactionResponse, TerraCommand, RawTransaction } from '@chainlink/gauntlet-terra'
import { Contract, CONTRACT_LIST, getContract, TerraABI, TERRA_OPERATIONS } from '../../lib/contracts'
import { DEFAULT_RELEASE_VERSION } from '../../lib/constants'
import schema from '../../lib/schema'
Expand Down Expand Up @@ -185,28 +185,30 @@ export default class AbstractCommand extends TerraCommand {
}

// create and sign transaction, without executing
makeRawTransaction = async () => {
makeRawTransaction = async (): Promise<RawTransaction> => {
const operations = {
[TERRA_OPERATIONS.DEPLOY]: this.abstractPrepareDeploy,
[TERRA_OPERATIONS.EXECUTE]: this.abstractPrepareCall,
[TERRA_OPERATIONS.QUERY]: () => { throw Error("makeRawTransaction: cannot make a tx from a query commmand") },
[TERRA_OPERATIONS.QUERY]: () => {
throw Error('makeRawTransaction: cannot make a tx from a query commmand')
},
// TODO: [TERRA_OPERATIONS.UPLOAD]: this.abstractPrepareUpload,
}

return await operations[this.opts.action](this.params, this.args[0])
}
}

abstractPrepareDeploy = async(params:any) => {
const codeId = this.codeIds[this.opts.contract.id]
this.require(!!codeId, `Code Id for contract ${this.opts.contract.id} not found`)
return await this.prepareDeploy(codeId, params)
}
abstractPrepareDeploy = async (params: any) => {
const codeId = this.codeIds[this.opts.contract.id]
this.require(!!codeId, `Code Id for contract ${this.opts.contract.id} not found`)
return await this.prepareDeploy(codeId, params)
}

abstractPrepareCall = async(params:any, address:string) => {
return await this.prepareCall(address, {
[this.opts.function]: params,
})
}
abstractPrepareCall = async (params: any, address: string) => {
return await this.prepareCall(address, {
[this.opts.function]: params,
})
}

execute = async () => {
const operations = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
import { TerraCommand, TransactionResponse } from '@chainlink/gauntlet-terra'
import { MultisigTerraCommand } from '../contracts/multisig'
import { Result, Command } from '@chainlink/gauntlet-core'
import { logger } from '@chainlink/gauntlet-core/dist/utils'
import DeployLink from '../../commands/contracts/link/deploy'
import AbstractCommand from '.'
import { makeAbstractCommand } from '.'

class EmptyCommand extends Command {
constructor() {
super({help : false}, [])
}
constructor() {
super({ help: false }, [])
}
}

export default (commands: any[], slug: string) : Command => {
type ICommandConstructor = (flags: any, args: string[]) => void

export default (commands: any, slug: string): Command => {
const slugs: string[] = slug.split(':')
if (slugs.length < 3) {
throw Error(`Command ${slugs.join(':')} not found`)
throw Error(`Command ${slug} not found`)
}
const op: string = slugs.pop()!
const command: any = commands[slugs.join()]
if (!!command) throw Error(`Command ${slugs.join(':')} not found`)
const instruction = slugs.join(':')

const commandType = commands[instruction] ? commands[instruction] : AbstractCommand

switch (op) {
case 'multisig':
Expand All @@ -24,25 +31,34 @@ export default (commands: any[], slug: string) : Command => {
case 'execute':
case 'approve': // vote yes, then execute if threshold is reached
class WrappedCommand extends MultisigTerraCommand {
static id = slugs.join()
static id = instruction
static commandType = commandType

constructor(flags, args) {
super(flags, args)
super(flags, args)
if (commandType === AbstractCommand) {
throw Error(`Command ${instruction} not found`)
// TODO: get this working for abstract commands. Something like:
// this.command = await makeAbstractCommand(instruction, flags, args)
} else {
this.command = new commandType(flags, args)
}
}

multisigOp = () => {
return op
}
commandType = () => {
return command
}
}

let cmd = new EmptyCommand()
let wc = Object.setPrototypeOf(WrappedCommand, EmptyCommand.prototype)
wc = Object.assign(wc, cmd)
return wc
// This is a temporary workaround for a bug in the type specification for findPolymorphic in @gauntlet-core.
// At runtime, it's used as a constructor. It must be callable and able to construct an actual command object
// when passed flags & args, (ie, it should be a class). But it's declared as if it were an instance of a type
// satisfying ICommand, which will cause typescript to reject it during compilation if it's a class satisfying
// the ICommand interface. The only way to satisfy both constraints is for it to look like an instance at compile
// time, and a class at runtime. The workaround is to return something that is both at once: add all properties
// of an instance of EmtpyCommand to the class WrappedCommand and return the resulting hybrid.
return Object.assign(WrappedCommand, new EmptyCommand())
default:
throw Error(`Command ${slugs.join(':')} not found`)
throw Error(`Command ${slugs.join(':')} not found`)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TerraCommand, TransactionResponse } from '@chainlink/gauntlet-terra'
import { TerraCommand, TransactionResponse, RawTransaction } from '@chainlink/gauntlet-terra'
import { Result } from '@chainlink/gauntlet-core'
import { logger, prompt } from '@chainlink/gauntlet-core/dist/utils'
import { CATEGORIES, CW20_BASE_CODE_IDs } from '../../../lib/constants'
Expand All @@ -19,9 +19,8 @@ export default class DeployLink extends TerraCommand {
super(flags, args)
}

execute = async () => {
await prompt(`Begin deploying LINK Token?`)
const deploy = await this.deploy(CW20_BASE_CODE_IDs[this.flags.network], {
genParams = () => {
return {
name: 'ChainLink Token',
symbol: 'LINK',
decimals: 18,
Expand All @@ -36,7 +35,18 @@ export default class DeployLink extends TerraCommand {
mint: {
minter: this.wallet.key.accAddress,
},
})
}
}

makeRawTransaction = async (): Promise<RawTransaction> => {
const codeId = CW20_BASE_CODE_IDs[this.flags.network]
this.require(!!codeId, `Code Id for link token contract not found`)
return await this.prepareDeploy(CW20_BASE_CODE_IDs[this.flags.network], this.genParams())
}

execute = async () => {
await prompt(`Begin deploying LINK Token?`)
const deploy = await this.deploy(CW20_BASE_CODE_IDs[this.flags.network], this.genParams())
const result = await this.provider.wasm.contractQuery(deploy.address!, { token_info: {} })
logger.success(`LINK token successfully deployed at ${deploy.address} (txhash: ${deploy.hash})`)
logger.debug(result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,59 @@
// abort a proposal early (before it expires), disallowing any further voting on it.

import { logger, prompt } from '@chainlink/gauntlet-core/dist/utils'
import { Result } from '@chainlink/gauntlet-core'
import { Result, ICommand } from '@chainlink/gauntlet-core'
import { TerraCommand, RawTransaction, TransactionResponse } from '@chainlink/gauntlet-terra'
import { CATEGORIES } from '../../../lib/constants'
import { CONTRACT_LIST, Contract, getContract, TERRA_OPERATIONS } from '../../../lib/contracts'
import AbstractCommand from '../../abstract'

type ProposalContext = {
rawTx: RawTransaction,
multisigSigner: string,
proposalState: any,
type ProposalContext = {
rawTx: RawTransaction
multisigSigner: string
proposalState: any
}

type StringGetter = () => string
export type ICommandConstructor = (flags: any, args: string[]) => void

abstract class MultisigTerraCommand extends TerraCommand {
static category = CATEGORIES.MULTISIG
abstract class MultisigTerraCommand extends TerraCommand {
static category = CATEGORIES.MULTISIG

commandType: typeof TerraCommand
multisigOp: StringGetter

command: TerraCommand
multisigAddress: string
multisigContract: Promise<Contract>

constructor(flags, args) {
super(flags, args)
}

postConstructor(flags, args) {
// Called after child constructor
logger.debug(`Running ${this.commandType} in multisig mode`)

commandType:any
multisigOp:StringGetter

command:AbstractCommand
multisigAddress:string
multisigContract: Promise<Contract>

constructor(flags, args) {
super(flags, args)

logger.info(`Running ${this.commandType()} in multisig mode`)
this.command = new this.commandType()(flags, args)
this.command.invokeMiddlewares(this.command, this.command.middlewares)
this.require(!!process.env.MULTISIG_ADDRESS, 'Please set MULTISIG_ADDRESS env var')
this.multisigContract = getContract(CONTRACT_LIST.MULTISIG, flags.version)
this.multisigAddress = process.env.MULTISIG_ADDRESS!
}

execute = async (): Promise<Result<TransactionResponse>> => {
const tx = this.command.makeRawTransaction()
console.debug(tx)

return {
responses: [],
} as Result<TransactionResponse>
}
this.command.invokeMiddlewares(this.command, this.command.middlewares)
this.require(!!process.env.MULTISIG_WALLET, 'Please set MULTISIG_WALLET env var')
this.multisigContract = getContract(CONTRACT_LIST.MULTISIG, flags.version)
this.multisigAddress = process.env.MULTISIG_WALLET!
}

execute = async (): Promise<Result<TransactionResponse>> => {
const tx = this.command.makeRawTransaction()
console.debug(tx)

return {
responses: [],
} as Result<TransactionResponse>
}
}

export const wrapCommand = (command) => {
return class CustomCommand extends MultisigTerraCommand {
static id = `${command.id}:multisig`
static category = CATEGORIES.MULTISIG
return class CustomCommand extends MultisigTerraCommand {
static id = `${command.id}:multisig`
static category = CATEGORIES.MULTISIG
}
}

Expand Down
12 changes: 0 additions & 12 deletions packages-ts/gauntlet-terra-contracts/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,3 @@ export const CW20_BASE_CODE_IDs = {
local: 32,
'bombay-testnet': 148,
}

export const CW4_GROUP_CODE_IDs = {
mainnet: -1,
local: -1,
'bombay-testnet': 36895,
}

export const CW3_FLEX_MULTISIG_CODE_IDs = {
mainnet: -1,
local: -1,
'bombay-testnet': 36059,
}
5 changes: 5 additions & 0 deletions packages-ts/gauntlet-terra/src/commands/internal/terra.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Result, WriteCommand } from '@chainlink/gauntlet-core'
import { RawTransaction } from '../types'
import { logger } from '@chainlink/gauntlet-core/dist/utils'
import { EventsByType, MsgStoreCode, TxLog } from '@terra-money/terra.js'
import { SignMode } from '@terra-money/terra.proto/cosmos/tx/signing/v1beta1/signing'
Expand Down Expand Up @@ -29,6 +30,10 @@ export default abstract class TerraCommand extends WriteCommand<TransactionRespo
this.use(withNetwork, withProvider, withWallet, withCodeIds)
}

makeRawTransaction = async (): Promise<RawTransaction> => {
throw Error('makeRawTransaction: not implemented!')
}

parseResponseValue(receipt: any, eventType: string, attributeType: string) {
try {
const parsed = JSON.parse(receipt?.raw_log)
Expand Down

0 comments on commit f7891ab

Please sign in to comment.