Add method for retrieving fills

This commit is contained in:
Gary Wang 2020-08-13 12:45:16 -07:00
parent b5ee5e2127
commit 9b7e39c8fe
4 changed files with 82 additions and 15 deletions

View File

@ -8,7 +8,7 @@ WIP
`yarn add @project-serum/serum`
```js
import { Connection, PublicKey } from '@solana/web3.js';
import { Account, Connection, PublicKey } from '@solana/web3.js';
import { Market } from '@project-serum/serum';
let connection = new Connection('https://testnet.solana.com');
@ -45,4 +45,14 @@ for (let order of await market.loadBids(connection)) {
await market.cancelOrder(connection, owner, order);
}
}
for (let fill of await market.loadFills(connection)) {
console.log(
fill.orderId,
fill.owner.toBase58(),
fill.price,
fill.size,
fill.side,
);
}
```

View File

@ -1,6 +1,6 @@
{
"name": "@project-serum/serum",
"version": "0.3.2",
"version": "0.3.3",
"description": "Library for interacting with the serum dex",
"license": "MIT",
"repository": "project-serum/serum-js",

View File

@ -272,6 +272,35 @@ export class Market {
return decodeEventQueue(data);
}
async loadFills(connection: Connection, limit = 100) {
// TODO: once there's a separate source of fills use that instead
const { data } = throwIfNull(
await connection.getAccountInfo(this._decoded.eventQueue),
);
const events = decodeEventQueue(data, limit);
return events
.filter((event) => event.eventFlags.fill && event.quantityPaid.gtn(0))
.map((event) =>
event.eventFlags.bid
? {
...event,
size: this.baseSizeLotsToNumber(event.quantityReleased),
price: this.priceLotsToNumber(
event.quantityPaid.divRound(event.quantityReleased),
),
side: 'buy',
}
: {
...event,
size: this.baseSizeLotsToNumber(event.quantityPaid),
price: this.priceLotsToNumber(
event.quantityReleased.divRound(event.quantityPaid),
),
side: 'sell',
},
);
}
private get _baseSplTokenMultiplier() {
return new BN(10).pow(new BN(this._baseSplTokenDecimals));
}

View File

@ -69,34 +69,62 @@ export interface Event {
owner: PublicKey;
}
function decodeQueue(headerLayout, nodeLayout, buffer) {
function decodeQueue(
headerLayout,
nodeLayout,
buffer: Buffer,
history?: number,
) {
const header = headerLayout.decode(buffer);
const allocLen = Math.floor(
(buffer.length - headerLayout.span) / nodeLayout.span,
);
const nodes: any[] = [];
for (let i = 0; i < header.count; ++i) {
const nodeIndex = (header.head + i) % allocLen;
nodes.push(
nodeLayout.decode(
buffer,
headerLayout.span + nodeIndex * nodeLayout.span,
),
);
if (history) {
for (let i = 0; i < Math.min(history, allocLen); ++i) {
const nodeIndex =
(header.head + header.count + allocLen - 1 - i) % allocLen;
nodes.push(
nodeLayout.decode(
buffer,
headerLayout.span + nodeIndex * nodeLayout.span,
),
);
}
} else {
for (let i = 0; i < header.count; ++i) {
const nodeIndex = (header.head + i) % allocLen;
nodes.push(
nodeLayout.decode(
buffer,
headerLayout.span + nodeIndex * nodeLayout.span,
),
);
}
}
return { header, nodes };
}
export function decodeRequestQueue(buffer: Buffer) {
const { header, nodes } = decodeQueue(REQUEST_QUEUE_HEADER, REQUEST, buffer);
export function decodeRequestQueue(buffer: Buffer, history?: number) {
const { header, nodes } = decodeQueue(
REQUEST_QUEUE_HEADER,
REQUEST,
buffer,
history,
);
if (!header.accountFlags.initialized || !header.accountFlags.requestQueue) {
throw new Error('Invalid requests queue');
}
return nodes;
}
export function decodeEventQueue(buffer: Buffer): Event[] {
const { header, nodes } = decodeQueue(EVENT_QUEUE_HEADER, EVENT, buffer);
export function decodeEventQueue(buffer: Buffer, history?: number): Event[] {
const { header, nodes } = decodeQueue(
EVENT_QUEUE_HEADER,
EVENT,
buffer,
history,
);
if (!header.accountFlags.initialized || !header.accountFlags.eventQueue) {
throw new Error('Invalid events queue');
}