Add instruction layouts
This commit is contained in:
parent
ec3bf95181
commit
c0a5f28e96
|
@ -0,0 +1,70 @@
|
|||
import { blob, Layout, struct, u16, u32, u8, union } from 'buffer-layout';
|
||||
import { u64 } from './layout';
|
||||
|
||||
class VersionedLayout extends Layout {
|
||||
constructor(version, inner, property) {
|
||||
super(inner.span > 0 ? inner.span + 1 : inner.span, property);
|
||||
this.version = version;
|
||||
this.inner = inner;
|
||||
}
|
||||
|
||||
decode(b, offset = 0) {
|
||||
if (b.readUInt8(offset) !== this._version) {
|
||||
throw new Error('invalid version');
|
||||
}
|
||||
return this.inner.decode(b, offset + 1);
|
||||
}
|
||||
|
||||
encode(src, b, offset = 0) {
|
||||
b.writeUInt8(this.version, offset);
|
||||
return 1 + this.inner.encode(src, b, offset + 1);
|
||||
}
|
||||
|
||||
getSpan(b, offset = 0) {
|
||||
return 1 + this.inner.getSpan(b, offset + 1);
|
||||
}
|
||||
}
|
||||
|
||||
export const INSTRUCTION_LAYOUT = new VersionedLayout(
|
||||
0,
|
||||
union(u32('instruction')),
|
||||
);
|
||||
INSTRUCTION_LAYOUT.inner.addVariant(
|
||||
0,
|
||||
struct([
|
||||
u64('baseLotSize'),
|
||||
u64('quoteLotSize'),
|
||||
u16('feeRateBps'),
|
||||
u64('vaultSignerNonce'),
|
||||
u64('quoteDustThreshold'),
|
||||
]),
|
||||
'initializeMarket',
|
||||
);
|
||||
INSTRUCTION_LAYOUT.inner.addVariant(
|
||||
1,
|
||||
struct([
|
||||
u8('side'), // buy = 0, sell = 1
|
||||
blob(3),
|
||||
u64('limitPrice'),
|
||||
u64('maxQuantity'),
|
||||
u8('orderType'), // limit = 0, ioc = 1, postOnly = 2
|
||||
blob(3),
|
||||
]),
|
||||
'newOrder',
|
||||
);
|
||||
INSTRUCTION_LAYOUT.inner.addVariant(
|
||||
2,
|
||||
struct([u16('limit'), blob(2)]),
|
||||
'matchOrders',
|
||||
);
|
||||
INSTRUCTION_LAYOUT.inner.addVariant(
|
||||
3,
|
||||
struct([u16('limit'), blob(2)]),
|
||||
'consumeEvents',
|
||||
);
|
||||
INSTRUCTION_LAYOUT.inner.addVariant(4, struct([]), 'cancelOrder');
|
||||
|
||||
export function encodeInstruction(instruction) {
|
||||
const b = Buffer.alloc(100);
|
||||
return b.slice(0, INSTRUCTION_LAYOUT.encode(instruction, b));
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
import { encodeInstruction, INSTRUCTION_LAYOUT } from './instructions';
|
||||
import BN from 'bn.js';
|
||||
|
||||
describe('instruction', () => {
|
||||
it('encodes initialize market', () => {
|
||||
let b = encodeInstruction({
|
||||
initializeMarket: {
|
||||
baseLotSize: new BN(10),
|
||||
quoteLotSize: new BN(100000),
|
||||
feeRateBps: 5,
|
||||
vaultSignerNonce: new BN(1),
|
||||
quoteDustThreshold: new BN(10),
|
||||
},
|
||||
});
|
||||
expect(b.toString('hex')).toEqual(
|
||||
'00000000000a00000000000000a086010000000000050001000000000000000a00000000000000',
|
||||
);
|
||||
});
|
||||
|
||||
it('encodes new order', () => {
|
||||
let b = encodeInstruction({
|
||||
newOrder: {
|
||||
side: 1, // buy
|
||||
limitPrice: new BN(10),
|
||||
maxQuantity: new BN(5),
|
||||
orderType: 2, // postOnly
|
||||
},
|
||||
});
|
||||
expect(b.toString('hex')).toEqual(
|
||||
'0001000000010000000a00000000000000050000000000000002000000',
|
||||
);
|
||||
});
|
||||
});
|
|
@ -2,16 +2,17 @@ import { seq, struct } from 'buffer-layout';
|
|||
import { publicKeyLayout, u128, u64, WideBits } from './layout';
|
||||
import { SLAB_LAYOUT } from './slab-layout';
|
||||
|
||||
const ACCOUNT_FLAGS_LAYOUT = new WideBits();
|
||||
ACCOUNT_FLAGS_LAYOUT.addBoolean('initialized');
|
||||
ACCOUNT_FLAGS_LAYOUT.addBoolean('market');
|
||||
ACCOUNT_FLAGS_LAYOUT.addBoolean('openOrders');
|
||||
ACCOUNT_FLAGS_LAYOUT.addBoolean('requestQueue');
|
||||
ACCOUNT_FLAGS_LAYOUT.addBoolean('eventQueue');
|
||||
ACCOUNT_FLAGS_LAYOUT.addBoolean('bids');
|
||||
ACCOUNT_FLAGS_LAYOUT.addBoolean('asks');
|
||||
|
||||
export function accountFlags(property = 'accountFlags') {
|
||||
const layout = new WideBits(property);
|
||||
layout.addBoolean('initialized');
|
||||
layout.addBoolean('market');
|
||||
layout.addBoolean('openOrders');
|
||||
layout.addBoolean('requestQueue');
|
||||
layout.addBoolean('eventQueue');
|
||||
layout.addBoolean('bids');
|
||||
layout.addBoolean('asks');
|
||||
return layout;
|
||||
return ACCOUNT_FLAGS_LAYOUT.replicate(property);
|
||||
}
|
||||
|
||||
export const MARKET_STATE_LAYOUT = struct([
|
||||
|
|
|
@ -3,12 +3,17 @@ import { publicKeyLayout, u128, u64, zeros } from './layout';
|
|||
|
||||
const SLAB_HEADER_LAYOUT = struct(
|
||||
[
|
||||
// Number of modified slab nodes
|
||||
u32('bumpIndex'),
|
||||
zeros(4), // Consider slabs with more than 2^32 nodes to be invalid
|
||||
|
||||
// Linked list of unused nodes
|
||||
u32('freeListLen'),
|
||||
zeros(4),
|
||||
u32('freeListHead'),
|
||||
|
||||
u32('root'),
|
||||
|
||||
u32('leafCount'),
|
||||
zeros(4),
|
||||
],
|
||||
|
@ -19,17 +24,22 @@ const SLAB_NODE_LAYOUT = union(u32('tag'), blob(60), 'node');
|
|||
SLAB_NODE_LAYOUT.addVariant(0, struct([]), 'uninitialized');
|
||||
SLAB_NODE_LAYOUT.addVariant(
|
||||
1,
|
||||
struct([u32('prefixLen'), u128('key'), seq(u32(), 2, 'children')]),
|
||||
struct([
|
||||
// Only the first prefixLen high-order bits of key are meaningful
|
||||
u32('prefixLen'),
|
||||
u128('key'),
|
||||
seq(u32(), 2, 'children'),
|
||||
]),
|
||||
'innerNode',
|
||||
);
|
||||
SLAB_NODE_LAYOUT.addVariant(
|
||||
2,
|
||||
struct([
|
||||
u8('ownerSlot'),
|
||||
u8('ownerSlot'), // Index into OPEN_ORDERS_LAYOUT.orders
|
||||
blob(3),
|
||||
u128('key'),
|
||||
u128('key'), // (price, seqNum)
|
||||
publicKeyLayout('owner'),
|
||||
u64('quantity'),
|
||||
u64('quantity'), // In units of lot size
|
||||
]),
|
||||
'leafNode',
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue