@ocap/types 1.28.8 → 1.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +23 -1
- package/interfaces/base.ts +38 -0
- package/interfaces/config.ts +166 -0
- package/interfaces/index.ts +254 -0
- package/interfaces/indexdb.ts +444 -0
- package/interfaces/pipeline.ts +525 -0
- package/interfaces/resolver.ts +503 -0
- package/interfaces/state.ts +327 -0
- package/interfaces/statedb.ts +193 -0
- package/interfaces/testing.ts +122 -0
- package/lib/enum_pb.d.ts +0 -3
- package/lib/rpc_pb.d.ts +0 -1591
- package/lib/service_pb.d.ts +0 -2
- package/lib/state_pb.d.ts +0 -840
- package/lib/trace-type_pb.d.ts +0 -1304
- package/lib/tx_pb.d.ts +0 -1687
- package/lib/type_pb.d.ts +0 -1781
- package/lib/vendor_pb.d.ts +0 -406
- package/package.json +10 -4
- package/tests/interfaces-reexport.spec.ts +76 -0
- package/tests/interfaces.spec.ts +265 -0
- package/tests/pipeline.spec.ts +249 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
// core/types/tests/interfaces.spec.ts
|
|
2
|
+
// 冒烟测试:验证接口定义可正确导入和使用
|
|
3
|
+
|
|
4
|
+
import { describe, expect, test } from 'bun:test';
|
|
5
|
+
import { BN } from '@ocap/util';
|
|
6
|
+
import type {
|
|
7
|
+
// base
|
|
8
|
+
BN as BNType,
|
|
9
|
+
BytesType,
|
|
10
|
+
DeepPartial,
|
|
11
|
+
// hooks
|
|
12
|
+
HookPhase,
|
|
13
|
+
IAccountState,
|
|
14
|
+
IAny,
|
|
15
|
+
IChainConfig,
|
|
16
|
+
// statedb
|
|
17
|
+
IDBTransaction,
|
|
18
|
+
IHookHandler,
|
|
19
|
+
IHookResult,
|
|
20
|
+
IPage,
|
|
21
|
+
IPageInfo,
|
|
22
|
+
IPagedResult,
|
|
23
|
+
IRangeFilter,
|
|
24
|
+
ISearchResult,
|
|
25
|
+
// state
|
|
26
|
+
IState,
|
|
27
|
+
IStateContext,
|
|
28
|
+
IStateWithOwner,
|
|
29
|
+
ITimeFilter,
|
|
30
|
+
PartialBy,
|
|
31
|
+
RequiredBy,
|
|
32
|
+
StateChangeType,
|
|
33
|
+
StateKind,
|
|
34
|
+
Timestamp,
|
|
35
|
+
} from '../interfaces';
|
|
36
|
+
|
|
37
|
+
describe('core/types/interfaces', () => {
|
|
38
|
+
describe('base types', () => {
|
|
39
|
+
test('should define BytesType as string | Buffer | Uint8Array', () => {
|
|
40
|
+
const str: BytesType = 'hello';
|
|
41
|
+
const buf: BytesType = Buffer.from('hello');
|
|
42
|
+
const arr: BytesType = new Uint8Array([1, 2, 3]);
|
|
43
|
+
expect(str).toBeDefined();
|
|
44
|
+
expect(buf).toBeDefined();
|
|
45
|
+
expect(arr).toBeDefined();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('should define BN type compatible with @ocap/util BN class', () => {
|
|
49
|
+
// BN class from @ocap/util should satisfy BNType from @ocap/types
|
|
50
|
+
const fromStr: BNType = new BN('1000000');
|
|
51
|
+
const fromNum: BNType = new BN(1000000);
|
|
52
|
+
const fromNull: BNType = new BN(null);
|
|
53
|
+
expect(fromStr.toString()).toBe('1000000');
|
|
54
|
+
expect(fromNum.toString()).toBe('1000000');
|
|
55
|
+
expect(fromNull.toString()).toBe('0');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('should define Timestamp as string | number | Date', () => {
|
|
59
|
+
const str: Timestamp = '2024-01-01T00:00:00Z';
|
|
60
|
+
const num: Timestamp = Date.now();
|
|
61
|
+
const date: Timestamp = new Date();
|
|
62
|
+
expect(str).toBeDefined();
|
|
63
|
+
expect(num).toBeDefined();
|
|
64
|
+
expect(date).toBeDefined();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('should define IAny interface', () => {
|
|
68
|
+
const any: IAny = {
|
|
69
|
+
typeUrl: 'type.googleapis.com/example',
|
|
70
|
+
value: new Uint8Array([1, 2, 3]),
|
|
71
|
+
};
|
|
72
|
+
expect(any.typeUrl).toBe('type.googleapis.com/example');
|
|
73
|
+
expect(any.value).toBeInstanceOf(Uint8Array);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('should define utility types', () => {
|
|
77
|
+
type Example = { a: string; b: number; c: boolean };
|
|
78
|
+
type PartialA = PartialBy<Example, 'a'>;
|
|
79
|
+
type RequiredC = RequiredBy<Partial<Example>, 'c'>;
|
|
80
|
+
type Deep = DeepPartial<Example>;
|
|
81
|
+
|
|
82
|
+
const partial: PartialA = { b: 1, c: true };
|
|
83
|
+
const required: RequiredC = { c: false };
|
|
84
|
+
const deep: Deep = { a: 'test' };
|
|
85
|
+
|
|
86
|
+
expect(partial).toBeDefined();
|
|
87
|
+
expect(required).toBeDefined();
|
|
88
|
+
expect(deep).toBeDefined();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('state types', () => {
|
|
93
|
+
test('should define IStateContext', () => {
|
|
94
|
+
const context: IStateContext = {
|
|
95
|
+
genesisTx: 'tx123',
|
|
96
|
+
renaissanceTx: 'tx456',
|
|
97
|
+
genesisTime: new Date(),
|
|
98
|
+
renaissanceTime: '2024-01-01',
|
|
99
|
+
};
|
|
100
|
+
expect(context.genesisTx).toBe('tx123');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('should define IState', () => {
|
|
104
|
+
const state: IState = {
|
|
105
|
+
address: 'z1234567890',
|
|
106
|
+
context: {
|
|
107
|
+
genesisTx: 'tx123',
|
|
108
|
+
renaissanceTx: 'tx456',
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
expect(state.address).toBe('z1234567890');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('should define IStateWithOwner extending IState', () => {
|
|
115
|
+
const state: IStateWithOwner = {
|
|
116
|
+
address: 'z1234567890',
|
|
117
|
+
owner: 'z0987654321',
|
|
118
|
+
issuer: 'z1111111111',
|
|
119
|
+
};
|
|
120
|
+
expect(state.owner).toBeDefined();
|
|
121
|
+
expect(state.issuer).toBeDefined();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('should define StateKind union', () => {
|
|
125
|
+
const types: StateKind[] = [
|
|
126
|
+
'account',
|
|
127
|
+
'asset',
|
|
128
|
+
'token',
|
|
129
|
+
'token-factory',
|
|
130
|
+
'asset-factory',
|
|
131
|
+
'stake',
|
|
132
|
+
'delegation',
|
|
133
|
+
'rollup',
|
|
134
|
+
'rollup-block',
|
|
135
|
+
'evidence',
|
|
136
|
+
];
|
|
137
|
+
expect(types).toHaveLength(10);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('should define StateChangeType union', () => {
|
|
141
|
+
const types: StateChangeType[] = ['create', 'update', 'delete'];
|
|
142
|
+
expect(types).toHaveLength(3);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe('execution types', () => {
|
|
147
|
+
test('should define IChainConfig', () => {
|
|
148
|
+
const config: IChainConfig = {
|
|
149
|
+
chainId: 'test-chain',
|
|
150
|
+
chainName: 'Test Chain',
|
|
151
|
+
consensus: {},
|
|
152
|
+
transaction: {},
|
|
153
|
+
token: {},
|
|
154
|
+
};
|
|
155
|
+
expect(config.chainId).toBe('test-chain');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test('should define IAccountState extending IState', () => {
|
|
159
|
+
const account: IAccountState = {
|
|
160
|
+
address: 'z1234567890',
|
|
161
|
+
balance: '1000000',
|
|
162
|
+
nonce: '1',
|
|
163
|
+
numTxs: '10',
|
|
164
|
+
pk: 'pk123',
|
|
165
|
+
moniker: 'alice',
|
|
166
|
+
};
|
|
167
|
+
expect(account.balance).toBe('1000000');
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe('hook types', () => {
|
|
172
|
+
test('should define HookPhase union', () => {
|
|
173
|
+
const phases: HookPhase[] = ['pre-check', 'post-check', 'pre-apply', 'post-apply', 'pre-commit', 'post-commit'];
|
|
174
|
+
expect(phases).toHaveLength(6);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test('should define IHookResult', () => {
|
|
178
|
+
const result: IHookResult = {
|
|
179
|
+
continue: true,
|
|
180
|
+
code: 0,
|
|
181
|
+
message: 'success',
|
|
182
|
+
};
|
|
183
|
+
expect(result.continue).toBe(true);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test('should define IHookHandler', () => {
|
|
187
|
+
const handler: IHookHandler = {
|
|
188
|
+
name: 'test-hook',
|
|
189
|
+
priority: 50,
|
|
190
|
+
handler: async () => ({ continue: true }),
|
|
191
|
+
};
|
|
192
|
+
expect(handler.name).toBe('test-hook');
|
|
193
|
+
expect(handler.priority).toBe(50);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe('statedb types', () => {
|
|
198
|
+
test('should define IDBTransaction', () => {
|
|
199
|
+
const tx: IDBTransaction = {
|
|
200
|
+
id: 'tx-123',
|
|
201
|
+
state: 'pending',
|
|
202
|
+
};
|
|
203
|
+
expect(tx.state).toBe('pending');
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe('indexdb types', () => {
|
|
208
|
+
test('should define IPage', () => {
|
|
209
|
+
const page: IPage = {
|
|
210
|
+
cursor: 'abc123',
|
|
211
|
+
size: 20,
|
|
212
|
+
order: 'desc',
|
|
213
|
+
};
|
|
214
|
+
expect(page.size).toBe(20);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test('should define IPageInfo extending IPage', () => {
|
|
218
|
+
const pageInfo: IPageInfo = {
|
|
219
|
+
cursor: 'abc123',
|
|
220
|
+
size: 20,
|
|
221
|
+
order: 'desc',
|
|
222
|
+
next: 'def456',
|
|
223
|
+
hasMore: true,
|
|
224
|
+
};
|
|
225
|
+
expect(pageInfo.hasMore).toBe(true);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test('should define IPagedResult', () => {
|
|
229
|
+
const result: IPagedResult<{ id: string }> = {
|
|
230
|
+
data: [{ id: '1' }, { id: '2' }],
|
|
231
|
+
page: { hasMore: false },
|
|
232
|
+
total: 2,
|
|
233
|
+
};
|
|
234
|
+
expect(result.data).toHaveLength(2);
|
|
235
|
+
expect(result.total).toBe(2);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test('should define ITimeFilter', () => {
|
|
239
|
+
const filter: ITimeFilter = {
|
|
240
|
+
start: '2024-01-01',
|
|
241
|
+
end: new Date(),
|
|
242
|
+
};
|
|
243
|
+
expect(filter.start).toBeDefined();
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test('should define IRangeFilter', () => {
|
|
247
|
+
const filter: IRangeFilter = {
|
|
248
|
+
min: 0,
|
|
249
|
+
max: '1000000',
|
|
250
|
+
};
|
|
251
|
+
expect(filter.min).toBe(0);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
test('should define ISearchResult', () => {
|
|
255
|
+
const result: ISearchResult = {
|
|
256
|
+
type: 'account',
|
|
257
|
+
address: 'z1234567890',
|
|
258
|
+
score: 0.95,
|
|
259
|
+
highlights: ['<em>alice</em>'],
|
|
260
|
+
data: { moniker: 'alice' },
|
|
261
|
+
};
|
|
262
|
+
expect(result.score).toBe(0.95);
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
});
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
// core/types/tests/pipeline.spec.ts
|
|
2
|
+
// Tests for 5-phase context type hierarchy
|
|
3
|
+
|
|
4
|
+
import { describe, expect, test } from 'bun:test';
|
|
5
|
+
import type {
|
|
6
|
+
IBaseContext,
|
|
7
|
+
IChainConfig,
|
|
8
|
+
IDecodedContext,
|
|
9
|
+
IGasContext,
|
|
10
|
+
IReadyContext,
|
|
11
|
+
IStateDB,
|
|
12
|
+
IWithSender,
|
|
13
|
+
} from '../interfaces';
|
|
14
|
+
import type { TStakeTx, TTransferTx } from '../lib/tx_pb';
|
|
15
|
+
|
|
16
|
+
describe('Pipeline Context Types', () => {
|
|
17
|
+
const mockStateDB = {} as IStateDB;
|
|
18
|
+
const mockConfig = { chainId: 'test', chainName: 'Test' } as IChainConfig;
|
|
19
|
+
const mockIndexDB = {} as IBaseContext['indexdb'];
|
|
20
|
+
|
|
21
|
+
describe('IBaseContext', () => {
|
|
22
|
+
test('should require mandatory fields', () => {
|
|
23
|
+
const context: IBaseContext = {
|
|
24
|
+
txBase64: 'base64data',
|
|
25
|
+
statedb: mockStateDB,
|
|
26
|
+
config: mockConfig,
|
|
27
|
+
indexdb: mockIndexDB,
|
|
28
|
+
};
|
|
29
|
+
expect(context.txBase64).toBe('base64data');
|
|
30
|
+
expect(context.statedb).toBe(mockStateDB);
|
|
31
|
+
expect(context.config).toBe(mockConfig);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('should allow optional fields', () => {
|
|
35
|
+
const context: IBaseContext = {
|
|
36
|
+
txBase64: 'base64data',
|
|
37
|
+
statedb: mockStateDB,
|
|
38
|
+
config: mockConfig,
|
|
39
|
+
indexdb: mockIndexDB,
|
|
40
|
+
logger: { debug: () => {}, info: () => {}, warn: () => {}, error: () => {} },
|
|
41
|
+
extra: { key: 'value' },
|
|
42
|
+
};
|
|
43
|
+
expect(context.logger).toBeDefined();
|
|
44
|
+
expect(context.extra?.key).toBe('value');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('IDecodedContext', () => {
|
|
49
|
+
test('should include tx and itx fields', () => {
|
|
50
|
+
const context: IDecodedContext<TTransferTx> = {
|
|
51
|
+
txBase64: 'base64data',
|
|
52
|
+
statedb: mockStateDB,
|
|
53
|
+
config: mockConfig,
|
|
54
|
+
indexdb: mockIndexDB,
|
|
55
|
+
tx: {
|
|
56
|
+
from: 'z123',
|
|
57
|
+
chainId: 'test',
|
|
58
|
+
nonce: 1,
|
|
59
|
+
pk: new Uint8Array(),
|
|
60
|
+
itx: { typeUrl: '', value: new Uint8Array() },
|
|
61
|
+
},
|
|
62
|
+
txHash: 'hash123',
|
|
63
|
+
txTime: '2024-01-01T00:00:00Z',
|
|
64
|
+
txSize: 256,
|
|
65
|
+
txBaseGas: true,
|
|
66
|
+
itx: { to: 'z456', value: '100', tokens: [] },
|
|
67
|
+
txType: 'fg:t:transfer',
|
|
68
|
+
};
|
|
69
|
+
expect(context.txHash).toBe('hash123');
|
|
70
|
+
expect(context.txType).toBe('fg:t:transfer');
|
|
71
|
+
expect(context.itx?.to).toBe('z456');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('IGasContext', () => {
|
|
76
|
+
test('should include gas calculation fields', () => {
|
|
77
|
+
const context: IGasContext = {
|
|
78
|
+
txBase64: 'base64data',
|
|
79
|
+
statedb: mockStateDB,
|
|
80
|
+
config: mockConfig,
|
|
81
|
+
indexdb: mockIndexDB,
|
|
82
|
+
tx: {
|
|
83
|
+
from: 'z123',
|
|
84
|
+
chainId: 'test',
|
|
85
|
+
nonce: 1,
|
|
86
|
+
pk: new Uint8Array(),
|
|
87
|
+
itx: { typeUrl: '', value: new Uint8Array() },
|
|
88
|
+
},
|
|
89
|
+
txHash: 'hash123',
|
|
90
|
+
txTime: '2024-01-01T00:00:00Z',
|
|
91
|
+
txSize: 256,
|
|
92
|
+
txBaseGas: true,
|
|
93
|
+
itx: {},
|
|
94
|
+
txType: 'fg:t:transfer',
|
|
95
|
+
gasEstimate: { create: 1, update: 2, payment: 0 },
|
|
96
|
+
senderUpdates: {},
|
|
97
|
+
gasPaid: false,
|
|
98
|
+
};
|
|
99
|
+
expect(context.gasEstimate?.create).toBe(1);
|
|
100
|
+
expect(context.gasPaid).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe('IReadyContext', () => {
|
|
105
|
+
test('should include state snapshot', () => {
|
|
106
|
+
const context: IReadyContext = {
|
|
107
|
+
txBase64: 'base64data',
|
|
108
|
+
statedb: mockStateDB,
|
|
109
|
+
config: mockConfig,
|
|
110
|
+
indexdb: mockIndexDB,
|
|
111
|
+
tx: {
|
|
112
|
+
from: 'z123',
|
|
113
|
+
chainId: 'test',
|
|
114
|
+
nonce: 1,
|
|
115
|
+
pk: new Uint8Array(),
|
|
116
|
+
itx: { typeUrl: '', value: new Uint8Array() },
|
|
117
|
+
},
|
|
118
|
+
txHash: 'hash123',
|
|
119
|
+
txTime: '2024-01-01T00:00:00Z',
|
|
120
|
+
txSize: 256,
|
|
121
|
+
txBaseGas: true,
|
|
122
|
+
itx: {},
|
|
123
|
+
txType: 'fg:t:transfer',
|
|
124
|
+
stateSnapshot: { z123: { address: 'z123', tokens: {} } },
|
|
125
|
+
};
|
|
126
|
+
expect(context.stateSnapshot).toBeDefined();
|
|
127
|
+
expect(context.stateSnapshot.z123).toBeDefined();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test('should support generic TItx', () => {
|
|
131
|
+
type TransferContext = IReadyContext<TTransferTx>;
|
|
132
|
+
const context: TransferContext = {
|
|
133
|
+
txBase64: 'base64data',
|
|
134
|
+
statedb: mockStateDB,
|
|
135
|
+
config: mockConfig,
|
|
136
|
+
indexdb: mockIndexDB,
|
|
137
|
+
tx: {
|
|
138
|
+
from: 'z123',
|
|
139
|
+
chainId: 'test',
|
|
140
|
+
nonce: 1,
|
|
141
|
+
pk: new Uint8Array(),
|
|
142
|
+
itx: { typeUrl: '', value: new Uint8Array() },
|
|
143
|
+
},
|
|
144
|
+
txHash: 'hash123',
|
|
145
|
+
txTime: '2024-01-01T00:00:00Z',
|
|
146
|
+
txSize: 256,
|
|
147
|
+
txBaseGas: true,
|
|
148
|
+
itx: { to: 'z456', value: '100', tokens: [] },
|
|
149
|
+
txType: 'fg:t:transfer',
|
|
150
|
+
stateSnapshot: {},
|
|
151
|
+
};
|
|
152
|
+
expect(context.itx?.to).toBe('z456');
|
|
153
|
+
expect(context.itx?.value).toBe('100');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test('should support TStakeTx via generic', () => {
|
|
157
|
+
type StakeContext = IReadyContext<TStakeTx>;
|
|
158
|
+
const context: StakeContext = {
|
|
159
|
+
txBase64: 'base64data',
|
|
160
|
+
statedb: mockStateDB,
|
|
161
|
+
config: mockConfig,
|
|
162
|
+
indexdb: mockIndexDB,
|
|
163
|
+
tx: {
|
|
164
|
+
from: 'z123',
|
|
165
|
+
chainId: 'test',
|
|
166
|
+
nonce: 1,
|
|
167
|
+
pk: new Uint8Array(),
|
|
168
|
+
itx: { typeUrl: '', value: new Uint8Array() },
|
|
169
|
+
},
|
|
170
|
+
txHash: 'hash123',
|
|
171
|
+
txTime: '2024-01-01T00:00:00Z',
|
|
172
|
+
txSize: 256,
|
|
173
|
+
txBaseGas: true,
|
|
174
|
+
itx: { to: 'z456', tokens: [] },
|
|
175
|
+
txType: 'fg:t:stake',
|
|
176
|
+
stateSnapshot: {},
|
|
177
|
+
};
|
|
178
|
+
expect(context.itx?.to).toBe('z456');
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe('Mixin Interfaces', () => {
|
|
183
|
+
test('should allow combining phase types with mixins', () => {
|
|
184
|
+
type TransferContext = IReadyContext<TTransferTx> & IWithSender;
|
|
185
|
+
const context: TransferContext = {
|
|
186
|
+
txBase64: 'base64data',
|
|
187
|
+
statedb: mockStateDB,
|
|
188
|
+
config: mockConfig,
|
|
189
|
+
indexdb: mockIndexDB,
|
|
190
|
+
tx: {
|
|
191
|
+
from: 'z123',
|
|
192
|
+
chainId: 'test',
|
|
193
|
+
nonce: 1,
|
|
194
|
+
pk: new Uint8Array(),
|
|
195
|
+
itx: { typeUrl: '', value: new Uint8Array() },
|
|
196
|
+
},
|
|
197
|
+
txHash: 'hash123',
|
|
198
|
+
txTime: '2024-01-01T00:00:00Z',
|
|
199
|
+
txSize: 256,
|
|
200
|
+
txBaseGas: true,
|
|
201
|
+
itx: { to: 'z456', value: '100', tokens: [] },
|
|
202
|
+
txType: 'fg:t:transfer',
|
|
203
|
+
stateSnapshot: {},
|
|
204
|
+
senderState: {
|
|
205
|
+
address: 'z123',
|
|
206
|
+
balance: '1000',
|
|
207
|
+
nonce: '1',
|
|
208
|
+
numTxs: '10',
|
|
209
|
+
pk: 'pk',
|
|
210
|
+
moniker: 'alice',
|
|
211
|
+
tokens: {},
|
|
212
|
+
context: { genesisTime: '', genesisTx: '' },
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
expect(context.senderState.address).toBe('z123');
|
|
216
|
+
expect(context.senderState.balance).toBe('1000');
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
describe('Dynamic extension', () => {
|
|
221
|
+
test('should allow protocol-specific fields via index signature', () => {
|
|
222
|
+
const context: IReadyContext = {
|
|
223
|
+
txBase64: 'base64data',
|
|
224
|
+
statedb: mockStateDB,
|
|
225
|
+
config: mockConfig,
|
|
226
|
+
indexdb: mockIndexDB,
|
|
227
|
+
tx: {
|
|
228
|
+
from: 'z123',
|
|
229
|
+
chainId: 'test',
|
|
230
|
+
nonce: 1,
|
|
231
|
+
pk: new Uint8Array(),
|
|
232
|
+
itx: { typeUrl: '', value: new Uint8Array() },
|
|
233
|
+
},
|
|
234
|
+
txHash: 'hash123',
|
|
235
|
+
txTime: '2024-01-01T00:00:00Z',
|
|
236
|
+
txSize: 256,
|
|
237
|
+
txBaseGas: true,
|
|
238
|
+
itx: {},
|
|
239
|
+
txType: 'fg:t:transfer',
|
|
240
|
+
stateSnapshot: {},
|
|
241
|
+
// Protocol-specific fields
|
|
242
|
+
factoryState: { address: 'z789' },
|
|
243
|
+
customField: 'value',
|
|
244
|
+
};
|
|
245
|
+
expect(context.factoryState).toBeDefined();
|
|
246
|
+
expect(context.customField).toBe('value');
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|