@elizaos/plugin-wallet 2.0.0-beta.1

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 (200) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/auto-enable.ts +76 -0
  4. package/dist/LpManagementService-BWrQ5-cO.mjs +353 -0
  5. package/dist/MockLpService-D_Apn4Fd.mjs +99 -0
  6. package/dist/aerodrome-CfnESC32.mjs +890 -0
  7. package/dist/chunk-hT5z_Zn9.mjs +35 -0
  8. package/dist/index.d.mts +34727 -0
  9. package/dist/index.mjs +21590 -0
  10. package/dist/lib/server-wallet-trade.d.mts +34 -0
  11. package/dist/lib/server-wallet-trade.mjs +306 -0
  12. package/dist/meteora-BPX39hZo.mjs +22640 -0
  13. package/dist/orca-Bybp1HXO.mjs +249 -0
  14. package/dist/pancakeswp-CkEXlXti.mjs +604 -0
  15. package/dist/plugin-ZO_MTyd0.mjs +529 -0
  16. package/dist/raydium-rfaM9yEf.mjs +539 -0
  17. package/dist/sdk/index.d.mts +32492 -0
  18. package/dist/sdk/index.mjs +6415 -0
  19. package/dist/types-D5252NZk.mjs +487 -0
  20. package/dist/uniswap-CReXgXVN.mjs +573 -0
  21. package/dist/wallet-action.d.mts +6 -0
  22. package/dist/wallet-action.mjs +820 -0
  23. package/package.json +152 -0
  24. package/src/actions/failure-codes.ts +79 -0
  25. package/src/actions/index.ts +1 -0
  26. package/src/analytics/birdeye/actions/wallet-search-address.ts +9 -0
  27. package/src/analytics/birdeye/birdeye-task.ts +175 -0
  28. package/src/analytics/birdeye/birdeye.ts +813 -0
  29. package/src/analytics/birdeye/constants.ts +74 -0
  30. package/src/analytics/birdeye/providers/agent-portfolio-provider.ts +18 -0
  31. package/src/analytics/birdeye/providers/market.ts +227 -0
  32. package/src/analytics/birdeye/providers/portfolio-factory.test.ts +138 -0
  33. package/src/analytics/birdeye/providers/portfolio-factory.ts +252 -0
  34. package/src/analytics/birdeye/providers/trending.ts +365 -0
  35. package/src/analytics/birdeye/providers/wallet.ts +14 -0
  36. package/src/analytics/birdeye/search-category.test.ts +207 -0
  37. package/src/analytics/birdeye/search-category.ts +506 -0
  38. package/src/analytics/birdeye/service.ts +992 -0
  39. package/src/analytics/birdeye/tasks/birdeye.ts +232 -0
  40. package/src/analytics/birdeye/types/api/common.ts +305 -0
  41. package/src/analytics/birdeye/types/api/defi.ts +220 -0
  42. package/src/analytics/birdeye/types/api/pair.ts +200 -0
  43. package/src/analytics/birdeye/types/api/search.ts +86 -0
  44. package/src/analytics/birdeye/types/api/token.ts +635 -0
  45. package/src/analytics/birdeye/types/api/trader.ts +76 -0
  46. package/src/analytics/birdeye/types/api/wallet.ts +181 -0
  47. package/src/analytics/birdeye/types/shared.ts +106 -0
  48. package/src/analytics/birdeye/utils.ts +700 -0
  49. package/src/analytics/dexscreener/errors.ts +28 -0
  50. package/src/analytics/dexscreener/index.ts +3 -0
  51. package/src/analytics/dexscreener/search-category.test.ts +49 -0
  52. package/src/analytics/dexscreener/search-category.ts +42 -0
  53. package/src/analytics/dexscreener/service.ts +595 -0
  54. package/src/analytics/dexscreener/types.ts +128 -0
  55. package/src/analytics/lpinfo/index.d.ts +7 -0
  56. package/src/analytics/lpinfo/index.ts +52 -0
  57. package/src/analytics/lpinfo/kamino/README.md +102 -0
  58. package/src/analytics/lpinfo/kamino/index.ts +24 -0
  59. package/src/analytics/lpinfo/kamino/providers/kaminoLiquidityProvider.ts +422 -0
  60. package/src/analytics/lpinfo/kamino/providers/kaminoPoolProvider.ts +365 -0
  61. package/src/analytics/lpinfo/kamino/providers/kaminoProvider.ts +496 -0
  62. package/src/analytics/lpinfo/kamino/services/kaminoLiquidityService.ts +1123 -0
  63. package/src/analytics/lpinfo/kamino/services/kaminoService.ts +758 -0
  64. package/src/analytics/lpinfo/steer/README.md +169 -0
  65. package/src/analytics/lpinfo/steer/index.ts +23 -0
  66. package/src/analytics/lpinfo/steer/providers/steerLiquidityProvider.ts +544 -0
  67. package/src/analytics/lpinfo/steer/services/steerLiquidityService.ts +1690 -0
  68. package/src/analytics/lpinfo/steer/steer-display-types.ts +99 -0
  69. package/src/analytics/news/index.ts +52 -0
  70. package/src/analytics/news/interfaces/types.ts +222 -0
  71. package/src/analytics/news/providers/defiNewsProvider.ts +734 -0
  72. package/src/analytics/news/services/newsDataService.ts +332 -0
  73. package/src/analytics/news/utils/formatters.ts +151 -0
  74. package/src/analytics/token-info/action.ts +240 -0
  75. package/src/analytics/token-info/index.ts +3 -0
  76. package/src/analytics/token-info/params.ts +215 -0
  77. package/src/analytics/token-info/providers.ts +681 -0
  78. package/src/analytics/token-info/service.ts +168 -0
  79. package/src/analytics/token-info/types.ts +74 -0
  80. package/src/audit/audit-log.ts +45 -0
  81. package/src/browser-shim/build-shim.ts +123 -0
  82. package/src/browser-shim/index.ts +5 -0
  83. package/src/browser-shim/shim.template.js +563 -0
  84. package/src/chains/evm/.github/workflows/npm-deploy.yml +112 -0
  85. package/src/chains/evm/LICENSE +21 -0
  86. package/src/chains/evm/README.md +106 -0
  87. package/src/chains/evm/actions/helpers.ts +147 -0
  88. package/src/chains/evm/actions/swap.ts +839 -0
  89. package/src/chains/evm/actions/transfer.ts +254 -0
  90. package/src/chains/evm/biome.json +61 -0
  91. package/src/chains/evm/bridge-router.ts +660 -0
  92. package/src/chains/evm/build.ts +89 -0
  93. package/src/chains/evm/chain-handler.ts +416 -0
  94. package/src/chains/evm/constants.ts +23 -0
  95. package/src/chains/evm/contracts/artifacts/OZGovernor.json +1707 -0
  96. package/src/chains/evm/contracts/artifacts/TimelockController.json +1007 -0
  97. package/src/chains/evm/contracts/artifacts/VoteToken.json +895 -0
  98. package/src/chains/evm/dex/aerodrome/index.ts +34 -0
  99. package/src/chains/evm/dex/aerodrome/services/AerodromeLpService.ts +558 -0
  100. package/src/chains/evm/dex/aerodrome/types.ts +318 -0
  101. package/src/chains/evm/dex/pancakeswp/index.ts +35 -0
  102. package/src/chains/evm/dex/pancakeswp/services/PancakeSwapV3LpService.ts +743 -0
  103. package/src/chains/evm/dex/pancakeswp/types.ts +65 -0
  104. package/src/chains/evm/dex/uniswap/index.ts +35 -0
  105. package/src/chains/evm/dex/uniswap/services/UniswapV3LpService.ts +759 -0
  106. package/src/chains/evm/dex/uniswap/types.ts +390 -0
  107. package/src/chains/evm/generated/specs/spec-helpers.ts +73 -0
  108. package/src/chains/evm/generated/specs/specs.ts +151 -0
  109. package/src/chains/evm/gov-router.ts +250 -0
  110. package/src/chains/evm/index.browser.ts +16 -0
  111. package/src/chains/evm/index.ts +31 -0
  112. package/src/chains/evm/prompts.ts +193 -0
  113. package/src/chains/evm/providers/get-balance.ts +123 -0
  114. package/src/chains/evm/providers/wallet.ts +715 -0
  115. package/src/chains/evm/routes/sign.ts +333 -0
  116. package/src/chains/evm/rpc-providers.ts +410 -0
  117. package/src/chains/evm/service.ts +140 -0
  118. package/src/chains/evm/templates/index.ts +10 -0
  119. package/src/chains/evm/types/index.ts +432 -0
  120. package/src/chains/evm/vitest.config.ts +18 -0
  121. package/src/chains/registry.ts +668 -0
  122. package/src/chains/solana/README.md +367 -0
  123. package/src/chains/wallet-action.ts +533 -0
  124. package/src/chains/wallet-router.test.ts +296 -0
  125. package/src/contracts.ts +65 -0
  126. package/src/core-augmentation.ts +10 -0
  127. package/src/index.ts +71 -0
  128. package/src/lib/server-wallet-trade.ts +192 -0
  129. package/src/lib/wallet-export-guard.ts +330 -0
  130. package/src/lp/actions/liquidity.ts +827 -0
  131. package/src/lp/e2e/real-token-tests.ts +428 -0
  132. package/src/lp/e2e/scenarios.ts +470 -0
  133. package/src/lp/e2e/test-utils.ts +145 -0
  134. package/src/lp/lp-manager-entry.ts +303 -0
  135. package/src/lp/services/ConcentratedLiquidityService.ts +120 -0
  136. package/src/lp/services/DexInteractionService.ts +226 -0
  137. package/src/lp/services/LpManagementService.test.ts +148 -0
  138. package/src/lp/services/LpManagementService.ts +632 -0
  139. package/src/lp/services/UserLpProfileService.ts +163 -0
  140. package/src/lp/services/VaultService.ts +153 -0
  141. package/src/lp/services/YieldOptimizationService.ts +344 -0
  142. package/src/lp/services/__tests__/MockLpService.ts +146 -0
  143. package/src/lp/tasks/LpAutoRebalanceTask.ts +117 -0
  144. package/src/lp/tasks/__tests__/LpAutoRebalanceTask.test.ts +370 -0
  145. package/src/lp/types.ts +582 -0
  146. package/src/lp/utils/solanaClient.ts +143 -0
  147. package/src/plugin.ts +125 -0
  148. package/src/policy/policy.ts +19 -0
  149. package/src/providers/canonical-provider.ts +27 -0
  150. package/src/providers/unified-wallet-provider.ts +79 -0
  151. package/src/register-routes.ts +11 -0
  152. package/src/routes/plugin.ts +47 -0
  153. package/src/routes/wallet-market-overview-route.ts +869 -0
  154. package/src/sdk/abi.ts +258 -0
  155. package/src/sdk/bridge/abis.ts +126 -0
  156. package/src/sdk/bridge/client.ts +518 -0
  157. package/src/sdk/bridge/index.ts +56 -0
  158. package/src/sdk/bridge/solana.ts +604 -0
  159. package/src/sdk/bridge/types.ts +202 -0
  160. package/src/sdk/convenience.ts +347 -0
  161. package/src/sdk/escrow/MutualStakeEscrow.ts +480 -0
  162. package/src/sdk/escrow/types.ts +64 -0
  163. package/src/sdk/escrow/verifiers.ts +73 -0
  164. package/src/sdk/identity/erc8004.ts +692 -0
  165. package/src/sdk/identity/reputation.ts +449 -0
  166. package/src/sdk/identity/uaid.ts +497 -0
  167. package/src/sdk/identity/validation.ts +372 -0
  168. package/src/sdk/index.ts +763 -0
  169. package/src/sdk/policy/SpendingPolicy.ts +260 -0
  170. package/src/sdk/policy/UptoBillingPolicy.ts +320 -0
  171. package/src/sdk/router/PaymentRouter.ts +215 -0
  172. package/src/sdk/router/index.ts +8 -0
  173. package/src/sdk/swap/SwapModule.ts +310 -0
  174. package/src/sdk/swap/abi.ts +117 -0
  175. package/src/sdk/swap/index.ts +34 -0
  176. package/src/sdk/swap/types.ts +135 -0
  177. package/src/sdk/tokens/decimals.ts +140 -0
  178. package/src/sdk/tokens/registry.ts +911 -0
  179. package/src/sdk/tokens/solana.ts +419 -0
  180. package/src/sdk/tokens/transfers.ts +327 -0
  181. package/src/sdk/types.ts +158 -0
  182. package/src/sdk/wallet-core.ts +115 -0
  183. package/src/sdk/x402/budget.ts +168 -0
  184. package/src/sdk/x402/chains/abstract/index.ts +280 -0
  185. package/src/sdk/x402/client.ts +320 -0
  186. package/src/sdk/x402/index.ts +46 -0
  187. package/src/sdk/x402/middleware.ts +92 -0
  188. package/src/sdk/x402/multi-asset.ts +144 -0
  189. package/src/sdk/x402/types.ts +156 -0
  190. package/src/services/wallet-backend-service.ts +328 -0
  191. package/src/types/wallet-router.ts +227 -0
  192. package/src/utils/intent-trajectory.ts +106 -0
  193. package/src/wallet/backend.ts +62 -0
  194. package/src/wallet/errors.ts +49 -0
  195. package/src/wallet/index.ts +27 -0
  196. package/src/wallet/local-eoa-backend.ts +201 -0
  197. package/src/wallet/pending.ts +60 -0
  198. package/src/wallet/select-backend.ts +47 -0
  199. package/src/wallet/steward-backend.ts +161 -0
  200. package/src/wallet-action.ts +1 -0
@@ -0,0 +1,480 @@
1
+ import type { Address, Hex, PublicClient, WalletClient } from "viem";
2
+ import type {
3
+ CreateEscrowParams,
4
+ EscrowCreated,
5
+ EscrowDetails,
6
+ TxResult,
7
+ } from "./types.js";
8
+ import { TaskStatus } from "./types.js";
9
+ import {
10
+ encodeOptimisticVerifierData,
11
+ resolveVerifierAddress,
12
+ } from "./verifiers.js";
13
+
14
+ // ─── ABIs ────────────────────────────────────────────────────────────────────
15
+
16
+ const StakeVaultFactoryAbi = [
17
+ {
18
+ name: "createEscrow",
19
+ type: "function",
20
+ stateMutability: "nonpayable",
21
+ inputs: [
22
+ { name: "_buyer", type: "address" },
23
+ { name: "_seller", type: "address" },
24
+ { name: "_token", type: "address" },
25
+ { name: "_paymentAmount", type: "uint256" },
26
+ { name: "_buyerStake", type: "uint256" },
27
+ { name: "_sellerStake", type: "uint256" },
28
+ { name: "_verifier", type: "address" },
29
+ { name: "_verifierData", type: "bytes" },
30
+ { name: "_deadline", type: "uint256" },
31
+ { name: "_challengeWindow", type: "uint256" },
32
+ ],
33
+ outputs: [{ name: "vault", type: "address" }],
34
+ },
35
+ {
36
+ name: "VaultCreated",
37
+ type: "event",
38
+ inputs: [
39
+ { name: "vault", type: "address", indexed: true },
40
+ { name: "buyer", type: "address", indexed: true },
41
+ { name: "seller", type: "address", indexed: true },
42
+ { name: "token", type: "address", indexed: false },
43
+ { name: "paymentAmount", type: "uint256", indexed: false },
44
+ { name: "buyerStake", type: "uint256", indexed: false },
45
+ { name: "sellerStake", type: "uint256", indexed: false },
46
+ { name: "verifier", type: "address", indexed: false },
47
+ { name: "deadline", type: "uint256", indexed: false },
48
+ ],
49
+ },
50
+ ] as const;
51
+
52
+ const StakeVaultAbi = [
53
+ {
54
+ name: "fund",
55
+ type: "function",
56
+ stateMutability: "nonpayable",
57
+ inputs: [],
58
+ outputs: [],
59
+ },
60
+ {
61
+ name: "accept",
62
+ type: "function",
63
+ stateMutability: "nonpayable",
64
+ inputs: [],
65
+ outputs: [],
66
+ },
67
+ {
68
+ name: "fulfill",
69
+ type: "function",
70
+ stateMutability: "nonpayable",
71
+ inputs: [{ name: "proof", type: "bytes" }],
72
+ outputs: [],
73
+ },
74
+ {
75
+ name: "verify",
76
+ type: "function",
77
+ stateMutability: "nonpayable",
78
+ inputs: [],
79
+ outputs: [],
80
+ },
81
+ {
82
+ name: "challenge",
83
+ type: "function",
84
+ stateMutability: "nonpayable",
85
+ inputs: [{ name: "evidence", type: "bytes" }],
86
+ outputs: [],
87
+ },
88
+ {
89
+ name: "resolve",
90
+ type: "function",
91
+ stateMutability: "nonpayable",
92
+ inputs: [{ name: "sellerWins", type: "bool" }],
93
+ outputs: [],
94
+ },
95
+ {
96
+ name: "cancel",
97
+ type: "function",
98
+ stateMutability: "nonpayable",
99
+ inputs: [],
100
+ outputs: [],
101
+ },
102
+ {
103
+ name: "reclaimExpired",
104
+ type: "function",
105
+ stateMutability: "nonpayable",
106
+ inputs: [],
107
+ outputs: [],
108
+ },
109
+ {
110
+ name: "getEscrowDetails",
111
+ type: "function",
112
+ stateMutability: "view",
113
+ inputs: [],
114
+ outputs: [
115
+ { name: "_buyer", type: "address" },
116
+ { name: "_seller", type: "address" },
117
+ { name: "_token", type: "address" },
118
+ { name: "_paymentAmount", type: "uint256" },
119
+ { name: "_buyerStake", type: "uint256" },
120
+ { name: "_sellerStake", type: "uint256" },
121
+ { name: "_verifier", type: "address" },
122
+ { name: "_deadline", type: "uint256" },
123
+ { name: "_challengeWindow", type: "uint256" },
124
+ { name: "_status", type: "uint8" },
125
+ { name: "_fulfilledAt", type: "uint256" },
126
+ ],
127
+ },
128
+ {
129
+ name: "status",
130
+ type: "function",
131
+ stateMutability: "view",
132
+ inputs: [],
133
+ outputs: [{ name: "", type: "uint8" }],
134
+ },
135
+ ] as const;
136
+
137
+ function toTaskStatus(value: unknown): TaskStatus {
138
+ const status = Number(value);
139
+ if (!Number.isInteger(status) || !(status in TaskStatus)) {
140
+ throw new Error(`Invalid escrow task status: ${String(value)}`);
141
+ }
142
+ return status as TaskStatus;
143
+ }
144
+
145
+ const ERC20ApproveAbi = [
146
+ {
147
+ name: "approve",
148
+ type: "function",
149
+ stateMutability: "nonpayable",
150
+ inputs: [
151
+ { name: "spender", type: "address" },
152
+ { name: "amount", type: "uint256" },
153
+ ],
154
+ outputs: [{ name: "", type: "bool" }],
155
+ },
156
+ ] as const;
157
+
158
+ /** Base USDC address */
159
+ const BASE_USDC: Address = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
160
+
161
+ /**
162
+ * MutualStakeEscrow — SDK class for creating and managing mutual-stake escrow vaults
163
+ *
164
+ * Wraps the StakeVault and StakeVaultFactory contracts with a clean TypeScript API.
165
+ * Both buyer and seller deposit collateral, ensuring aligned incentives.
166
+ */
167
+ export class MutualStakeEscrow {
168
+ private publicClient: PublicClient;
169
+ private walletClient: WalletClient;
170
+ private factoryAddress: Address;
171
+ private chainId: number;
172
+
173
+ constructor(params: {
174
+ publicClient: PublicClient;
175
+ walletClient: WalletClient;
176
+ factoryAddress: Address;
177
+ chainId: number;
178
+ }) {
179
+ this.publicClient = params.publicClient;
180
+ this.walletClient = params.walletClient;
181
+ this.factoryAddress = params.factoryAddress;
182
+ this.chainId = params.chainId;
183
+ }
184
+
185
+ /**
186
+ * Create a new escrow vault via the factory
187
+ * @param params - Escrow creation parameters
188
+ * @returns The deployed vault address and transaction hash
189
+ */
190
+ async create(params: CreateEscrowParams): Promise<EscrowCreated> {
191
+ const account = this.walletClient.account;
192
+ if (!account) throw new Error("Wallet client must have an account");
193
+
194
+ const token = params.token ?? BASE_USDC;
195
+ const verifierAddress = resolveVerifierAddress(
196
+ params.verifier,
197
+ this.chainId,
198
+ );
199
+ const verifierData = params.verifierData ?? encodeOptimisticVerifierData();
200
+
201
+ const txHash = await this.walletClient.writeContract({
202
+ address: this.factoryAddress,
203
+ abi: StakeVaultFactoryAbi,
204
+ functionName: "createEscrow",
205
+ args: [
206
+ account.address,
207
+ params.seller,
208
+ token,
209
+ params.paymentAmount,
210
+ params.buyerStake,
211
+ params.sellerStake,
212
+ verifierAddress,
213
+ verifierData,
214
+ BigInt(params.deadline),
215
+ BigInt(params.challengeWindow),
216
+ ],
217
+ account,
218
+ chain: this.walletClient.chain,
219
+ });
220
+
221
+ await this.publicClient.waitForTransactionReceipt({ hash: txHash });
222
+
223
+ // Read vault address from return data via simulation
224
+ // (VaultCreated event parsing reserved for future use)
225
+ const vaultAddress = (await this.publicClient.readContract({
226
+ address: this.factoryAddress,
227
+ abi: StakeVaultFactoryAbi,
228
+ functionName: "createEscrow",
229
+ args: [
230
+ account.address,
231
+ params.seller,
232
+ token,
233
+ params.paymentAmount,
234
+ params.buyerStake,
235
+ params.sellerStake,
236
+ verifierAddress,
237
+ verifierData,
238
+ BigInt(params.deadline),
239
+ BigInt(params.challengeWindow),
240
+ ],
241
+ })) as Address;
242
+
243
+ return { address: vaultAddress, txHash };
244
+ }
245
+
246
+ /**
247
+ * Fund an escrow as buyer (deposits payment + buyerStake)
248
+ * @param vaultAddress - Address of the StakeVault
249
+ * @param approveAmount - Total amount to approve (payment + buyerStake)
250
+ */
251
+ async fund(vaultAddress: Address, approveAmount: bigint): Promise<TxResult> {
252
+ const account = this.walletClient.account;
253
+ if (!account) throw new Error("Wallet client must have an account");
254
+
255
+ const details = await this.getDetails(vaultAddress);
256
+
257
+ // Approve token transfer
258
+ await this.walletClient.writeContract({
259
+ address: details.token,
260
+ abi: ERC20ApproveAbi,
261
+ functionName: "approve",
262
+ args: [vaultAddress, approveAmount],
263
+ account,
264
+ chain: this.walletClient.chain,
265
+ });
266
+
267
+ const txHash = await this.walletClient.writeContract({
268
+ address: vaultAddress,
269
+ abi: StakeVaultAbi,
270
+ functionName: "fund",
271
+ args: [],
272
+ account,
273
+ chain: this.walletClient.chain,
274
+ });
275
+
276
+ return { txHash };
277
+ }
278
+
279
+ /**
280
+ * Accept an escrow as seller (deposits sellerStake)
281
+ * @param vaultAddress - Address of the StakeVault
282
+ */
283
+ async accept(vaultAddress: Address): Promise<TxResult> {
284
+ const account = this.walletClient.account;
285
+ if (!account) throw new Error("Wallet client must have an account");
286
+
287
+ const details = await this.getDetails(vaultAddress);
288
+
289
+ // Approve seller stake transfer
290
+ await this.walletClient.writeContract({
291
+ address: details.token,
292
+ abi: ERC20ApproveAbi,
293
+ functionName: "approve",
294
+ args: [vaultAddress, details.sellerStake],
295
+ account,
296
+ chain: this.walletClient.chain,
297
+ });
298
+
299
+ const txHash = await this.walletClient.writeContract({
300
+ address: vaultAddress,
301
+ abi: StakeVaultAbi,
302
+ functionName: "accept",
303
+ args: [],
304
+ account,
305
+ chain: this.walletClient.chain,
306
+ });
307
+
308
+ return { txHash };
309
+ }
310
+
311
+ /**
312
+ * Submit fulfillment proof as seller
313
+ * @param vaultAddress - Address of the StakeVault
314
+ * @param proof - Completion proof bytes
315
+ */
316
+ async fulfill(vaultAddress: Address, proof: Hex): Promise<TxResult> {
317
+ const account = this.walletClient.account;
318
+ if (!account) throw new Error("Wallet client must have an account");
319
+
320
+ const txHash = await this.walletClient.writeContract({
321
+ address: vaultAddress,
322
+ abi: StakeVaultAbi,
323
+ functionName: "fulfill",
324
+ args: [proof],
325
+ account,
326
+ chain: this.walletClient.chain,
327
+ });
328
+
329
+ return { txHash };
330
+ }
331
+
332
+ /**
333
+ * Verify completion after challenge window (anyone can call)
334
+ * @param vaultAddress - Address of the StakeVault
335
+ */
336
+ async verify(vaultAddress: Address): Promise<TxResult> {
337
+ const account = this.walletClient.account;
338
+ if (!account) throw new Error("Wallet client must have an account");
339
+
340
+ const txHash = await this.walletClient.writeContract({
341
+ address: vaultAddress,
342
+ abi: StakeVaultAbi,
343
+ functionName: "verify",
344
+ args: [],
345
+ account,
346
+ chain: this.walletClient.chain,
347
+ });
348
+
349
+ return { txHash };
350
+ }
351
+
352
+ /**
353
+ * Challenge a fulfillment as buyer
354
+ * @param vaultAddress - Address of the StakeVault
355
+ * @param evidence - Challenge evidence bytes
356
+ */
357
+ async challenge(vaultAddress: Address, evidence: Hex): Promise<TxResult> {
358
+ const account = this.walletClient.account;
359
+ if (!account) throw new Error("Wallet client must have an account");
360
+
361
+ const txHash = await this.walletClient.writeContract({
362
+ address: vaultAddress,
363
+ abi: StakeVaultAbi,
364
+ functionName: "challenge",
365
+ args: [evidence],
366
+ account,
367
+ chain: this.walletClient.chain,
368
+ });
369
+
370
+ return { txHash };
371
+ }
372
+
373
+ /**
374
+ * Cancel escrow before seller accepts (buyer only)
375
+ * @param vaultAddress - Address of the StakeVault
376
+ */
377
+ async cancel(vaultAddress: Address): Promise<TxResult> {
378
+ const account = this.walletClient.account;
379
+ if (!account) throw new Error("Wallet client must have an account");
380
+
381
+ const txHash = await this.walletClient.writeContract({
382
+ address: vaultAddress,
383
+ abi: StakeVaultAbi,
384
+ functionName: "cancel",
385
+ args: [],
386
+ account,
387
+ chain: this.walletClient.chain,
388
+ });
389
+
390
+ return { txHash };
391
+ }
392
+
393
+ /**
394
+ * Reclaim funds after deadline expiry
395
+ * @param vaultAddress - Address of the StakeVault
396
+ */
397
+ async reclaimExpired(vaultAddress: Address): Promise<TxResult> {
398
+ const account = this.walletClient.account;
399
+ if (!account) throw new Error("Wallet client must have an account");
400
+
401
+ const txHash = await this.walletClient.writeContract({
402
+ address: vaultAddress,
403
+ abi: StakeVaultAbi,
404
+ functionName: "reclaimExpired",
405
+ args: [],
406
+ account,
407
+ chain: this.walletClient.chain,
408
+ });
409
+
410
+ return { txHash };
411
+ }
412
+
413
+ /**
414
+ * Get full escrow details from on-chain
415
+ * @param vaultAddress - Address of the StakeVault
416
+ */
417
+ async getDetails(vaultAddress: Address): Promise<EscrowDetails> {
418
+ const result = await this.publicClient.readContract({
419
+ address: vaultAddress,
420
+ abi: StakeVaultAbi,
421
+ functionName: "getEscrowDetails",
422
+ args: [],
423
+ });
424
+
425
+ const [
426
+ buyer,
427
+ seller,
428
+ token,
429
+ paymentAmount,
430
+ buyerStake,
431
+ sellerStake,
432
+ verifier,
433
+ deadline,
434
+ challengeWindow,
435
+ statusNum,
436
+ fulfilledAt,
437
+ ] = result as [
438
+ Address,
439
+ Address,
440
+ Address,
441
+ bigint,
442
+ bigint,
443
+ bigint,
444
+ Address,
445
+ bigint,
446
+ bigint,
447
+ number,
448
+ bigint,
449
+ ];
450
+
451
+ return {
452
+ buyer,
453
+ seller,
454
+ token,
455
+ paymentAmount,
456
+ buyerStake,
457
+ sellerStake,
458
+ verifier,
459
+ deadline,
460
+ challengeWindow,
461
+ status: statusNum as TaskStatus,
462
+ fulfilledAt,
463
+ };
464
+ }
465
+
466
+ /**
467
+ * Get the current status of an escrow
468
+ * @param vaultAddress - Address of the StakeVault
469
+ */
470
+ async getStatus(vaultAddress: Address): Promise<TaskStatus> {
471
+ const result = await this.publicClient.readContract({
472
+ address: vaultAddress,
473
+ abi: StakeVaultAbi,
474
+ functionName: "status",
475
+ args: [],
476
+ });
477
+
478
+ return toTaskStatus(result);
479
+ }
480
+ }
@@ -0,0 +1,64 @@
1
+ import type { Address, Hash, Hex } from "viem";
2
+
3
+ /** Mirrors the on-chain TaskStatus enum */
4
+ export enum TaskStatus {
5
+ Created = 0,
6
+ Funded = 1,
7
+ Fulfilled = 2,
8
+ Challenged = 3,
9
+ Resolved = 4,
10
+ Cancelled = 5,
11
+ }
12
+
13
+ /** Supported built-in verifier types */
14
+ export type VerifierType = "optimistic" | "hash";
15
+
16
+ /** Parameters for creating a new mutual-stake escrow */
17
+ export interface CreateEscrowParams {
18
+ /** Seller/service-provider address */
19
+ seller: Address;
20
+ /** Payment amount in token's smallest unit (e.g., 6 decimals for USDC) */
21
+ paymentAmount: bigint;
22
+ /** Buyer's anti-grief collateral */
23
+ buyerStake: bigint;
24
+ /** Seller's anti-fraud collateral */
25
+ sellerStake: bigint;
26
+ /** Verifier type or custom verifier contract address */
27
+ verifier: VerifierType | Address;
28
+ /** Verifier-specific configuration data (auto-generated for built-in verifiers) */
29
+ verifierData?: Hex;
30
+ /** Challenge window in seconds after fulfillment */
31
+ challengeWindow: number;
32
+ /** Unix timestamp deadline for the task */
33
+ deadline: number;
34
+ /** ERC-20 token address (defaults to USDC on Base) */
35
+ token?: Address;
36
+ }
37
+
38
+ /** Result from creating an escrow */
39
+ export interface EscrowCreated {
40
+ /** Address of the deployed StakeVault contract */
41
+ address: Address;
42
+ /** Transaction hash of the factory call */
43
+ txHash: Hash;
44
+ }
45
+
46
+ /** Full escrow details from on-chain */
47
+ export interface EscrowDetails {
48
+ buyer: Address;
49
+ seller: Address;
50
+ token: Address;
51
+ paymentAmount: bigint;
52
+ buyerStake: bigint;
53
+ sellerStake: bigint;
54
+ verifier: Address;
55
+ deadline: bigint;
56
+ challengeWindow: bigint;
57
+ status: TaskStatus;
58
+ fulfilledAt: bigint;
59
+ }
60
+
61
+ /** Transaction result */
62
+ export interface TxResult {
63
+ txHash: Hash;
64
+ }
@@ -0,0 +1,73 @@
1
+ import {
2
+ type Address,
3
+ encodeAbiParameters,
4
+ type Hex,
5
+ parseAbiParameters,
6
+ } from "viem";
7
+ import type { VerifierType } from "./types.js";
8
+
9
+ /**
10
+ * Known verifier contract addresses on Base mainnet.
11
+ * These are deployed once and shared by all StakeVault instances.
12
+ */
13
+ export const VERIFIER_ADDRESSES: Record<
14
+ string,
15
+ Record<VerifierType, Address>
16
+ > = {
17
+ // Base mainnet (chain ID 8453)
18
+ "8453": {
19
+ optimistic: "0x0000000000000000000000000000000000000000", // Pre-deployment: set after deploying StakeVault verifier contracts to Base
20
+ hash: "0x0000000000000000000000000000000000000000", // Pre-deployment: set after deploying StakeVault verifier contracts to Base
21
+ },
22
+ // Base Sepolia testnet (chain ID 84532)
23
+ "84532": {
24
+ optimistic: "0x0000000000000000000000000000000000000000", // Pre-deployment: set after deploying StakeVault verifier contracts to Base
25
+ hash: "0x0000000000000000000000000000000000000000", // Pre-deployment: set after deploying StakeVault verifier contracts to Base
26
+ },
27
+ };
28
+
29
+ /**
30
+ * Resolve a verifier type to its deployed contract address for a given chain
31
+ * @param verifier - Built-in verifier type or custom contract address
32
+ * @param chainId - Chain ID to look up
33
+ * @returns The verifier contract address
34
+ */
35
+ export function resolveVerifierAddress(
36
+ verifier: VerifierType | Address,
37
+ chainId: number,
38
+ ): Address {
39
+ if (verifier.startsWith("0x") && verifier.length === 42) {
40
+ return verifier as Address;
41
+ }
42
+
43
+ const chainAddresses = VERIFIER_ADDRESSES[chainId.toString()];
44
+ if (!chainAddresses) {
45
+ throw new Error(`No verifier addresses configured for chain ${chainId}`);
46
+ }
47
+
48
+ const address = chainAddresses[verifier as VerifierType];
49
+ if (!address || address === "0x0000000000000000000000000000000000000000") {
50
+ throw new Error(
51
+ `Verifier "${verifier}" not deployed on chain ${chainId}. Deploy it first or pass a custom address.`,
52
+ );
53
+ }
54
+
55
+ return address;
56
+ }
57
+
58
+ /**
59
+ * Encode verifier configuration data for the HashVerifier
60
+ * @param expectedHash - SHA256 hash of the expected output
61
+ * @returns ABI-encoded bytes for the verifierData field
62
+ */
63
+ export function encodeHashVerifierData(expectedHash: Hex): Hex {
64
+ return encodeAbiParameters(parseAbiParameters("bytes32"), [expectedHash]);
65
+ }
66
+
67
+ /**
68
+ * Encode verifier configuration data for the OptimisticVerifier
69
+ * @returns Empty bytes (optimistic verifier has no config)
70
+ */
71
+ export function encodeOptimisticVerifierData(): Hex {
72
+ return "0x";
73
+ }