@agirails/sdk 2.0.2 → 2.0.3

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 (49) hide show
  1. package/README.md +22 -22
  2. package/dist/ACTPClient.d.ts +24 -24
  3. package/dist/ACTPClient.d.ts.map +1 -1
  4. package/dist/ACTPClient.js +18 -18
  5. package/dist/ACTPClient.js.map +1 -1
  6. package/dist/adapters/BasicAdapter.d.ts +152 -0
  7. package/dist/adapters/BasicAdapter.d.ts.map +1 -0
  8. package/dist/adapters/BasicAdapter.js +168 -0
  9. package/dist/adapters/BasicAdapter.js.map +1 -0
  10. package/dist/adapters/StandardAdapter.d.ts +211 -0
  11. package/dist/adapters/StandardAdapter.d.ts.map +1 -0
  12. package/dist/adapters/StandardAdapter.js +260 -0
  13. package/dist/adapters/StandardAdapter.js.map +1 -0
  14. package/dist/adapters/index.d.ts +4 -4
  15. package/dist/adapters/index.d.ts.map +1 -1
  16. package/dist/adapters/index.js +7 -7
  17. package/dist/adapters/index.js.map +1 -1
  18. package/dist/cli/commands/pay.d.ts +1 -1
  19. package/dist/cli/commands/pay.js +2 -2
  20. package/dist/cli/commands/pay.js.map +1 -1
  21. package/dist/cli/commands/tx.d.ts +1 -1
  22. package/dist/cli/commands/tx.js +13 -13
  23. package/dist/cli/commands/tx.js.map +1 -1
  24. package/dist/cli/commands/watch.js +2 -2
  25. package/dist/cli/commands/watch.js.map +1 -1
  26. package/dist/index.d.ts +3 -3
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +6 -6
  29. package/dist/index.js.map +1 -1
  30. package/dist/protocol/ACTPKernel.d.ts +5 -5
  31. package/dist/protocol/ACTPKernel.js +5 -5
  32. package/dist/runtime/BlockchainRuntime.d.ts +1 -1
  33. package/dist/runtime/BlockchainRuntime.js +1 -1
  34. package/dist/runtime/IACTPRuntime.d.ts +1 -1
  35. package/dist/utils/ErrorRecoveryGuide.d.ts +2 -2
  36. package/dist/utils/ErrorRecoveryGuide.js +2 -2
  37. package/package.json +1 -1
  38. package/src/ACTPClient.ts +26 -26
  39. package/src/adapters/{BeginnerAdapter.ts → BasicAdapter.ts} +11 -11
  40. package/src/adapters/{IntermediateAdapter.ts → StandardAdapter.ts} +15 -15
  41. package/src/adapters/index.ts +4 -4
  42. package/src/cli/commands/pay.ts +2 -2
  43. package/src/cli/commands/tx.ts +13 -13
  44. package/src/cli/commands/watch.ts +2 -2
  45. package/src/index.ts +8 -8
  46. package/src/protocol/ACTPKernel.ts +5 -5
  47. package/src/runtime/BlockchainRuntime.ts +1 -1
  48. package/src/runtime/IACTPRuntime.ts +1 -1
  49. package/src/utils/ErrorRecoveryGuide.ts +2 -2
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ /**
3
+ * BasicAdapter - High-level, opinionated API for simple use cases
4
+ *
5
+ * Provides the simplest possible interface for creating and checking transactions.
6
+ * Designed for developers who want to "just make it work" without deep protocol knowledge.
7
+ *
8
+ * Key Features:
9
+ * - Smart defaults (24h deadline, 2-day dispute window)
10
+ * - Inferred requester (from constructor)
11
+ * - User-friendly input (strings, no BigInt)
12
+ * - User-friendly output (formatted amounts, ISO dates)
13
+ *
14
+ * @module adapters/BasicAdapter
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.BasicAdapter = void 0;
18
+ const BaseAdapter_1 = require("./BaseAdapter");
19
+ /**
20
+ * BasicAdapter - High-level API for simple payment flows.
21
+ *
22
+ * This adapter provides the simplest possible interface:
23
+ * - `pay()` - Create and fund a transaction in one call
24
+ * - `checkStatus()` - Get transaction status with action hints
25
+ *
26
+ * All complexity is hidden behind smart defaults.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const client = await ACTPClient.create({ mode: 'mock' });
31
+ *
32
+ * // Simple payment (all defaults)
33
+ * const result = await client.basic.pay({
34
+ * to: '0xProvider123',
35
+ * amount: '100',
36
+ * });
37
+ * console.log('Transaction ID:', result.txId);
38
+ * console.log('Amount:', result.amount); // "100.00 USDC"
39
+ *
40
+ * // Check status
41
+ * const status = await client.basic.checkStatus(result.txId);
42
+ * if (status.canAccept) {
43
+ * console.log('Provider can accept this transaction');
44
+ * }
45
+ * ```
46
+ */
47
+ class BasicAdapter extends BaseAdapter_1.BaseAdapter {
48
+ /**
49
+ * Creates a new BasicAdapter instance.
50
+ *
51
+ * @param runtime - ACTP runtime implementation (MockRuntime or BlockchainRuntime)
52
+ * @param requesterAddress - The requester's Ethereum address
53
+ * @param easHelper - Optional EAS helper for attestation verification (SECURITY FIX C-4)
54
+ */
55
+ constructor(runtime, requesterAddress, easHelper) {
56
+ super(requesterAddress);
57
+ this.runtime = runtime;
58
+ this.easHelper = easHelper;
59
+ }
60
+ /**
61
+ * Create a payment transaction with smart defaults.
62
+ *
63
+ * This is the simplest way to create a transaction - just specify
64
+ * recipient and amount. All other parameters use sensible defaults.
65
+ *
66
+ * Smart defaults:
67
+ * - Requester: Inferred from constructor
68
+ * - Deadline: 24 hours from now
69
+ * - Dispute window: 2 days (172800 seconds)
70
+ *
71
+ * Validations performed:
72
+ * - Address format (0x-prefixed hex)
73
+ * - Amount format (positive number)
74
+ * - Deadline in future
75
+ * - Cannot pay yourself
76
+ *
77
+ * @param params - Payment parameters
78
+ * @returns User-friendly payment result
79
+ * @throws {ValidationError} If inputs are invalid
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const result = await adapter.pay({
84
+ * to: '0xProvider123',
85
+ * amount: '100.50',
86
+ * deadline: '+7d', // Optional: 7 days from now
87
+ * });
88
+ * ```
89
+ */
90
+ async pay(params) {
91
+ // Validate and parse inputs
92
+ const provider = this.validateAddress(params.to, 'to');
93
+ const amount = this.parseAmount(params.amount);
94
+ const currentTime = this.runtime.time.now();
95
+ const deadline = this.parseDeadline(params.deadline, currentTime);
96
+ // SECURITY FIX (L-1): Validate dispute window bounds
97
+ const disputeWindow = this.validateDisputeWindow(params.disputeWindow);
98
+ const requester = this.requesterAddress;
99
+ // Additional validations
100
+ if (requester.toLowerCase() === provider.toLowerCase()) {
101
+ throw new BaseAdapter_1.ValidationError('Cannot pay yourself (requester equals provider)');
102
+ }
103
+ if (deadline <= currentTime) {
104
+ throw new BaseAdapter_1.ValidationError('Deadline must be in the future');
105
+ }
106
+ // Create transaction
107
+ const txId = await this.runtime.createTransaction({
108
+ provider,
109
+ requester,
110
+ amount: amount.toString(),
111
+ deadline,
112
+ disputeWindow,
113
+ });
114
+ // Link escrow (auto-transitions to COMMITTED)
115
+ await this.runtime.linkEscrow(txId, amount.toString());
116
+ // Fetch transaction details for user-friendly response
117
+ const tx = await this.runtime.getTransaction(txId);
118
+ if (!tx) {
119
+ throw new Error(`Transaction ${txId} not found after creation`);
120
+ }
121
+ return {
122
+ txId,
123
+ provider,
124
+ requester,
125
+ amount: this.formatAmount(amount),
126
+ deadline: new Date(deadline * 1000).toISOString(),
127
+ state: tx.state,
128
+ };
129
+ }
130
+ /**
131
+ * Check payment status by transaction ID.
132
+ *
133
+ * Returns current state plus action hints (what can be done next).
134
+ *
135
+ * Action hints:
136
+ * - `canAccept`: Provider can accept (INITIATED state, before deadline)
137
+ * - `canComplete`: Provider can mark as delivered (COMMITTED state)
138
+ * - `canDispute`: Requester can dispute (DELIVERED state, within dispute window)
139
+ *
140
+ * @param txId - Transaction ID to check
141
+ * @returns Status with action hints
142
+ * @throws {Error} If transaction not found
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * const status = await adapter.checkStatus(txId);
147
+ * console.log('State:', status.state); // "COMMITTED"
148
+ * if (status.canComplete) {
149
+ * // Provider can deliver now
150
+ * }
151
+ * ```
152
+ */
153
+ async checkStatus(txId) {
154
+ const tx = await this.runtime.getTransaction(txId);
155
+ if (!tx) {
156
+ throw new Error(`Transaction ${txId} not found`);
157
+ }
158
+ const now = this.runtime.time.now();
159
+ return {
160
+ state: tx.state,
161
+ canAccept: tx.state === 'INITIATED' && tx.deadline > now,
162
+ canComplete: tx.state === 'COMMITTED' || tx.state === 'IN_PROGRESS',
163
+ canDispute: tx.state === 'DELIVERED' && tx.completedAt !== null && tx.completedAt + tx.disputeWindow > now,
164
+ };
165
+ }
166
+ }
167
+ exports.BasicAdapter = BasicAdapter;
168
+ //# sourceMappingURL=BasicAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BasicAdapter.js","sourceRoot":"","sources":["../../src/adapters/BasicAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * StandardAdapter - Balanced API for developers with some protocol knowledge
3
+ *
4
+ * Provides more control than BasicAdapter while still offering convenience:
5
+ * - Explicit transaction lifecycle methods
6
+ * - Direct escrow operations
7
+ * - State transition control
8
+ *
9
+ * Use this adapter when you need fine-grained control but still want
10
+ * user-friendly input parsing and validation.
11
+ *
12
+ * @module adapters/StandardAdapter
13
+ */
14
+ import { BaseAdapter } from './BaseAdapter';
15
+ import { IACTPRuntime } from '../runtime/IACTPRuntime';
16
+ import { MockTransaction, TransactionState } from '../runtime/types/MockState';
17
+ import { EASHelper } from '../protocol/EASHelper';
18
+ /**
19
+ * Parameters for creating a transaction (standard level).
20
+ *
21
+ * More explicit than BasicPayParams but still with smart defaults.
22
+ */
23
+ export interface StandardTransactionParams {
24
+ /** Provider's Ethereum address */
25
+ provider: string;
26
+ /** Amount in user-friendly format ("100", "100.50", "100 USDC") */
27
+ amount: string | number;
28
+ /** Optional: Deadline as relative time ("+24h") or Unix timestamp. Defaults to +24h */
29
+ deadline?: string | number;
30
+ /** Optional: Dispute window in seconds. Defaults to 172800 (2 days) */
31
+ disputeWindow?: number;
32
+ /** Optional: Service description */
33
+ serviceDescription?: string;
34
+ }
35
+ /**
36
+ * StandardAdapter - Balanced API for transaction lifecycle control.
37
+ *
38
+ * Provides explicit methods for each stage of the ACTP lifecycle:
39
+ * - `createTransaction()` - Create transaction without escrow
40
+ * - `linkEscrow()` - Link escrow (auto-transitions to COMMITTED)
41
+ * - `transitionState()` - Manually transition state
42
+ * - `releaseEscrow()` - Release funds to provider
43
+ * - `getEscrowBalance()` - Check escrow balance
44
+ * - `getTransaction()` - Get transaction details
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const client = await ACTPClient.create({ mode: 'mock' });
49
+ *
50
+ * // Create transaction (INITIATED state)
51
+ * const txId = await client.standard.createTransaction({
52
+ * provider: '0xProvider123',
53
+ * amount: '100',
54
+ * deadline: '+7d',
55
+ * });
56
+ *
57
+ * // Link escrow (auto-transitions to COMMITTED)
58
+ * await client.standard.linkEscrow(txId, '100');
59
+ *
60
+ * // Provider delivers
61
+ * await client.standard.transitionState(txId, 'DELIVERED');
62
+ *
63
+ * // Release funds after dispute window
64
+ * await client.standard.releaseEscrow(escrowId);
65
+ * ```
66
+ */
67
+ export declare class StandardAdapter extends BaseAdapter {
68
+ private runtime;
69
+ private easHelper?;
70
+ /**
71
+ * Creates a new StandardAdapter instance.
72
+ *
73
+ * @param runtime - ACTP runtime implementation (MockRuntime or BlockchainRuntime)
74
+ * @param requesterAddress - The requester's Ethereum address
75
+ * @param easHelper - Optional EAS helper for attestation verification (SECURITY FIX C-4)
76
+ */
77
+ constructor(runtime: IACTPRuntime, requesterAddress: string, easHelper?: EASHelper | undefined);
78
+ /**
79
+ * Create a transaction (INITIATED state, no escrow yet).
80
+ *
81
+ * Unlike `basic.pay()`, this only creates the transaction
82
+ * without linking escrow. You must call `linkEscrow()` separately.
83
+ *
84
+ * @param params - Transaction parameters
85
+ * @returns Transaction ID
86
+ * @throws {ValidationError} If inputs are invalid
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * const txId = await adapter.createTransaction({
91
+ * provider: '0xProvider123',
92
+ * amount: '100',
93
+ * deadline: '+24h',
94
+ * });
95
+ * ```
96
+ */
97
+ createTransaction(params: StandardTransactionParams): Promise<string>;
98
+ /**
99
+ * Link escrow to a transaction.
100
+ *
101
+ * Automatically transitions INITIATED or QUOTED → COMMITTED.
102
+ * Deducts funds from requester and locks in escrow.
103
+ *
104
+ * @param txId - Transaction ID
105
+ * @returns Escrow ID
106
+ * @throws {Error} If transaction not found or in wrong state
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * const escrowId = await adapter.linkEscrow(txId);
111
+ * ```
112
+ */
113
+ linkEscrow(txId: string): Promise<string>;
114
+ /**
115
+ * Transition transaction to a new state.
116
+ *
117
+ * Validates the transition against the ACTP 8-state machine.
118
+ *
119
+ * Valid transitions:
120
+ * - INITIATED → QUOTED, COMMITTED, CANCELLED
121
+ * - QUOTED → COMMITTED, CANCELLED
122
+ * - COMMITTED → IN_PROGRESS, DELIVERED, CANCELLED
123
+ * - IN_PROGRESS → DELIVERED, CANCELLED
124
+ * - DELIVERED → SETTLED, DISPUTED
125
+ * - DISPUTED → SETTLED
126
+ *
127
+ * @param txId - Transaction ID
128
+ * @param newState - Target state
129
+ * @throws {Error} If transition is invalid
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * // Provider marks work as delivered
134
+ * await adapter.transitionState(txId, 'DELIVERED');
135
+ * ```
136
+ */
137
+ transitionState(txId: string, newState: TransactionState): Promise<void>;
138
+ /**
139
+ * Release escrow funds to the provider.
140
+ *
141
+ * Can only be called when transaction is in DELIVERED state
142
+ * and dispute window has expired.
143
+ *
144
+ * SECURITY FIX (C-4 + HIGH-5): MANDATORY attestation verification before release.
145
+ * When EASHelper is available (testnet/mainnet modes), attestation verification
146
+ * is REQUIRED - not optional. This prevents releasing funds without proper
147
+ * delivery proof.
148
+ *
149
+ * Verifications performed:
150
+ * - Attestation exists and is not revoked
151
+ * - Attestation belongs to this transaction (prevents replay attacks)
152
+ * - Attestation has not been used for a different transaction
153
+ *
154
+ * @param escrowId - Escrow ID
155
+ * @param attestationParams - Attestation verification params (REQUIRED when EASHelper available)
156
+ * @param attestationParams.txId - Transaction ID (bytes32)
157
+ * @param attestationParams.attestationUID - Attestation UID (bytes32)
158
+ * @throws {Error} If escrow not found or dispute window active
159
+ * @throws {Error} If EASHelper is available but attestationParams not provided (HIGH-5)
160
+ * @throws {Error} If attestation verification fails
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * // With attestation verification (REQUIRED in testnet/mainnet)
165
+ * await adapter.releaseEscrow(escrowId, {
166
+ * txId: '0x...',
167
+ * attestationUID: '0x...'
168
+ * });
169
+ *
170
+ * // Mock mode only (no attestation required)
171
+ * await adapter.releaseEscrow(escrowId);
172
+ * ```
173
+ */
174
+ releaseEscrow(escrowId: string, attestationParams?: {
175
+ txId: string;
176
+ attestationUID: string;
177
+ }): Promise<void>;
178
+ /**
179
+ * Get escrow balance.
180
+ *
181
+ * Returns formatted balance string (e.g., "100.00 USDC").
182
+ *
183
+ * @param escrowId - Escrow ID
184
+ * @returns Formatted balance
185
+ * @throws {Error} If escrow not found
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * const balance = await adapter.getEscrowBalance(escrowId);
190
+ * console.log(balance); // "100.00 USDC"
191
+ * ```
192
+ */
193
+ getEscrowBalance(escrowId: string): Promise<string>;
194
+ /**
195
+ * Get transaction details.
196
+ *
197
+ * Returns the full transaction object from the runtime.
198
+ *
199
+ * @param txId - Transaction ID
200
+ * @returns Transaction object or null if not found
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * const tx = await adapter.getTransaction(txId);
205
+ * console.log('State:', tx?.state);
206
+ * console.log('Amount:', tx?.amount);
207
+ * ```
208
+ */
209
+ getTransaction(txId: string): Promise<MockTransaction | null>;
210
+ }
211
+ //# sourceMappingURL=StandardAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StandardAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/StandardAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,WAAW,EAAmD,MAAM,eAAe,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IAEjB,mEAAmE;IACnE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAExB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE3B,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,oCAAoC;IACpC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,eAAgB,SAAQ,WAAW;IAS5C,OAAO,CAAC,OAAO;IAEf,OAAO,CAAC,SAAS,CAAC;IAVpB;;;;;;OAMG;gBAEO,OAAO,EAAE,YAAY,EAC7B,gBAAgB,EAAE,MAAM,EAChB,SAAS,CAAC,uBAAW;IAK/B;;;;;;;;;;;;;;;;;;OAkBG;IACG,iBAAiB,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,MAAM,CAAC;IA6B3E;;;;;;;;;;;;;;OAcG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW/C;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACG,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACG,aAAa,CACjB,QAAQ,EAAE,MAAM,EAChB,iBAAiB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,GAC3D,OAAO,CAAC,IAAI,CAAC;IAgDhB;;;;;;;;;;;;;;OAcG;IACG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKzD;;;;;;;;;;;;;;OAcG;IACG,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;CAGpE"}
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ /**
3
+ * StandardAdapter - Balanced API for developers with some protocol knowledge
4
+ *
5
+ * Provides more control than BasicAdapter while still offering convenience:
6
+ * - Explicit transaction lifecycle methods
7
+ * - Direct escrow operations
8
+ * - State transition control
9
+ *
10
+ * Use this adapter when you need fine-grained control but still want
11
+ * user-friendly input parsing and validation.
12
+ *
13
+ * @module adapters/StandardAdapter
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.StandardAdapter = void 0;
17
+ const BaseAdapter_1 = require("./BaseAdapter");
18
+ /**
19
+ * StandardAdapter - Balanced API for transaction lifecycle control.
20
+ *
21
+ * Provides explicit methods for each stage of the ACTP lifecycle:
22
+ * - `createTransaction()` - Create transaction without escrow
23
+ * - `linkEscrow()` - Link escrow (auto-transitions to COMMITTED)
24
+ * - `transitionState()` - Manually transition state
25
+ * - `releaseEscrow()` - Release funds to provider
26
+ * - `getEscrowBalance()` - Check escrow balance
27
+ * - `getTransaction()` - Get transaction details
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const client = await ACTPClient.create({ mode: 'mock' });
32
+ *
33
+ * // Create transaction (INITIATED state)
34
+ * const txId = await client.standard.createTransaction({
35
+ * provider: '0xProvider123',
36
+ * amount: '100',
37
+ * deadline: '+7d',
38
+ * });
39
+ *
40
+ * // Link escrow (auto-transitions to COMMITTED)
41
+ * await client.standard.linkEscrow(txId, '100');
42
+ *
43
+ * // Provider delivers
44
+ * await client.standard.transitionState(txId, 'DELIVERED');
45
+ *
46
+ * // Release funds after dispute window
47
+ * await client.standard.releaseEscrow(escrowId);
48
+ * ```
49
+ */
50
+ class StandardAdapter extends BaseAdapter_1.BaseAdapter {
51
+ /**
52
+ * Creates a new StandardAdapter instance.
53
+ *
54
+ * @param runtime - ACTP runtime implementation (MockRuntime or BlockchainRuntime)
55
+ * @param requesterAddress - The requester's Ethereum address
56
+ * @param easHelper - Optional EAS helper for attestation verification (SECURITY FIX C-4)
57
+ */
58
+ constructor(runtime, requesterAddress, easHelper) {
59
+ super(requesterAddress);
60
+ this.runtime = runtime;
61
+ this.easHelper = easHelper;
62
+ }
63
+ /**
64
+ * Create a transaction (INITIATED state, no escrow yet).
65
+ *
66
+ * Unlike `basic.pay()`, this only creates the transaction
67
+ * without linking escrow. You must call `linkEscrow()` separately.
68
+ *
69
+ * @param params - Transaction parameters
70
+ * @returns Transaction ID
71
+ * @throws {ValidationError} If inputs are invalid
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * const txId = await adapter.createTransaction({
76
+ * provider: '0xProvider123',
77
+ * amount: '100',
78
+ * deadline: '+24h',
79
+ * });
80
+ * ```
81
+ */
82
+ async createTransaction(params) {
83
+ const provider = this.validateAddress(params.provider, 'provider');
84
+ const amount = this.parseAmount(params.amount);
85
+ const currentTime = this.runtime.time.now();
86
+ const deadline = this.parseDeadline(params.deadline, currentTime);
87
+ // SECURITY FIX (L-1): Validate dispute window bounds
88
+ const disputeWindow = this.validateDisputeWindow(params.disputeWindow);
89
+ const requester = this.requesterAddress;
90
+ // Validation
91
+ if (requester.toLowerCase() === provider.toLowerCase()) {
92
+ throw new BaseAdapter_1.ValidationError('Cannot create transaction with yourself as provider');
93
+ }
94
+ if (deadline <= currentTime) {
95
+ throw new BaseAdapter_1.ValidationError('Deadline must be in the future');
96
+ }
97
+ return this.runtime.createTransaction({
98
+ provider,
99
+ requester,
100
+ amount: amount.toString(),
101
+ deadline,
102
+ disputeWindow,
103
+ serviceDescription: params.serviceDescription,
104
+ });
105
+ }
106
+ /**
107
+ * Link escrow to a transaction.
108
+ *
109
+ * Automatically transitions INITIATED or QUOTED → COMMITTED.
110
+ * Deducts funds from requester and locks in escrow.
111
+ *
112
+ * @param txId - Transaction ID
113
+ * @returns Escrow ID
114
+ * @throws {Error} If transaction not found or in wrong state
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * const escrowId = await adapter.linkEscrow(txId);
119
+ * ```
120
+ */
121
+ async linkEscrow(txId) {
122
+ const tx = await this.runtime.getTransaction(txId);
123
+ if (!tx) {
124
+ throw new Error(`Transaction ${txId} not found`);
125
+ }
126
+ // Use the transaction's amount (already in correct format)
127
+ return this.runtime.linkEscrow(txId, tx.amount);
128
+ }
129
+ /**
130
+ * Transition transaction to a new state.
131
+ *
132
+ * Validates the transition against the ACTP 8-state machine.
133
+ *
134
+ * Valid transitions:
135
+ * - INITIATED → QUOTED, COMMITTED, CANCELLED
136
+ * - QUOTED → COMMITTED, CANCELLED
137
+ * - COMMITTED → IN_PROGRESS, DELIVERED, CANCELLED
138
+ * - IN_PROGRESS → DELIVERED, CANCELLED
139
+ * - DELIVERED → SETTLED, DISPUTED
140
+ * - DISPUTED → SETTLED
141
+ *
142
+ * @param txId - Transaction ID
143
+ * @param newState - Target state
144
+ * @throws {Error} If transition is invalid
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * // Provider marks work as delivered
149
+ * await adapter.transitionState(txId, 'DELIVERED');
150
+ * ```
151
+ */
152
+ async transitionState(txId, newState) {
153
+ return this.runtime.transitionState(txId, newState);
154
+ }
155
+ /**
156
+ * Release escrow funds to the provider.
157
+ *
158
+ * Can only be called when transaction is in DELIVERED state
159
+ * and dispute window has expired.
160
+ *
161
+ * SECURITY FIX (C-4 + HIGH-5): MANDATORY attestation verification before release.
162
+ * When EASHelper is available (testnet/mainnet modes), attestation verification
163
+ * is REQUIRED - not optional. This prevents releasing funds without proper
164
+ * delivery proof.
165
+ *
166
+ * Verifications performed:
167
+ * - Attestation exists and is not revoked
168
+ * - Attestation belongs to this transaction (prevents replay attacks)
169
+ * - Attestation has not been used for a different transaction
170
+ *
171
+ * @param escrowId - Escrow ID
172
+ * @param attestationParams - Attestation verification params (REQUIRED when EASHelper available)
173
+ * @param attestationParams.txId - Transaction ID (bytes32)
174
+ * @param attestationParams.attestationUID - Attestation UID (bytes32)
175
+ * @throws {Error} If escrow not found or dispute window active
176
+ * @throws {Error} If EASHelper is available but attestationParams not provided (HIGH-5)
177
+ * @throws {Error} If attestation verification fails
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * // With attestation verification (REQUIRED in testnet/mainnet)
182
+ * await adapter.releaseEscrow(escrowId, {
183
+ * txId: '0x...',
184
+ * attestationUID: '0x...'
185
+ * });
186
+ *
187
+ * // Mock mode only (no attestation required)
188
+ * await adapter.releaseEscrow(escrowId);
189
+ * ```
190
+ */
191
+ async releaseEscrow(escrowId, attestationParams) {
192
+ // Determine whether the underlying runtime requires attestation.
193
+ // BlockchainRuntime exposes isAttestationRequired(), but it's not part of the generic interface.
194
+ const runtimeAny = this.runtime;
195
+ const runtimeSupportsAttestationFlag = typeof runtimeAny?.isAttestationRequired === 'function';
196
+ const attestationRequired = runtimeSupportsAttestationFlag
197
+ ? Boolean(runtimeAny.isAttestationRequired())
198
+ : Boolean(this.easHelper);
199
+ if (attestationRequired && !attestationParams) {
200
+ throw new Error('Attestation verification is REQUIRED for escrow release. ' +
201
+ 'Provide attestationParams: { txId: string, attestationUID: string }.');
202
+ }
203
+ // If caller provided attestation params, ensure they match the escrow/tx being released.
204
+ if (attestationParams) {
205
+ // Support legacy escrowId format "escrow-{txId}-{timestamp}".
206
+ // Standard is escrowId === txId.
207
+ const legacyMatch = escrowId.match(/^escrow-(.+)-\d+$/);
208
+ const txIdFromEscrowId = legacyMatch ? legacyMatch[1] : escrowId;
209
+ if (txIdFromEscrowId.toLowerCase() !== attestationParams.txId.toLowerCase()) {
210
+ throw new Error(`Attestation txId (${attestationParams.txId}) does not match escrow/txId (${txIdFromEscrowId}). ` +
211
+ `Refusing to release escrow with mismatched attestation.`);
212
+ }
213
+ // If runtime does NOT handle attestation internally but EASHelper exists, verify here.
214
+ // Otherwise, pass attestationUID down so BlockchainRuntime can enforce/record.
215
+ if (!runtimeSupportsAttestationFlag && this.easHelper) {
216
+ await this.easHelper.verifyAndRecordForRelease(attestationParams.txId, attestationParams.attestationUID);
217
+ }
218
+ }
219
+ return this.runtime.releaseEscrow(escrowId, attestationParams?.attestationUID);
220
+ }
221
+ /**
222
+ * Get escrow balance.
223
+ *
224
+ * Returns formatted balance string (e.g., "100.00 USDC").
225
+ *
226
+ * @param escrowId - Escrow ID
227
+ * @returns Formatted balance
228
+ * @throws {Error} If escrow not found
229
+ *
230
+ * @example
231
+ * ```typescript
232
+ * const balance = await adapter.getEscrowBalance(escrowId);
233
+ * console.log(balance); // "100.00 USDC"
234
+ * ```
235
+ */
236
+ async getEscrowBalance(escrowId) {
237
+ const balance = await this.runtime.getEscrowBalance(escrowId);
238
+ return this.formatAmount(balance);
239
+ }
240
+ /**
241
+ * Get transaction details.
242
+ *
243
+ * Returns the full transaction object from the runtime.
244
+ *
245
+ * @param txId - Transaction ID
246
+ * @returns Transaction object or null if not found
247
+ *
248
+ * @example
249
+ * ```typescript
250
+ * const tx = await adapter.getTransaction(txId);
251
+ * console.log('State:', tx?.state);
252
+ * console.log('Amount:', tx?.amount);
253
+ * ```
254
+ */
255
+ async getTransaction(txId) {
256
+ return this.runtime.getTransaction(txId);
257
+ }
258
+ }
259
+ exports.StandardAdapter = StandardAdapter;
260
+ //# sourceMappingURL=StandardAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StandardAdapter.js","sourceRoot":"","sources":["../../src/adapters/StandardAdapter.ts"],"names":[],"mappings":"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"}
@@ -3,13 +3,13 @@
3
3
  *
4
4
  * This module exports all adapter classes and types for the Three-Level API:
5
5
  * - BaseAdapter: Abstract base with shared utilities
6
- * - BeginnerAdapter: High-level, opinionated API
7
- * - IntermediateAdapter: Balanced control API
6
+ * - BasicAdapter: High-level, opinionated API
7
+ * - StandardAdapter: Balanced control API
8
8
  *
9
9
  * @module adapters
10
10
  */
11
11
  export { BaseAdapter, ValidationError, DEFAULT_DISPUTE_WINDOW_SECONDS, DEFAULT_DEADLINE_SECONDS, MIN_AMOUNT_WEI, MAX_DEADLINE_HOURS, MAX_DEADLINE_DAYS, } from './BaseAdapter';
12
- export { BeginnerAdapter, BeginnerPayParams, BeginnerPayResult } from './BeginnerAdapter';
13
- export { IntermediateAdapter, IntermediateTransactionParams } from './IntermediateAdapter';
12
+ export { BasicAdapter, BasicPayParams, BasicPayResult } from './BasicAdapter';
13
+ export { StandardAdapter, StandardTransactionParams } from './StandardAdapter';
14
14
  export { IACTPRuntime, CreateTransactionParams } from '../runtime/IACTPRuntime';
15
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,WAAW,EACX,eAAe,EACf,8BAA8B,EAC9B,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AAG3F,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,WAAW,EACX,eAAe,EACf,8BAA8B,EAC9B,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAG/E,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC"}