Skip to content

Commit

Permalink
Implement Cradle testing scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDeeKay committed Mar 19, 2024
1 parent dc019f2 commit 626707f
Show file tree
Hide file tree
Showing 29 changed files with 165,171 additions and 117 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"author": "Terra Money <[email protected]>",
"type": "module",
"workspaces": [
"contracts"
"contracts",
"tests-cradle"
],
"scripts": {
"deploy:enterprise-factory": "TERRARIUMS_ARCH_ARM64=true yarn terrariums run tasks/deploy_enterprise_factory.ts --network testnet --signer pisco",
Expand All @@ -24,7 +25,8 @@
"warp:migration-jobs:mainnet": "yarn terrariums run tasks/warp_migration_jobs.ts --network mainnet --signer phoenix",
"docker:enterprise-api": "docker build . -f apps/enterprise-api/Dockerfile -t payments/api",
"docker:enterprise-indexers": "docker build . -f indexers/enterprise/Dockerfile -t payments/indexers",
"postinstall": "husky install"
"postinstall": "husky install",
"tests-cradle": "yarn workspace tests-cradle start"
},
"dependencies": {
"@terra-money/terrariums": "file:../terrariums",
Expand Down
5 changes: 5 additions & 0 deletions tests-cradle/.env_template
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
NETWORK=mainnet
LCD_ENDPOINT=<your Cradle endpoint>
JWT_TOKEN=<your Cradle JWT>
CHAIN_ID=phoenix-1
MNEMONIC_KEY=<your mnemonic>
157,305 changes: 157,305 additions & 0 deletions tests-cradle/dist/main.js

Large diffs are not rendered by default.

61 changes: 61 additions & 0 deletions tests-cradle/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"name": "tests-cradle",
"version": "0.1.36",
"private": true,
"description": "A suite of tests that interact with a fork of mainnet (Cradle).",
"license": "ISC",
"author": "Terra Money <[email protected]>",
"main": "dist/index.js",
"scripts": {
"start": "yarn cradle",
"cradle": "esbuild src/main.ts --bundle --platform=node --outdir=dist --outbase=src && node ./dist/main.js"
},
"lint-staged": {
"./src/{**/*,*}.{ts,tsx}": [
"prettier --write"
]
},
"generate-types": {
"contracts": [
"warp-controller",
"warp-account",
"warp-resolver",
"warp-templates"
],
"output": "src/types/contracts"
},
"dependencies": {
"@cosmjs/cosmwasm-stargate": "0.32.1",
"@cosmjs/stargate": "0.32.1",
"@terra-money/feather.js": "2.0.0",
"@types/node": "^16.11.56",
"axios": "^1.1.2",
"big.js": "^6.2.1",
"chain-registry": "1.20.0",
"cosmjs-utils": "0.1.0",
"date-fns": "^2.29.3",
"dotenv": "^16.0.1",
"jsonpath": "^1.1.1",
"jsonpath-plus": "^7.2.0",
"lodash": "^4.17.21",
"pino": "^8.4.2",
"typescript": "^4.8.2"
},
"devDependencies": {
"@chialab/esbuild-plugin-require-resolve": "^0.17.1",
"@types/big.js": "^6.1.6",
"@types/jest": "^29.5.1",
"@types/lodash": "^4.14.191",
"esbuild": "^0.14.54",
"esbuild-node-externals": "^1.6.0",
"husky": "^8.0.2",
"jest": "^29.5.0",
"json-schema-to-typescript": "^11.0.2",
"lint-staged": "^13.0.4",
"pinst": "^3.0.0",
"prettier": "^2.8.0",
"ts-jest": "^29.1.0",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.1.0"
}
}
Empty file added tests-cradle/src/claims.ts
Empty file.
54 changes: 54 additions & 0 deletions tests-cradle/src/council.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {LCDClient} from "@terra-money/feather.js";
import {DaoContracts} from "./main";
import {queryGovConfig} from "./gov_controller_utils";


export type DaoCouncilMembers = {
members: string[],
}

interface CouncilMembersResponse {
members: CouncilMember[]
}

interface CouncilMember {
user: string,
weight: string,
}

export const queryDaoCouncil = async (lcd: LCDClient, dao: DaoContracts): Promise<DaoCouncilMembers> => {
let response: CouncilMembersResponse;
let startAfter: string | null = null;

let members: string[] = [];

do {
response = await lcd.wasm.contractQuery<CouncilMembersResponse>(dao.council_membership_contract, {
members: {
start_after: startAfter,
limit: 100,
}
});
if (response.members.length > 0) {
startAfter = response.members[response.members.length - 1].user;
}

members = [...members, ...response.members.map((member) => member.user)];
} while (response.members.length > 0)

return {
members
}
}

export const hasDaoCouncil = async (lcd: LCDClient, dao: DaoContracts): Promise<boolean> => {
const govConfig = await queryGovConfig(lcd, dao);

if (govConfig.council_gov_config === undefined) {
return true;
}

const council = await queryDaoCouncil(lcd, dao);

return council.members.length > 0
}
22 changes: 22 additions & 0 deletions tests-cradle/src/cradle_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {env} from "process";

export const advanceTimeBy = async (millis: number) => {
console.log(`Advancing chain time by ${millis} milliseconds.`)

const endpoint = env.LCD_ENDPOINT + '/next';

const headers = {
'Authorization': `Bearer ${env.JWT_TOKEN}`,
'Content-Type': 'application/json'
};

const options = {
method: 'POST',
headers: headers,
body: JSON.stringify({interval: millis})
};

await fetch(endpoint, options)
.then((response) => response.json())
.then(() => console.log(`Chain time successfully advanced.`));
}
15 changes: 15 additions & 0 deletions tests-cradle/src/cw20_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {LCDClient} from "@terra-money/feather.js";

interface BalanceResponse {
balance: string,
}

export const queryCw20Balance = async (lcd: LCDClient, cw20Contract: string, address: string): Promise<number> => {
const response = await lcd.wasm.contractQuery<BalanceResponse>(cw20Contract, {
balance: {
address: address,
}
});

return parseInt(response.balance, 10)
}
68 changes: 68 additions & 0 deletions tests-cradle/src/cw721_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import {LCDClient, MsgExecuteContract} from "@terra-money/feather.js";
import {ExecuteCtx, executeTx} from "./txUtils";

export interface TokensResponse {
tokens: string[]
}

export interface OwnerOfResponse {
owner: string,
}

export const queryOwnerOf = async (lcd: LCDClient, cw721Contract: string, token: string): Promise<string> => {
const response = await lcd.wasm.contractQuery<OwnerOfResponse>(cw721Contract, {
owner_of: {
token_id: token,
}
});

return response.owner
}

export const queryAllTokens = async (lcd: LCDClient, cw721Contract: string, startAfter: string | null = null, limit: number | null = null): Promise<TokensResponse> => {
return await lcd.wasm.contractQuery<TokensResponse>(cw721Contract, {
all_tokens: {
start_after: startAfter,
limit: limit ?? 100,
}
});
}

export const queryAllOwnerTokens = async (lcd: LCDClient, cw721Contract: string, owner: string): Promise<string[]> => {
let tokensOwned: string[] = [];

let response: TokensResponse;
let startAfter: string | null = null;
do {
response = await lcd.wasm.contractQuery<TokensResponse>(cw721Contract, {
tokens: {
owner,
start_after: startAfter,
limit: 100,
}
})

tokensOwned = [...tokensOwned, ...response.tokens];

if (response.tokens.length > 0) {
startAfter = response.tokens[response.tokens.length - 1]
}
} while (response.tokens.length > 0);

return tokensOwned
}

export const approveTokens = async (ctx: ExecuteCtx, cw721Contract: string, owner: string, tokens: string[], spender: string)=> {
const msgs = tokens.map((token) => new MsgExecuteContract(
owner,
cw721Contract,
{
approve: {
spender,
token_id: token,
}
}
));

await executeTx(ctx, msgs);
}
33 changes: 33 additions & 0 deletions tests-cradle/src/dao_queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// TODO: rename this file

import {LCDClient} from "@terra-money/feather.js";
import {DaoContracts} from "./main";
import {DaoInfoResponse} from "./types/enterprise";

export const queryDaoInfo = async (lcd: LCDClient, dao: DaoContracts): Promise<DaoInfoResponse> => {
return lcd.wasm.contractQuery<DaoInfoResponse>(dao.enterprise, {
dao_info: {}
});
}

export const isNotDaoContract = (dao: DaoContracts, address: string): boolean => {
return address !== dao.attestation_contract
&& address !== dao.council_membership_contract
&& address !== dao.enterprise_factory_contract
&& address !== dao.enterprise_governance_contract
&& address !== dao.enterprise_governance_controller_contract
&& address !== dao.enterprise_outposts_contract
&& address !== dao.enterprise_treasury_contract
&& address !== dao.funds_distributor_contract
&& address !== dao.membership_contract
}

export const isNotContract = async (lcd: LCDClient, address: string): Promise<boolean> => {
try {
await lcd.wasm.contractInfo(address);
return false
} catch (e) {
// TODO: what if it fails for other reasons?
return true
}
}
10 changes: 10 additions & 0 deletions tests-cradle/src/enterprise_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {LCDClient} from "@terra-money/feather.js";
import {ComponentContractsResponse} from "./types/enterprise";
import {DaoContracts} from "./main";

export const getDaoComponents = async (lcd: LCDClient, daoEnterprise: string): Promise<DaoContracts> => {
const componentContracts = await lcd.wasm.contractQuery<ComponentContractsResponse>(daoEnterprise, {
component_contracts: {}
});
return { ...componentContracts, enterprise: daoEnterprise }
}
9 changes: 9 additions & 0 deletions tests-cradle/src/gov_controller_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {DaoContracts} from "./main";
import {GovConfigResponse} from "./types/enterprise_governance_controller";
import {LCDClient} from "@terra-money/feather.js";

export const queryGovConfig = async (lcd: LCDClient, dao: DaoContracts): Promise<GovConfigResponse> => {
return lcd.wasm.contractQuery<GovConfigResponse>(dao.enterprise_governance_controller_contract, {
gov_config: {}
});
}
75 changes: 75 additions & 0 deletions tests-cradle/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
LCDClient,
LCDClientConfig,
MnemonicKey,
Wallet
} from '@terra-money/feather.js';
import dotenv from 'dotenv';
import {env} from 'process';
import {ComponentContractsResponse} from "./types/enterprise";
import {ExecuteCtx} from "./txUtils";
import {verifyUpgradeCorrectness} from "./tests";

dotenv.config();

export type DaoContracts = ComponentContractsResponse & { enterprise: string };

// TODO: move this somewhere else
const LION_DAO_ENTERPRISE: string = "terra1htmjh7ka8andv354m5j3kleffqpkcam6qhjty7ryanw6xgwnz5zs0ckd9u";
const PIXELIONS_DAO_ENTERPRISE: string = "terra1ruv2e3l32pwfmn8l2chay9njymaleccx9frgnkys4g6q7mkap8vs363z9e";

const mainnetConfig: Record<string, LCDClientConfig> = {
'phoenix-1': {
chainID: env.CHAIN_ID,
lcd: env.LCD_ENDPOINT,
gasAdjustment: 1.75,
gasPrices: {uluna: 0.15},
prefix: 'terra',
},
};

const lcd = new LCDClient(mainnetConfig);

const wallet = new Wallet(lcd, new MnemonicKey({mnemonic: env.MNEMONIC_KEY, coinType: 330}));

const ctx: ExecuteCtx = {
lcd,
wallet,
chainId: env.CHAIN_ID,
}

const run = async () => {

const newVersion = {
major: 1,
minor: 2,
patch: 0,
};

try {
for (const dao of [LION_DAO_ENTERPRISE, PIXELIONS_DAO_ENTERPRISE]) {
await verifyUpgradeCorrectness(
ctx,
dao,
newVersion,
[],
{
major: newVersion.major,
minor: newVersion.minor,
patch: newVersion.patch + 1,
},
{
major: newVersion.major,
minor: newVersion.minor,
patch: newVersion.patch + 2,
},
);
console.log('\n\n');
}
} catch (e) {
console.log(e);
throw e;
}
}

run();
Loading

0 comments on commit 626707f

Please sign in to comment.