@ocap/types
Version:
Typescript definitions generated from protobuf
250 lines (238 loc) • 7.38 kB
text/typescript
// core/types/tests/pipeline.spec.ts
// Tests for 5-phase context type hierarchy
import { describe, expect, test } from 'bun:test';
import type {
IBaseContext,
IChainConfig,
IDecodedContext,
IGasContext,
IReadyContext,
IStateDB,
IWithSender,
} from '../interfaces';
import type { TStakeTx, TTransferTx } from '../lib/tx_pb';
describe('Pipeline Context Types', () => {
const mockStateDB = {} as IStateDB;
const mockConfig = { chainId: 'test', chainName: 'Test' } as IChainConfig;
const mockIndexDB = {} as IBaseContext['indexdb'];
describe('IBaseContext', () => {
test('should require mandatory fields', () => {
const context: IBaseContext = {
txBase64: 'base64data',
statedb: mockStateDB,
config: mockConfig,
indexdb: mockIndexDB,
};
expect(context.txBase64).toBe('base64data');
expect(context.statedb).toBe(mockStateDB);
expect(context.config).toBe(mockConfig);
});
test('should allow optional fields', () => {
const context: IBaseContext = {
txBase64: 'base64data',
statedb: mockStateDB,
config: mockConfig,
indexdb: mockIndexDB,
logger: { debug: () => {}, info: () => {}, warn: () => {}, error: () => {} },
extra: { key: 'value' },
};
expect(context.logger).toBeDefined();
expect(context.extra?.key).toBe('value');
});
});
describe('IDecodedContext', () => {
test('should include tx and itx fields', () => {
const context: IDecodedContext<TTransferTx> = {
txBase64: 'base64data',
statedb: mockStateDB,
config: mockConfig,
indexdb: mockIndexDB,
tx: {
from: 'z123',
chainId: 'test',
nonce: 1,
pk: new Uint8Array(),
itx: { typeUrl: '', value: new Uint8Array() },
},
txHash: 'hash123',
txTime: '2024-01-01T00:00:00Z',
txSize: 256,
txBaseGas: true,
itx: { to: 'z456', value: '100', tokens: [] },
txType: 'fg:t:transfer',
};
expect(context.txHash).toBe('hash123');
expect(context.txType).toBe('fg:t:transfer');
expect(context.itx?.to).toBe('z456');
});
});
describe('IGasContext', () => {
test('should include gas calculation fields', () => {
const context: IGasContext = {
txBase64: 'base64data',
statedb: mockStateDB,
config: mockConfig,
indexdb: mockIndexDB,
tx: {
from: 'z123',
chainId: 'test',
nonce: 1,
pk: new Uint8Array(),
itx: { typeUrl: '', value: new Uint8Array() },
},
txHash: 'hash123',
txTime: '2024-01-01T00:00:00Z',
txSize: 256,
txBaseGas: true,
itx: {},
txType: 'fg:t:transfer',
gasEstimate: { create: 1, update: 2, payment: 0 },
senderUpdates: {},
gasPaid: false,
};
expect(context.gasEstimate?.create).toBe(1);
expect(context.gasPaid).toBe(false);
});
});
describe('IReadyContext', () => {
test('should include state snapshot', () => {
const context: IReadyContext = {
txBase64: 'base64data',
statedb: mockStateDB,
config: mockConfig,
indexdb: mockIndexDB,
tx: {
from: 'z123',
chainId: 'test',
nonce: 1,
pk: new Uint8Array(),
itx: { typeUrl: '', value: new Uint8Array() },
},
txHash: 'hash123',
txTime: '2024-01-01T00:00:00Z',
txSize: 256,
txBaseGas: true,
itx: {},
txType: 'fg:t:transfer',
stateSnapshot: { z123: { address: 'z123', tokens: {} } },
};
expect(context.stateSnapshot).toBeDefined();
expect(context.stateSnapshot.z123).toBeDefined();
});
test('should support generic TItx', () => {
type TransferContext = IReadyContext<TTransferTx>;
const context: TransferContext = {
txBase64: 'base64data',
statedb: mockStateDB,
config: mockConfig,
indexdb: mockIndexDB,
tx: {
from: 'z123',
chainId: 'test',
nonce: 1,
pk: new Uint8Array(),
itx: { typeUrl: '', value: new Uint8Array() },
},
txHash: 'hash123',
txTime: '2024-01-01T00:00:00Z',
txSize: 256,
txBaseGas: true,
itx: { to: 'z456', value: '100', tokens: [] },
txType: 'fg:t:transfer',
stateSnapshot: {},
};
expect(context.itx?.to).toBe('z456');
expect(context.itx?.value).toBe('100');
});
test('should support TStakeTx via generic', () => {
type StakeContext = IReadyContext<TStakeTx>;
const context: StakeContext = {
txBase64: 'base64data',
statedb: mockStateDB,
config: mockConfig,
indexdb: mockIndexDB,
tx: {
from: 'z123',
chainId: 'test',
nonce: 1,
pk: new Uint8Array(),
itx: { typeUrl: '', value: new Uint8Array() },
},
txHash: 'hash123',
txTime: '2024-01-01T00:00:00Z',
txSize: 256,
txBaseGas: true,
itx: { to: 'z456', tokens: [] },
txType: 'fg:t:stake',
stateSnapshot: {},
};
expect(context.itx?.to).toBe('z456');
});
});
describe('Mixin Interfaces', () => {
test('should allow combining phase types with mixins', () => {
type TransferContext = IReadyContext<TTransferTx> & IWithSender;
const context: TransferContext = {
txBase64: 'base64data',
statedb: mockStateDB,
config: mockConfig,
indexdb: mockIndexDB,
tx: {
from: 'z123',
chainId: 'test',
nonce: 1,
pk: new Uint8Array(),
itx: { typeUrl: '', value: new Uint8Array() },
},
txHash: 'hash123',
txTime: '2024-01-01T00:00:00Z',
txSize: 256,
txBaseGas: true,
itx: { to: 'z456', value: '100', tokens: [] },
txType: 'fg:t:transfer',
stateSnapshot: {},
senderState: {
address: 'z123',
balance: '1000',
nonce: '1',
numTxs: '10',
pk: 'pk',
moniker: 'alice',
tokens: {},
context: { genesisTime: '', genesisTx: '' },
},
};
expect(context.senderState.address).toBe('z123');
expect(context.senderState.balance).toBe('1000');
});
});
describe('Dynamic extension', () => {
test('should allow protocol-specific fields via index signature', () => {
const context: IReadyContext = {
txBase64: 'base64data',
statedb: mockStateDB,
config: mockConfig,
indexdb: mockIndexDB,
tx: {
from: 'z123',
chainId: 'test',
nonce: 1,
pk: new Uint8Array(),
itx: { typeUrl: '', value: new Uint8Array() },
},
txHash: 'hash123',
txTime: '2024-01-01T00:00:00Z',
txSize: 256,
txBaseGas: true,
itx: {},
txType: 'fg:t:transfer',
stateSnapshot: {},
// Protocol-specific fields
factoryState: { address: 'z789' },
customField: 'value',
};
expect(context.factoryState).toBeDefined();
expect(context.customField).toBe('value');
});
});
});