Skip to content

Commit

Permalink
Add tests for auto-compound
Browse files Browse the repository at this point in the history
  • Loading branch information
imstar15 committed Nov 25, 2023
1 parent 42a4a70 commit 053aaa3
Show file tree
Hide file tree
Showing 4 changed files with 695 additions and 1,765 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"clean": "npm exec -- tsc --build --clean tsconfig.build.json",
"test": "npm run build && jest --verbose --forceExit --runInBand ./test/functional",
"test:sdk": "npm run build && jest --verbose --runInBand ./test/sdk",
"test:compound": "npm run build && jest --verbose --runInBand ./test/compound",
"changeset": "changeset",
"lint": "eslint . --ext .ts",
"prepare": "husky install"
Expand All @@ -35,7 +36,7 @@
"eslint-plugin-jest": "^27.4.0",
"eslint-plugin-prettier": "^5.0.0",
"husky": "^8.0.3",
"jest": "26.6.3",
"jest": "29.7.0",
"lint-staged": "^14.0.1",
"prettier": "^3.0.3",
"ts-node": "^10.9.1",
Expand Down
94 changes: 60 additions & 34 deletions packages/adapter/src/chains/oak.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,26 @@ export class OakAdapter extends ChainAdapter {
return getDerivativeAccountV2(api, accountId, paraId, accountOptions);
}

// Get delegator state
/**
* Ensure balance enough
* @param account
* @param amount
*/
async ensureBalance(account: HexString, amount: BN): Promise<void> {
const api = this.getApi();
const balanceCodec = await api.query.system.account(account);
const balance = balanceCodec as unknown as any;
const freeBalance = balance.data.free.sub(balance.data.frozen);
if (freeBalance.lt(amount)) {
throw new Error("Balance is not enough");
}
}

/**
* Get delegator state
* @param delegator
* @returns
*/
async getDelegatorState(delegator: HexString): Promise<any> {
const api = this.getApi();
const delegatorStateCodec =
Expand Down Expand Up @@ -266,7 +285,7 @@ export class OakAdapter extends ChainAdapter {
* Delegate to collator with auto-compounding
* @param collator
* @param amount
* @param percentage
* @param percentage, an integer between 0 and 100
* @param keyringPair
* @returns
*/
Expand All @@ -277,23 +296,24 @@ export class OakAdapter extends ChainAdapter {
keyringPair: KeyringPair,
): Promise<SendExtrinsicResult> {
const api = this.getApi();
this.ensureBalance(u8aToHex(keyringPair.addressRaw), amount);
// Check if delegation exists
const delegatorWalletAddress = u8aToHex(keyringPair.addressRaw);
const delegatorState = await this.getDelegatorState(delegatorWalletAddress);
if (_.isUndefined(delegatorState)) {
throw new Error("Delegator state not found");
}
const { delegations } = delegatorState;
const foundDelegation = _.find(
delegations,
({ owner }) => owner.toHex() === collator,
);
const { length: delegationsLength } = delegations;
if (!_.isUndefined(foundDelegation)) {
throw new Error("Delegation already exists");
let delegationsLength = 0;
if (!_.isUndefined(delegatorState)) {
const { delegations } = delegatorState;
const foundDelegation = _.find(
delegations,
({ owner }) => owner.toHex() === collator,
);
delegationsLength = delegations.length;
if (!_.isUndefined(foundDelegation)) {
throw new Error("Delegation already exists");
}
}

const { minDelegationCodec } = api.consts.parachainStaking;
const { minDelegation: minDelegationCodec } = api.consts.parachainStaking;
const minDelegation = minDelegationCodec as u128;
if (amount.lt(minDelegation)) {
throw new Error(
Expand All @@ -304,14 +324,14 @@ export class OakAdapter extends ChainAdapter {
const candidateInfoCodec =
await api.query.parachainStaking.candidateInfo(collator);
const candidateInfo = candidateInfoCodec as unknown as Option<any>;
if (candidateInfo.isSome) {
if (candidateInfo.isNone) {
throw new Error("Candidate info not found");
}
const { delegationCount: candidateDelegationCount } =
candidateInfo.unwrap();

const autoCompoundingDelegationsLength =
this.getAutoCompoundingDelegationsLength(collator);
await this.getAutoCompoundingDelegationsLength(collator);

// Delegate to collator
const delegateExtrinsic = api.tx.parachainStaking.delegateWithAutoCompound(
Expand All @@ -334,22 +354,25 @@ export class OakAdapter extends ChainAdapter {
* @returns
*/
async getAutoCompoundingDelegationPercentage(
delegator: HexString,
collator: HexString,
delegator: HexString,
): Promise<number> {
const api = this.getApi();
const autoCompoundingDelegationsCodec =
await api.query.parachainStaking.autoCompoundingDelegations(collator);
const autoCompoundingDelegations =
autoCompoundingDelegationsCodec as unknown as Option<any>;
const delegation = _.find(autoCompoundingDelegations, { delegator });
return _.isUndefined(delegation) ? 0 : delegation.percentage.toNumber();
autoCompoundingDelegationsCodec as unknown as any[];
const delegation = _.find(
autoCompoundingDelegations,
(item) => item.delegator.toHex() === delegator,
);
return _.isUndefined(delegation) ? 0 : delegation.value.toNumber();
}

/**
* Set auto-compounding delegation percentage
* @param collator
* @param percentage
* @param percentage, an integer between 0 and 100
* @param keyringPair
* @returns
*/
Expand All @@ -359,10 +382,24 @@ export class OakAdapter extends ChainAdapter {
keyringPair: KeyringPair,
): Promise<SendExtrinsicResult> {
const api = this.getApi();
// const delegatorWalletAddress = u8aToHex(keyringPair.addressRaw);

const autoCompoundingDelegationsLength =
await this.getAutoCompoundingDelegationsLength(collator);

const delegatorState = await this.getDelegatorState(
u8aToHex(keyringPair.addressRaw),
);
if (_.isUndefined(delegatorState)) {
throw new Error("Delegator state not found");
}
const { delegations } = delegatorState;
const { length: delegationsLength } = delegations;

const setAutoCompoundExtrinsic = api.tx.parachainStaking.setAutoCompound(
collator,
percentage,
autoCompoundingDelegationsLength + 1,
delegationsLength + 1,
);
const result = await sendExtrinsic(
api,
Expand All @@ -386,22 +423,11 @@ export class OakAdapter extends ChainAdapter {
): Promise<SendExtrinsicResult> {
const api = this.getApi();

const autoCompoundingDelegationsLength =
await this.getAutoCompoundingDelegationsLength(collator);

const delegatorState = await this.getDelegatorState(collator);
if (_.isUndefined(delegatorState)) {
throw new Error("Delegator state not found");
}
const { delegations } = delegatorState;
const { length: delegationsLength } = delegations;

this.ensureBalance(u8aToHex(keyringPair.addressRaw), amount);
// Create bondMoreExtrinsic
const bondMoreExtrinsic = api.tx.parachainStaking.delegatorBondMore(
collator,
amount,
autoCompoundingDelegationsLength + 1,
delegationsLength + 1,
);

const result = await sendExtrinsic(api, bondMoreExtrinsic, keyringPair);
Expand Down
140 changes: 140 additions & 0 deletions test/compound/compound.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// import _ from "lodash";
import BN from "bn.js";
import { u8aToHex } from "@polkadot/util";
import { ApiPromise, WsProvider } from "@polkadot/api";
import type { KeyringPair } from "@polkadot/keyring/types";
import { chains } from "@oak-network/config";
import { OakAdapter } from "@oak-network/adapter";
import { rpc, types, runtime } from "@oak-network/types";
import {
DEFAULT_TIMEOUT_INITIALIZE,
DEFAULT_TIMEOUT_PER_TEST,
} from "../utils/constants";
import { getKeyringPair } from "../utils/helpFn";

describe("test-compound", () => {
let keyringPair: KeyringPair | undefined;
let turingApi: ApiPromise | undefined;
let turingAdapter: OakAdapter | undefined;
beforeAll(async () => {
// Create keyringPair
keyringPair = await getKeyringPair();
const {
DevChains: { turingLocal: turingConfig },
} = chains;
console.log("turingConfig.endpoint: ", turingConfig.endpoint);

// Initialize adapters
turingApi = await ApiPromise.create({
provider: new WsProvider(turingConfig.endpoint),
rpc,
runtime,
types,
});
turingAdapter = new OakAdapter(turingApi, turingConfig);
await turingAdapter.initialize();
}, DEFAULT_TIMEOUT_INITIALIZE);

afterAll(async () => {
await turingApi?.disconnect();
});

it("get-auto-compounding-delegation-percentage", async () => {
expect(turingApi).toBeDefined();
expect(keyringPair).toBeDefined();
const pools = await turingApi.query.parachainStaking.candidatePool();
const collatorWalletAddress = pools[0].owner.toHex();
const result = await turingAdapter?.getAutoCompoundingDelegationPercentage(
collatorWalletAddress,
u8aToHex(keyringPair?.addressRaw),
);
console.log(result);
expect(result).toBeDefined();
});

it("get-delegation", async () => {
expect(turingApi).toBeDefined();
expect(keyringPair).toBeDefined();
const pools = await turingApi.query.parachainStaking.candidatePool();
const collatorWalletAddress = pools[0].owner.toHex();
const result = await turingAdapter?.getDelegation(
u8aToHex(keyringPair?.addressRaw),
collatorWalletAddress,
);
expect(result).toBeDefined();
});

it(
"delegate-with-auto-compound",
async () => {
expect(turingApi).toBeDefined();
expect(keyringPair).toBeDefined();
const pools = await turingApi.query.parachainStaking.candidatePool();
const collatorWalletAddress = pools[0].owner.toHex();
const { minDelegation } = turingApi.consts.parachainStaking;
const result = await turingAdapter?.delegateWithAutoCompound(
collatorWalletAddress,
minDelegation,
50,
keyringPair,
);
expect(result).toBeDefined();
},
DEFAULT_TIMEOUT_PER_TEST,
);

it(
"set-auto-compound",
async () => {
expect(turingApi).toBeDefined();
expect(keyringPair).toBeDefined();
const pools = await turingApi.query.parachainStaking.candidatePool();
const collatorWalletAddress = pools[0].owner.toHex();
const result = await turingAdapter?.setAutoCompound(
collatorWalletAddress,
70,
keyringPair,
);
expect(result).toBeDefined();
},
DEFAULT_TIMEOUT_PER_TEST,
);

it(
"bond-more",
async () => {
expect(turingApi).toBeDefined();
expect(keyringPair).toBeDefined();
const pools = await turingApi.query.parachainStaking.candidatePool();
const collatorWalletAddress = pools[0].owner.toHex();
const result = await turingAdapter?.bondMore(
collatorWalletAddress,
new BN("10000000000"),
keyringPair,
);
expect(result).toBeDefined();
},
DEFAULT_TIMEOUT_PER_TEST,
);

it(
"ensure-balance",
async () => {
expect(turingApi).toBeDefined();
expect(keyringPair).toBeDefined();
// const pools = await turingApi.query.parachainStaking.candidatePool();
// const collatorWalletAddress = pools[0].owner.toHex();
// const result = await turingAdapter?.bondMore(
// collatorWalletAddress,
// new BN("10000000000"),
// keyringPair,
// );
// expect(result).toBeDefined();
await turingAdapter?.ensureBalance(
u8aToHex(keyringPair?.addressRaw),
new BN("10000000000"),
);
},
DEFAULT_TIMEOUT_PER_TEST,
);
});
Loading

0 comments on commit 053aaa3

Please sign in to comment.