UNPKG

@ocap/types

Version:
250 lines (238 loc) 7.38 kB
// 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'); }); }); });