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

feat: Automate deployments through tasks! #67

Merged
merged 9 commits into from
Jun 10, 2022
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ module.exports = {
'@typescript-eslint',
],
rules: {
'import/extensions': 0,
'import/no-unresolved': 0,
},
};
98 changes: 74 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,13 +328,63 @@ task(async ({ wallets, refs, config, client }) => {
});
```

As of Terrain 0.4.0 it is possible to deploy and instantiate contracts from tasks. This can be useful for multi-contract, or multi-stage deployments.

```js
const { task } = require("@terra-money/terrain");

task(async ({ wallets, client, deploy }) => {
// First deploy the counter smart contract.
const counterCodeId = await deploy.storeCode(wallets.test1, "counter");
const counterAddress = await deploy.instantiate(
// Signer
wallets.test1,
// Contract name
"counter",
// Code ID
counterCodeId,
// Instance ID
"default",
// Contract admin
wallets.test1.key.accAddress
);

// Now deploy a CW20 with the counter contract set as the minter in instantiation.
const cw20CodeId = await deploy.storeCode(wallets.test1, "cw20-base");
const cw20Address = await deploy.instantiate(
wallets.test1,
"cw20-base",
cw20CodeId,
"default",
wallets.test1.key.accAddress,
// Custom instantiation message.
// with no message provided the default from config.terrain will be used.
{
name: "counter",
symbol: "CTR",
decimals: 6,
initial_balances: [],
mint: {
minter: counterAddress,
},
}
);

// Update the CW20 address in counter.
// Note: It's important to use the address returned by deploy.instantiate
// Refs are only read into memory at the start of the task.
await client.execute(wallets.test1, counterAddress, {
update_token: { token: cw20Address },
});

console.log(`CW20 Address: ${cw20Address}`);
});
```
---

# Migrating CosmWasm Contracts on Terra

(Thanks to @octalmage)

On Terra, it is possible to initilize contracts as **_migratable_**. A migratable contract allows an adminstrator to upload a new version of a contract and then send a migrate message to move to the new code.
On Terra it is possible to initalize contracts as migratable. This functionallity allows the adminstrator to upload a new version of the contract, then send a migrate message to move to the new code.

<a href="https://docs.terra.money/docs/develop/dapp/quick-start/contract-migration.html" target="_blank">This tutorial</a> builds on top of the Terrain Quick Start Guide and walks you through a contract migration.

Expand Down Expand Up @@ -428,7 +478,7 @@ npm unlink terrain
<!-- commands -->
* [`terrain console`](#terrain-console)
* [`terrain contract:instantiate CONTRACT`](#terrain-contractinstantiate-contract)
* [`terrain contract:migrate [CONTRACT]`](#terrain-contractmigrate-contract)
* [`terrain contract:migrate CONTRACT`](#terrain-contractmigrate-contract)
* [`terrain contract:new NAME`](#terrain-contractnew-name)
* [`terrain contract:store CONTRACT`](#terrain-contractstore-contract)
* [`terrain contract:updateAdmin CONTRACT ADMIN`](#terrain-contractupdateadmin-contract-admin)
Expand Down Expand Up @@ -469,32 +519,32 @@ Instantiate the contract.

```
USAGE
$ terrain contract:instantiate [CONTRACT] --signer <value> [--network <value>] [--config-path <value>] [--refs-path
<value>] [--keys-path <value>] [--instance-id <value>] [--code-id <value>] [--set-signer-as-admin]
$ terrain contract:instantiate [CONTRACT] [--signer <value>] [--set-signer-as-admin] [--network <value>] [--config-path
<value>] [--refs-path <value>] [--keys-path <value>] [--instance-id <value>] [--code-id <value>]

FLAGS
--code-id=<value> target code id for migration, can do only once after columbus-5 upgrade
--code-id=<value> specfic codeId to instantiate
--config-path=<value> [default: ./config.terrain.json]
--instance-id=<value> [default: default]
--keys-path=<value> [default: ./keys.terrain.js]
--network=<value> [default: localterra]
--refs-path=<value> [default: ./refs.terrain.json]
--set-signer-as-admin
--signer=<value> (required)
--set-signer-as-admin set signer (deployer) as admin to allow migration.
--signer=<value> [default: test1]

DESCRIPTION
Instantiate the contract.
```

_See code: [src/commands/contract/instantiate.ts](https://github.com/terra-money/terrain/blob/v0.3.1/src/commands/contract/instantiate.ts)_

## `terrain contract:migrate [CONTRACT]`
## `terrain contract:migrate CONTRACT`

Migrate the contract.

```
USAGE
$ terrain contract:migrate [CONTRACT] --signer <value> [--no-rebuild] [--network <value>] [--config-path <value>]
$ terrain contract:migrate [CONTRACT] [--signer <value>] [--no-rebuild] [--network <value>] [--config-path <value>]
[--refs-path <value>] [--keys-path <value>] [--instance-id <value>] [--code-id <value>] [--arm64]

FLAGS
Expand All @@ -507,7 +557,7 @@ FLAGS
--network=<value> [default: localterra]
--no-rebuild deploy the wasm bytecode as is.
--refs-path=<value> [default: ./refs.terrain.json]
--signer=<value> (required)
--signer=<value> [default: test1]

DESCRIPTION
Migrate the contract.
Expand Down Expand Up @@ -547,17 +597,17 @@ Store code on chain.

```
USAGE
$ terrain contract:store [CONTRACT] --signer <value> [--no-rebuild] [--network <value>] [--config-path <value>]
$ terrain contract:store [CONTRACT] [--signer <value>] [--no-rebuild] [--network <value>] [--config-path <value>]
[--refs-path <value>] [--keys-path <value>] [--code-id <value>]

FLAGS
--code-id=<value>
--config-path=<value> [default: ./config.terrain.json]
--keys-path=<value> [default: ./keys.terrain.js]
--network=<value> [default: localterra]
--no-rebuild
--no-rebuild deploy the wasm bytecode as is.
--refs-path=<value> [default: ./refs.terrain.json]
--signer=<value> (required)
--signer=<value> [default: test1]

DESCRIPTION
Store code on chain.
Expand All @@ -571,7 +621,7 @@ Update the admin of a contract.

```
USAGE
$ terrain contract:updateAdmin [CONTRACT] [ADMIN] --signer <value> [--network <value>] [--config-path <value>]
$ terrain contract:updateAdmin [CONTRACT] [ADMIN] [--signer <value>] [--network <value>] [--config-path <value>]
[--refs-path <value>] [--keys-path <value>] [--instance-id <value>]

FLAGS
Expand All @@ -580,7 +630,7 @@ FLAGS
--keys-path=<value> [default: ./keys.terrain.js]
--network=<value> [default: localterra]
--refs-path=<value> [default: ./refs.terrain.json]
--signer=<value> (required)
--signer=<value> [default: test1]

DESCRIPTION
Update the admin of a contract.
Expand All @@ -594,23 +644,23 @@ Build wasm bytecode, store code on chain and instantiate.

```
USAGE
$ terrain deploy [CONTRACT] --signer <value> [--no-rebuild] [--network <value>] [--config-path <value>]
[--refs-path <value>] [--keys-path <value>] [--instance-id <value>] [--set-signer-as-admin] [--admin-address
<value>] [--frontend-refs-path <value>] [--arm64]
$ terrain deploy [CONTRACT] [--signer <value>] [--arm64] [--no-rebuild] [--set-signer-as-admin] [--network
<value>] [--config-path <value>] [--refs-path <value>] [--keys-path <value>] [--instance-id <value>]
[--admin-address <value>] [--frontend-refs-path <value>]

FLAGS
--admin-address=<value> set custom address as contract admin to allow migration.
--arm64 use rust-optimizer-arm64 for optimization. Not recommended for production, but it will
optimize quicker on arm64 hardware during development.
--config-path=<value> [default: ./config.terrain.json]
--frontend-refs-path=<value> [default: ./frontend/src/refs.terrain.json]
--instance-id=<value> [default: default]
--instance-id=<value> [default: default] enable management of multiple instances of the same contract
--keys-path=<value> [default: ./keys.terrain.js]
--network=<value> [default: localterra]
--no-rebuild deploy the wasm bytecode as is.
--refs-path=<value> [default: ./refs.terrain.json]
--set-signer-as-admin set signer (deployer) as admin to allow migration.
--signer=<value> (required)
--signer=<value> [default: test1]

DESCRIPTION
Build wasm bytecode, store code on chain and instantiate.
Expand Down Expand Up @@ -766,7 +816,7 @@ _See code: [src/commands/test/coverage.ts](https://github.com/terra-money/terrai

## `terrain wallet:new`

Generate a new wallet.
Generate a new wallet to use for signing contracts

```
USAGE
Expand All @@ -777,7 +827,7 @@ FLAGS
--outfile=<value> absolute path to store the mnemonic key to. If omitted, output to stdout

DESCRIPTION
Generate a new wallet.
Generate a new wallet to use for signing contracts
```

_See code: [src/commands/wallet/new.ts](https://github.com/terra-money/terrain/blob/v0.3.1/src/commands/wallet/new.ts)_
Expand Down
7 changes: 4 additions & 3 deletions src/commands/contract/instantiate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@ import { LCDClient } from '@terra-money/terra.js';
import { loadConfig, loadConnections, loadRefs } from '../../config';
import { instantiate } from '../../lib/deployment';
import { getSigner } from '../../lib/signer';
import * as flag from '../../lib/flag';

export default class ContractInstantiate extends Command {
static description = 'Instantiate the contract.';

static flags = {
signer: flag.signer,
'set-signer-as-admin': flag.setSignerAsAdmin,
network: flags.string({ default: 'localterra' }),
'config-path': flags.string({ default: './config.terrain.json' }),
'refs-path': flags.string({ default: './refs.terrain.json' }),
'keys-path': flags.string({ default: './keys.terrain.js' }),
'instance-id': flags.string({ default: 'default' }),
signer: flags.string({ required: true }),
'code-id': flags.integer({
description:
'target code id for migration, can do only once after columbus-5 upgrade',
'specfic codeId to instantiate',
}),
'set-signer-as-admin': flags.boolean({ default: false }),
};

static args = [{ name: 'contract', required: true }];
Expand Down
8 changes: 3 additions & 5 deletions src/commands/contract/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@ import { LCDClient } from '@terra-money/terra.js';
import { loadConfig, loadConnections } from '../../config';
import { migrate, storeCode } from '../../lib/deployment';
import { getSigner } from '../../lib/signer';
import * as flag from '../../lib/flag';

export default class ContractMigrate extends Command {
static description = 'Migrate the contract.';

static flags = {
'no-rebuild': flags.boolean({
description: 'deploy the wasm bytecode as is.',
default: false,
}),
signer: flag.signer,
'no-rebuild': flag.noRebuild,
network: flags.string({ default: 'localterra' }),
'config-path': flags.string({ default: './config.terrain.json' }),
'refs-path': flags.string({ default: './refs.terrain.json' }),
'keys-path': flags.string({ default: './keys.terrain.js' }),
'instance-id': flags.string({ default: 'default' }),
signer: flags.string({ required: true }),
'code-id': flags.integer({
description:
'target code id for migration',
Expand Down
5 changes: 3 additions & 2 deletions src/commands/contract/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ import { LCDClient } from '@terra-money/terra.js';
import { loadConfig, loadConnections } from '../../config';
import { storeCode } from '../../lib/deployment';
import { getSigner } from '../../lib/signer';
import * as flag from '../../lib/flag';

export default class CodeStore extends Command {
static description = 'Store code on chain.';

static flags = {
'no-rebuild': flags.boolean({ default: false }),
signer: flag.signer,
'no-rebuild': flag.noRebuild,
network: flags.string({ default: 'localterra' }),
'config-path': flags.string({ default: './config.terrain.json' }),
'refs-path': flags.string({ default: './refs.terrain.json' }),
'keys-path': flags.string({ default: './keys.terrain.js' }),
'code-id': flags.integer({}),
signer: flags.string({ required: true }),
};

static args = [{ name: 'contract', required: true }];
Expand Down
3 changes: 2 additions & 1 deletion src/commands/contract/updateAdmin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ import { LCDClient, MsgUpdateContractAdmin } from "@terra-money/terra.js";
import { cli } from "cli-ux";
import { loadConnections, loadRefs } from "../../config";
import { getSigner } from "../../lib/signer";
import * as flag from '../../lib/flag';
import { waitForInclusionInBlock } from '../../lib/waitForInclusionBlock';


export default class ContractUpdateAdmin extends Command {
static description = "Update the admin of a contract.";

static flags = {
signer: flag.signer,
network: flags.string({ default: "localterra" }),
"config-path": flags.string({ default: "./config.terrain.json" }),
"refs-path": flags.string({ default: "./refs.terrain.json" }),
"keys-path": flags.string({ default: "./keys.terrain.js" }),
"instance-id": flags.string({ default: "default" }),
signer: flags.string({ required: true }),
};

static args = [
Expand Down
20 changes: 6 additions & 14 deletions src/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,27 @@ import * as fs from 'fs';
import { loadConfig, loadConnections } from '../config';
import { instantiate, storeCode } from '../lib/deployment';
import { getSigner } from '../lib/signer';
import * as flag from '../lib/flag';

export default class Deploy extends Command {
static description = 'Build wasm bytecode, store code on chain and instantiate.';

static flags = {
'no-rebuild': flags.boolean({
description: 'deploy the wasm bytecode as is.',
default: false,
}),
signer: flag.signer,
arm64: flag.arm64,
'no-rebuild': flag.noRebuild,
'set-signer-as-admin': flag.setSignerAsAdmin,
network: flags.string({ default: 'localterra' }),
'config-path': flags.string({ default: './config.terrain.json' }),
'refs-path': flags.string({ default: './refs.terrain.json' }),
'keys-path': flags.string({ default: './keys.terrain.js' }),
'instance-id': flags.string({ default: 'default' }),
signer: flags.string({ required: true }),
'set-signer-as-admin': flags.boolean({
description: 'set signer (deployer) as admin to allow migration.',
default: false,
}),
'instance-id': flag.instanceId,
'admin-address': flags.string({
description: 'set custom address as contract admin to allow migration.',
}),
'frontend-refs-path': flags.string({
default: './frontend/src/refs.terrain.json',
}),
arm64: flags.boolean({
description: 'use rust-optimizer-arm64 for optimization. Not recommended for production, but it will optimize quicker on arm64 hardware during development.',
default: false,
}),
};

static args = [{ name: 'contract', required: true }];
Expand Down
1 change: 0 additions & 1 deletion src/commands/task/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ export default class Run extends Command {
}
}


function runScript(
scriptPath: string,
env: {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/wallet/new.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MnemonicKey } from '@terra-money/terra.js';
import * as fs from 'fs';

export default class WalletNew extends Command {
static description = 'Generate a new wallet.';
static description = 'Generate a new wallet to use for signing contracts';

static flags = {
outfile: flags.string({
Expand Down
16 changes: 13 additions & 3 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,21 @@ type Fee = {
amount: { [coin: string]: number };
};

export type InstantiateMessage = Record<string, any>;

export type ContractConfig = {
store: { fee: Fee };
// TODO: Remove since fee in config is deprecated.
octalmage marked this conversation as resolved.
Show resolved Hide resolved
/**
* @deprecated The property should not be used
*/
store?: { fee: Fee };
instantiation: {
fee: Fee;
instantiateMsg: Record<string, any>;
// TODO: Remove since fee in config is deprecated.
/**
* @deprecated The property should not be used
*/
fee?: Fee;
instantiateMsg: InstantiateMessage;
};
};

Expand Down
Loading