@agirails/sdk 2.0.0-beta

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.
Files changed (154) hide show
  1. package/README.md +183 -0
  2. package/dist/ACTPClient.d.ts +52 -0
  3. package/dist/ACTPClient.d.ts.map +1 -0
  4. package/dist/ACTPClient.js +120 -0
  5. package/dist/ACTPClient.js.map +1 -0
  6. package/dist/abi/ACTPKernel.json +1340 -0
  7. package/dist/abi/ERC20.json +38 -0
  8. package/dist/abi/EscrowVault.json +64 -0
  9. package/dist/builders/DeliveryProofBuilder.d.ts +37 -0
  10. package/dist/builders/DeliveryProofBuilder.d.ts.map +1 -0
  11. package/dist/builders/DeliveryProofBuilder.js +165 -0
  12. package/dist/builders/DeliveryProofBuilder.js.map +1 -0
  13. package/dist/builders/QuoteBuilder.d.ts +68 -0
  14. package/dist/builders/QuoteBuilder.d.ts.map +1 -0
  15. package/dist/builders/QuoteBuilder.js +255 -0
  16. package/dist/builders/QuoteBuilder.js.map +1 -0
  17. package/dist/builders/index.d.ts +3 -0
  18. package/dist/builders/index.d.ts.map +1 -0
  19. package/dist/builders/index.js +10 -0
  20. package/dist/builders/index.js.map +1 -0
  21. package/dist/config/networks.d.ts +27 -0
  22. package/dist/config/networks.d.ts.map +1 -0
  23. package/dist/config/networks.js +103 -0
  24. package/dist/config/networks.js.map +1 -0
  25. package/dist/errors/index.d.ts +38 -0
  26. package/dist/errors/index.d.ts.map +1 -0
  27. package/dist/errors/index.js +87 -0
  28. package/dist/errors/index.js.map +1 -0
  29. package/dist/index.d.ts +19 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +68 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/protocol/ACTPKernel.d.ts +30 -0
  34. package/dist/protocol/ACTPKernel.d.ts.map +1 -0
  35. package/dist/protocol/ACTPKernel.js +261 -0
  36. package/dist/protocol/ACTPKernel.js.map +1 -0
  37. package/dist/protocol/EASHelper.d.ts +23 -0
  38. package/dist/protocol/EASHelper.d.ts.map +1 -0
  39. package/dist/protocol/EASHelper.js +106 -0
  40. package/dist/protocol/EASHelper.js.map +1 -0
  41. package/dist/protocol/EscrowVault.d.ts +24 -0
  42. package/dist/protocol/EscrowVault.d.ts.map +1 -0
  43. package/dist/protocol/EscrowVault.js +114 -0
  44. package/dist/protocol/EscrowVault.js.map +1 -0
  45. package/dist/protocol/EventMonitor.d.ts +18 -0
  46. package/dist/protocol/EventMonitor.d.ts.map +1 -0
  47. package/dist/protocol/EventMonitor.js +92 -0
  48. package/dist/protocol/EventMonitor.js.map +1 -0
  49. package/dist/protocol/MessageSigner.d.ts +23 -0
  50. package/dist/protocol/MessageSigner.d.ts.map +1 -0
  51. package/dist/protocol/MessageSigner.js +178 -0
  52. package/dist/protocol/MessageSigner.js.map +1 -0
  53. package/dist/protocol/ProofGenerator.d.ts +22 -0
  54. package/dist/protocol/ProofGenerator.d.ts.map +1 -0
  55. package/dist/protocol/ProofGenerator.js +64 -0
  56. package/dist/protocol/ProofGenerator.js.map +1 -0
  57. package/dist/protocol/QuoteBuilder.d.ts +2 -0
  58. package/dist/protocol/QuoteBuilder.d.ts.map +1 -0
  59. package/dist/protocol/QuoteBuilder.js +7 -0
  60. package/dist/protocol/QuoteBuilder.js.map +1 -0
  61. package/dist/types/eip712.d.ts +106 -0
  62. package/dist/types/eip712.d.ts.map +1 -0
  63. package/dist/types/eip712.js +84 -0
  64. package/dist/types/eip712.js.map +1 -0
  65. package/dist/types/escrow.d.ts +18 -0
  66. package/dist/types/escrow.d.ts.map +1 -0
  67. package/dist/types/escrow.js +3 -0
  68. package/dist/types/escrow.js.map +1 -0
  69. package/dist/types/index.d.ts +6 -0
  70. package/dist/types/index.d.ts.map +1 -0
  71. package/dist/types/index.js +22 -0
  72. package/dist/types/index.js.map +1 -0
  73. package/dist/types/message.d.ts +109 -0
  74. package/dist/types/message.d.ts.map +1 -0
  75. package/dist/types/message.js +3 -0
  76. package/dist/types/message.js.map +1 -0
  77. package/dist/types/state.d.ts +19 -0
  78. package/dist/types/state.d.ts.map +1 -0
  79. package/dist/types/state.js +49 -0
  80. package/dist/types/state.js.map +1 -0
  81. package/dist/types/transaction.d.ts +36 -0
  82. package/dist/types/transaction.d.ts.map +1 -0
  83. package/dist/types/transaction.js +3 -0
  84. package/dist/types/transaction.js.map +1 -0
  85. package/dist/utils/IPFSClient.d.ts +37 -0
  86. package/dist/utils/IPFSClient.d.ts.map +1 -0
  87. package/dist/utils/IPFSClient.js +128 -0
  88. package/dist/utils/IPFSClient.js.map +1 -0
  89. package/dist/utils/NonceManager.d.ts +34 -0
  90. package/dist/utils/NonceManager.d.ts.map +1 -0
  91. package/dist/utils/NonceManager.js +114 -0
  92. package/dist/utils/NonceManager.js.map +1 -0
  93. package/dist/utils/ReceivedNonceTracker.d.ts +35 -0
  94. package/dist/utils/ReceivedNonceTracker.d.ts.map +1 -0
  95. package/dist/utils/ReceivedNonceTracker.js +196 -0
  96. package/dist/utils/ReceivedNonceTracker.js.map +1 -0
  97. package/dist/utils/canonicalJson.d.ts +4 -0
  98. package/dist/utils/canonicalJson.d.ts.map +1 -0
  99. package/dist/utils/canonicalJson.js +21 -0
  100. package/dist/utils/canonicalJson.js.map +1 -0
  101. package/dist/utils/computeTypeHash.d.ts +3 -0
  102. package/dist/utils/computeTypeHash.d.ts.map +1 -0
  103. package/dist/utils/computeTypeHash.js +30 -0
  104. package/dist/utils/computeTypeHash.js.map +1 -0
  105. package/dist/utils/validation.d.ts +6 -0
  106. package/dist/utils/validation.d.ts.map +1 -0
  107. package/dist/utils/validation.js +46 -0
  108. package/dist/utils/validation.js.map +1 -0
  109. package/package.json +73 -0
  110. package/src/ACTPClient.ts +276 -0
  111. package/src/__tests__/ProofGenerator.test.ts +124 -0
  112. package/src/__tests__/QuoteBuilder.test.ts +516 -0
  113. package/src/__tests__/StateMachine.test.ts +82 -0
  114. package/src/__tests__/builders/DeliveryProofBuilder.test.ts +581 -0
  115. package/src/__tests__/integration/ACTPClient.test.ts +263 -0
  116. package/src/__tests__/integration.test.ts +289 -0
  117. package/src/__tests__/protocol/EASHelper.test.ts +472 -0
  118. package/src/__tests__/protocol/EventMonitor.test.ts +382 -0
  119. package/src/__tests__/security/ACTPKernel.security.test.ts +1167 -0
  120. package/src/__tests__/security/EscrowVault.security.test.ts +570 -0
  121. package/src/__tests__/security/MessageSigner.security.test.ts +286 -0
  122. package/src/__tests__/security/NonceReplay.security.test.ts +501 -0
  123. package/src/__tests__/security/validation.security.test.ts +376 -0
  124. package/src/__tests__/utils/IPFSClient.test.ts +262 -0
  125. package/src/__tests__/utils/NonceManager.test.ts +205 -0
  126. package/src/__tests__/utils/canonicalJson.test.ts +153 -0
  127. package/src/abi/ACTPKernel.json +1340 -0
  128. package/src/abi/ERC20.json +40 -0
  129. package/src/abi/EscrowVault.json +66 -0
  130. package/src/builders/DeliveryProofBuilder.ts +326 -0
  131. package/src/builders/QuoteBuilder.ts +483 -0
  132. package/src/builders/index.ts +17 -0
  133. package/src/config/networks.ts +165 -0
  134. package/src/errors/index.ts +130 -0
  135. package/src/index.ts +108 -0
  136. package/src/protocol/ACTPKernel.ts +625 -0
  137. package/src/protocol/EASHelper.ts +197 -0
  138. package/src/protocol/EscrowVault.ts +237 -0
  139. package/src/protocol/EventMonitor.ts +161 -0
  140. package/src/protocol/MessageSigner.ts +336 -0
  141. package/src/protocol/ProofGenerator.ts +119 -0
  142. package/src/protocol/QuoteBuilder.ts +15 -0
  143. package/src/types/eip712.ts +175 -0
  144. package/src/types/escrow.ts +26 -0
  145. package/src/types/index.ts +10 -0
  146. package/src/types/message.ts +145 -0
  147. package/src/types/state.ts +77 -0
  148. package/src/types/transaction.ts +54 -0
  149. package/src/utils/IPFSClient.ts +248 -0
  150. package/src/utils/NonceManager.ts +293 -0
  151. package/src/utils/ReceivedNonceTracker.ts +397 -0
  152. package/src/utils/canonicalJson.ts +38 -0
  153. package/src/utils/computeTypeHash.ts +50 -0
  154. package/src/utils/validation.ts +82 -0
@@ -0,0 +1,263 @@
1
+ /**
2
+ * ACTPClient Integration Test Suite
3
+ *
4
+ * Coverage Target: 80%+ (statements, functions, lines, branches)
5
+ *
6
+ * Test Categories:
7
+ * 1. Client Initialization (4 tests)
8
+ * 2. Module Access (3 tests)
9
+ * 3. Network Utilities (3 tests)
10
+ * 4. Configuration Validation (2 tests)
11
+ *
12
+ * References:
13
+ * - ACTPClient.ts implementation
14
+ * - Factory pattern with async initialization
15
+ */
16
+
17
+ import { Wallet } from 'ethers';
18
+ import { ACTPClient } from '../../ACTPClient';
19
+
20
+ // Test private key and addresses
21
+ const testPrivateKey = '0x' + '1'.repeat(64);
22
+ const testWallet = new Wallet(testPrivateKey);
23
+ const testAddress = testWallet.address;
24
+
25
+ describe('ACTPClient - Client Initialization', () => {
26
+ beforeEach(() => {
27
+ jest.clearAllMocks();
28
+ });
29
+
30
+ it('should initialize client with privateKey', async () => {
31
+ const client = await ACTPClient.create({
32
+ network: 'base-sepolia',
33
+ privateKey: testPrivateKey
34
+ });
35
+
36
+ expect(client).toBeDefined();
37
+ expect(client.kernel).toBeDefined();
38
+ expect(client.escrow).toBeDefined();
39
+ expect(client.events).toBeDefined();
40
+ expect(client.proofGenerator).toBeDefined();
41
+ expect(client.messageSigner).toBeDefined();
42
+
43
+ const address = await client.getAddress();
44
+ expect(address).toBe(testAddress);
45
+ });
46
+
47
+ it('should initialize client with signer', async () => {
48
+ const signer = new Wallet(testPrivateKey);
49
+
50
+ const client = await ACTPClient.create({
51
+ network: 'base-sepolia',
52
+ signer
53
+ });
54
+
55
+ expect(client).toBeDefined();
56
+ expect(client.kernel).toBeDefined();
57
+
58
+ const address = await client.getAddress();
59
+ expect(address).toBe(testAddress);
60
+ });
61
+
62
+ it('should initialize client with custom provider', async () => {
63
+ // Note: Using custom provider requires proper Provider interface
64
+ // For this test, we just verify client can be created without provider
65
+ const client = await ACTPClient.create({
66
+ network: 'base-sepolia',
67
+ privateKey: testPrivateKey
68
+ });
69
+
70
+ expect(client).toBeDefined();
71
+ expect(client.getProvider()).toBeDefined();
72
+ });
73
+
74
+ it('should initialize client with contract overrides', async () => {
75
+ const customKernelAddress = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
76
+ const customEscrowAddress = '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
77
+
78
+ const client = await ACTPClient.create({
79
+ network: 'base-sepolia',
80
+ privateKey: testPrivateKey,
81
+ contracts: {
82
+ actpKernel: customKernelAddress,
83
+ escrowVault: customEscrowAddress
84
+ }
85
+ });
86
+
87
+ expect(client).toBeDefined();
88
+ const networkConfig = client.getNetworkConfig();
89
+ expect(networkConfig.contracts.actpKernel).toBe(customKernelAddress);
90
+ expect(networkConfig.contracts.escrowVault).toBe(customEscrowAddress);
91
+ });
92
+
93
+ it('should initialize client with gas settings overrides', async () => {
94
+ const maxFeePerGas = BigInt('2000000000'); // 2 gwei
95
+ const maxPriorityFeePerGas = BigInt('1000000000'); // 1 gwei
96
+
97
+ const client = await ACTPClient.create({
98
+ network: 'base-sepolia',
99
+ privateKey: testPrivateKey,
100
+ gasSettings: {
101
+ maxFeePerGas,
102
+ maxPriorityFeePerGas
103
+ }
104
+ });
105
+
106
+ expect(client).toBeDefined();
107
+ const networkConfig = client.getNetworkConfig();
108
+ expect(networkConfig.gasSettings?.maxFeePerGas).toEqual(maxFeePerGas);
109
+ expect(networkConfig.gasSettings?.maxPriorityFeePerGas).toEqual(maxPriorityFeePerGas);
110
+ });
111
+
112
+ it('should reject initialization for Base Mainnet (contracts not deployed)', async () => {
113
+ // Base Mainnet has zero addresses - contracts not deployed yet
114
+ await expect(
115
+ ACTPClient.create({
116
+ network: 'base-mainnet',
117
+ privateKey: testPrivateKey
118
+ })
119
+ ).rejects.toThrow('Network configuration error for Base Mainnet');
120
+ });
121
+ });
122
+
123
+ describe('ACTPClient - Module Access', () => {
124
+ let client: ACTPClient;
125
+
126
+ beforeAll(async () => {
127
+ client = await ACTPClient.create({
128
+ network: 'base-sepolia',
129
+ privateKey: testPrivateKey
130
+ });
131
+ });
132
+
133
+ it('should access kernel module', () => {
134
+ expect(client.kernel).toBeDefined();
135
+ expect(typeof client.kernel.createTransaction).toBe('function');
136
+ expect(typeof client.kernel.transitionState).toBe('function');
137
+ });
138
+
139
+ it('should access escrow module', () => {
140
+ expect(client.escrow).toBeDefined();
141
+ expect(typeof client.escrow.approveToken).toBe('function');
142
+ expect(typeof client.escrow.releaseEscrow).toBe('function');
143
+ });
144
+
145
+ it('should access events module', () => {
146
+ expect(client.events).toBeDefined();
147
+ expect(typeof client.events.watchTransaction).toBe('function');
148
+ expect(typeof client.events.onTransactionCreated).toBe('function');
149
+ });
150
+
151
+ it('should access proofGenerator module', () => {
152
+ expect(client.proofGenerator).toBeDefined();
153
+ expect(typeof client.proofGenerator.hashContent).toBe('function');
154
+ });
155
+
156
+ it('should access messageSigner module', () => {
157
+ expect(client.messageSigner).toBeDefined();
158
+ expect(typeof client.messageSigner.signMessage).toBe('function');
159
+ });
160
+ });
161
+
162
+ describe('ACTPClient - Network Utilities', () => {
163
+ let client: ACTPClient;
164
+
165
+ beforeAll(async () => {
166
+ client = await ACTPClient.create({
167
+ network: 'base-sepolia',
168
+ privateKey: testPrivateKey
169
+ });
170
+ });
171
+
172
+ it('should get signer address', async () => {
173
+ const address = await client.getAddress();
174
+ expect(address).toBe(testAddress);
175
+ });
176
+
177
+ it('should get network configuration', () => {
178
+ const networkConfig = client.getNetworkConfig();
179
+ expect(networkConfig).toBeDefined();
180
+ expect(networkConfig.chainId).toBe(84532);
181
+ expect(networkConfig.name).toBe('Base Sepolia');
182
+ expect(networkConfig.contracts).toBeDefined();
183
+ });
184
+
185
+ it('should have frozen network configuration', () => {
186
+ const networkConfig = client.getNetworkConfig();
187
+
188
+ // Verify config is frozen
189
+ expect(Object.isFrozen(networkConfig)).toBe(true);
190
+ expect(Object.isFrozen(networkConfig.contracts)).toBe(true);
191
+ expect(Object.isFrozen(networkConfig.gasSettings)).toBe(true);
192
+ });
193
+ });
194
+
195
+ describe('ACTPClient - Configuration Validation', () => {
196
+ beforeEach(() => {
197
+ jest.clearAllMocks();
198
+ });
199
+
200
+ it('should throw ValidationError when network is missing', async () => {
201
+ await expect(
202
+ ACTPClient.create({
203
+ network: null as any,
204
+ privateKey: testPrivateKey
205
+ })
206
+ ).rejects.toThrow('Network is required');
207
+ });
208
+
209
+ it('should throw ValidationError when auth credentials are missing', async () => {
210
+ await expect(
211
+ ACTPClient.create({
212
+ network: 'base-sepolia'
213
+ // No privateKey, signer, or provider
214
+ })
215
+ ).rejects.toThrow('Provide either privateKey, signer, or provider with signer access');
216
+ });
217
+
218
+ it('should accept valid configuration with all optional fields', async () => {
219
+ const client = await ACTPClient.create({
220
+ network: 'base-sepolia',
221
+ privateKey: testPrivateKey,
222
+ rpcUrl: 'https://custom-rpc.example.com',
223
+ contracts: {
224
+ actpKernel: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
225
+ escrowVault: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
226
+ usdc: '0xcccccccccccccccccccccccccccccccccccccccc'
227
+ },
228
+ gasSettings: {
229
+ maxFeePerGas: BigInt('2000000000'),
230
+ maxPriorityFeePerGas: BigInt('1000000000')
231
+ }
232
+ });
233
+
234
+ expect(client).toBeDefined();
235
+ const networkConfig = client.getNetworkConfig();
236
+ expect(networkConfig.contracts.actpKernel).toBe('0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
237
+ expect(networkConfig.contracts.usdc).toBe('0xcccccccccccccccccccccccccccccccccccccccc');
238
+ });
239
+
240
+ it('should accept configuration with EAS helper', async () => {
241
+ const client = await ACTPClient.create({
242
+ network: 'base-sepolia',
243
+ privateKey: testPrivateKey,
244
+ eas: {
245
+ contractAddress: '0xdddddddddddddddddddddddddddddddddddddddd',
246
+ deliveryProofSchemaId: '0x' + '1'.repeat(64)
247
+ }
248
+ });
249
+
250
+ expect(client).toBeDefined();
251
+ expect(client.eas).toBeDefined();
252
+ });
253
+
254
+ it('should not initialize EAS helper when config is missing', async () => {
255
+ const client = await ACTPClient.create({
256
+ network: 'base-sepolia',
257
+ privateKey: testPrivateKey
258
+ });
259
+
260
+ expect(client).toBeDefined();
261
+ expect(client.eas).toBeUndefined();
262
+ });
263
+ });
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Integration Tests - SDK Logic (No Blockchain Required)
3
+ *
4
+ * These tests validate SDK functionality without needing deployed contracts.
5
+ */
6
+
7
+ import { keccak256, toUtf8Bytes, hexlify, Wallet, randomBytes, HDNodeWallet } from 'ethers';
8
+ import { ProofGenerator } from '../protocol/ProofGenerator';
9
+ import { MessageSigner } from '../protocol/MessageSigner';
10
+ import { State, StateMachine } from '../types/state';
11
+ import { ACTPMessage } from '../types/message';
12
+
13
+ describe('SDK Integration Tests', () => {
14
+ let wallet: HDNodeWallet;
15
+ let proofGenerator: ProofGenerator;
16
+ let messageSigner: MessageSigner;
17
+
18
+ beforeAll(async () => {
19
+ // Create test wallet
20
+ wallet = Wallet.createRandom();
21
+ proofGenerator = new ProofGenerator();
22
+ messageSigner = new MessageSigner(wallet);
23
+
24
+ // Initialize EIP-712 domain for message signing
25
+ const mockKernelAddress = '0x' + '1'.repeat(40);
26
+ await messageSigner.initDomain(mockKernelAddress);
27
+ });
28
+
29
+ describe('Complete Transaction Lifecycle (Mock)', () => {
30
+ it('should follow complete state machine flow', () => {
31
+ // Start state
32
+ let currentState = State.INITIATED;
33
+ expect(StateMachine.isTerminalState(currentState)).toBe(false);
34
+
35
+ // INITIATED → QUOTED
36
+ expect(StateMachine.isValidTransition(currentState, State.QUOTED)).toBe(true);
37
+ currentState = State.QUOTED;
38
+
39
+ // QUOTED → COMMITTED
40
+ expect(StateMachine.isValidTransition(currentState, State.COMMITTED)).toBe(true);
41
+ currentState = State.COMMITTED;
42
+
43
+ // COMMITTED → IN_PROGRESS
44
+ expect(StateMachine.isValidTransition(currentState, State.IN_PROGRESS)).toBe(true);
45
+ currentState = State.IN_PROGRESS;
46
+
47
+ // IN_PROGRESS → DELIVERED
48
+ expect(StateMachine.isValidTransition(currentState, State.DELIVERED)).toBe(true);
49
+ currentState = State.DELIVERED;
50
+
51
+ // DELIVERED → SETTLED
52
+ expect(StateMachine.isValidTransition(currentState, State.SETTLED)).toBe(true);
53
+ currentState = State.SETTLED;
54
+
55
+ // Final state
56
+ expect(StateMachine.isTerminalState(currentState)).toBe(true);
57
+ });
58
+
59
+ it('should reject invalid state transitions', () => {
60
+ // Can't jump from INITIATED to SETTLED
61
+ expect(StateMachine.isValidTransition(State.INITIATED, State.SETTLED)).toBe(false);
62
+
63
+ // Can't go backwards from SETTLED
64
+ expect(StateMachine.isValidTransition(State.SETTLED, State.INITIATED)).toBe(false);
65
+
66
+ // Can't transition from terminal state
67
+ expect(StateMachine.isValidTransition(State.CANCELLED, State.INITIATED)).toBe(false);
68
+ });
69
+ });
70
+
71
+ describe('Delivery Proof Generation & Verification', () => {
72
+ const txId = '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef';
73
+ const deliverable = 'This is the completed translation work. Lorem ipsum dolor sit amet.';
74
+
75
+ it('should generate and verify delivery proof', () => {
76
+ // Generate proof
77
+ const proof = proofGenerator.generateDeliveryProof({
78
+ txId,
79
+ deliverable,
80
+ metadata: {
81
+ language: 'es',
82
+ wordCount: 100
83
+ }
84
+ });
85
+
86
+ expect(proof.txId).toBe(txId);
87
+ expect(proof.contentHash).toMatch(/^0x[a-f0-9]{64}$/);
88
+ expect(proof.metadata.language).toBe('es');
89
+
90
+ // Verify deliverable
91
+ const isValid = proofGenerator.verifyDeliverable(deliverable, proof.contentHash);
92
+ expect(isValid).toBe(true);
93
+
94
+ // Wrong deliverable should fail
95
+ const isInvalid = proofGenerator.verifyDeliverable('wrong content', proof.contentHash);
96
+ expect(isInvalid).toBe(false);
97
+ });
98
+
99
+ it('should encode and decode proof for on-chain submission', () => {
100
+ const proof = proofGenerator.generateDeliveryProof({
101
+ txId,
102
+ deliverable
103
+ });
104
+
105
+ // Encode for on-chain
106
+ const encoded = proofGenerator.encodeProof(proof);
107
+ expect(encoded).toMatch(/^0x[a-f0-9]+$/);
108
+
109
+ // Decode
110
+ const decoded = proofGenerator.decodeProof(encoded);
111
+ expect(decoded.txId).toBe(proof.txId);
112
+ expect(decoded.contentHash).toBe(proof.contentHash);
113
+ expect(decoded.timestamp).toBe(proof.timestamp);
114
+ });
115
+ });
116
+
117
+ describe('Message Signing & Verification', () => {
118
+ it('should sign and verify ACTP messages', async () => {
119
+ const message: ACTPMessage = {
120
+ type: 'quote.request',
121
+ version: '1.0',
122
+ from: messageSigner.addressToDID(wallet.address),
123
+ to: messageSigner.addressToDID('0x' + '1'.repeat(40)),
124
+ timestamp: Date.now(),
125
+ nonce: hexlify(randomBytes(32)),
126
+ serviceRequest: {
127
+ capabilityType: 'translation',
128
+ parameters: {}
129
+ }
130
+ };
131
+
132
+ // Sign
133
+ const signature = await messageSigner.signMessage(message);
134
+ expect(signature).toMatch(/^0x[a-f0-9]{130}$/);
135
+
136
+ // Verify
137
+ const isValid = await messageSigner.verifySignature(message, signature);
138
+ expect(isValid).toBe(true);
139
+ });
140
+
141
+ it('should reject invalid signatures', async () => {
142
+ const message: ACTPMessage = {
143
+ type: 'quote.request',
144
+ version: '1.0',
145
+ from: messageSigner.addressToDID(wallet.address),
146
+ to: messageSigner.addressToDID('0x' + '1'.repeat(40)),
147
+ timestamp: Date.now(),
148
+ nonce: hexlify(randomBytes(32))
149
+ };
150
+
151
+ // Sign with this wallet
152
+ const signature = await messageSigner.signMessage(message);
153
+
154
+ // Modify message (tamper)
155
+ message.timestamp = Date.now() + 1000;
156
+
157
+ // Verification should fail
158
+ const isValid = await messageSigner.verifySignature(message, signature);
159
+ expect(isValid).toBe(false);
160
+ });
161
+
162
+ it('should convert between DID and address', () => {
163
+ const address = wallet.address;
164
+ const did = messageSigner.addressToDID(address);
165
+
166
+ expect(did).toBe(`did:ethr:${address}`);
167
+
168
+ // DID resolution would happen here in real implementation
169
+ expect(did).toMatch(/^did:ethr:0x[a-fA-F0-9]{40}$/);
170
+ });
171
+ });
172
+
173
+ describe('Content Hashing (Keccak256)', () => {
174
+ it('should produce consistent hashes', () => {
175
+ const content = 'Test content for hashing';
176
+
177
+ const hash1 = proofGenerator.hashContent(content);
178
+ const hash2 = proofGenerator.hashContent(content);
179
+
180
+ expect(hash1).toBe(hash2);
181
+ });
182
+
183
+ it('should produce different hashes for different content', () => {
184
+ const content1 = 'Content A';
185
+ const content2 = 'Content B';
186
+
187
+ const hash1 = proofGenerator.hashContent(content1);
188
+ const hash2 = proofGenerator.hashContent(content2);
189
+
190
+ expect(hash1).not.toBe(hash2);
191
+ });
192
+
193
+ it('should handle binary data', () => {
194
+ const buffer = Buffer.from([1, 2, 3, 4, 5]);
195
+ const hash = proofGenerator.hashContent(buffer);
196
+
197
+ expect(hash).toMatch(/^0x[a-f0-9]{64}$/);
198
+ });
199
+
200
+ it('should match ethers.js keccak256', () => {
201
+ const content = 'Hello, ACTP!';
202
+ const contentBytes = toUtf8Bytes(content);
203
+
204
+ const sdkHash = proofGenerator.hashContent(content);
205
+ const ethersHash = keccak256(contentBytes);
206
+
207
+ expect(sdkHash).toBe(ethersHash);
208
+ });
209
+ });
210
+
211
+ describe('Error Scenarios', () => {
212
+ it('should throw on invalid state transitions', () => {
213
+ expect(() => {
214
+ StateMachine.validateTransition(State.INITIATED, State.SETTLED);
215
+ }).toThrow('Invalid state transition');
216
+ });
217
+
218
+ it('should identify terminal states correctly', () => {
219
+ expect(StateMachine.isTerminalState(State.SETTLED)).toBe(true);
220
+ expect(StateMachine.isTerminalState(State.CANCELLED)).toBe(true);
221
+ expect(StateMachine.isTerminalState(State.IN_PROGRESS)).toBe(false);
222
+ });
223
+
224
+ it('should list valid next states', () => {
225
+ const nextStates = StateMachine.getNextValidStates(State.DELIVERED);
226
+ expect(nextStates).toContain(State.SETTLED);
227
+ expect(nextStates).toContain(State.DISPUTED);
228
+ expect(nextStates).toHaveLength(2);
229
+ });
230
+ });
231
+
232
+ describe('Full Mock Transaction Flow', () => {
233
+ it('should simulate complete transaction', async () => {
234
+ console.log('\n=== Mock Transaction Flow ===\n');
235
+
236
+ // 1. Create transaction (INITIATED)
237
+ const txId = hexlify(randomBytes(32));
238
+ let state = State.INITIATED;
239
+ console.log(`1. Transaction created: ${txId}`);
240
+ console.log(` State: ${State[state]}`);
241
+
242
+ // 2. Quote provided (QUOTED)
243
+ state = State.QUOTED;
244
+ console.log(`\n2. Quote provided`);
245
+ console.log(` State: ${State[state]}`);
246
+
247
+ // 3. Funds escrowed (COMMITTED)
248
+ state = State.COMMITTED;
249
+ console.log(`\n3. Funds escrowed`);
250
+ console.log(` State: ${State[state]}`);
251
+
252
+ // 4. Work started (IN_PROGRESS)
253
+ state = State.IN_PROGRESS;
254
+ console.log(`\n4. Work started`);
255
+ console.log(` State: ${State[state]}`);
256
+
257
+ // 5. Work delivered (DELIVERED)
258
+ const deliverable = 'Completed translation: Hola, mundo!';
259
+ const proof = proofGenerator.generateDeliveryProof({
260
+ txId,
261
+ deliverable,
262
+ metadata: { language: 'es', wordCount: 3 }
263
+ });
264
+
265
+ state = State.DELIVERED;
266
+ console.log(`\n5. Work delivered`);
267
+ console.log(` State: ${State[state]}`);
268
+ console.log(` Content Hash: ${proof.contentHash}`);
269
+
270
+ // 6. Verify delivery
271
+ const isValid = proofGenerator.verifyDeliverable(deliverable, proof.contentHash);
272
+ console.log(`\n6. Delivery verified: ${isValid}`);
273
+
274
+ // 7. Settle transaction (SETTLED)
275
+ state = State.SETTLED;
276
+ console.log(`\n7. Transaction settled`);
277
+ console.log(` State: ${State[state]}`);
278
+ console.log(` Terminal: ${StateMachine.isTerminalState(state)}`);
279
+
280
+ // Assertions
281
+ expect(state).toBe(State.SETTLED);
282
+ expect(StateMachine.isTerminalState(state)).toBe(true);
283
+ expect(isValid).toBe(true);
284
+
285
+ console.log('\n=== Transaction Complete ===\n');
286
+ });
287
+ });
288
+ });
289
+