refactor to chai/mocha, still prior credit error

This commit is contained in:
Sayantan Karmakar 2022-04-09 02:40:56 +05:30
parent dfb7bb106f
commit 2737aa106a
8 changed files with 447 additions and 2097 deletions

View File

@ -1,11 +0,0 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: "ts-jest/presets/default",
testEnvironment: "node",
collectCoverage: true,
verbose: true,
testPathIgnorePatterns: ["/node_modules/"],
roots: ["<rootDir>/tests"],
testTimeout: 90000,
resolver: "ts-jest-resolver",
};

View File

@ -12,7 +12,7 @@
],
"scripts": {
"build": "rm -rf dist/; tsc",
"test": "jest --forceExit --detectOpenHandles",
"test": "ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts",
"prepare": "cd .. && husky install ts/.husky",
"lint": "eslint --fix"
},
@ -23,22 +23,25 @@
]
},
"devDependencies": {
"@types/jest": "^27.4.1",
"@types/mocha": "^9.1.0",
"@typescript-eslint/eslint-plugin": "^5.17.0",
"@typescript-eslint/parser": "^5.17.0",
"chai": "^4.3.6",
"eslint": "^8.2.0",
"eslint-plugin-import": "^2.25.2",
"husky": "^7.0.0",
"jest": "^27.5.1",
"lint-staged": "^12.3.7",
"mocha": "^9.2.2",
"prettier": "^2.6.1",
"ts-jest": "^27.1.4",
"ts-jest-resolver": "^2.0.0",
"ts-mocha": "^9.0.2",
"typescript": "^4.6.3"
},
"dependencies": {
"@project-serum/serum": "^0.13.62",
"@solana/spl-token": "^0.2.0",
"@solana/web3.js": "^1.37.0"
"@solana/web3.js": "^1.37.0",
"@types/bn.js": "^5.1.0",
"@types/chai": "^4.3.0",
"bn.js": "^5.2.0"
}
}

View File

@ -3,15 +3,31 @@ import {
getOrCreateAssociatedTokenAccount,
} from "@solana/spl-token";
import { Coin } from "./coin";
import { Connection, Keypair, PublicKey, Transaction } from "@solana/web3.js";
import BN from "bn.js";
import {
Connection,
Keypair,
PublicKey,
sendAndConfirmTransaction,
Transaction,
} from "@solana/web3.js";
import { DexMarket, MarketAccounts } from "./market";
import { DexInstructions, Market as SerumMarket } from "@project-serum/serum";
import { getVaultOwnerAndNonce } from "./utils";
export type MarketArgs = {
tickSize: number;
lotSize: number;
feeRate: number;
quoteDustThreshold: BN;
};
export class Dex {
public address: PublicKey;
coins: Coin[];
markets: DexMarket[];
connection: Connection;
constructor(address: PublicKey, connection: Connection) {
@ -52,12 +68,7 @@ export class Dex {
public async initDexMarket(
baseCoin: Coin,
quoteCoin: Coin,
marketOptions: {
baseLotSize: number;
quoteLotSize: number;
feeRate: number;
quoteDustThreshold: number;
},
marketArgs: MarketArgs,
payer: Keypair,
): Promise<DexMarket> {
const marketAccounts: MarketAccounts = {
@ -68,15 +79,8 @@ export class Dex {
asks: Keypair.generate(),
};
await DexMarket.createMarketAccounts(
marketAccounts,
payer,
this.connection,
this.address,
);
const [vaultOwner, vaultOwnerNonce] = await PublicKey.findProgramAddress(
[this.address.toBuffer()],
const [vaultOwner, vaultOwnerNonce] = await getVaultOwnerAndNonce(
marketAccounts.market.publicKey,
this.address,
);
@ -97,6 +101,22 @@ export class Dex {
true,
);
const accountsIx = await DexMarket.createMarketAccountsInstructions(
marketAccounts,
payer,
this.connection,
this.address,
);
let baseLotSize;
let quoteLotSize;
if (marketArgs.lotSize > 0) {
baseLotSize = Math.round(10 ** baseCoin.decimals * marketArgs.lotSize);
quoteLotSize = Math.round(
marketArgs.lotSize * 10 ** quoteCoin.decimals * marketArgs.tickSize,
);
}
const initSerumMarketIx = await DexInstructions.initializeMarket({
market: marketAccounts.market.publicKey,
requestQueue: marketAccounts.requestQueue.publicKey,
@ -107,17 +127,24 @@ export class Dex {
quoteVault: quoteVault.address,
baseMint: baseCoin.mint,
quoteMint: quoteCoin.mint,
baseLotSize: marketOptions.baseLotSize,
quoteLotSize: marketOptions.quoteLotSize,
feeRateBps: marketOptions.feeRate,
quoteDustThreshold: marketOptions.quoteDustThreshold,
baseLotSize: new BN(baseLotSize),
quoteLotSize: new BN(quoteLotSize),
feeRateBps: marketArgs.feeRate,
quoteDustThreshold: marketArgs.quoteDustThreshold,
vaultSignerNonce: vaultOwnerNonce,
programId: this.address,
});
const tx = new Transaction().add(initSerumMarketIx);
const tx = new Transaction().add(...accountsIx, initSerumMarketIx);
const txSig = await this.connection.sendTransaction(tx, []);
const txSig = await sendAndConfirmTransaction(this.connection, tx, [
marketAccounts.market,
marketAccounts.requestQueue,
marketAccounts.eventQueue,
marketAccounts.bids,
marketAccounts.asks,
payer,
]);
await this.connection.confirmTransaction(txSig, "confirmed");

View File

@ -4,7 +4,7 @@ import {
Keypair,
PublicKey,
SystemProgram,
Transaction,
TransactionInstruction,
} from "@solana/web3.js";
import { Coin } from "./coin";
@ -32,6 +32,8 @@ export class DexMarket {
public quoteCoin: Coin;
public marketSymbol: string;
constructor(
marketAccounts: MarketAccounts,
serumMarket: Market,
@ -43,14 +45,15 @@ export class DexMarket {
this.marketAccounts = marketAccounts;
this.baseCoin = baseCoin;
this.quoteCoin = quoteCoin;
this.marketSymbol = `${baseCoin.symbol}/${quoteCoin.symbol}`;
}
static async createMarketAccounts(
static async createMarketAccountsInstructions(
accounts: MarketAccounts,
payer: Keypair,
connection: Connection,
dexProgram: PublicKey,
): Promise<void> {
): Promise<TransactionInstruction[]> {
const { market, requestQueue, eventQueue, bids, asks } = accounts;
const marketIx = SystemProgram.createAccount({
@ -99,18 +102,6 @@ export class DexMarket {
programId: dexProgram,
});
const tx = new Transaction();
tx.add(marketIx, requestQueueIx, eventQueueIx, bidsIx, asksIx);
const txSig = await connection.sendTransaction(tx, [
payer,
market,
requestQueue,
eventQueue,
bids,
asks,
]);
await connection.confirmTransaction(txSig, "confirmed");
return [marketIx, requestQueueIx, eventQueueIx, bidsIx, asksIx];
}
}

21
ts/src/utils.ts Normal file
View File

@ -0,0 +1,21 @@
import { PublicKey } from "@solana/web3.js";
import BN from "bn.js";
export async function getVaultOwnerAndNonce(
marketAddress: PublicKey,
dexAddress: PublicKey,
): Promise<[vaultOwner: PublicKey, nonce: BN]> {
const nonce = new BN(0);
// eslint-disable-next-line no-constant-condition
while (true) {
try {
const vaultOwner = await PublicKey.createProgramAddress(
[marketAddress.toBuffer(), nonce.toArrayLike(Buffer, "le", 8)],
dexAddress,
);
return [vaultOwner, nonce];
} catch (e) {
nonce.iaddn(1);
}
}
}

View File

@ -1,13 +1,16 @@
import {
clusterApiUrl,
Connection,
Keypair,
LAMPORTS_PER_SOL,
PublicKey,
} from "@solana/web3.js";
import { Dex, DexMarket } from "../src";
import BN from "bn.js";
import { assert } from "chai";
import { Dex } from "../src";
describe("Serum Dev Tools", () => {
const connection = new Connection("http://localhost:8899", "confirmed");
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
const owner = Keypair.generate();
const dexAddress = new PublicKey(
@ -16,12 +19,14 @@ describe("Serum Dev Tools", () => {
const dex = new Dex(dexAddress, connection);
beforeAll(async () => {
const tx = await connection.requestAirdrop(
before(async () => {
const sig = await connection.requestAirdrop(
owner.publicKey,
20 * LAMPORTS_PER_SOL,
);
await connection.confirmTransaction(tx);
await connection.confirmTransaction(sig);
console.log(await connection.getBalance(owner.publicKey, "confirmed"));
});
it("can create coin", async () => {
@ -29,40 +34,26 @@ describe("Serum Dev Tools", () => {
const coin = dex.getCoin("SAYA");
expect(coin.symbol).toBe("SAYA");
expect(coin.decimals).toBe(6);
expect(coin.mint).toBe(mint);
assert.equal(coin.mint, mint);
});
it("can create dex accounts", async () => {
const market = Keypair.generate();
const requestQueue = Keypair.generate();
const eventQueue = Keypair.generate();
const bids = Keypair.generate();
const asks = Keypair.generate();
await DexMarket.createMarketAccounts(
{ market, requestQueue, eventQueue, bids, asks },
owner,
connection,
dexAddress,
);
await dex.createCoin("SRM", 6, owner, owner.publicKey, null);
const dexMarket = await dex.initDexMarket(
dex.getCoin("SAYA"),
dex.getCoin("SRM"),
{
baseLotSize: 10,
quoteLotSize: 10,
tickSize: 0.001,
lotSize: 10,
feeRate: 10,
quoteDustThreshold: 10,
quoteDustThreshold: new BN(100),
},
owner,
);
expect(dexMarket.address.toBase58()).toBe(
assert.equal(
dexMarket.address.toBase58(),
dexMarket.serumMarket.address.toBase58(),
);
});

View File

@ -2,9 +2,13 @@
"compilerOptions": {
"module": "commonjs",
"target": "es2015",
"lib": ["es2015"],
"declaration": true,
"outDir": "./dist",
"types": ["jest"]
"typeRoots": ["./node_modules/@types"],
"types": ["mocha", "chai"],
// for BN constructor
"esModuleInterop": true
},
"include": ["src/**/*", "**/*.spec.ts", "**/*.test.ts"]
}

File diff suppressed because it is too large Load Diff