@agirails/sdk 2.2.0 → 2.2.2
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/dist/ACTPClient.d.ts +200 -0
- package/dist/ACTPClient.d.ts.map +1 -1
- package/dist/ACTPClient.js +266 -2
- package/dist/ACTPClient.js.map +1 -1
- package/dist/abi/ACTPKernel.json +16 -0
- package/dist/adapters/AdapterRegistry.d.ts +140 -0
- package/dist/adapters/AdapterRegistry.d.ts.map +1 -0
- package/dist/adapters/AdapterRegistry.js +166 -0
- package/dist/adapters/AdapterRegistry.js.map +1 -0
- package/dist/adapters/AdapterRouter.d.ts +165 -0
- package/dist/adapters/AdapterRouter.d.ts.map +1 -0
- package/dist/adapters/AdapterRouter.js +350 -0
- package/dist/adapters/AdapterRouter.js.map +1 -0
- package/dist/adapters/BaseAdapter.d.ts +17 -0
- package/dist/adapters/BaseAdapter.d.ts.map +1 -1
- package/dist/adapters/BaseAdapter.js +21 -0
- package/dist/adapters/BaseAdapter.js.map +1 -1
- package/dist/adapters/BasicAdapter.d.ts +72 -3
- package/dist/adapters/BasicAdapter.d.ts.map +1 -1
- package/dist/adapters/BasicAdapter.js +170 -2
- package/dist/adapters/BasicAdapter.js.map +1 -1
- package/dist/adapters/IAdapter.d.ts +230 -0
- package/dist/adapters/IAdapter.d.ts.map +1 -0
- package/dist/adapters/IAdapter.js +44 -0
- package/dist/adapters/IAdapter.js.map +1 -0
- package/dist/adapters/StandardAdapter.d.ts +70 -1
- package/dist/adapters/StandardAdapter.d.ts.map +1 -1
- package/dist/adapters/StandardAdapter.js +184 -0
- package/dist/adapters/StandardAdapter.js.map +1 -1
- package/dist/adapters/X402Adapter.d.ts +208 -0
- package/dist/adapters/X402Adapter.d.ts.map +1 -0
- package/dist/adapters/X402Adapter.js +423 -0
- package/dist/adapters/X402Adapter.js.map +1 -0
- package/dist/adapters/index.d.ts +8 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +19 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +4 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +184 -4
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/config/networks.js +3 -3
- package/dist/config/networks.js.map +1 -1
- package/dist/erc8004/ERC8004Bridge.d.ts +155 -0
- package/dist/erc8004/ERC8004Bridge.d.ts.map +1 -0
- package/dist/erc8004/ERC8004Bridge.js +325 -0
- package/dist/erc8004/ERC8004Bridge.js.map +1 -0
- package/dist/erc8004/ReputationReporter.d.ts +223 -0
- package/dist/erc8004/ReputationReporter.d.ts.map +1 -0
- package/dist/erc8004/ReputationReporter.js +266 -0
- package/dist/erc8004/ReputationReporter.js.map +1 -0
- package/dist/erc8004/index.d.ts +36 -0
- package/dist/erc8004/index.d.ts.map +1 -0
- package/dist/erc8004/index.js +46 -0
- package/dist/erc8004/index.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -2
- package/dist/index.js.map +1 -1
- package/dist/protocol/ACTPKernel.d.ts +1 -1
- package/dist/protocol/ACTPKernel.d.ts.map +1 -1
- package/dist/protocol/ACTPKernel.js +16 -7
- package/dist/protocol/ACTPKernel.js.map +1 -1
- package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
- package/dist/runtime/BlockchainRuntime.js +2 -0
- package/dist/runtime/BlockchainRuntime.js.map +1 -1
- package/dist/runtime/IACTPRuntime.d.ts +6 -0
- package/dist/runtime/IACTPRuntime.d.ts.map +1 -1
- package/dist/runtime/MockRuntime.d.ts +12 -0
- package/dist/runtime/MockRuntime.d.ts.map +1 -1
- package/dist/runtime/MockRuntime.js +41 -0
- package/dist/runtime/MockRuntime.js.map +1 -1
- package/dist/runtime/types/MockState.d.ts +6 -0
- package/dist/runtime/types/MockState.d.ts.map +1 -1
- package/dist/runtime/types/MockState.js.map +1 -1
- package/dist/types/adapter.d.ts +359 -0
- package/dist/types/adapter.d.ts.map +1 -0
- package/dist/types/adapter.js +115 -0
- package/dist/types/adapter.js.map +1 -0
- package/dist/types/erc8004.d.ts +184 -0
- package/dist/types/erc8004.d.ts.map +1 -0
- package/dist/types/erc8004.js +132 -0
- package/dist/types/erc8004.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/transaction.d.ts +12 -0
- package/dist/types/transaction.d.ts.map +1 -1
- package/dist/types/x402.d.ts +162 -0
- package/dist/types/x402.d.ts.map +1 -0
- package/dist/types/x402.js +162 -0
- package/dist/types/x402.js.map +1 -0
- package/package.json +3 -2
- package/src/ACTPClient.ts +318 -2
- package/src/abi/ACTPKernel.json +16 -0
- package/src/adapters/AdapterRegistry.ts +173 -0
- package/src/adapters/AdapterRouter.ts +417 -0
- package/src/adapters/BaseAdapter.ts +25 -0
- package/src/adapters/BasicAdapter.ts +199 -3
- package/src/adapters/IAdapter.ts +292 -0
- package/src/adapters/StandardAdapter.ts +220 -1
- package/src/adapters/X402Adapter.ts +653 -0
- package/src/adapters/index.ts +27 -0
- package/src/cli/commands/init.ts +208 -3
- package/src/config/networks.ts +3 -3
- package/src/erc8004/ERC8004Bridge.ts +461 -0
- package/src/erc8004/ReputationReporter.ts +472 -0
- package/src/erc8004/index.ts +61 -0
- package/src/index.ts +43 -0
- package/src/protocol/ACTPKernel.ts +26 -7
- package/src/runtime/BlockchainRuntime.ts +2 -0
- package/src/runtime/IACTPRuntime.ts +6 -0
- package/src/runtime/MockRuntime.ts +42 -0
- package/src/runtime/types/MockState.ts +7 -0
- package/src/types/adapter.ts +296 -0
- package/src/types/erc8004.ts +293 -0
- package/src/types/index.ts +3 -0
- package/src/types/transaction.ts +12 -0
- package/src/types/x402.ts +219 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IAdapter - Common interface for all payment adapters.
|
|
3
|
+
*
|
|
4
|
+
* This interface defines the contract that all payment adapters must implement,
|
|
5
|
+
* enabling the AdapterRouter to select and use any adapter interchangeably.
|
|
6
|
+
*
|
|
7
|
+
* CRITICAL ACTP COMPLIANCE:
|
|
8
|
+
* - pay() creates transaction + locks escrow -> state = COMMITTED
|
|
9
|
+
* - Caller must transition to IN_PROGRESS before work
|
|
10
|
+
* - Caller must transition to DELIVERED with proof after work
|
|
11
|
+
* - Caller must call release() to settle (NO auto-settle)
|
|
12
|
+
*
|
|
13
|
+
* @module adapters/IAdapter
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
AdapterMetadata,
|
|
18
|
+
UnifiedPayParams,
|
|
19
|
+
UnifiedPayResult,
|
|
20
|
+
} from '../types/adapter';
|
|
21
|
+
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// TransactionStatus - Adapter-agnostic status
|
|
24
|
+
// ============================================================================
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Valid transaction states across all adapters.
|
|
28
|
+
*/
|
|
29
|
+
export type AdapterTransactionState =
|
|
30
|
+
| 'INITIATED'
|
|
31
|
+
| 'COMMITTED'
|
|
32
|
+
| 'IN_PROGRESS'
|
|
33
|
+
| 'DELIVERED'
|
|
34
|
+
| 'SETTLED'
|
|
35
|
+
| 'DISPUTED'
|
|
36
|
+
| 'CANCELLED';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Transaction status returned by getStatus().
|
|
40
|
+
*
|
|
41
|
+
* Provides a consistent view of transaction state across different
|
|
42
|
+
* adapter implementations with action hints for what can be done next.
|
|
43
|
+
*/
|
|
44
|
+
export interface TransactionStatus {
|
|
45
|
+
/** Current transaction state */
|
|
46
|
+
state: AdapterTransactionState;
|
|
47
|
+
|
|
48
|
+
/** Can provider start work? (COMMITTED -> IN_PROGRESS) */
|
|
49
|
+
canStartWork: boolean;
|
|
50
|
+
|
|
51
|
+
/** Can provider mark as delivered? (IN_PROGRESS -> DELIVERED) */
|
|
52
|
+
canDeliver: boolean;
|
|
53
|
+
|
|
54
|
+
/** Can escrow be released? (DELIVERED + dispute window expired) */
|
|
55
|
+
canRelease: boolean;
|
|
56
|
+
|
|
57
|
+
/** Can requester dispute? (DELIVERED, within dispute window) */
|
|
58
|
+
canDispute: boolean;
|
|
59
|
+
|
|
60
|
+
/** Transaction amount (formatted string) */
|
|
61
|
+
amount: string;
|
|
62
|
+
|
|
63
|
+
/** Deadline as ISO 8601 string (optional) */
|
|
64
|
+
deadline?: string;
|
|
65
|
+
|
|
66
|
+
/** Dispute window end as ISO 8601 string (optional) */
|
|
67
|
+
disputeWindowEnds?: string;
|
|
68
|
+
|
|
69
|
+
/** Provider address */
|
|
70
|
+
provider: string;
|
|
71
|
+
|
|
72
|
+
/** Requester address */
|
|
73
|
+
requester: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ============================================================================
|
|
77
|
+
// IAdapter Interface
|
|
78
|
+
// ============================================================================
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Common interface for all payment adapters.
|
|
82
|
+
*
|
|
83
|
+
* Implementations include:
|
|
84
|
+
* - BasicAdapter: High-level, opinionated API
|
|
85
|
+
* - StandardAdapter: Balanced control API
|
|
86
|
+
* - X402Adapter: HTTP 402 Payment Required protocol (Phase 1 Step 2)
|
|
87
|
+
* - ERC8004Adapter: Identity-based payments (Phase 1 Step 3)
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* class CustomAdapter implements IAdapter {
|
|
92
|
+
* readonly metadata: AdapterMetadata = {
|
|
93
|
+
* id: 'custom',
|
|
94
|
+
* name: 'Custom Adapter',
|
|
95
|
+
* usesEscrow: true,
|
|
96
|
+
* supportsDisputes: true,
|
|
97
|
+
* requiresIdentity: false,
|
|
98
|
+
* settlementMode: 'explicit',
|
|
99
|
+
* priority: 50,
|
|
100
|
+
* };
|
|
101
|
+
*
|
|
102
|
+
* async pay(params: UnifiedPayParams): Promise<UnifiedPayResult> {
|
|
103
|
+
* // Implementation...
|
|
104
|
+
* }
|
|
105
|
+
*
|
|
106
|
+
* canHandle(params: UnifiedPayParams): boolean {
|
|
107
|
+
* return true; // Can handle all params
|
|
108
|
+
* }
|
|
109
|
+
*
|
|
110
|
+
* validate(params: UnifiedPayParams): void {
|
|
111
|
+
* // Throw if invalid
|
|
112
|
+
* }
|
|
113
|
+
* }
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export interface IAdapter {
|
|
117
|
+
/**
|
|
118
|
+
* Adapter metadata describing capabilities.
|
|
119
|
+
*
|
|
120
|
+
* Used by AdapterRouter for selection and by developers
|
|
121
|
+
* to understand adapter behavior.
|
|
122
|
+
*/
|
|
123
|
+
readonly metadata: AdapterMetadata;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Execute payment through this adapter.
|
|
127
|
+
*
|
|
128
|
+
* IMPORTANT: Returns with state=COMMITTED, NOT settled.
|
|
129
|
+
* Caller must follow ACTP lifecycle:
|
|
130
|
+
* 1. pay() -> COMMITTED
|
|
131
|
+
* 2. startWork() -> IN_PROGRESS
|
|
132
|
+
* 3. deliver() -> DELIVERED
|
|
133
|
+
* 4. release() -> SETTLED (explicit!)
|
|
134
|
+
*
|
|
135
|
+
* @param params - Unified payment parameters
|
|
136
|
+
* @returns Promise resolving to payment result
|
|
137
|
+
* @throws {ValidationError} If params are invalid
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* const result = await adapter.pay({
|
|
142
|
+
* to: '0xProvider...',
|
|
143
|
+
* amount: '100',
|
|
144
|
+
* deadline: '+24h',
|
|
145
|
+
* });
|
|
146
|
+
* console.log(result.state); // 'COMMITTED'
|
|
147
|
+
* console.log(result.releaseRequired); // true
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
pay(params: UnifiedPayParams): Promise<UnifiedPayResult>;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Check if this adapter can handle the given parameters.
|
|
154
|
+
*
|
|
155
|
+
* Used by AdapterRouter to filter adapters that are capable
|
|
156
|
+
* of processing a specific payment request.
|
|
157
|
+
*
|
|
158
|
+
* @param params - Payment parameters to check
|
|
159
|
+
* @returns True if adapter can handle these params
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```typescript
|
|
163
|
+
* if (adapter.canHandle({ to: 'https://api.example.com', amount: '10' })) {
|
|
164
|
+
* // This adapter supports HTTP endpoints
|
|
165
|
+
* }
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
canHandle(params: UnifiedPayParams): boolean;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Validate parameters before execution.
|
|
172
|
+
*
|
|
173
|
+
* Called by AdapterRouter before routing to ensure
|
|
174
|
+
* parameters are valid for this specific adapter.
|
|
175
|
+
*
|
|
176
|
+
* @param params - Parameters to validate
|
|
177
|
+
* @throws {ValidationError} If params are invalid
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript
|
|
181
|
+
* try {
|
|
182
|
+
* adapter.validate(params);
|
|
183
|
+
* } catch (error) {
|
|
184
|
+
* console.error('Invalid params:', error.message);
|
|
185
|
+
* }
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
validate(params: UnifiedPayParams): void;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Get transaction status by ID.
|
|
192
|
+
*
|
|
193
|
+
* Returns current state plus action hints indicating
|
|
194
|
+
* what operations are available.
|
|
195
|
+
*
|
|
196
|
+
* @param txId - Transaction ID
|
|
197
|
+
* @returns Promise resolving to transaction status
|
|
198
|
+
* @throws {Error} If transaction not found
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* const status = await adapter.getStatus(txId);
|
|
203
|
+
* if (status.canRelease) {
|
|
204
|
+
* await adapter.release(escrowId);
|
|
205
|
+
* }
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
getStatus(txId: string): Promise<TransactionStatus>;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Transition to IN_PROGRESS state (provider starts work).
|
|
212
|
+
*
|
|
213
|
+
* Must be called by provider after accepting the transaction.
|
|
214
|
+
* ACTP requires this explicit transition.
|
|
215
|
+
*
|
|
216
|
+
* @param txId - Transaction ID
|
|
217
|
+
* @throws {Error} If transaction not found or wrong state
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* // Provider acknowledges and starts work
|
|
222
|
+
* await adapter.startWork(txId);
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
startWork(txId: string): Promise<void>;
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Transition to DELIVERED state (provider completes work).
|
|
229
|
+
*
|
|
230
|
+
* @param txId - Transaction ID
|
|
231
|
+
* @param proof - Delivery proof (ABI-encoded dispute window)
|
|
232
|
+
* @throws {Error} If transaction not found or wrong state
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* // Provider marks work as delivered with 2-hour dispute window
|
|
237
|
+
* const proof = ethers.AbiCoder.defaultAbiCoder().encode(['uint256'], [7200]);
|
|
238
|
+
* await adapter.deliver(txId, proof);
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
deliver(txId: string, proof: string): Promise<void>;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Release escrow funds (EXPLICIT settlement).
|
|
245
|
+
*
|
|
246
|
+
* MUST be called after dispute window expires or requester approves.
|
|
247
|
+
* This is the ONLY way to settle - NO auto-settle.
|
|
248
|
+
*
|
|
249
|
+
* @param escrowId - Escrow ID (usually same as txId)
|
|
250
|
+
* @param attestationUID - Optional attestation UID for verification
|
|
251
|
+
* @throws {Error} If escrow not found or dispute window active
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```typescript
|
|
255
|
+
* // After dispute window expires
|
|
256
|
+
* await adapter.release(result.escrowId);
|
|
257
|
+
* // Transaction is now SETTLED
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
release(escrowId: string, attestationUID?: string): Promise<void>;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// ============================================================================
|
|
264
|
+
// Type Guards
|
|
265
|
+
// ============================================================================
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Type guard to check if an object implements IAdapter.
|
|
269
|
+
*
|
|
270
|
+
* @param obj - Object to check
|
|
271
|
+
* @returns True if object implements IAdapter
|
|
272
|
+
*/
|
|
273
|
+
export function isAdapter(obj: unknown): obj is IAdapter {
|
|
274
|
+
if (!obj || typeof obj !== 'object') {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const adapter = obj as Partial<IAdapter>;
|
|
279
|
+
|
|
280
|
+
return (
|
|
281
|
+
typeof adapter.metadata === 'object' &&
|
|
282
|
+
adapter.metadata !== null &&
|
|
283
|
+
typeof adapter.metadata.id === 'string' &&
|
|
284
|
+
typeof adapter.pay === 'function' &&
|
|
285
|
+
typeof adapter.canHandle === 'function' &&
|
|
286
|
+
typeof adapter.validate === 'function' &&
|
|
287
|
+
typeof adapter.getStatus === 'function' &&
|
|
288
|
+
typeof adapter.startWork === 'function' &&
|
|
289
|
+
typeof adapter.deliver === 'function' &&
|
|
290
|
+
typeof adapter.release === 'function'
|
|
291
|
+
);
|
|
292
|
+
}
|
|
@@ -16,6 +16,12 @@ import { BaseAdapter, ValidationError } from './BaseAdapter';
|
|
|
16
16
|
import { IACTPRuntime } from '../runtime/IACTPRuntime';
|
|
17
17
|
import { MockTransaction, TransactionState } from '../runtime/types/MockState';
|
|
18
18
|
import { EASHelper } from '../protocol/EASHelper';
|
|
19
|
+
import { IAdapter, TransactionStatus } from './IAdapter';
|
|
20
|
+
import {
|
|
21
|
+
AdapterMetadata,
|
|
22
|
+
UnifiedPayParams,
|
|
23
|
+
UnifiedPayResult,
|
|
24
|
+
} from '../types/adapter';
|
|
19
25
|
|
|
20
26
|
/**
|
|
21
27
|
* Parameters for creating a transaction (standard level).
|
|
@@ -37,6 +43,9 @@ export interface StandardTransactionParams {
|
|
|
37
43
|
|
|
38
44
|
/** Optional: Service description */
|
|
39
45
|
serviceDescription?: string;
|
|
46
|
+
|
|
47
|
+
/** Optional: ERC-8004 agent ID (for reputation reporting) */
|
|
48
|
+
agentId?: string;
|
|
40
49
|
}
|
|
41
50
|
|
|
42
51
|
/**
|
|
@@ -71,7 +80,20 @@ export interface StandardTransactionParams {
|
|
|
71
80
|
* await client.standard.releaseEscrow(escrowId);
|
|
72
81
|
* ```
|
|
73
82
|
*/
|
|
74
|
-
export class StandardAdapter extends BaseAdapter {
|
|
83
|
+
export class StandardAdapter extends BaseAdapter implements IAdapter {
|
|
84
|
+
/**
|
|
85
|
+
* Adapter metadata for router selection.
|
|
86
|
+
*/
|
|
87
|
+
public readonly metadata: AdapterMetadata = {
|
|
88
|
+
id: 'standard',
|
|
89
|
+
name: 'Standard Adapter',
|
|
90
|
+
usesEscrow: true,
|
|
91
|
+
supportsDisputes: true,
|
|
92
|
+
requiresIdentity: false,
|
|
93
|
+
settlementMode: 'timed', // Auto-release after dispute window
|
|
94
|
+
priority: 60, // Higher priority than basic (preferred when escrow required)
|
|
95
|
+
};
|
|
96
|
+
|
|
75
97
|
/**
|
|
76
98
|
* Creates a new StandardAdapter instance.
|
|
77
99
|
*
|
|
@@ -143,6 +165,7 @@ export class StandardAdapter extends BaseAdapter {
|
|
|
143
165
|
deadline,
|
|
144
166
|
disputeWindow,
|
|
145
167
|
serviceDescription: params.serviceDescription,
|
|
168
|
+
agentId: params.agentId, // ERC-8004 agent ID for reputation reporting
|
|
146
169
|
});
|
|
147
170
|
}
|
|
148
171
|
|
|
@@ -333,4 +356,200 @@ export class StandardAdapter extends BaseAdapter {
|
|
|
333
356
|
async getTransaction(txId: string): Promise<MockTransaction | null> {
|
|
334
357
|
return this.runtime.getTransaction(txId);
|
|
335
358
|
}
|
|
359
|
+
|
|
360
|
+
// ==========================================================================
|
|
361
|
+
// IAdapter Implementation
|
|
362
|
+
// ==========================================================================
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Unified pay method for IAdapter interface.
|
|
366
|
+
*
|
|
367
|
+
* Creates transaction AND links escrow in one call.
|
|
368
|
+
*
|
|
369
|
+
* @param params - Unified payment parameters
|
|
370
|
+
* @returns Promise resolving to unified payment result
|
|
371
|
+
*/
|
|
372
|
+
async pay(params: UnifiedPayParams): Promise<UnifiedPayResult> {
|
|
373
|
+
// Validate using IAdapter validate()
|
|
374
|
+
this.validate(params);
|
|
375
|
+
|
|
376
|
+
// Map to StandardTransactionParams
|
|
377
|
+
const standardParams: StandardTransactionParams = {
|
|
378
|
+
provider: params.to,
|
|
379
|
+
amount: params.amount,
|
|
380
|
+
deadline: params.deadline,
|
|
381
|
+
disputeWindow: params.disputeWindow,
|
|
382
|
+
serviceDescription: params.description,
|
|
383
|
+
agentId: params.erc8004AgentId, // Pass ERC-8004 agent ID
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
// Create transaction
|
|
387
|
+
const txId = await this.createTransaction(standardParams);
|
|
388
|
+
|
|
389
|
+
// Link escrow (auto-transitions to COMMITTED)
|
|
390
|
+
await this.linkEscrow(txId);
|
|
391
|
+
|
|
392
|
+
// Fetch transaction for response
|
|
393
|
+
const tx = await this.runtime.getTransaction(txId);
|
|
394
|
+
if (!tx) {
|
|
395
|
+
throw new Error(`Transaction ${txId} not found after creation`);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const provider = this.validateAddress(params.to, 'to');
|
|
399
|
+
const deadline = tx.deadline;
|
|
400
|
+
|
|
401
|
+
return {
|
|
402
|
+
txId,
|
|
403
|
+
escrowId: txId,
|
|
404
|
+
adapter: this.metadata.id,
|
|
405
|
+
state: 'COMMITTED',
|
|
406
|
+
success: true,
|
|
407
|
+
amount: this.formatAmount(tx.amount),
|
|
408
|
+
releaseRequired: true, // ACTP requires explicit release()
|
|
409
|
+
provider,
|
|
410
|
+
requester: this.requesterAddress,
|
|
411
|
+
deadline: new Date(deadline * 1000).toISOString(),
|
|
412
|
+
erc8004AgentId: params.erc8004AgentId, // Return agent ID
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Check if this adapter can handle the given parameters.
|
|
418
|
+
*
|
|
419
|
+
* StandardAdapter can handle any Ethereum address recipient.
|
|
420
|
+
*
|
|
421
|
+
* @param params - Payment parameters to check
|
|
422
|
+
* @returns True if params have a valid Ethereum address
|
|
423
|
+
*/
|
|
424
|
+
canHandle(params: UnifiedPayParams): boolean {
|
|
425
|
+
// StandardAdapter handles Ethereum addresses only
|
|
426
|
+
if (typeof params.to !== 'string') {
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Check if it's an Ethereum address (0x-prefixed hex)
|
|
431
|
+
return /^0x[a-fA-F0-9]{40}$/.test(params.to);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Validate parameters before execution.
|
|
436
|
+
*
|
|
437
|
+
* @param params - Parameters to validate
|
|
438
|
+
* @throws {ValidationError} If params are invalid
|
|
439
|
+
*/
|
|
440
|
+
validate(params: UnifiedPayParams): void {
|
|
441
|
+
// Validate address
|
|
442
|
+
this.validateAddress(params.to, 'to');
|
|
443
|
+
|
|
444
|
+
// Validate amount (will throw if invalid)
|
|
445
|
+
this.parseAmount(params.amount);
|
|
446
|
+
|
|
447
|
+
// Validate deadline if provided
|
|
448
|
+
if (params.deadline !== undefined) {
|
|
449
|
+
this.parseDeadline(params.deadline);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Validate dispute window if provided
|
|
453
|
+
if (params.disputeWindow !== undefined) {
|
|
454
|
+
this.validateDisputeWindow(params.disputeWindow);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Get transaction status by ID.
|
|
460
|
+
*
|
|
461
|
+
* Returns TransactionStatus with action hints.
|
|
462
|
+
*
|
|
463
|
+
* @param txId - Transaction ID
|
|
464
|
+
* @returns Promise resolving to transaction status
|
|
465
|
+
*/
|
|
466
|
+
async getStatus(txId: string): Promise<TransactionStatus> {
|
|
467
|
+
const tx = await this.runtime.getTransaction(txId);
|
|
468
|
+
|
|
469
|
+
if (!tx) {
|
|
470
|
+
throw new Error(`Transaction ${txId} not found`);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
const now = this.runtime.time.now();
|
|
474
|
+
const disputeWindowEnds = tx.completedAt
|
|
475
|
+
? tx.completedAt + tx.disputeWindow
|
|
476
|
+
: undefined;
|
|
477
|
+
|
|
478
|
+
return {
|
|
479
|
+
state: tx.state as TransactionStatus['state'],
|
|
480
|
+
canStartWork: tx.state === 'COMMITTED',
|
|
481
|
+
canDeliver: tx.state === 'IN_PROGRESS',
|
|
482
|
+
canRelease:
|
|
483
|
+
tx.state === 'DELIVERED' &&
|
|
484
|
+
disputeWindowEnds !== undefined &&
|
|
485
|
+
now >= disputeWindowEnds,
|
|
486
|
+
canDispute:
|
|
487
|
+
tx.state === 'DELIVERED' &&
|
|
488
|
+
disputeWindowEnds !== undefined &&
|
|
489
|
+
now < disputeWindowEnds,
|
|
490
|
+
amount: this.formatAmount(tx.amount),
|
|
491
|
+
deadline: new Date(tx.deadline * 1000).toISOString(),
|
|
492
|
+
disputeWindowEnds: disputeWindowEnds
|
|
493
|
+
? new Date(disputeWindowEnds * 1000).toISOString()
|
|
494
|
+
: undefined,
|
|
495
|
+
provider: tx.provider,
|
|
496
|
+
requester: tx.requester,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Transition to IN_PROGRESS state (provider starts work).
|
|
502
|
+
*
|
|
503
|
+
* @param txId - Transaction ID
|
|
504
|
+
*/
|
|
505
|
+
async startWork(txId: string): Promise<void> {
|
|
506
|
+
await this.runtime.transitionState(txId, 'IN_PROGRESS');
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Transition to DELIVERED state (provider completes work).
|
|
511
|
+
*
|
|
512
|
+
* When no proof is provided, fetches the transaction's actual disputeWindow
|
|
513
|
+
* and encodes it as proof. This ensures consistency with the dispute window
|
|
514
|
+
* specified at transaction creation time.
|
|
515
|
+
*
|
|
516
|
+
* @param txId - Transaction ID
|
|
517
|
+
* @param proof - Optional delivery proof (ABI-encoded dispute window).
|
|
518
|
+
* If not provided, uses transaction's disputeWindow.
|
|
519
|
+
*/
|
|
520
|
+
async deliver(txId: string, proof?: string): Promise<void> {
|
|
521
|
+
let deliveryProof = proof;
|
|
522
|
+
|
|
523
|
+
if (!deliveryProof) {
|
|
524
|
+
// Fetch transaction to get its actual disputeWindow
|
|
525
|
+
const tx = await this.runtime.getTransaction(txId);
|
|
526
|
+
if (!tx) {
|
|
527
|
+
throw new Error(`Transaction ${txId} not found`);
|
|
528
|
+
}
|
|
529
|
+
// Use transaction's disputeWindow, not a default
|
|
530
|
+
deliveryProof = this.encodeDisputeWindowProof(tx.disputeWindow);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
await this.runtime.transitionState(txId, 'DELIVERED', deliveryProof);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Release escrow funds (EXPLICIT settlement).
|
|
538
|
+
*
|
|
539
|
+
* Wrapper around releaseEscrow() for IAdapter interface.
|
|
540
|
+
*
|
|
541
|
+
* @param escrowId - Escrow ID (usually same as txId)
|
|
542
|
+
* @param attestationUID - Optional attestation UID for verification
|
|
543
|
+
*/
|
|
544
|
+
async release(escrowId: string, attestationUID?: string): Promise<void> {
|
|
545
|
+
// Find txId from escrowId (they're usually the same)
|
|
546
|
+
const legacyMatch = escrowId.match(/^escrow-(.+)-\d+$/);
|
|
547
|
+
const txId = legacyMatch ? legacyMatch[1] : escrowId;
|
|
548
|
+
|
|
549
|
+
if (attestationUID) {
|
|
550
|
+
await this.releaseEscrow(escrowId, { txId, attestationUID });
|
|
551
|
+
} else {
|
|
552
|
+
await this.releaseEscrow(escrowId);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
336
555
|
}
|