Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
c4a68d2
chore: bump the SDK to 31.0.0-beta.7 and drop chain v7 support
prashantasdeveloper Aug 14, 2026
f863b76
fix: align the staking tests with the v8 bonding model
prashantasdeveloper Aug 14, 2026
facc891
test: add coverage for the ticker registration config getter
prashantasdeveloper Aug 14, 2026
e0c412d
test: add coverage for funding round issuance
prashantasdeveloper Aug 14, 2026
51c8b7a
test: add coverage for the v8 POLYX balance breakdown
prashantasdeveloper Aug 14, 2026
a09dc2f
test: add coverage for v8 protocol fees
prashantasdeveloper Aug 14, 2026
13d0f97
test: add coverage for the rebuilt transaction groups
prashantasdeveloper Aug 14, 2026
e6a8348
test: add coverage for portfolio level asset pre-approval
prashantasdeveloper Aug 14, 2026
28a2e40
test: add coverage for registrar gated DID registration
prashantasdeveloper Aug 14, 2026
0f48658
test: add coverage for the realigned transfer errors
prashantasdeveloper Aug 14, 2026
6bbd894
test: add coverage for the transferFunds instruction result
prashantasdeveloper Aug 14, 2026
81b80f9
test: add coverage for the mediator lock and unlock cycle
prashantasdeveloper Aug 14, 2026
71be7c2
test: add coverage for the aggregated next checkpoint getter
prashantasdeveloper Aug 14, 2026
d4c5e95
test: add coverage for corporate action documents
prashantasdeveloper Aug 14, 2026
950d77a
fix: bump the SDK to 31.0.0-beta.8 and flip the two pinned defects
prashantasdeveloper Aug 14, 2026
6326a7c
chore: move off the beta tag to the stable SDK 31.0.0 release
prashantasdeveloper Aug 17, 2026
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
2 changes: 2 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ yarn test:stop:evm # stops and removes env started with --profile evm
## Notes

- EVM tooling is only expected on chain v8+ presets.
- The suite requires a **chain v8 preset** (`envs/8.0`, `envs/latest`). The Polymesh SDK dropped v7
support in v31 and throws on connecting to a v7 node, so `envs/7.2` can no longer be used here.
2 changes: 1 addition & 1 deletion tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
},
"dependencies": {
"@polymeshassociation/local-signing-manager": "^4.1.1",
"@polymeshassociation/polymesh-sdk": "30.1.0",
"@polymeshassociation/polymesh-sdk": "31.0.0",
"cross-fetch": "^4.1.0",
"dotenv": "^16.5.0"
},
Expand Down
7 changes: 1 addition & 6 deletions tests/src/__tests__/rest/subsidy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
quitSubsidyParams,
setSubsidyAllowanceParams,
} from '~/rest/subsidy';
import { isChainV7 } from '~/util';

const handles = ['subsidizer', 'beneficiary'];
let factory: TestFactory;
Expand Down Expand Up @@ -92,12 +91,8 @@ describe('Subsidy', () => {
options: { processMode: ProcessMode.Submit, signer: beneficiary.signer },
});

const quitTag = isChainV7(factory.polymeshSdk)
? 'relayer.removePayingKey'
: 'relayer.removeSubsidy';

const result = await restClient.subsidy.quitSubsidy(params);

expect(result).toEqual(assertTagPresent(expect, quitTag));
expect(result).toEqual(assertTagPresent(expect, 'relayer.removeSubsidy'));
});
});
65 changes: 65 additions & 0 deletions tests/src/__tests__/sdk/accounts/balance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { BigNumber, Polymesh } from '@polymeshassociation/polymesh-sdk';
import { Account } from '@polymeshassociation/polymesh-sdk/types';

import { TestFactory } from '~/helpers';

let factory: TestFactory;

/*
Chain v8 changed how a POLYX balance is derived. `free` is now what the Account can actually
spend, and the raw chain values are exposed as `reserved` and `frozen`.
*/
describe('accountBalance', () => {
let sdk: Polymesh;
let account: Account;

beforeAll(async () => {
factory = await TestFactory.create({});
sdk = factory.polymeshSdk;

account = sdk.accountManagement.getSigningAccount() as Account;
});

afterAll(async () => {
await factory.close();
});

it('should expose the full POLYX balance breakdown', async () => {
const balance = await account.getBalance();

expect(balance).toEqual({
free: expect.any(BigNumber),
locked: expect.any(BigNumber),
total: expect.any(BigNumber),
reserved: expect.any(BigNumber),
frozen: expect.any(BigNumber),
});
});

it('should keep the balance components consistent', async () => {
const { free, locked, total, reserved, frozen } = await account.getBalance();

expect(total).toEqual(free.plus(locked));
expect(locked).toEqual(total.minus(free));
expect(free.gte(0)).toBe(true);
expect(reserved.gte(0)).toBe(true);
expect(frozen.gte(0)).toBe(true);
expect(locked.gte(reserved)).toBe(true);
});

it('should report a spendable free balance for a funded Account', async () => {
const { free, total } = await account.getBalance();

expect(free.gt(0)).toBe(true);
expect(free.lte(total)).toBe(true);
});

it('should return the same balance through accountManagement', async () => {
const [fromAccount, fromManagement] = await Promise.all([
account.getBalance(),
sdk.accountManagement.getAccountBalance({ account }),
]);

expect(fromManagement).toEqual(fromAccount);
});
});
87 changes: 40 additions & 47 deletions tests/src/__tests__/sdk/accounts/staking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ import { BigNumber, Polymesh } from '@polymeshassociation/polymesh-sdk';
import { Account } from '@polymeshassociation/polymesh-sdk/types';

import { TestFactory } from '~/helpers';
import { isChainV7 } from '~/util';

let factory: TestFactory;
const handles = ['stash', 'controller', 'payee'];
const handles = ['stash', 'payee'];

describe('staking', () => {
let sdk: Polymesh;
let stash: Account;
let controller: Account;
let payee: Account;
let unbondedAccount: Account;

const bondAmount = new BigNumber(10);

beforeAll(async () => {
factory = await TestFactory.create({ handles });
Expand All @@ -22,33 +23,38 @@ describe('staking', () => {
const stashAddress = factory.signingManager.addAccount({
mnemonic: stashMnemonic,
});
const controllerMnemonic = LocalSigningManager.generateAccount();
const controllerAddress = factory.signingManager.addAccount({
mnemonic: controllerMnemonic,
});
const payeeMnemonic = LocalSigningManager.generateAccount();
const payeeAddress = factory.signingManager.addAccount({
mnemonic: payeeMnemonic,
});
const unbondedMnemonic = LocalSigningManager.generateAccount();
const unbondedAddress = factory.signingManager.addAccount({
mnemonic: unbondedMnemonic,
});

await factory.createIdentityForAddresses([stashAddress, controllerAddress, payeeAddress]);
await factory.createIdentityForAddresses([stashAddress, payeeAddress, unbondedAddress]);

[stash, controller, payee] = await Promise.all([
[stash, payee, unbondedAccount] = await Promise.all([
sdk.accountManagement.getAccount({ address: stashAddress }),
sdk.accountManagement.getAccount({ address: controllerAddress }),
sdk.accountManagement.getAccount({ address: payeeAddress }),
sdk.accountManagement.getAccount({ address: unbondedAddress }),
]);
});

afterAll(async () => {
await factory.close();
});

it('should return a null payee for an Account that has never bonded', async () => {
const currentPayee = await unbondedAccount.staking.getPayee();

expect(currentPayee).toBeNull();
});

it('should allow an account to bond polyx', async () => {
const bondTx = await sdk.staking.bond(
{
amount: new BigNumber(10),
controller: stash,
amount: bondAmount,
payee: stash,
autoStake: true,
},
Expand All @@ -69,30 +75,32 @@ describe('staking', () => {
expect(currentLedger?.stash.address).toEqual(stash.address);
});

it('should allow for a controller to be reassigned', async () => {
if (!isChainV7(sdk)) {
return;
}
it('should report bonded POLYX as reserved on the stash balance', async () => {
const { free, locked, total, reserved, frozen } = await stash.getBalance();

const setControllerTx = await sdk.staking.setController(
{ controller },
{ signingAccount: stash }
);

await expect(setControllerTx.run()).resolves.not.toThrow();
expect(reserved.gte(bondAmount)).toBe(true);
expect(total).toEqual(free.plus(locked));
expect(locked).toEqual(total.minus(free));
expect(frozen.gte(0)).toBe(true);
});

it('should reject pairing a stash that is already its own controller', async () => {
/*
As of chain v8 a stash is bonded as its own controller, so `setController` only has an
effect for legacy stashes that still have a separate controller
*/
const currentController = await stash.staking.getController();
expect(currentController?.address).toEqual(controller.address);
expect(currentController?.address).toEqual(stash.address);

const setControllerTx = await sdk.staking.setController({ signingAccount: stash });

await expect(setControllerTx.run()).rejects.toThrow(/AlreadyPaired/);
});

it('should allow for a payee to be reassigned', async () => {
if (!isChainV7(sdk)) {
return;
}

const setPayeeTx = await sdk.staking.setPayee(
{ payee, autoStake: false },
{ signingAccount: controller }
{ signingAccount: stash }
);

await expect(setPayeeTx.run()).resolves.not.toThrow();
Expand All @@ -103,11 +111,7 @@ describe('staking', () => {
});

it('should allow for the stash to bond extra', async () => {
if (!isChainV7(sdk)) {
return;
}

const ledgerBefore = await controller.staking.getLedger();
const ledgerBefore = await stash.staking.getLedger();

const bondMoreTx = await sdk.staking.bondExtra(
{ amount: new BigNumber(5) },
Expand All @@ -116,30 +120,19 @@ describe('staking', () => {

await expect(bondMoreTx.run()).resolves.not.toThrow();

const ledgerAfter = await controller.staking.getLedger();
const ledgerAfter = await stash.staking.getLedger();

expect(ledgerBefore?.total.plus(5)).toEqual(ledgerAfter?.total);
});

it('should allow for a controller to unbond', async () => {
if (!isChainV7(sdk)) {
return;
}

const unbondTx = await sdk.staking.unbond(
{ amount: new BigNumber(10) },
{ signingAccount: controller }
);
const unbondTx = await sdk.staking.unbond({ amount: bondAmount }, { signingAccount: stash });

await expect(unbondTx.run()).resolves.not.toThrow();
});

it('should allow for the controller to call withdraw', async () => {
if (!isChainV7(sdk)) {
return;
}

const withdraw = await sdk.staking.withdraw({ signingAccount: controller });
const withdraw = await sdk.staking.withdraw({ signingAccount: stash });

await expect(withdraw.run()).resolves.not.toThrow();
});
Expand Down
79 changes: 79 additions & 0 deletions tests/src/__tests__/sdk/assets/fundingRound.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { BigNumber, Polymesh } from '@polymeshassociation/polymesh-sdk';
import { FungibleAsset } from '@polymeshassociation/polymesh-sdk/types';

import { TestFactory } from '~/helpers';
import { createAsset } from '~/sdk/assets/createAsset';
import { issueTokens } from '~/sdk/assets/issueTokens';

let factory: TestFactory;

describe('getIssuedInFundingRound', () => {
let sdk: Polymesh;
let asset: FungibleAsset;

const firstRound = 'Series A';
const secondRound = 'Series B';
const initialSupply = new BigNumber(100);

beforeAll(async () => {
factory = await TestFactory.create({});
sdk = factory.polymeshSdk;

asset = await createAsset(sdk, {
ticker: factory.nextTicker(),
name: 'Funding round test',
isDivisible: true,
initialSupply,
fundingRound: firstRound,
});
});

afterAll(async () => {
await factory.close();
});

it('should report the initial supply against the initial funding round', async () => {
const [currentRound, issued] = await Promise.all([
asset.currentFundingRound(),
asset.getIssuedInFundingRound(firstRound),
]);

expect(currentRound).toEqual(firstRound);
expect(issued).toEqual(initialSupply);
});

it('should report zero for a funding round the Asset never had', async () => {
const issued = await asset.getIssuedInFundingRound('Never Happened');

expect(issued).toEqual(new BigNumber(0));
});

it('should accumulate further issuance into the current funding round', async () => {
const extra = new BigNumber(25);

await issueTokens(asset, extra);

const issued = await asset.getIssuedInFundingRound(firstRound);

expect(issued).toEqual(initialSupply.plus(extra));
});

it('should track each funding round separately', async () => {
const modifyTx = await asset.modify({ fundingRound: secondRound });
await modifyTx.run();

expect(modifyTx.isSuccess).toBe(true);
await expect(asset.currentFundingRound()).resolves.toEqual(secondRound);

const secondRoundAmount = new BigNumber(40);
await issueTokens(asset, secondRoundAmount);

const [firstRoundIssued, secondRoundIssued] = await Promise.all([
asset.getIssuedInFundingRound(firstRound),
asset.getIssuedInFundingRound(secondRound),
]);

expect(firstRoundIssued).toEqual(initialSupply.plus(25));
expect(secondRoundIssued).toEqual(secondRoundAmount);
});
});
11 changes: 11 additions & 0 deletions tests/src/__tests__/sdk/assets/manageCheckpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,18 @@ describe('manageCheckpoints', () => {
await factory.close();
});

it('should report a null next Checkpoint for an Asset without Schedules', async () => {
await expect(asset.checkpoints.schedules.getNextCheckpoint()).resolves.toBeNull();
});

it('should execute mangeCheckpoints without errors', async () => {
await expect(manageCheckpoints(sdk, asset)).resolves.not.toThrow();
});

it('should report a null next Checkpoint once every Schedule has been removed', async () => {
const schedules = await asset.checkpoints.schedules.get();
expect(schedules).toHaveLength(0);

await expect(asset.checkpoints.schedules.getNextCheckpoint()).resolves.toBeNull();
});
});
Loading
Loading