Skip to content

Commit

Permalink
add staking e2e tests
Browse files Browse the repository at this point in the history
  • Loading branch information
drohit-cb committed Nov 26, 2024
1 parent afd6b1b commit ca6068a
Show file tree
Hide file tree
Showing 3 changed files with 226 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .github/workflows/e2e_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@ jobs:
NAME: ${{ secrets.NAME }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
WALLET_DATA: ${{ secrets.WALLET_DATA }}
STAKE_API_KEY_NAME: ${{ secrets.STAKE_API_KEY_NAME }}
STAKE_API_PRIVATE_KEY: ${{ secrets.STAKE_API_PRIVATE_KEY }}
STAKE_ADDRESS_ID_1: ${{ secrets.STAKE_ADDRESS_ID_1 }}
STAKE_ADDRESS_ID_2: ${{ secrets.STAKE_ADDRESS_ID_2 }}
STAKE_VALIDATOR_ADDRESS_1: ${{ secrets.STAKE_VALIDATOR_ADDRESS_1 }}
run: npm run test:dry-run && npm run test:e2e
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"test": "npx jest --no-cache --testMatch=**/*_test.ts",
"test:dry-run": "npm install && npm ci && npm publish --dry-run",
"test:e2e": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}'",
"test:e2e:stake": "npx jest --no-cache --testMatch=**/e2e.ts --coverageThreshold '{}' -t Stake",
"test:types": "tsd --files src/tests/types.test-d.ts",
"clean": "rm -rf dist/*",
"build": "tsc",
Expand Down
221 changes: 220 additions & 1 deletion src/tests/e2e.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import fs from "fs";
import dotenv from "dotenv";
import { Coinbase, Wallet } from "../index";
import {
Coinbase,
Wallet,
StakingReward,
StakingBalance,
ExternalAddress,
ValidatorStatus,
Validator,
StakeOptionsMode,
TransactionStatus,
} from "../index";

import { StakingOperationStatusEnum } from "../client";
import { TransferStatus } from "../coinbase/types";

describe("Coinbase SDK E2E Test", () => {
Expand Down Expand Up @@ -129,3 +141,210 @@ describe("Coinbase SDK E2E Test", () => {
});
}, 60000);
});

describe("Coinbase SDK Stake E2E Test", () => {
const requiredEnvVars = [
"STAKE_API_KEY_NAME",
"STAKE_API_PRIVATE_KEY",
"STAKE_ADDRESS_ID_1",
"STAKE_ADDRESS_ID_2",
"STAKE_VALIDATOR_ADDRESS_1",
];

beforeAll(() => {
dotenv.config();

requiredEnvVars.forEach(envVar => {
if (!process.env[envVar]) {
throw new Error(`Required environment variable ${envVar} is not set`);
}
});

Coinbase.configure({
apiKeyName: process.env.STAKE_API_KEY_NAME as string,
privateKey: process.env.STAKE_API_PRIVATE_KEY as string,
});
});

it("should be able to access environment variables", () => {
requiredEnvVars.forEach(envVar => {
expect(process.env[envVar]).toBeDefined();
});
});

describe("Stake: Reward Tests", () => {
it("should list shared eth staking rewards via StakingReward.list", async () => {
const networkId = Coinbase.networks.EthereumMainnet;
const assetId = Coinbase.assets.Eth;
const addressIds = [process.env.STAKE_ADDRESS_ID_1 as string];
// May 1, 2024 - May 20, 2024
const startTime = new Date(2024, 4, 1, 0, 0, 0).toISOString();
const endTime = new Date(2024, 4, 20, 23, 59, 59).toISOString();
const rewards = await StakingReward.list(networkId, assetId, addressIds, startTime, endTime);

expect(rewards).toBeDefined();
expect(rewards.length).toEqual(20);
});

it("should list shared eth staking rewards via ExternalAddress", async () => {
// May 1, 2024 - May 20, 2024
const startTime = new Date(2024, 4, 1, 0, 0, 0).toISOString();
const endTime = new Date(2024, 4, 20, 23, 59, 59).toISOString();

const address = new ExternalAddress(
Coinbase.networks.EthereumMainnet,
process.env.STAKE_ADDRESS_ID_1 as string,
);

const rewards = await address.stakingRewards(Coinbase.assets.Eth, startTime, endTime);

expect(rewards).toBeDefined();
expect(rewards.length).toEqual(20);
});
});

describe("Stake: Balance Tests", () => {
it("should list shared eth staking balances via StakingBalance.list", async () => {
const networkId = Coinbase.networks.EthereumMainnet;
const assetId = Coinbase.assets.Eth;
const addressId = process.env.STAKE_VALIDATOR_ADDRESS_1 as string;
// Nov 1, 2024 - Nov 20, 2024
const startTime = new Date(2024, 10, 1, 0, 0, 0).toISOString();
const endTime = new Date(2024, 10, 20, 23, 59, 59).toISOString();
const stakingBalances = await StakingBalance.list(
networkId,
assetId,
addressId,
startTime,
endTime,
);

expect(stakingBalances).toBeDefined();
expect(stakingBalances.length).toEqual(20);
});
});

describe("Stake: Validator Tests", () => {
it("should list validators", async () => {
const networkId = Coinbase.networks.EthereumMainnet;
const assetId = Coinbase.assets.Eth;
const status = ValidatorStatus.ACTIVE;

const validators = await Validator.list(networkId, assetId, status);

expect(validators).toBeDefined();
expect(validators.length).toEqual(1);
const validator = validators[0];
expect(validator.getStatus()).toEqual(ValidatorStatus.ACTIVE);
expect(validator.getValidatorId()).toEqual(process.env.STAKE_VALIDATOR_ADDRESS_1 as string);
});

it("should fetch a validator", async () => {
const networkId = Coinbase.networks.EthereumMainnet;
const assetId = Coinbase.assets.Eth;
const validatorId = process.env.STAKE_VALIDATOR_ADDRESS_1 as string;

const validator = await Validator.fetch(networkId, assetId, validatorId);

expect(validator).toBeDefined();
expect(validator.getStatus()).toEqual(ValidatorStatus.ACTIVE);
expect(validator.getValidatorId()).toEqual(validatorId);
});
});

describe("Stake: Context Tests", () => {
it("should return stakeable balances for shared ETH staking", async () => {
const address = new ExternalAddress(
Coinbase.networks.EthereumMainnet,
process.env.STAKE_ADDRESS_ID_2 as string,
);

const stakeableBalance = await address.stakeableBalance(
Coinbase.assets.Eth,
StakeOptionsMode.PARTIAL,
);

expect(stakeableBalance).toBeDefined();
expect(stakeableBalance.toNumber()).toBeGreaterThanOrEqual(0);
});

it("should return unstakeable balances for shared ETH staking", async () => {
const address = new ExternalAddress(
Coinbase.networks.EthereumMainnet,
process.env.STAKE_ADDRESS_ID_1 as string,
);

const stakeableBalance = await address.unstakeableBalance(
Coinbase.assets.Eth,
StakeOptionsMode.PARTIAL,
);

expect(stakeableBalance).toBeDefined();
expect(stakeableBalance.toNumber()).toBeGreaterThanOrEqual(0);
});

it("should return claimable balances for shared ETH staking", async () => {
const address = new ExternalAddress(
Coinbase.networks.EthereumMainnet,
process.env.STAKE_ADDRESS_ID_1 as string,
);

const stakeableBalance = await address.claimableBalance(
Coinbase.assets.Eth,
StakeOptionsMode.PARTIAL,
);

expect(stakeableBalance).toBeDefined();
expect(stakeableBalance.toNumber()).toBeGreaterThanOrEqual(0);
});

it("should return unstakeable balances for Dedicated ETH staking", async () => {
// This address is expected to have 1 validator associated with it, thus returning a 32 unstake balance.

const address = new ExternalAddress(
Coinbase.networks.EthereumMainnet,
process.env.STAKE_ADDRESS_ID_2 as string,
);

const stakeableBalance = await address.unstakeableBalance(
Coinbase.assets.Eth,
StakeOptionsMode.NATIVE,
);

expect(stakeableBalance).toBeDefined();
expect(stakeableBalance.toNumber()).toBeGreaterThanOrEqual(32);
});
});

describe("Stake: Build Tests", () => {
it("should return an unsigned tx for shared ETH staking", async () => {
const address = new ExternalAddress(
Coinbase.networks.EthereumHolesky,
process.env.STAKE_ADDRESS_ID_2 as string,
);

const stakingOperation = await address.buildStakeOperation(
0.0001,
Coinbase.assets.Eth,
StakeOptionsMode.PARTIAL,
);

await stakingOperation.wait({ timeoutSeconds: 5, intervalSeconds: 1 });

expect(stakingOperation).toBeDefined();
expect(stakingOperation.getID()).toBeDefined();
expect(stakingOperation.getStatus()).toEqual(StakingOperationStatusEnum.Complete);
expect(stakingOperation.getAddressID()).toEqual(process.env.STAKE_ADDRESS_ID_2 as string);
expect(stakingOperation.getNetworkID()).toEqual(Coinbase.networks.EthereumHolesky);
expect(stakingOperation.isCompleteState()).toBe(true);
expect(stakingOperation.getSignedVoluntaryExitMessages()).toEqual([]);
expect(stakingOperation.getTransactions().length).toEqual(1);
expect(stakingOperation.getTransactions()[0].isSigned()).toBe(false);
expect(stakingOperation.getTransactions()[0].getNetworkId()).toEqual(
Coinbase.networks.EthereumHolesky,
);
expect(stakingOperation.getTransactions()[0].getUnsignedPayload()).toBeDefined();
expect(stakingOperation.getTransactions()[0].getStatus()).toEqual(TransactionStatus.PENDING);
});
});
});

0 comments on commit ca6068a

Please sign in to comment.