refactor to chai/mocha, still prior credit error
This commit is contained in:
parent
dfb7bb106f
commit
2737aa106a
|
@ -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",
|
||||
};
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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(),
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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"]
|
||||
}
|
||||
|
|
2356
ts/yarn.lock
2356
ts/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue