@abbababa/sdk 0.1.1 → 0.3.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.
Files changed (41) hide show
  1. package/README.md +86 -10
  2. package/dist/buyer.d.ts +26 -11
  3. package/dist/buyer.d.ts.map +1 -1
  4. package/dist/buyer.js +48 -15
  5. package/dist/buyer.js.map +1 -1
  6. package/dist/index.d.ts +2 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/seller.d.ts +30 -2
  11. package/dist/seller.d.ts.map +1 -1
  12. package/dist/seller.js +66 -1
  13. package/dist/seller.js.map +1 -1
  14. package/dist/types.d.ts +36 -9
  15. package/dist/types.d.ts.map +1 -1
  16. package/dist/types.js +21 -1
  17. package/dist/types.js.map +1 -1
  18. package/dist/wallet/abi.d.ts +288 -49
  19. package/dist/wallet/abi.d.ts.map +1 -1
  20. package/dist/wallet/abi.js +216 -43
  21. package/dist/wallet/abi.js.map +1 -1
  22. package/dist/wallet/constants.d.ts +14 -8
  23. package/dist/wallet/constants.d.ts.map +1 -1
  24. package/dist/wallet/constants.js +24 -20
  25. package/dist/wallet/constants.js.map +1 -1
  26. package/dist/wallet/escrow.d.ts +112 -15
  27. package/dist/wallet/escrow.d.ts.map +1 -1
  28. package/dist/wallet/escrow.js +322 -84
  29. package/dist/wallet/escrow.js.map +1 -1
  30. package/dist/wallet/index.d.ts +2 -2
  31. package/dist/wallet/index.d.ts.map +1 -1
  32. package/dist/wallet/index.js +6 -8
  33. package/dist/wallet/index.js.map +1 -1
  34. package/dist/wallet/session-keys.d.ts +9 -6
  35. package/dist/wallet/session-keys.d.ts.map +1 -1
  36. package/dist/wallet/session-keys.js +53 -54
  37. package/dist/wallet/session-keys.js.map +1 -1
  38. package/dist/wallet/smart-account.d.ts.map +1 -1
  39. package/dist/wallet/smart-account.js +4 -3
  40. package/dist/wallet/smart-account.js.map +1 -1
  41. package/package.json +2 -1
@@ -1,21 +1,39 @@
1
1
  import { type TokenInfo } from './constants.js';
2
- import type { EscrowDetails } from '../types.js';
2
+ import type { EscrowDetails, AgentStats } from '../types.js';
3
+ /** Dispute resolution outcome */
4
+ export declare enum DisputeOutcome {
5
+ None = 0,
6
+ BuyerRefund = 1,
7
+ SellerPaid = 2,
8
+ Split = 3
9
+ }
10
+ /** Escrow status codes */
11
+ export declare enum EscrowStatus {
12
+ None = 0,
13
+ Funded = 1,
14
+ Delivered = 2,
15
+ Released = 3,
16
+ Refunded = 4,
17
+ Disputed = 5,
18
+ Resolved = 6,
19
+ Abandoned = 7
20
+ }
3
21
  /**
4
- * Client for interacting with the ServiceEscrow smart contracts.
5
- * Supports V3 (multi-token) with automatic fallback to V2 (USDC only).
22
+ * Client for interacting with the AbbababaEscrowV1 smart contract.
23
+ * Supports UUPS upgradeable escrow with criteriaHash, 3-tier dispute resolution,
24
+ * 24h dispute window, auto-release, and abandonment detection.
6
25
  * Uses a ZeroDev Kernel account client for sending UserOperations.
7
26
  */
8
27
  export declare class EscrowClient {
9
28
  private kernelClient;
10
29
  private chainId;
11
30
  private escrowAddress;
12
- private escrowVersion;
13
31
  private tokenAddress;
14
32
  private tokenDecimals;
15
33
  constructor(kernelClient: unknown, token?: TokenInfo, chainId?: number);
16
34
  /**
17
35
  * Convert a platform transaction ID (CUID string) to a bytes32 escrow ID.
18
- * Uses keccak256, matching the existing backend pattern in escrow.ts (ethers.id).
36
+ * Uses keccak256, matching the existing backend pattern.
19
37
  */
20
38
  static toEscrowId(transactionId: string): `0x${string}`;
21
39
  /**
@@ -23,23 +41,102 @@ export declare class EscrowClient {
23
41
  * Must be called before fundEscrow.
24
42
  */
25
43
  approveToken(amount: bigint): Promise<string>;
26
- /** @deprecated Use approveToken() instead. */
27
- approveUSDC(amount: bigint): Promise<string>;
28
44
  /**
29
- * Fund an escrow. Calls createEscrow on the escrow contract.
30
- * V3: passes token address as 4th argument.
31
- * V2 fallback: USDC only (3 arguments).
45
+ * Generate a criteriaHash from success criteria JSON.
46
+ * The criteriaHash is stored on-chain to enable Tier 1 algorithmic resolution.
47
+ */
48
+ static toCriteriaHash(criteria: object | string): `0x${string}`;
49
+ /**
50
+ * Fund an escrow. Calls V1 createEscrow with 6 args including deadline and criteriaHash.
32
51
  * The contract will safeTransferFrom the token (amount + 1% buyer fee) from the caller.
52
+ *
53
+ * @param transactionId - Platform transaction ID (CUID)
54
+ * @param sellerAddress - Seller's wallet address
55
+ * @param amount - Amount in smallest token units (e.g., USDC with 6 decimals)
56
+ * @param deadline - Unix timestamp for delivery deadline
57
+ * @param criteriaHash - keccak256 hash of success criteria JSON (enables algorithmic dispute resolution)
58
+ */
59
+ fundEscrow(transactionId: string, sellerAddress: string, amount: bigint, deadline: bigint, criteriaHash?: `0x${string}`): Promise<string>;
60
+ /**
61
+ * Submit delivery proof on-chain. Called by the seller after completing work.
62
+ */
63
+ submitDelivery(transactionId: string, proofHash: `0x${string}`): Promise<string>;
64
+ /**
65
+ * Accept delivery and release funds immediately. Called by the buyer.
66
+ */
67
+ acceptDelivery(transactionId: string): Promise<string>;
68
+ /**
69
+ * Finalize release after the 24h dispute window has passed without a dispute.
70
+ * Can be called by anyone.
33
71
  */
34
- fundEscrow(transactionId: string, sellerAddress: string, amount: bigint): Promise<string>;
72
+ finalizeRelease(transactionId: string): Promise<string>;
35
73
  /**
36
- * Release escrow funds to the seller.
37
- * Callable by the buyer or an arbitrator.
74
+ * Dispute a delivery within the 24h dispute window. Called by the buyer.
38
75
  */
39
- releaseEscrow(transactionId: string): Promise<string>;
76
+ disputeEscrow(transactionId: string): Promise<string>;
40
77
  /**
41
- * Read escrow details from the contract (view function, no gas needed).
78
+ * Claim funds for an abandoned escrow (deadline + 7 days passed with no delivery).
79
+ * Called by the buyer to reclaim funds.
80
+ */
81
+ claimAbandoned(transactionId: string): Promise<string>;
82
+ /**
83
+ * Read escrow details from the V1 contract (view function, no gas needed).
42
84
  */
43
85
  getEscrow(transactionId: string): Promise<EscrowDetails | null>;
86
+ /**
87
+ * Check if the 24h dispute window is currently active for an escrow.
88
+ */
89
+ isDisputeWindowActive(transactionId: string): Promise<boolean>;
90
+ /**
91
+ * Check if an escrow can be finalized (dispute window passed, no dispute filed).
92
+ */
93
+ canFinalize(transactionId: string): Promise<boolean>;
94
+ /**
95
+ * Check if an escrow can be claimed as abandoned (deadline + 7 days passed).
96
+ */
97
+ canClaimAbandoned(transactionId: string): Promise<boolean>;
98
+ }
99
+ /**
100
+ * Read-only client for the AbbababaScoreV1 on-chain reputation system.
101
+ * No wallet needed — all methods are view functions.
102
+ */
103
+ export declare class ScoreClient {
104
+ private chainId;
105
+ private scoreAddress;
106
+ constructor(chainId?: number);
107
+ private getPublicClient;
108
+ /**
109
+ * Get an agent's trust score (int256 — can be negative).
110
+ */
111
+ getScore(agentAddress: string): Promise<bigint>;
112
+ /**
113
+ * Get full agent stats from the reputation contract.
114
+ */
115
+ getAgentStats(agentAddress: string): Promise<AgentStats>;
116
+ }
117
+ /**
118
+ * Client for interacting with the AbbababaResolverV1 contract.
119
+ * Used for submitting dispute resolutions (requires appropriate role).
120
+ */
121
+ export declare class ResolverClient {
122
+ private kernelClient;
123
+ private chainId;
124
+ private resolverAddress;
125
+ constructor(kernelClient: unknown, chainId?: number);
126
+ /**
127
+ * Submit Tier 1 algorithmic resolution.
128
+ * Requires ALGORITHM_ROLE on the resolver contract.
129
+ */
130
+ submitAlgorithmicResolution(transactionId: string, outcome: DisputeOutcome, buyerPercent: number, sellerPercent: number, reason: string): Promise<string>;
131
+ /**
132
+ * Submit Tier 2 peer arbitration result.
133
+ * Requires PEER_ARBITER_ROLE on the resolver contract.
134
+ */
135
+ submitPeerArbitrationResult(transactionId: string, outcome: DisputeOutcome, buyerPercent: number, sellerPercent: number, reviewers: [string, string, string, string, string]): Promise<string>;
136
+ /**
137
+ * Submit Tier 3 human review result.
138
+ * Requires HUMAN_REVIEWER_ROLE on the resolver contract.
139
+ */
140
+ submitHumanReview(transactionId: string, outcome: DisputeOutcome, buyerPercent: number, sellerPercent: number, reason: string): Promise<string>;
44
141
  }
45
142
  //# sourceMappingURL=escrow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"escrow.d.ts","sourceRoot":"","sources":["../../src/wallet/escrow.ts"],"names":[],"mappings":"AAWA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAShD;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAO;IAC5B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,aAAa,CAAQ;gBAEjB,YAAY,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,SAAwB;IA6BrF;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE;IAIvD;;;OAGG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmBnD,8CAA8C;IACxC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlD;;;;;OAKG;IACG,UAAU,CACd,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC;IA0BlB;;;OAGG;IACG,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAkB3D;;OAEG;IACG,SAAS,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;CA+DtE"}
1
+ {"version":3,"file":"escrow.d.ts","sourceRoot":"","sources":["../../src/wallet/escrow.ts"],"names":[],"mappings":"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"}
@@ -1,58 +1,68 @@
1
1
  import { encodeFunctionData, keccak256, toBytes, createPublicClient, http, } from 'viem';
2
- import { polygonAmoy, polygon, baseSepolia, base } from 'viem/chains';
3
- import { SERVICE_ESCROW_V2_ABI, SERVICE_ESCROW_V3_ABI, ERC20_ABI } from './abi.js';
4
- import { ESCROW_ADDRESSES, ESCROW_V2_ADDRESSES, USDC_ADDRESSES, POLYGON_AMOY_CHAIN_ID, POLYGON_MAINNET_CHAIN_ID, BASE_SEPOLIA_CHAIN_ID, BASE_MAINNET_CHAIN_ID, } from './constants.js';
2
+ import { baseSepolia, base } from 'viem/chains';
3
+ import { ABBABABA_ESCROW_ABI, ABBABABA_SCORE_ABI, ABBABABA_RESOLVER_ABI, ERC20_ABI } from './abi.js';
4
+ import { ESCROW_V1_ADDRESSES, SCORE_V1_ADDRESSES, RESOLVER_V1_ADDRESSES, BASE_SEPOLIA_CHAIN_ID, BASE_MAINNET_CHAIN_ID, getToken, } from './constants.js';
5
+ /** Dispute resolution outcome */
6
+ export var DisputeOutcome;
7
+ (function (DisputeOutcome) {
8
+ DisputeOutcome[DisputeOutcome["None"] = 0] = "None";
9
+ DisputeOutcome[DisputeOutcome["BuyerRefund"] = 1] = "BuyerRefund";
10
+ DisputeOutcome[DisputeOutcome["SellerPaid"] = 2] = "SellerPaid";
11
+ DisputeOutcome[DisputeOutcome["Split"] = 3] = "Split";
12
+ })(DisputeOutcome || (DisputeOutcome = {}));
13
+ /** Escrow status codes */
14
+ export var EscrowStatus;
15
+ (function (EscrowStatus) {
16
+ EscrowStatus[EscrowStatus["None"] = 0] = "None";
17
+ EscrowStatus[EscrowStatus["Funded"] = 1] = "Funded";
18
+ EscrowStatus[EscrowStatus["Delivered"] = 2] = "Delivered";
19
+ EscrowStatus[EscrowStatus["Released"] = 3] = "Released";
20
+ EscrowStatus[EscrowStatus["Refunded"] = 4] = "Refunded";
21
+ EscrowStatus[EscrowStatus["Disputed"] = 5] = "Disputed";
22
+ EscrowStatus[EscrowStatus["Resolved"] = 6] = "Resolved";
23
+ EscrowStatus[EscrowStatus["Abandoned"] = 7] = "Abandoned";
24
+ })(EscrowStatus || (EscrowStatus = {}));
5
25
  const CHAINS = {
6
- [POLYGON_AMOY_CHAIN_ID]: polygonAmoy,
7
- [POLYGON_MAINNET_CHAIN_ID]: polygon,
8
26
  [BASE_SEPOLIA_CHAIN_ID]: baseSepolia,
9
27
  [BASE_MAINNET_CHAIN_ID]: base,
10
28
  };
29
+ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
30
+ const ZERO_BYTES32 = '0x0000000000000000000000000000000000000000000000000000000000000000';
11
31
  /**
12
- * Client for interacting with the ServiceEscrow smart contracts.
13
- * Supports V3 (multi-token) with automatic fallback to V2 (USDC only).
32
+ * Client for interacting with the AbbababaEscrowV1 smart contract.
33
+ * Supports UUPS upgradeable escrow with criteriaHash, 3-tier dispute resolution,
34
+ * 24h dispute window, auto-release, and abandonment detection.
14
35
  * Uses a ZeroDev Kernel account client for sending UserOperations.
15
36
  */
16
37
  export class EscrowClient {
17
38
  kernelClient;
18
39
  chainId;
19
40
  escrowAddress;
20
- escrowVersion;
21
41
  tokenAddress;
22
42
  tokenDecimals;
23
43
  constructor(kernelClient, token, chainId = BASE_SEPOLIA_CHAIN_ID) {
24
44
  this.kernelClient = kernelClient;
25
45
  this.chainId = chainId;
26
- // Resolve token (default USDC for backward compat)
46
+ // Resolve token (default USDC)
27
47
  if (token) {
28
48
  this.tokenAddress = token.address;
29
49
  this.tokenDecimals = token.decimals;
30
50
  }
31
51
  else {
32
- const usdc = USDC_ADDRESSES[chainId];
52
+ const usdc = getToken(chainId, 'USDC');
33
53
  if (!usdc)
34
54
  throw new Error(`No USDC address for chain ${chainId}`);
35
- this.tokenAddress = usdc;
36
- this.tokenDecimals = 6;
37
- }
38
- // Try V3 first, fall back to V2
39
- const v3 = ESCROW_ADDRESSES[chainId];
40
- const v2 = ESCROW_V2_ADDRESSES[chainId];
41
- if (v3) {
42
- this.escrowAddress = v3;
43
- this.escrowVersion = 3;
44
- }
45
- else if (v2) {
46
- this.escrowAddress = v2;
47
- this.escrowVersion = 2;
48
- }
49
- else {
50
- throw new Error(`No escrow contract for chain ${chainId}`);
55
+ this.tokenAddress = usdc.address;
56
+ this.tokenDecimals = usdc.decimals;
51
57
  }
58
+ const v1 = ESCROW_V1_ADDRESSES[chainId];
59
+ if (!v1)
60
+ throw new Error(`No V1 escrow contract for chain ${chainId}`);
61
+ this.escrowAddress = v1;
52
62
  }
53
63
  /**
54
64
  * Convert a platform transaction ID (CUID string) to a bytes32 escrow ID.
55
- * Uses keccak256, matching the existing backend pattern in escrow.ts (ethers.id).
65
+ * Uses keccak256, matching the existing backend pattern.
56
66
  */
57
67
  static toEscrowId(transactionId) {
58
68
  return keccak256(toBytes(transactionId));
@@ -76,33 +86,31 @@ export class EscrowClient {
76
86
  });
77
87
  return txHash;
78
88
  }
79
- /** @deprecated Use approveToken() instead. */
80
- async approveUSDC(amount) {
81
- return this.approveToken(amount);
89
+ /**
90
+ * Generate a criteriaHash from success criteria JSON.
91
+ * The criteriaHash is stored on-chain to enable Tier 1 algorithmic resolution.
92
+ */
93
+ static toCriteriaHash(criteria) {
94
+ const json = typeof criteria === 'string' ? criteria : JSON.stringify(criteria);
95
+ return keccak256(toBytes(json));
82
96
  }
83
97
  /**
84
- * Fund an escrow. Calls createEscrow on the escrow contract.
85
- * V3: passes token address as 4th argument.
86
- * V2 fallback: USDC only (3 arguments).
98
+ * Fund an escrow. Calls V1 createEscrow with 6 args including deadline and criteriaHash.
87
99
  * The contract will safeTransferFrom the token (amount + 1% buyer fee) from the caller.
100
+ *
101
+ * @param transactionId - Platform transaction ID (CUID)
102
+ * @param sellerAddress - Seller's wallet address
103
+ * @param amount - Amount in smallest token units (e.g., USDC with 6 decimals)
104
+ * @param deadline - Unix timestamp for delivery deadline
105
+ * @param criteriaHash - keccak256 hash of success criteria JSON (enables algorithmic dispute resolution)
88
106
  */
89
- async fundEscrow(transactionId, sellerAddress, amount) {
107
+ async fundEscrow(transactionId, sellerAddress, amount, deadline, criteriaHash = '0x0000000000000000000000000000000000000000000000000000000000000000') {
90
108
  const escrowId = EscrowClient.toEscrowId(transactionId);
91
- let data;
92
- if (this.escrowVersion === 3) {
93
- data = encodeFunctionData({
94
- abi: SERVICE_ESCROW_V3_ABI,
95
- functionName: 'createEscrow',
96
- args: [escrowId, sellerAddress, amount, this.tokenAddress],
97
- });
98
- }
99
- else {
100
- data = encodeFunctionData({
101
- abi: SERVICE_ESCROW_V2_ABI,
102
- functionName: 'createEscrow',
103
- args: [escrowId, sellerAddress, amount],
104
- });
105
- }
109
+ const data = encodeFunctionData({
110
+ abi: ABBABABA_ESCROW_ABI,
111
+ functionName: 'createEscrow',
112
+ args: [escrowId, sellerAddress, amount, this.tokenAddress, deadline, criteriaHash],
113
+ });
106
114
  const txHash = await this.kernelClient.sendTransaction({
107
115
  to: this.escrowAddress,
108
116
  data,
@@ -110,15 +118,29 @@ export class EscrowClient {
110
118
  return txHash;
111
119
  }
112
120
  /**
113
- * Release escrow funds to the seller.
114
- * Callable by the buyer or an arbitrator.
121
+ * Submit delivery proof on-chain. Called by the seller after completing work.
115
122
  */
116
- async releaseEscrow(transactionId) {
123
+ async submitDelivery(transactionId, proofHash) {
117
124
  const escrowId = EscrowClient.toEscrowId(transactionId);
118
- const abi = this.escrowVersion === 3 ? SERVICE_ESCROW_V3_ABI : SERVICE_ESCROW_V2_ABI;
119
125
  const data = encodeFunctionData({
120
- abi,
121
- functionName: 'release',
126
+ abi: ABBABABA_ESCROW_ABI,
127
+ functionName: 'submitDelivery',
128
+ args: [escrowId, proofHash],
129
+ });
130
+ const txHash = await this.kernelClient.sendTransaction({
131
+ to: this.escrowAddress,
132
+ data,
133
+ });
134
+ return txHash;
135
+ }
136
+ /**
137
+ * Accept delivery and release funds immediately. Called by the buyer.
138
+ */
139
+ async acceptDelivery(transactionId) {
140
+ const escrowId = EscrowClient.toEscrowId(transactionId);
141
+ const data = encodeFunctionData({
142
+ abi: ABBABABA_ESCROW_ABI,
143
+ functionName: 'accept',
122
144
  args: [escrowId],
123
145
  });
124
146
  const txHash = await this.kernelClient.sendTransaction({
@@ -128,57 +150,273 @@ export class EscrowClient {
128
150
  return txHash;
129
151
  }
130
152
  /**
131
- * Read escrow details from the contract (view function, no gas needed).
153
+ * Finalize release after the 24h dispute window has passed without a dispute.
154
+ * Can be called by anyone.
155
+ */
156
+ async finalizeRelease(transactionId) {
157
+ const escrowId = EscrowClient.toEscrowId(transactionId);
158
+ const data = encodeFunctionData({
159
+ abi: ABBABABA_ESCROW_ABI,
160
+ functionName: 'finalizeRelease',
161
+ args: [escrowId],
162
+ });
163
+ const txHash = await this.kernelClient.sendTransaction({
164
+ to: this.escrowAddress,
165
+ data,
166
+ });
167
+ return txHash;
168
+ }
169
+ /**
170
+ * Dispute a delivery within the 24h dispute window. Called by the buyer.
171
+ */
172
+ async disputeEscrow(transactionId) {
173
+ const escrowId = EscrowClient.toEscrowId(transactionId);
174
+ const data = encodeFunctionData({
175
+ abi: ABBABABA_ESCROW_ABI,
176
+ functionName: 'dispute',
177
+ args: [escrowId],
178
+ });
179
+ const txHash = await this.kernelClient.sendTransaction({
180
+ to: this.escrowAddress,
181
+ data,
182
+ });
183
+ return txHash;
184
+ }
185
+ /**
186
+ * Claim funds for an abandoned escrow (deadline + 7 days passed with no delivery).
187
+ * Called by the buyer to reclaim funds.
188
+ */
189
+ async claimAbandoned(transactionId) {
190
+ const escrowId = EscrowClient.toEscrowId(transactionId);
191
+ const data = encodeFunctionData({
192
+ abi: ABBABABA_ESCROW_ABI,
193
+ functionName: 'claimAbandoned',
194
+ args: [escrowId],
195
+ });
196
+ const txHash = await this.kernelClient.sendTransaction({
197
+ to: this.escrowAddress,
198
+ data,
199
+ });
200
+ return txHash;
201
+ }
202
+ /**
203
+ * Read escrow details from the V1 contract (view function, no gas needed).
132
204
  */
133
205
  async getEscrow(transactionId) {
134
206
  const escrowId = EscrowClient.toEscrowId(transactionId);
135
- const viemChain = CHAINS[this.chainId] ?? polygonAmoy;
207
+ const viemChain = CHAINS[this.chainId] ?? baseSepolia;
136
208
  const publicClient = createPublicClient({
137
209
  chain: viemChain,
138
210
  transport: http(),
139
211
  });
140
- if (this.escrowVersion === 3) {
141
- const result = await publicClient.readContract({
142
- address: this.escrowAddress,
143
- abi: SERVICE_ESCROW_V3_ABI,
144
- functionName: 'getEscrow',
145
- args: [escrowId],
146
- });
147
- const [token, buyer, seller, amount, buyerFee, status, createdAt, expiresAt] = result;
148
- if (buyer === '0x0000000000000000000000000000000000000000') {
149
- return null;
150
- }
151
- return {
152
- token,
153
- buyer,
154
- seller,
155
- amount,
156
- buyerFee,
157
- status,
158
- createdAt: Number(createdAt),
159
- expiresAt: Number(expiresAt),
160
- };
161
- }
162
- // V2 fallback
163
212
  const result = await publicClient.readContract({
164
213
  address: this.escrowAddress,
165
- abi: SERVICE_ESCROW_V2_ABI,
214
+ abi: ABBABABA_ESCROW_ABI,
166
215
  functionName: 'getEscrow',
167
216
  args: [escrowId],
168
217
  });
169
- const [buyer, seller, amount, buyerFee, status, createdAt, expiresAt] = result;
170
- if (buyer === '0x0000000000000000000000000000000000000000') {
218
+ const [token, buyer, seller, amount, buyerFee, status, createdAt, deadline, deliveredAt, proofHash, criteriaHash] = result;
219
+ if (buyer === ZERO_ADDRESS) {
171
220
  return null;
172
221
  }
173
222
  return {
223
+ token,
174
224
  buyer,
175
225
  seller,
176
226
  amount,
177
227
  buyerFee,
178
228
  status,
179
229
  createdAt: Number(createdAt),
180
- expiresAt: Number(expiresAt),
230
+ deadline: Number(deadline),
231
+ deliveredAt: Number(deliveredAt),
232
+ proofHash: proofHash === ZERO_BYTES32 ? null : proofHash,
233
+ criteriaHash: criteriaHash === ZERO_BYTES32 ? null : criteriaHash,
181
234
  };
182
235
  }
236
+ /**
237
+ * Check if the 24h dispute window is currently active for an escrow.
238
+ */
239
+ async isDisputeWindowActive(transactionId) {
240
+ const escrowId = EscrowClient.toEscrowId(transactionId);
241
+ const viemChain = CHAINS[this.chainId] ?? baseSepolia;
242
+ const publicClient = createPublicClient({
243
+ chain: viemChain,
244
+ transport: http(),
245
+ });
246
+ const result = await publicClient.readContract({
247
+ address: this.escrowAddress,
248
+ abi: ABBABABA_ESCROW_ABI,
249
+ functionName: 'isDisputeWindowActive',
250
+ args: [escrowId],
251
+ });
252
+ return result;
253
+ }
254
+ /**
255
+ * Check if an escrow can be finalized (dispute window passed, no dispute filed).
256
+ */
257
+ async canFinalize(transactionId) {
258
+ const escrowId = EscrowClient.toEscrowId(transactionId);
259
+ const viemChain = CHAINS[this.chainId] ?? baseSepolia;
260
+ const publicClient = createPublicClient({
261
+ chain: viemChain,
262
+ transport: http(),
263
+ });
264
+ const result = await publicClient.readContract({
265
+ address: this.escrowAddress,
266
+ abi: ABBABABA_ESCROW_ABI,
267
+ functionName: 'canFinalize',
268
+ args: [escrowId],
269
+ });
270
+ return result;
271
+ }
272
+ /**
273
+ * Check if an escrow can be claimed as abandoned (deadline + 7 days passed).
274
+ */
275
+ async canClaimAbandoned(transactionId) {
276
+ const escrowId = EscrowClient.toEscrowId(transactionId);
277
+ const viemChain = CHAINS[this.chainId] ?? baseSepolia;
278
+ const publicClient = createPublicClient({
279
+ chain: viemChain,
280
+ transport: http(),
281
+ });
282
+ const result = await publicClient.readContract({
283
+ address: this.escrowAddress,
284
+ abi: ABBABABA_ESCROW_ABI,
285
+ functionName: 'canClaimAbandoned',
286
+ args: [escrowId],
287
+ });
288
+ return result;
289
+ }
290
+ }
291
+ /**
292
+ * Read-only client for the AbbababaScoreV1 on-chain reputation system.
293
+ * No wallet needed — all methods are view functions.
294
+ */
295
+ export class ScoreClient {
296
+ chainId;
297
+ scoreAddress;
298
+ constructor(chainId = BASE_SEPOLIA_CHAIN_ID) {
299
+ this.chainId = chainId;
300
+ const addr = SCORE_V1_ADDRESSES[chainId];
301
+ if (!addr)
302
+ throw new Error(`No Score contract for chain ${chainId}`);
303
+ this.scoreAddress = addr;
304
+ }
305
+ getPublicClient() {
306
+ const viemChain = CHAINS[this.chainId] ?? baseSepolia;
307
+ return createPublicClient({
308
+ chain: viemChain,
309
+ transport: http(),
310
+ });
311
+ }
312
+ /**
313
+ * Get an agent's trust score (int256 — can be negative).
314
+ */
315
+ async getScore(agentAddress) {
316
+ const publicClient = this.getPublicClient();
317
+ const result = await publicClient.readContract({
318
+ address: this.scoreAddress,
319
+ abi: ABBABABA_SCORE_ABI,
320
+ functionName: 'getScore',
321
+ args: [agentAddress],
322
+ });
323
+ return result;
324
+ }
325
+ /**
326
+ * Get full agent stats from the reputation contract.
327
+ */
328
+ async getAgentStats(agentAddress) {
329
+ const publicClient = this.getPublicClient();
330
+ const [score, stats] = await Promise.all([
331
+ publicClient.readContract({
332
+ address: this.scoreAddress,
333
+ abi: ABBABABA_SCORE_ABI,
334
+ functionName: 'getScore',
335
+ args: [agentAddress],
336
+ }),
337
+ publicClient.readContract({
338
+ address: this.scoreAddress,
339
+ abi: ABBABABA_SCORE_ABI,
340
+ functionName: 'getStats',
341
+ args: [agentAddress],
342
+ }),
343
+ ]);
344
+ const [jobsCompleted, disputesLost, abandonments, lastActiveBlock] = stats;
345
+ return {
346
+ score: score,
347
+ totalJobs: jobsCompleted,
348
+ disputesLost,
349
+ jobsAbandoned: abandonments,
350
+ needsBond: score < 0n,
351
+ };
352
+ }
353
+ }
354
+ /**
355
+ * Client for interacting with the AbbababaResolverV1 contract.
356
+ * Used for submitting dispute resolutions (requires appropriate role).
357
+ */
358
+ export class ResolverClient {
359
+ kernelClient;
360
+ chainId;
361
+ resolverAddress;
362
+ constructor(kernelClient, chainId = BASE_SEPOLIA_CHAIN_ID) {
363
+ this.kernelClient = kernelClient;
364
+ this.chainId = chainId;
365
+ const addr = RESOLVER_V1_ADDRESSES[chainId];
366
+ if (!addr)
367
+ throw new Error(`No Resolver contract for chain ${chainId}`);
368
+ this.resolverAddress = addr;
369
+ }
370
+ /**
371
+ * Submit Tier 1 algorithmic resolution.
372
+ * Requires ALGORITHM_ROLE on the resolver contract.
373
+ */
374
+ async submitAlgorithmicResolution(transactionId, outcome, buyerPercent, sellerPercent, reason) {
375
+ const escrowId = EscrowClient.toEscrowId(transactionId);
376
+ const data = encodeFunctionData({
377
+ abi: ABBABABA_RESOLVER_ABI,
378
+ functionName: 'submitAlgorithmicResolution',
379
+ args: [escrowId, outcome, BigInt(buyerPercent), BigInt(sellerPercent), reason],
380
+ });
381
+ const txHash = await this.kernelClient.sendTransaction({
382
+ to: this.resolverAddress,
383
+ data,
384
+ });
385
+ return txHash;
386
+ }
387
+ /**
388
+ * Submit Tier 2 peer arbitration result.
389
+ * Requires PEER_ARBITER_ROLE on the resolver contract.
390
+ */
391
+ async submitPeerArbitrationResult(transactionId, outcome, buyerPercent, sellerPercent, reviewers) {
392
+ const escrowId = EscrowClient.toEscrowId(transactionId);
393
+ const data = encodeFunctionData({
394
+ abi: ABBABABA_RESOLVER_ABI,
395
+ functionName: 'submitPeerArbitrationResult',
396
+ args: [escrowId, outcome, BigInt(buyerPercent), BigInt(sellerPercent), reviewers],
397
+ });
398
+ const txHash = await this.kernelClient.sendTransaction({
399
+ to: this.resolverAddress,
400
+ data,
401
+ });
402
+ return txHash;
403
+ }
404
+ /**
405
+ * Submit Tier 3 human review result.
406
+ * Requires HUMAN_REVIEWER_ROLE on the resolver contract.
407
+ */
408
+ async submitHumanReview(transactionId, outcome, buyerPercent, sellerPercent, reason) {
409
+ const escrowId = EscrowClient.toEscrowId(transactionId);
410
+ const data = encodeFunctionData({
411
+ abi: ABBABABA_RESOLVER_ABI,
412
+ functionName: 'submitHumanReview',
413
+ args: [escrowId, outcome, BigInt(buyerPercent), BigInt(sellerPercent), reason],
414
+ });
415
+ const txHash = await this.kernelClient.sendTransaction({
416
+ to: this.resolverAddress,
417
+ data,
418
+ });
419
+ return txHash;
420
+ }
183
421
  }
184
422
  //# sourceMappingURL=escrow.js.map