@virtuals-protocol/acp-node 0.3.0-beta.38 → 0.3.0-beta.39

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/index.mjs CHANGED
@@ -8,7 +8,7 @@ var require_package = __commonJS({
8
8
  "package.json"(exports, module) {
9
9
  module.exports = {
10
10
  name: "@virtuals-protocol/acp-node",
11
- version: "0.3.0-beta.38",
11
+ version: "0.3.0-beta.39",
12
12
  main: "./dist/index.js",
13
13
  module: "./dist/index.mjs",
14
14
  types: "./dist/index.d.ts",
@@ -1346,7 +1346,7 @@ var FareAmount = class extends FareAmountBase {
1346
1346
  super(fare.formatAmount(truncateTo6Decimals(fareAmount.toString())), fare);
1347
1347
  }
1348
1348
  add(other) {
1349
- if (this.fare.contractAddress !== other.fare.contractAddress) {
1349
+ if (this.fare.contractAddress.toLowerCase() !== other.fare.contractAddress.toLowerCase()) {
1350
1350
  throw new Error("Token addresses do not match");
1351
1351
  }
1352
1352
  return new FareBigInt(this.amount + other.amount, this.fare);
@@ -1379,6 +1379,10 @@ var ACP_V2_ABI = [
1379
1379
  name: "AccessControlUnauthorizedAccount",
1380
1380
  type: "error"
1381
1381
  },
1382
+ { inputs: [], name: "AccountAlreadySubscribed", type: "error" },
1383
+ { inputs: [], name: "AccountDoesNotExist", type: "error" },
1384
+ { inputs: [], name: "AccountManagerNotSet", type: "error" },
1385
+ { inputs: [], name: "AccountNotActive", type: "error" },
1382
1386
  {
1383
1387
  inputs: [{ internalType: "address", name: "target", type: "address" }],
1384
1388
  name: "AddressEmptyCode",
@@ -1389,6 +1393,13 @@ var ACP_V2_ABI = [
1389
1393
  name: "AddressInsufficientBalance",
1390
1394
  type: "error"
1391
1395
  },
1396
+ { inputs: [], name: "AmountMustBeGreaterThanZero", type: "error" },
1397
+ { inputs: [], name: "AmountOrFeeRequired", type: "error" },
1398
+ { inputs: [], name: "AssetManagerNotSet", type: "error" },
1399
+ { inputs: [], name: "BudgetNotReceived", type: "error" },
1400
+ { inputs: [], name: "CannotSetBudgetOnSubscriptionJob", type: "error" },
1401
+ { inputs: [], name: "DestinationEndpointRequired", type: "error" },
1402
+ { inputs: [], name: "DurationMustBeGreaterThanZero", type: "error" },
1392
1403
  {
1393
1404
  inputs: [
1394
1405
  { internalType: "address", name: "implementation", type: "address" }
@@ -1398,22 +1409,46 @@ var ACP_V2_ABI = [
1398
1409
  },
1399
1410
  { inputs: [], name: "ERC1967NonPayable", type: "error" },
1400
1411
  { inputs: [], name: "EnforcedPause", type: "error" },
1412
+ { inputs: [], name: "EvaluatorFeeTooHigh", type: "error" },
1401
1413
  { inputs: [], name: "ExpectedPause", type: "error" },
1414
+ { inputs: [], name: "ExpiredAtMustBeInFuture", type: "error" },
1415
+ { inputs: [], name: "ExpiryTooShort", type: "error" },
1402
1416
  { inputs: [], name: "FailedInnerCall", type: "error" },
1417
+ { inputs: [], name: "InvalidCrossChainMemoType", type: "error" },
1403
1418
  { inputs: [], name: "InvalidInitialization", type: "error" },
1419
+ { inputs: [], name: "InvalidMemoType", type: "error" },
1420
+ { inputs: [], name: "InvalidModuleType", type: "error" },
1421
+ { inputs: [], name: "InvalidPaymentToken", type: "error" },
1422
+ { inputs: [], name: "InvalidRecipient", type: "error" },
1423
+ { inputs: [], name: "JobManagerNotSet", type: "error" },
1424
+ { inputs: [], name: "MemoManagerNotSet", type: "error" },
1404
1425
  { inputs: [], name: "NotInitializing", type: "error" },
1426
+ { inputs: [], name: "OnlyClient", type: "error" },
1427
+ { inputs: [], name: "OnlyMemoManager", type: "error" },
1428
+ { inputs: [], name: "OnlyProvider", type: "error" },
1429
+ { inputs: [], name: "PaymentManagerNotSet", type: "error" },
1430
+ { inputs: [], name: "PlatformFeeTooHigh", type: "error" },
1405
1431
  { inputs: [], name: "ReentrancyGuardReentrantCall", type: "error" },
1406
1432
  {
1407
1433
  inputs: [{ internalType: "address", name: "token", type: "address" }],
1408
1434
  name: "SafeERC20FailedOperation",
1409
1435
  type: "error"
1410
1436
  },
1437
+ { inputs: [], name: "SubscriptionAccountExpired", type: "error" },
1438
+ { inputs: [], name: "SubscriptionJobMustHaveZeroBudget", type: "error" },
1439
+ { inputs: [], name: "SubscriptionJobMustHaveZeroBudgetMemo", type: "error" },
1440
+ { inputs: [], name: "TokenAddressRequired", type: "error" },
1441
+ { inputs: [], name: "TokenMustBeERC20", type: "error" },
1411
1442
  { inputs: [], name: "UUPSUnauthorizedCallContext", type: "error" },
1412
1443
  {
1413
1444
  inputs: [{ internalType: "bytes32", name: "slot", type: "bytes32" }],
1414
1445
  name: "UUPSUnsupportedProxiableUUID",
1415
1446
  type: "error"
1416
1447
  },
1448
+ { inputs: [], name: "UnableToRefund", type: "error" },
1449
+ { inputs: [], name: "Unauthorized", type: "error" },
1450
+ { inputs: [], name: "ZeroAddress", type: "error" },
1451
+ { inputs: [], name: "ZeroAddressProvider", type: "error" },
1417
1452
  {
1418
1453
  anonymous: false,
1419
1454
  inputs: [
@@ -1453,56 +1488,6 @@ var ACP_V2_ABI = [
1453
1488
  name: "AccountStatusUpdated",
1454
1489
  type: "event"
1455
1490
  },
1456
- {
1457
- anonymous: false,
1458
- inputs: [
1459
- {
1460
- indexed: false,
1461
- internalType: "uint256",
1462
- name: "jobId",
1463
- type: "uint256"
1464
- },
1465
- {
1466
- indexed: true,
1467
- internalType: "address",
1468
- name: "evaluator",
1469
- type: "address"
1470
- },
1471
- {
1472
- indexed: false,
1473
- internalType: "uint256",
1474
- name: "evaluatorFee",
1475
- type: "uint256"
1476
- }
1477
- ],
1478
- name: "ClaimedEvaluatorFee",
1479
- type: "event"
1480
- },
1481
- {
1482
- anonymous: false,
1483
- inputs: [
1484
- {
1485
- indexed: false,
1486
- internalType: "uint256",
1487
- name: "jobId",
1488
- type: "uint256"
1489
- },
1490
- {
1491
- indexed: true,
1492
- internalType: "address",
1493
- name: "provider",
1494
- type: "address"
1495
- },
1496
- {
1497
- indexed: false,
1498
- internalType: "uint256",
1499
- name: "providerFee",
1500
- type: "uint256"
1501
- }
1502
- ],
1503
- name: "ClaimedProviderFee",
1504
- type: "event"
1505
- },
1506
1491
  {
1507
1492
  anonymous: false,
1508
1493
  inputs: [
@@ -1554,31 +1539,6 @@ var ACP_V2_ABI = [
1554
1539
  name: "Paused",
1555
1540
  type: "event"
1556
1541
  },
1557
- {
1558
- anonymous: false,
1559
- inputs: [
1560
- {
1561
- indexed: false,
1562
- internalType: "uint256",
1563
- name: "jobId",
1564
- type: "uint256"
1565
- },
1566
- {
1567
- indexed: true,
1568
- internalType: "address",
1569
- name: "client",
1570
- type: "address"
1571
- },
1572
- {
1573
- indexed: false,
1574
- internalType: "uint256",
1575
- name: "amount",
1576
- type: "uint256"
1577
- }
1578
- ],
1579
- name: "RefundedBudget",
1580
- type: "event"
1581
- },
1582
1542
  {
1583
1543
  anonymous: false,
1584
1544
  inputs: [
@@ -1726,6 +1686,13 @@ var ACP_V2_ABI = [
1726
1686
  stateMutability: "nonpayable",
1727
1687
  type: "function"
1728
1688
  },
1689
+ {
1690
+ inputs: [{ internalType: "uint256", name: "jobId", type: "uint256" }],
1691
+ name: "claimBudgetFromMemoManager",
1692
+ outputs: [],
1693
+ stateMutability: "nonpayable",
1694
+ type: "function"
1695
+ },
1729
1696
  {
1730
1697
  inputs: [
1731
1698
  { internalType: "address", name: "provider", type: "address" },
@@ -1839,6 +1806,28 @@ var ACP_V2_ABI = [
1839
1806
  stateMutability: "nonpayable",
1840
1807
  type: "function"
1841
1808
  },
1809
+ {
1810
+ inputs: [
1811
+ { internalType: "uint256", name: "jobId", type: "uint256" },
1812
+ { internalType: "string", name: "content", type: "string" },
1813
+ { internalType: "address", name: "token", type: "address" },
1814
+ { internalType: "uint256", name: "amount", type: "uint256" },
1815
+ { internalType: "address", name: "recipient", type: "address" },
1816
+ { internalType: "uint256", name: "feeAmount", type: "uint256" },
1817
+ { internalType: "enum ACPTypes.FeeType", name: "feeType", type: "uint8" },
1818
+ { internalType: "uint256", name: "duration", type: "uint256" },
1819
+ { internalType: "uint256", name: "expiredAt", type: "uint256" },
1820
+ {
1821
+ internalType: "enum ACPTypes.JobPhase",
1822
+ name: "nextPhase",
1823
+ type: "uint8"
1824
+ }
1825
+ ],
1826
+ name: "createSubscriptionMemo",
1827
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
1828
+ stateMutability: "nonpayable",
1829
+ type: "function"
1830
+ },
1842
1831
  {
1843
1832
  inputs: [
1844
1833
  { internalType: "address", name: "provider", type: "address" },
@@ -1907,7 +1896,8 @@ var ACP_V2_ABI = [
1907
1896
  name: "completedJobCount",
1908
1897
  type: "uint256"
1909
1898
  },
1910
- { internalType: "bool", name: "isActive", type: "bool" }
1899
+ { internalType: "bool", name: "isActive", type: "bool" },
1900
+ { internalType: "uint256", name: "expiry", type: "uint256" }
1911
1901
  ],
1912
1902
  internalType: "struct ACPTypes.Account",
1913
1903
  name: "",
@@ -2064,13 +2054,6 @@ var ACP_V2_ABI = [
2064
2054
  stateMutability: "view",
2065
2055
  type: "function"
2066
2056
  },
2067
- {
2068
- inputs: [],
2069
- name: "getPhases",
2070
- outputs: [{ internalType: "string[7]", name: "", type: "string[7]" }],
2071
- stateMutability: "pure",
2072
- type: "function"
2073
- },
2074
2057
  {
2075
2058
  inputs: [{ internalType: "bytes32", name: "role", type: "bytes32" }],
2076
2059
  name: "getRoleAdmin",
@@ -2115,11 +2098,8 @@ var ACP_V2_ABI = [
2115
2098
  type: "function"
2116
2099
  },
2117
2100
  {
2118
- inputs: [
2119
- { internalType: "uint256", name: "jobId", type: "uint256" },
2120
- { internalType: "address", name: "account", type: "address" }
2121
- ],
2122
- name: "isJobEvaluator",
2101
+ inputs: [{ internalType: "uint256", name: "jobId", type: "uint256" }],
2102
+ name: "isSubscriptionJob",
2123
2103
  outputs: [{ internalType: "bool", name: "", type: "bool" }],
2124
2104
  stateMutability: "view",
2125
2105
  type: "function"
@@ -2227,6 +2207,13 @@ var ACP_V2_ABI = [
2227
2207
  stateMutability: "nonpayable",
2228
2208
  type: "function"
2229
2209
  },
2210
+ {
2211
+ inputs: [{ internalType: "uint256", name: "jobId", type: "uint256" }],
2212
+ name: "setupEscrowFromMemoManager",
2213
+ outputs: [],
2214
+ stateMutability: "nonpayable",
2215
+ type: "function"
2216
+ },
2230
2217
  {
2231
2218
  inputs: [
2232
2219
  { internalType: "uint256", name: "memoId", type: "uint256" },
@@ -2262,6 +2249,18 @@ var ACP_V2_ABI = [
2262
2249
  stateMutability: "nonpayable",
2263
2250
  type: "function"
2264
2251
  },
2252
+ {
2253
+ inputs: [
2254
+ { internalType: "uint256", name: "accountId", type: "uint256" },
2255
+ { internalType: "uint256", name: "duration", type: "uint256" },
2256
+ { internalType: "string", name: "metadata", type: "string" },
2257
+ { internalType: "address", name: "provider", type: "address" }
2258
+ ],
2259
+ name: "updateAccountSubscriptionFromMemoManager",
2260
+ outputs: [],
2261
+ stateMutability: "nonpayable",
2262
+ type: "function"
2263
+ },
2265
2264
  {
2266
2265
  inputs: [
2267
2266
  { internalType: "uint256", name: "evaluatorFeeBP_", type: "uint256" }
@@ -3612,6 +3611,7 @@ var MemoType = /* @__PURE__ */ ((MemoType3) => {
3612
3611
  MemoType3[MemoType3["PAYABLE_TRANSFER_ESCROW"] = 8] = "PAYABLE_TRANSFER_ESCROW";
3613
3612
  MemoType3[MemoType3["NOTIFICATION"] = 9] = "NOTIFICATION";
3614
3613
  MemoType3[MemoType3["PAYABLE_NOTIFICATION"] = 10] = "PAYABLE_NOTIFICATION";
3614
+ MemoType3[MemoType3["PAYABLE_REQUEST_SUBSCRIPTION"] = 11] = "PAYABLE_REQUEST_SUBSCRIPTION";
3615
3615
  return MemoType3;
3616
3616
  })(MemoType || {});
3617
3617
  var AcpJobPhases = /* @__PURE__ */ ((AcpJobPhases3) => {
@@ -3680,6 +3680,35 @@ ${JSON.stringify(
3680
3680
  );
3681
3681
  }
3682
3682
  }
3683
+ /**
3684
+ * Returns a createAccount operation payload if the contract supports it (V2).
3685
+ * Returns null for V1 or when the ABI does not include createAccount.
3686
+ */
3687
+ createAccount(providerAddress, metadata) {
3688
+ try {
3689
+ const hasCreateAccount = this.abi.some(
3690
+ (item) => item.type === "function" && item.name === "createAccount"
3691
+ );
3692
+ if (!hasCreateAccount) return null;
3693
+ const data = encodeFunctionData({
3694
+ abi: this.abi,
3695
+ functionName: "createAccount",
3696
+ args: [providerAddress, metadata]
3697
+ });
3698
+ return {
3699
+ data,
3700
+ contractAddress: this.contractAddress
3701
+ };
3702
+ } catch {
3703
+ return null;
3704
+ }
3705
+ }
3706
+ /**
3707
+ * Returns the new account id from a createAccount user op receipt, or null if not supported.
3708
+ */
3709
+ async getAccountIdFromUserOpHash(_userOpHash) {
3710
+ return null;
3711
+ }
3683
3712
  get walletAddress() {
3684
3713
  return this.agentWalletAddress;
3685
3714
  }
@@ -3772,6 +3801,33 @@ ${JSON.stringify(
3772
3801
  throw new acpError_default("Failed to create payable memo", error);
3773
3802
  }
3774
3803
  }
3804
+ createSubscriptionMemo(jobId, content, amountBaseUnit, recipient, feeAmountBaseUnit, feeType, duration, nextPhase, expiredAt, token = this.config.baseFare.contractAddress) {
3805
+ try {
3806
+ const data = encodeFunctionData({
3807
+ abi: this.abi,
3808
+ functionName: "createSubscriptionMemo",
3809
+ args: [
3810
+ jobId,
3811
+ content,
3812
+ token,
3813
+ amountBaseUnit,
3814
+ recipient,
3815
+ feeAmountBaseUnit,
3816
+ feeType,
3817
+ duration,
3818
+ Math.floor(expiredAt.getTime() / 1e3),
3819
+ nextPhase
3820
+ ]
3821
+ });
3822
+ const payload = {
3823
+ data,
3824
+ contractAddress: this.contractAddress
3825
+ };
3826
+ return payload;
3827
+ } catch (error) {
3828
+ throw new acpError_default("Failed to create subscription memo", error);
3829
+ }
3830
+ }
3775
3831
  createCrossChainPayableMemo(jobId, content, token, amountBaseUnit, recipient, feeAmountBaseUnit, feeType, type, expiredAt, nextPhase, destinationEid, secured = true) {
3776
3832
  try {
3777
3833
  const data = encodeFunctionData({
@@ -4103,8 +4159,35 @@ function appendBuilderCodeData(data, suffix) {
4103
4159
  // src/acpJobOffering.ts
4104
4160
  import { zeroAddress as zeroAddress2 } from "viem";
4105
4161
  import Ajv from "ajv";
4162
+
4163
+ // src/acpAccount.ts
4164
+ var AcpAccount = class {
4165
+ constructor(contractClient, id, clientAddress, providerAddress, metadata, expiryAt) {
4166
+ this.contractClient = contractClient;
4167
+ this.id = id;
4168
+ this.clientAddress = clientAddress;
4169
+ this.providerAddress = providerAddress;
4170
+ this.metadata = metadata;
4171
+ this.expiryAt = expiryAt;
4172
+ }
4173
+ async updateMetadata(metadata) {
4174
+ const hash = await this.contractClient.updateAccountMetadata(
4175
+ this.id,
4176
+ JSON.stringify(metadata)
4177
+ );
4178
+ return hash;
4179
+ }
4180
+ };
4181
+
4182
+ // src/acpJobOffering.ts
4183
+ var PriceType = /* @__PURE__ */ ((PriceType2) => {
4184
+ PriceType2["FIXED"] = "fixed";
4185
+ PriceType2["PERCENTAGE"] = "percentage";
4186
+ PriceType2["SUBSCRIPTION"] = "subscription";
4187
+ return PriceType2;
4188
+ })(PriceType || {});
4106
4189
  var AcpJobOffering = class {
4107
- constructor(acpClient, acpContractClient, providerAddress, name, price, priceType, requiredFunds, slaMinutes, requirement, deliverable) {
4190
+ constructor(acpClient, acpContractClient, providerAddress, name, price, priceType = "fixed" /* FIXED */, requiredFunds, slaMinutes, requirement, deliverable, subscriptionTiers = [], isPrivate = false) {
4108
4191
  this.acpClient = acpClient;
4109
4192
  this.acpContractClient = acpContractClient;
4110
4193
  this.providerAddress = providerAddress;
@@ -4115,10 +4198,49 @@ var AcpJobOffering = class {
4115
4198
  this.slaMinutes = slaMinutes;
4116
4199
  this.requirement = requirement;
4117
4200
  this.deliverable = deliverable;
4201
+ this.subscriptionTiers = subscriptionTiers;
4202
+ this.isPrivate = isPrivate;
4118
4203
  this.ajv = new Ajv({ allErrors: true });
4119
4204
  }
4120
- async initiateJob(serviceRequirement, evaluatorAddress) {
4121
- const expiredAt = new Date(Date.now() + this.slaMinutes * 60 * 1e3);
4205
+ async initiateJob(serviceRequirement, evaluatorAddress, expiredAt = new Date(Date.now() + this.slaMinutes * 60 * 1e3), preferredSubscriptionTier) {
4206
+ this.validateRequest(serviceRequirement);
4207
+ const finalServiceRequirement = {
4208
+ name: this.name,
4209
+ requirement: serviceRequirement,
4210
+ priceValue: this.price,
4211
+ priceType: this.priceType
4212
+ };
4213
+ const subscriptionRequired = this.isSubscriptionRequired(
4214
+ preferredSubscriptionTier
4215
+ );
4216
+ this.validateSubscriptionTier(preferredSubscriptionTier);
4217
+ const effectivePrice = subscriptionRequired ? 0 : this.price;
4218
+ const effectivePriceType = subscriptionRequired ? "subscription" /* SUBSCRIPTION */ : this.priceType === "subscription" /* SUBSCRIPTION */ ? "fixed" /* FIXED */ : this.priceType;
4219
+ const fareAmount = new FareAmount(
4220
+ effectivePriceType === "fixed" /* FIXED */ ? effectivePrice : 0,
4221
+ this.acpContractClient.config.baseFare
4222
+ );
4223
+ const account = await this.resolveAccount(
4224
+ subscriptionRequired,
4225
+ preferredSubscriptionTier
4226
+ );
4227
+ const jobId = await this.createJob(
4228
+ account,
4229
+ evaluatorAddress,
4230
+ expiredAt,
4231
+ fareAmount,
4232
+ subscriptionRequired,
4233
+ preferredSubscriptionTier ?? ""
4234
+ );
4235
+ await this.sendInitialMemo(jobId, fareAmount, subscriptionRequired, {
4236
+ name: this.name,
4237
+ requirement: finalServiceRequirement,
4238
+ priceValue: effectivePrice,
4239
+ priceType: effectivePriceType
4240
+ });
4241
+ return jobId;
4242
+ }
4243
+ validateRequest(serviceRequirement) {
4122
4244
  if (this.providerAddress === this.acpClient.walletAddress) {
4123
4245
  throw new acpError_default(
4124
4246
  "Provider address cannot be the same as the client address"
@@ -4126,84 +4248,147 @@ var AcpJobOffering = class {
4126
4248
  }
4127
4249
  if (this.requirement && typeof this.requirement === "object") {
4128
4250
  const validator = this.ajv.compile(this.requirement);
4129
- const valid = validator(serviceRequirement);
4130
- if (!valid) {
4251
+ if (!validator(serviceRequirement)) {
4131
4252
  throw new acpError_default(this.ajv.errorsText(validator.errors));
4132
4253
  }
4133
4254
  }
4134
- const finalServiceRequirement = {
4135
- name: this.name,
4136
- requirement: serviceRequirement,
4137
- priceValue: this.price,
4138
- priceType: this.priceType
4139
- };
4140
- const fareAmount = new FareAmount(
4141
- this.priceType === "fixed" /* FIXED */ ? this.price : 0,
4142
- this.acpContractClient.config.baseFare
4143
- );
4144
- const account = await this.acpClient.getByClientAndProvider(
4255
+ }
4256
+ isSubscriptionRequired(preferredSubscriptionTier) {
4257
+ const hasSubscriptionTiers = this.subscriptionTiers.length > 0;
4258
+ return preferredSubscriptionTier != null || this.priceType === "subscription" /* SUBSCRIPTION */ && hasSubscriptionTiers;
4259
+ }
4260
+ validateSubscriptionTier(preferredSubscriptionTier) {
4261
+ if (!preferredSubscriptionTier) return;
4262
+ if (this.subscriptionTiers.length === 0) {
4263
+ throw new acpError_default(
4264
+ `Offering "${this.name}" does not support subscription tiers`
4265
+ );
4266
+ }
4267
+ if (!this.subscriptionTiers.includes(preferredSubscriptionTier)) {
4268
+ throw new acpError_default(
4269
+ `Preferred subscription tier "${preferredSubscriptionTier}" is not offered. Available: ${this.subscriptionTiers.join(", ")}`
4270
+ );
4271
+ }
4272
+ }
4273
+ /**
4274
+ * Resolve the account to use for the job.
4275
+ *
4276
+ * For non-subscription jobs: returns the existing account if found.
4277
+ * For subscription jobs, priority:
4278
+ * 1. Valid account matching preferred tier
4279
+ * 2. Any valid (non-expired) account
4280
+ * 3. Expired/unactivated account (expiryAt = 0) to reuse
4281
+ * 4. null — createJob will create a new one
4282
+ */
4283
+ async resolveAccount(subscriptionRequired, preferredSubscriptionTier) {
4284
+ const raw = await this.acpClient.getByClientAndProvider(
4145
4285
  this.acpContractClient.walletAddress,
4146
4286
  this.providerAddress,
4147
- this.acpContractClient
4287
+ this.acpContractClient,
4288
+ subscriptionRequired ? this.name : void 0
4148
4289
  );
4290
+ if (!subscriptionRequired) {
4291
+ if (!(raw instanceof AcpAccount)) return null;
4292
+ const meta = raw.metadata;
4293
+ if (meta && typeof meta === "object" && meta.name) return null;
4294
+ return raw;
4295
+ }
4296
+ const subscriptionCheck = raw && typeof raw === "object" && "accounts" in raw ? raw : null;
4297
+ if (!subscriptionCheck) return null;
4298
+ const now = Math.floor(Date.now() / 1e3);
4299
+ const allAccounts = subscriptionCheck.accounts ?? [];
4300
+ const matchedAccount = this.findPreferredAccount(allAccounts, preferredSubscriptionTier, now) ?? allAccounts.find((a) => a.expiryAt != null && a.expiryAt > now) ?? allAccounts.find((a) => a.expiryAt == null || a.expiryAt === 0);
4301
+ if (!matchedAccount) return null;
4302
+ return new AcpAccount(
4303
+ this.acpContractClient,
4304
+ matchedAccount.id,
4305
+ matchedAccount.clientAddress ?? this.acpContractClient.walletAddress,
4306
+ matchedAccount.providerAddress ?? this.providerAddress,
4307
+ matchedAccount.metadata,
4308
+ matchedAccount.expiryAt
4309
+ );
4310
+ }
4311
+ findPreferredAccount(accounts, preferredTier, now) {
4312
+ if (!preferredTier) return void 0;
4313
+ return accounts.find((a) => {
4314
+ if (a.expiryAt == null || a.expiryAt <= now) return false;
4315
+ const meta = typeof a.metadata === "string" ? (() => {
4316
+ try {
4317
+ return JSON.parse(a.metadata);
4318
+ } catch {
4319
+ return {};
4320
+ }
4321
+ })() : a.metadata ?? {};
4322
+ return meta?.name === preferredTier;
4323
+ });
4324
+ }
4325
+ async createJob(account, evaluatorAddress, expiredAt, fareAmount, subscriptionRequired, subscriptionTier) {
4149
4326
  const isV1 = [
4150
4327
  baseSepoliaAcpConfig.contractAddress,
4151
4328
  baseSepoliaAcpX402Config.contractAddress,
4152
4329
  baseAcpConfig.contractAddress,
4153
4330
  baseAcpX402Config.contractAddress
4154
4331
  ].includes(this.acpContractClient.config.contractAddress);
4155
- let createJobPayload;
4156
4332
  const chainId = this.acpContractClient.config.chain.id;
4157
4333
  const isUsdcPaymentToken = USDC_TOKEN_ADDRESS[chainId].toLowerCase() === fareAmount.fare.contractAddress.toLowerCase();
4158
4334
  const isX402Job = this.acpContractClient.config.x402Config && isUsdcPaymentToken;
4159
- if (isV1 || !account) {
4160
- createJobPayload = this.acpContractClient.createJob(
4161
- this.providerAddress,
4162
- evaluatorAddress || this.acpContractClient.walletAddress,
4163
- expiredAt,
4164
- fareAmount.fare.contractAddress,
4165
- fareAmount.amount,
4166
- "",
4167
- isX402Job
4168
- );
4169
- } else {
4170
- createJobPayload = this.acpContractClient.createJobWithAccount(
4171
- account.id,
4172
- evaluatorAddress || zeroAddress2,
4173
- fareAmount.amount,
4174
- fareAmount.fare.contractAddress,
4175
- expiredAt,
4176
- isX402Job
4177
- );
4178
- }
4179
- const { userOpHash } = await this.acpContractClient.handleOperation([
4180
- createJobPayload
4335
+ const budget = subscriptionRequired ? 0n : fareAmount.amount;
4336
+ const subscriptionMetadata = subscriptionRequired ? JSON.stringify({ name: subscriptionTier }) : "";
4337
+ const operation = isV1 || !account ? this.acpContractClient.createJob(
4338
+ this.providerAddress,
4339
+ evaluatorAddress || this.acpContractClient.walletAddress,
4340
+ expiredAt,
4341
+ fareAmount.fare.contractAddress,
4342
+ budget,
4343
+ subscriptionMetadata,
4344
+ isX402Job
4345
+ ) : this.acpContractClient.createJobWithAccount(
4346
+ account.id,
4347
+ evaluatorAddress || zeroAddress2,
4348
+ budget,
4349
+ fareAmount.fare.contractAddress,
4350
+ expiredAt,
4351
+ isX402Job
4352
+ );
4353
+ const { userOpHash, txnHash } = await this.acpContractClient.handleOperation([
4354
+ operation
4181
4355
  ]);
4182
- const jobId = await this.acpContractClient.getJobId(
4356
+ return this.acpContractClient.getJobId(
4183
4357
  userOpHash,
4184
4358
  this.acpContractClient.walletAddress,
4185
4359
  this.providerAddress
4186
4360
  );
4361
+ }
4362
+ async sendInitialMemo(jobId, fareAmount, subscriptionRequired, serviceRequirement) {
4187
4363
  const payloads = [];
4188
- const setBudgetWithPaymentTokenPayload = this.acpContractClient.setBudgetWithPaymentToken(
4189
- jobId,
4190
- fareAmount.amount,
4191
- fareAmount.fare.contractAddress
4192
- );
4193
- if (setBudgetWithPaymentTokenPayload) {
4194
- payloads.push(setBudgetWithPaymentTokenPayload);
4364
+ if (!subscriptionRequired) {
4365
+ const setBudgetPayload = this.acpContractClient.setBudgetWithPaymentToken(
4366
+ jobId,
4367
+ fareAmount.amount,
4368
+ fareAmount.fare.contractAddress
4369
+ );
4370
+ if (setBudgetPayload) {
4371
+ payloads.push(setBudgetPayload);
4372
+ }
4373
+ }
4374
+ let content = JSON.stringify(serviceRequirement);
4375
+ if (this.isPrivate) {
4376
+ const memoContent = await this.acpClient.createMemoContent(
4377
+ jobId,
4378
+ content
4379
+ );
4380
+ content = memoContent.url;
4195
4381
  }
4196
4382
  payloads.push(
4197
4383
  this.acpContractClient.createMemo(
4198
4384
  jobId,
4199
- JSON.stringify(finalServiceRequirement),
4200
- 0 /* MESSAGE */,
4385
+ content,
4386
+ this.isPrivate ? 4 /* OBJECT_URL */ : 0 /* MESSAGE */,
4201
4387
  true,
4202
4388
  1 /* NEGOTIATION */
4203
4389
  )
4204
4390
  );
4205
4391
  await this.acpContractClient.handleOperation(payloads);
4206
- return jobId;
4207
4392
  }
4208
4393
  };
4209
4394
  var acpJobOffering_default = AcpJobOffering;
@@ -4211,7 +4396,7 @@ var acpJobOffering_default = AcpJobOffering;
4211
4396
  // src/acpJob.ts
4212
4397
  import * as util from "util";
4213
4398
  var AcpJob = class {
4214
- constructor(acpClient, id, clientAddress, providerAddress, evaluatorAddress, price, priceTokenAddress, memos, phase, context, contractAddress, _deliverable, netPayableAmount) {
4399
+ constructor(acpClient, id, clientAddress, providerAddress, evaluatorAddress, price, priceTokenAddress, memos, phase, context, contractAddress, netPayableAmount) {
4215
4400
  this.acpClient = acpClient;
4216
4401
  this.id = id;
4217
4402
  this.clientAddress = clientAddress;
@@ -4223,10 +4408,10 @@ var AcpJob = class {
4223
4408
  this.phase = phase;
4224
4409
  this.context = context;
4225
4410
  this.contractAddress = contractAddress;
4226
- this._deliverable = _deliverable;
4227
4411
  this.netPayableAmount = netPayableAmount;
4228
4412
  this.priceType = "fixed" /* FIXED */;
4229
4413
  this.priceValue = 0;
4414
+ this.isPrivate = false;
4230
4415
  const content = this.memos.find(
4231
4416
  (m) => m.nextPhase === 1 /* NEGOTIATION */
4232
4417
  )?.content;
@@ -4249,6 +4434,9 @@ var AcpJob = class {
4249
4434
  if (contentObj.priceValue) {
4250
4435
  this.priceValue = contentObj.priceValue || this.price;
4251
4436
  }
4437
+ if (contentObj.isPrivate) {
4438
+ this.isPrivate = contentObj.isPrivate;
4439
+ }
4252
4440
  }
4253
4441
  get acpContractClient() {
4254
4442
  return this.acpClient.contractClientByAddress(this.contractAddress);
@@ -4283,27 +4471,49 @@ var AcpJob = class {
4283
4471
  get latestMemo() {
4284
4472
  return this.memos[this.memos.length - 1];
4285
4473
  }
4286
- async getDeliverable() {
4287
- if (!this._deliverable) {
4474
+ getDeliverable() {
4475
+ const deliverableMemo = this.memos.find(
4476
+ (m) => m.nextPhase === 4 /* COMPLETED */
4477
+ );
4478
+ if (!deliverableMemo) {
4288
4479
  return null;
4289
4480
  }
4290
- if (typeof this._deliverable !== "string") {
4291
- return this._deliverable;
4292
- }
4293
- const regex = /api\/memo-contents\/([0-9]+)$/;
4294
- const result = this._deliverable?.match(regex);
4295
- if (!result) {
4296
- return this._deliverable;
4297
- }
4298
- const deliverable = await this.acpClient.getMemoContent(this._deliverable);
4299
- return tryParseJson(deliverable) || deliverable;
4481
+ return tryParseJson(deliverableMemo.content) || deliverableMemo.content;
4300
4482
  }
4301
4483
  async createRequirement(content) {
4302
4484
  const operations = [];
4485
+ let finalContent = content;
4486
+ if (this.isPrivate) {
4487
+ const memoContent = await this.acpClient.createMemoContent(
4488
+ this.id,
4489
+ content
4490
+ );
4491
+ finalContent = memoContent.url;
4492
+ }
4303
4493
  operations.push(
4304
4494
  this.acpContractClient.createMemo(
4305
4495
  this.id,
4306
- content,
4496
+ finalContent,
4497
+ this.isPrivate ? 4 /* OBJECT_URL */ : 0 /* MESSAGE */,
4498
+ true,
4499
+ 2 /* TRANSACTION */
4500
+ )
4501
+ );
4502
+ return await this.acpContractClient.handleOperation(operations);
4503
+ }
4504
+ async acceptRequirement(memo, reason) {
4505
+ const operations = [];
4506
+ operations.push(
4507
+ this.acpContractClient.signMemo(
4508
+ memo.id,
4509
+ true,
4510
+ reason ?? "Requirement accepted"
4511
+ )
4512
+ );
4513
+ operations.push(
4514
+ this.acpContractClient.createMemo(
4515
+ this.id,
4516
+ reason ?? "Proceeding to delivery",
4307
4517
  0 /* MESSAGE */,
4308
4518
  true,
4309
4519
  2 /* TRANSACTION */
@@ -4311,7 +4521,38 @@ var AcpJob = class {
4311
4521
  );
4312
4522
  return await this.acpContractClient.handleOperation(operations);
4313
4523
  }
4314
- async createPayableRequirement(content, type, amount, recipient, expiredAt = new Date(Date.now() + 1e3 * 60 * 5)) {
4524
+ async createPayableRequirement(content, type, amount, recipient, expiredAt = new Date(Date.now() + 1e3 * 60 * 5), duration) {
4525
+ if (type === 11 /* PAYABLE_REQUEST_SUBSCRIPTION */ && !duration) {
4526
+ throw new acpError_default("Duration is required for subscription payment requests");
4527
+ }
4528
+ if (type === 11 /* PAYABLE_REQUEST_SUBSCRIPTION */) {
4529
+ this.priceType = "subscription" /* SUBSCRIPTION */;
4530
+ if (this.priceValue !== 0) {
4531
+ throw new acpError_default(
4532
+ `Subscription payment request zero budget, got: ${this.priceValue}`
4533
+ );
4534
+ }
4535
+ let parsed;
4536
+ try {
4537
+ const result = JSON.parse(content);
4538
+ if (typeof result !== "object" || result === null || Array.isArray(result)) {
4539
+ throw new Error();
4540
+ }
4541
+ parsed = result;
4542
+ } catch {
4543
+ throw new acpError_default(
4544
+ `Subscription memo content must be a JSON object string, got: ${content}`
4545
+ );
4546
+ }
4547
+ const missing = ["name", "duration", "price"].filter(
4548
+ (k) => !(k in parsed)
4549
+ );
4550
+ if (missing.length > 0) {
4551
+ throw new acpError_default(
4552
+ `Subscription memo content is missing required fields: ${missing.join(", ")}`
4553
+ );
4554
+ }
4555
+ }
4315
4556
  const operations = [];
4316
4557
  if (type === 8 /* PAYABLE_TRANSFER_ESCROW */) {
4317
4558
  operations.push(
@@ -4323,11 +4564,34 @@ var AcpJob = class {
4323
4564
  }
4324
4565
  const feeAmount = new FareAmount(0, this.acpContractClient.config.baseFare);
4325
4566
  const isPercentagePricing = this.priceType === "percentage" /* PERCENTAGE */;
4326
- if (amount.fare.chainId && amount.fare.chainId !== this.acpContractClient.config.chain.id) {
4567
+ let finalContent = content;
4568
+ if (this.isPrivate) {
4569
+ const memoContent = await this.acpClient.createMemoContent(
4570
+ this.id,
4571
+ content
4572
+ );
4573
+ finalContent = memoContent.url;
4574
+ }
4575
+ if (type === 11 /* PAYABLE_REQUEST_SUBSCRIPTION */) {
4327
4576
  operations.push(
4328
- this.acpContractClient.createCrossChainPayableMemo(
4577
+ this.acpContractClient.createSubscriptionMemo(
4329
4578
  this.id,
4330
4579
  content,
4580
+ amount.amount,
4581
+ recipient,
4582
+ isPercentagePricing ? BigInt(Math.round(this.priceValue * 1e4)) : feeAmount.amount,
4583
+ isPercentagePricing ? 3 /* PERCENTAGE_FEE */ : 0 /* NO_FEE */,
4584
+ duration,
4585
+ 2 /* TRANSACTION */,
4586
+ expiredAt,
4587
+ amount.fare.contractAddress
4588
+ )
4589
+ );
4590
+ } else if (amount.fare.chainId && amount.fare.chainId !== this.acpContractClient.config.chain.id) {
4591
+ operations.push(
4592
+ this.acpContractClient.createCrossChainPayableMemo(
4593
+ this.id,
4594
+ finalContent,
4331
4595
  amount.fare.contractAddress,
4332
4596
  amount.amount,
4333
4597
  recipient,
@@ -4343,7 +4607,7 @@ var AcpJob = class {
4343
4607
  operations.push(
4344
4608
  this.acpContractClient.createPayableMemo(
4345
4609
  this.id,
4346
- content,
4610
+ finalContent,
4347
4611
  amount.amount,
4348
4612
  recipient,
4349
4613
  isPercentagePricing ? BigInt(Math.round(this.priceValue * 1e4)) : feeAmount.amount,
@@ -4374,14 +4638,15 @@ var AcpJob = class {
4374
4638
  memo.payableDetails.token,
4375
4639
  this.config
4376
4640
  ) : new FareAmount(0, this.baseFare);
4377
- const totalAmount = baseFareAmount.fare.contractAddress === transferAmount.fare.contractAddress ? baseFareAmount.add(transferAmount) : baseFareAmount;
4641
+ const sameToken = baseFareAmount.fare.contractAddress.toLowerCase() === transferAmount.fare.contractAddress.toLowerCase();
4642
+ const totalAmount = sameToken ? baseFareAmount.add(transferAmount) : baseFareAmount;
4378
4643
  operations.push(
4379
4644
  this.acpContractClient.approveAllowance(
4380
4645
  totalAmount.amount,
4381
4646
  this.baseFare.contractAddress
4382
4647
  )
4383
4648
  );
4384
- if (baseFareAmount.fare.contractAddress !== transferAmount.fare.contractAddress) {
4649
+ if (!sameToken) {
4385
4650
  operations.push(
4386
4651
  this.acpContractClient.approveAllowance(
4387
4652
  transferAmount.amount,
@@ -4390,11 +4655,19 @@ var AcpJob = class {
4390
4655
  );
4391
4656
  }
4392
4657
  operations.push(this.acpContractClient.signMemo(memo.id, true, reason));
4658
+ let finalContent = `Payment made. ${reason ?? ""}`.trim();
4659
+ if (this.isPrivate) {
4660
+ const memoContent = await this.acpClient.createMemoContent(
4661
+ this.id,
4662
+ finalContent
4663
+ );
4664
+ finalContent = memoContent.url;
4665
+ }
4393
4666
  operations.push(
4394
4667
  this.acpContractClient.createMemo(
4395
4668
  this.id,
4396
- `Payment made. ${reason ?? ""}`.trim(),
4397
- 0 /* MESSAGE */,
4669
+ finalContent,
4670
+ this.isPrivate ? 4 /* OBJECT_URL */ : 0 /* MESSAGE */,
4398
4671
  true,
4399
4672
  3 /* EVALUATION */
4400
4673
  )
@@ -4479,12 +4752,20 @@ var AcpJob = class {
4479
4752
  }
4480
4753
  return await latestMemo.sign(false, memoContent);
4481
4754
  }
4755
+ let finalContent = memoContent;
4756
+ if (this.isPrivate) {
4757
+ const memoContent2 = await this.acpClient.createMemoContent(
4758
+ this.id,
4759
+ finalContent
4760
+ );
4761
+ finalContent = memoContent2.url;
4762
+ }
4482
4763
  const operations = [];
4483
4764
  operations.push(
4484
4765
  this.acpContractClient.createMemo(
4485
4766
  this.id,
4486
- memoContent,
4487
- 0 /* MESSAGE */,
4767
+ finalContent,
4768
+ this.isPrivate ? 4 /* OBJECT_URL */ : 0 /* MESSAGE */,
4488
4769
  true,
4489
4770
  5 /* REJECTED */
4490
4771
  )
@@ -4501,10 +4782,18 @@ var AcpJob = class {
4501
4782
  amount.fare.contractAddress
4502
4783
  )
4503
4784
  );
4785
+ let finalContent = memoContent;
4786
+ if (this.isPrivate) {
4787
+ const memoContent2 = await this.acpClient.createMemoContent(
4788
+ this.id,
4789
+ finalContent
4790
+ );
4791
+ finalContent = memoContent2.url;
4792
+ }
4504
4793
  operations.push(
4505
4794
  this.acpContractClient.createPayableMemo(
4506
4795
  this.id,
4507
- memoContent,
4796
+ finalContent,
4508
4797
  amount.amount,
4509
4798
  this.clientAddress,
4510
4799
  feeAmount.amount,
@@ -4575,19 +4864,70 @@ var AcpJob = class {
4575
4864
  );
4576
4865
  return await this.acpContractClient.handleOperation(operations);
4577
4866
  }
4867
+ async paySubscription(reason) {
4868
+ if (this.phase === 6 /* EXPIRED */) {
4869
+ throw new acpError_default("Job has expired, cannot process subscription payment");
4870
+ }
4871
+ if (this.phase === 4 /* COMPLETED */) {
4872
+ throw new acpError_default(
4873
+ "Job is already completed, cannot process subscription payment"
4874
+ );
4875
+ }
4876
+ const memo = this.memos.find(
4877
+ (m) => m.type === 11 /* PAYABLE_REQUEST_SUBSCRIPTION */
4878
+ );
4879
+ if (!memo) {
4880
+ throw new acpError_default("No subscription payment request memo found");
4881
+ }
4882
+ if (!memo.payableDetails) {
4883
+ throw new acpError_default("Subscription memo has no payable details");
4884
+ }
4885
+ const operations = [];
4886
+ operations.push(
4887
+ this.acpContractClient.approveAllowance(
4888
+ memo.payableDetails.amount,
4889
+ memo.payableDetails.token
4890
+ )
4891
+ );
4892
+ operations.push(
4893
+ this.acpContractClient.signMemo(
4894
+ memo.id,
4895
+ true,
4896
+ reason || "Subscription payment approved"
4897
+ )
4898
+ );
4899
+ operations.push(
4900
+ this.acpContractClient.createMemo(
4901
+ this.id,
4902
+ `Subscription payment made. ${reason ?? ""}`.trim(),
4903
+ 0 /* MESSAGE */,
4904
+ true,
4905
+ memo.nextPhase
4906
+ )
4907
+ );
4908
+ return await this.acpContractClient.handleOperation(operations);
4909
+ }
4578
4910
  async evaluate(accept, reason) {
4579
4911
  if (this.latestMemo?.nextPhase !== 4 /* COMPLETED */) {
4580
4912
  throw new acpError_default("No evaluation memo found");
4581
4913
  }
4582
4914
  const memo = this.latestMemo;
4583
- await memo.sign(accept, reason);
4915
+ return await memo.sign(accept, reason);
4584
4916
  }
4585
4917
  async createNotification(content) {
4586
4918
  const operations = [];
4919
+ let finalContent = content;
4920
+ if (this.isPrivate) {
4921
+ const memoContent = await this.acpClient.createMemoContent(
4922
+ this.id,
4923
+ content
4924
+ );
4925
+ finalContent = memoContent.url;
4926
+ }
4587
4927
  operations.push(
4588
4928
  this.acpContractClient.createMemo(
4589
4929
  this.id,
4590
- content,
4930
+ finalContent,
4591
4931
  9 /* NOTIFICATION */,
4592
4932
  true,
4593
4933
  4 /* COMPLETED */
@@ -4605,10 +4945,18 @@ var AcpJob = class {
4605
4945
  );
4606
4946
  const feeAmount = new FareAmount(0, this.acpContractClient.config.baseFare);
4607
4947
  const isPercentagePricing = this.priceType === "percentage" /* PERCENTAGE */ && !skipFee;
4948
+ let finalContent = content;
4949
+ if (this.isPrivate) {
4950
+ const memoContent = await this.acpClient.createMemoContent(
4951
+ this.id,
4952
+ content
4953
+ );
4954
+ finalContent = memoContent.url;
4955
+ }
4608
4956
  operations.push(
4609
4957
  this.acpContractClient.createPayableMemo(
4610
4958
  this.id,
4611
- content,
4959
+ finalContent,
4612
4960
  amount.amount,
4613
4961
  this.clientAddress,
4614
4962
  isPercentagePricing ? BigInt(Math.round(this.priceValue * 1e4)) : feeAmount.amount,
@@ -4715,9 +5063,17 @@ var AcpJob = class {
4715
5063
  );
4716
5064
  const feeAmount = new FareAmount(0, this.acpContractClient.config.baseFare);
4717
5065
  const isPercentagePricing = this.priceType === "percentage" /* PERCENTAGE */ && !skipFee;
5066
+ let finalContent = content;
5067
+ if (this.isPrivate) {
5068
+ const memoContent = await this.acpClient.createMemoContent(
5069
+ this.id,
5070
+ content
5071
+ );
5072
+ finalContent = memoContent.url;
5073
+ }
4718
5074
  const createMemoOperation = this.acpContractClient.createCrossChainPayableMemo(
4719
5075
  this.id,
4720
- content,
5076
+ finalContent,
4721
5077
  amount.fare.contractAddress,
4722
5078
  amount.amount,
4723
5079
  recipient,
@@ -4752,9 +5108,9 @@ var acpJob_default = AcpJob;
4752
5108
 
4753
5109
  // src/acpMemo.ts
4754
5110
  import util2 from "util";
4755
- var AcpMemo = class {
4756
- constructor(contractClient, id, type, content, nextPhase, status, senderAddress, signedReason, expiry, payableDetails, txHash, signedTxHash, state) {
4757
- this.contractClient = contractClient;
5111
+ var AcpMemo = class _AcpMemo {
5112
+ constructor(acpClient, id, type, content, nextPhase, status, senderAddress, signedReason, expiry, payableDetails, txHash, signedTxHash, state) {
5113
+ this.acpClient = acpClient;
4758
5114
  this.id = id;
4759
5115
  this.type = type;
4760
5116
  this.content = content;
@@ -4772,8 +5128,39 @@ var AcpMemo = class {
4772
5128
  this.payableDetails.feeAmount = BigInt(this.payableDetails.feeAmount);
4773
5129
  }
4774
5130
  }
5131
+ static async build(acpClient, id, type, content, nextPhase, status, senderAddress, signedReason, expiry, payableDetails, txHash, signedTxHash, state) {
5132
+ let memoContent = content;
5133
+ const regex = /api\/memo-contents\/([0-9]+)$/;
5134
+ const result = memoContent.match(regex);
5135
+ if (result) {
5136
+ memoContent = await acpClient.getMemoContent(content);
5137
+ }
5138
+ return new _AcpMemo(
5139
+ acpClient,
5140
+ id,
5141
+ type,
5142
+ memoContent,
5143
+ nextPhase,
5144
+ status,
5145
+ senderAddress,
5146
+ signedReason,
5147
+ expiry,
5148
+ payableDetails,
5149
+ txHash,
5150
+ signedTxHash,
5151
+ state
5152
+ );
5153
+ }
5154
+ async getContent() {
5155
+ const regex = /api\/memo-contents\/([0-9]+)$/;
5156
+ const result = this.content.match(regex);
5157
+ if (!result) {
5158
+ return this.content;
5159
+ }
5160
+ return this.acpClient.getMemoContent(this.content);
5161
+ }
4775
5162
  async create(jobId, isSecured = true) {
4776
- return this.contractClient.createMemo(
5163
+ return this.acpClient.acpContractClient.createMemo(
4777
5164
  jobId,
4778
5165
  this.content,
4779
5166
  this.type,
@@ -4782,44 +5169,30 @@ var AcpMemo = class {
4782
5169
  );
4783
5170
  }
4784
5171
  async sign(approved, reason) {
4785
- const payload = this.contractClient.signMemo(this.id, approved, reason);
4786
- return await this.contractClient.handleOperation([payload]);
4787
- }
4788
- [util2.inspect.custom]() {
4789
- return {
4790
- id: this.id,
4791
- senderAddress: this.senderAddress,
4792
- type: MemoType[this.type],
4793
- status: this.status,
4794
- content: this.content,
4795
- signedReason: this.signedReason,
4796
- txHash: this.txHash,
4797
- signedTxHash: this.signedTxHash,
4798
- nextPhase: AcpJobPhases[this.nextPhase],
4799
- expiry: this.expiry,
4800
- payableDetails: this.payableDetails
4801
- };
4802
- }
4803
- };
4804
- var acpMemo_default = AcpMemo;
4805
-
4806
- // src/acpAccount.ts
4807
- var AcpAccount = class {
4808
- constructor(contractClient, id, clientAddress, providerAddress, metadata) {
4809
- this.contractClient = contractClient;
4810
- this.id = id;
4811
- this.clientAddress = clientAddress;
4812
- this.providerAddress = providerAddress;
4813
- this.metadata = metadata;
4814
- }
4815
- async updateMetadata(metadata) {
4816
- const hash = await this.contractClient.updateAccountMetadata(
5172
+ const payload = this.acpClient.acpContractClient.signMemo(
4817
5173
  this.id,
4818
- JSON.stringify(metadata)
5174
+ approved,
5175
+ reason
4819
5176
  );
4820
- return hash;
5177
+ return await this.acpClient.acpContractClient.handleOperation([payload]);
5178
+ }
5179
+ [util2.inspect.custom]() {
5180
+ return {
5181
+ id: this.id,
5182
+ senderAddress: this.senderAddress,
5183
+ type: MemoType[this.type],
5184
+ status: this.status,
5185
+ content: this.content,
5186
+ signedReason: this.signedReason,
5187
+ txHash: this.txHash,
5188
+ signedTxHash: this.signedTxHash,
5189
+ nextPhase: AcpJobPhases[this.nextPhase],
5190
+ expiry: this.expiry,
5191
+ payableDetails: this.payableDetails
5192
+ };
4821
5193
  }
4822
5194
  };
5195
+ var acpMemo_default = AcpMemo;
4823
5196
 
4824
5197
  // src/acpClient.ts
4825
5198
  import axios, { AxiosError } from "axios";
@@ -4836,6 +5209,7 @@ var AcpAgent = class {
4836
5209
  this.twitterHandle = args.twitterHandle;
4837
5210
  this.metrics = args.metrics;
4838
5211
  this.resources = args.resources;
5212
+ this.subscriptions = Object.freeze([...args.subscriptions ?? []]);
4839
5213
  }
4840
5214
  };
4841
5215
  var acpAgent_default = AcpAgent;
@@ -4946,6 +5320,7 @@ var AcpClient = class {
4946
5320
  });
4947
5321
  return response.data.data;
4948
5322
  } catch (err) {
5323
+ console.log("err->>", err.response.data);
4949
5324
  throw new acpError_default("Failed to verify auth challenge", err);
4950
5325
  }
4951
5326
  }
@@ -5000,18 +5375,26 @@ var AcpClient = class {
5000
5375
  socket.on("onEvaluate" /* ON_EVALUATE */, async (data, callback) => {
5001
5376
  callback(true);
5002
5377
  if (this.onEvaluate) {
5003
- const job = this._hydrateJob(data);
5378
+ const job = await this._hydrateJob(data);
5004
5379
  this.onEvaluate(job);
5005
5380
  }
5006
5381
  });
5007
5382
  socket.on("onNewTask" /* ON_NEW_TASK */, async (data, callback) => {
5008
5383
  callback(true);
5009
5384
  if (this.onNewTask) {
5010
- const job = this._hydrateJob(data);
5011
- this.onNewTask(
5012
- job,
5013
- job.memos.find((m) => m.id == data.memoToSign)
5014
- );
5385
+ const job = await this._hydrateJob(data);
5386
+ if (job.phase === 6 /* EXPIRED */) {
5387
+ console.warn(`onNewTask skipped for job ${data.id}: job has expired`);
5388
+ return;
5389
+ }
5390
+ try {
5391
+ await this.onNewTask(
5392
+ job,
5393
+ job.memos.find((m) => m.id == data.memoToSign)
5394
+ );
5395
+ } catch (err) {
5396
+ console.error(`onNewTask error for job ${data.id}:`, err);
5397
+ }
5015
5398
  }
5016
5399
  });
5017
5400
  const cleanup = async () => {
@@ -5038,8 +5421,6 @@ var AcpClient = class {
5038
5421
  errCallback(err);
5039
5422
  } else if (err.response?.data.error?.message) {
5040
5423
  throw new acpError_default(err.response?.data.error.message);
5041
- } else {
5042
- throw new acpError_default(`Failed to fetch ${url}: ${err.message}`, err);
5043
5424
  }
5044
5425
  } else {
5045
5426
  throw new acpError_default(
@@ -5049,10 +5430,10 @@ var AcpClient = class {
5049
5430
  }
5050
5431
  }
5051
5432
  }
5052
- _hydrateMemo(memo, contractClient) {
5433
+ async _hydrateMemo(memo) {
5053
5434
  try {
5054
- return new acpMemo_default(
5055
- contractClient,
5435
+ return await acpMemo_default.build(
5436
+ this,
5056
5437
  memo.id,
5057
5438
  memo.memoType,
5058
5439
  memo.content,
@@ -5060,7 +5441,7 @@ var AcpClient = class {
5060
5441
  memo.status,
5061
5442
  memo.senderAddress,
5062
5443
  memo.signedReason,
5063
- memo.expiry ? new Date(Number(memo.expiry) * 1e3) : void 0,
5444
+ memo.expiry ? new Date(parseInt(memo.expiry) * 1e3) : void 0,
5064
5445
  memo.payableDetails,
5065
5446
  memo.txHash,
5066
5447
  memo.signedTxHash,
@@ -5070,7 +5451,7 @@ var AcpClient = class {
5070
5451
  throw new acpError_default(`Failed to hydrate memo ${memo.id}`, err);
5071
5452
  }
5072
5453
  }
5073
- _hydrateJob(job) {
5454
+ async _hydrateJob(job) {
5074
5455
  try {
5075
5456
  return new acpJob_default(
5076
5457
  this,
@@ -5080,31 +5461,27 @@ var AcpClient = class {
5080
5461
  job.evaluatorAddress,
5081
5462
  job.price,
5082
5463
  job.priceTokenAddress,
5083
- job.memos.map(
5084
- (memo) => this._hydrateMemo(
5085
- memo,
5086
- this.contractClientByAddress(job.contractAddress)
5087
- )
5088
- ),
5464
+ await Promise.all(job.memos.map((memo) => this._hydrateMemo(memo))),
5089
5465
  job.phase,
5090
5466
  job.context,
5091
5467
  job.contractAddress,
5092
- job.deliverable,
5093
5468
  job.netPayableAmount
5094
5469
  );
5095
5470
  } catch (err) {
5096
5471
  throw new acpError_default(`Failed to hydrate job ${job.id}`, err);
5097
5472
  }
5098
5473
  }
5099
- _hydrateJobs(rawJobs, options) {
5100
- const jobs = rawJobs.map((job) => {
5101
- try {
5102
- return this._hydrateJob(job);
5103
- } catch (err) {
5104
- console.warn(`${options?.logPrefix ?? "Skipped"}`, err);
5105
- return null;
5106
- }
5107
- });
5474
+ async _hydrateJobs(rawJobs, options) {
5475
+ const jobs = await Promise.all(
5476
+ rawJobs.map((job) => {
5477
+ try {
5478
+ return this._hydrateJob(job);
5479
+ } catch (err) {
5480
+ console.warn(`${options?.logPrefix ?? "Skipped"}`, err);
5481
+ return null;
5482
+ }
5483
+ })
5484
+ );
5108
5485
  return jobs.filter((job) => !!job);
5109
5486
  }
5110
5487
  _hydrateAgent(agent) {
@@ -5133,14 +5510,17 @@ var AcpClient = class {
5133
5510
  offering.requiredFunds,
5134
5511
  offering.slaMinutes,
5135
5512
  offering.requirement,
5136
- offering.deliverable
5513
+ offering.deliverable,
5514
+ offering.subscriptionTiers ?? [],
5515
+ offering.isPrivate
5137
5516
  );
5138
5517
  }),
5139
5518
  contractAddress: agent.contractAddress,
5140
5519
  twitterHandle: agent.twitterHandle,
5141
5520
  walletAddress: agent.walletAddress,
5142
5521
  metrics: agent.metrics,
5143
- resources: agent.resources
5522
+ resources: agent.resources,
5523
+ subscriptions: agent.subscriptions ?? []
5144
5524
  });
5145
5525
  }
5146
5526
  async browseAgents(keyword, options = {}) {
@@ -5189,65 +5569,87 @@ var AcpClient = class {
5189
5569
  return this._hydrateAgent(agent);
5190
5570
  });
5191
5571
  }
5192
- async initiateJob(providerAddress, serviceRequirement, fareAmount, evaluatorAddress, expiredAt = new Date(Date.now() + 1e3 * 60 * 60 * 24)) {
5572
+ async initiateJob(providerAddress, serviceRequirement, fareAmount, evaluatorAddress, expiredAt = new Date(Date.now() + 1e3 * 60 * 60 * 24), offeringName, preferredSubscriptionTier) {
5193
5573
  if (providerAddress === this.walletAddress) {
5194
5574
  throw new acpError_default(
5195
5575
  "Provider address cannot be the same as the client address"
5196
5576
  );
5197
5577
  }
5198
- const account = await this.getByClientAndProvider(
5199
- this.walletAddress,
5578
+ const subscriptionRequired = preferredSubscriptionTier != null;
5579
+ const { account } = await this._resolveSubscriptionAccount(
5200
5580
  providerAddress,
5201
- this.acpContractClient
5581
+ offeringName,
5582
+ preferredSubscriptionTier
5202
5583
  );
5584
+ const budget = subscriptionRequired ? 0n : fareAmount.amount;
5585
+ const subscriptionMetadata = subscriptionRequired ? JSON.stringify({ name: preferredSubscriptionTier ?? "" }) : "";
5203
5586
  const isV1 = [
5204
5587
  baseSepoliaAcpConfig.contractAddress,
5205
5588
  baseSepoliaAcpX402Config.contractAddress,
5206
5589
  baseAcpConfig.contractAddress,
5207
5590
  baseAcpX402Config.contractAddress
5208
5591
  ].includes(this.acpContractClient.config.contractAddress);
5209
- const defaultEvaluatorAddress = isV1 && !evaluatorAddress ? this.walletAddress : zeroAddress3;
5592
+ const resolvedEvaluator = evaluatorAddress || (isV1 ? this.walletAddress : zeroAddress3);
5210
5593
  const chainId = this.acpContractClient.config.chain.id;
5211
- const isUsdcPaymentToken = USDC_TOKEN_ADDRESS[chainId].toLowerCase() === fareAmount.fare.contractAddress.toLowerCase();
5212
- const isX402Job = this.acpContractClient.config.x402Config && isUsdcPaymentToken;
5213
- const createJobPayload = isV1 || !account ? this.acpContractClient.createJob(
5214
- providerAddress,
5215
- evaluatorAddress || defaultEvaluatorAddress,
5216
- expiredAt,
5217
- fareAmount.fare.contractAddress,
5218
- fareAmount.amount,
5219
- "",
5220
- isX402Job
5221
- ) : this.acpContractClient.createJobWithAccount(
5222
- account.id,
5223
- evaluatorAddress || defaultEvaluatorAddress,
5224
- fareAmount.amount,
5225
- fareAmount.fare.contractAddress,
5226
- expiredAt,
5227
- isX402Job
5228
- );
5229
- const { userOpHash } = await this.acpContractClient.handleOperation([
5230
- createJobPayload
5231
- ]);
5594
+ const isX402Job = this.acpContractClient.config.x402Config && USDC_TOKEN_ADDRESS[chainId].toLowerCase() === fareAmount.fare.contractAddress.toLowerCase();
5595
+ const createJobOperations = [];
5596
+ if (isV1 || !account) {
5597
+ createJobOperations.push(
5598
+ this.acpContractClient.createJob(
5599
+ providerAddress,
5600
+ resolvedEvaluator,
5601
+ expiredAt,
5602
+ fareAmount.fare.contractAddress,
5603
+ budget,
5604
+ subscriptionMetadata,
5605
+ isX402Job
5606
+ )
5607
+ );
5608
+ } else {
5609
+ createJobOperations.push(
5610
+ this.acpContractClient.createJobWithAccount(
5611
+ account.id,
5612
+ resolvedEvaluator,
5613
+ budget,
5614
+ fareAmount.fare.contractAddress,
5615
+ expiredAt,
5616
+ isX402Job
5617
+ )
5618
+ );
5619
+ }
5620
+ const { userOpHash } = await this.acpContractClient.handleOperation(createJobOperations);
5232
5621
  const jobId = await this.acpContractClient.getJobId(
5233
5622
  userOpHash,
5234
5623
  this.walletAddress,
5235
5624
  providerAddress
5236
5625
  );
5237
5626
  const payloads = [];
5238
- const setBudgetWithPaymentTokenPayload = this.acpContractClient.setBudgetWithPaymentToken(
5239
- jobId,
5240
- fareAmount.amount,
5241
- fareAmount.fare.contractAddress
5242
- );
5243
- if (setBudgetWithPaymentTokenPayload) {
5244
- payloads.push(setBudgetWithPaymentTokenPayload);
5627
+ if (!subscriptionRequired) {
5628
+ const setBudgetPayload = this.acpContractClient.setBudgetWithPaymentToken(
5629
+ jobId,
5630
+ fareAmount.amount,
5631
+ fareAmount.fare.contractAddress
5632
+ );
5633
+ if (setBudgetPayload) {
5634
+ payloads.push(setBudgetPayload);
5635
+ }
5636
+ }
5637
+ const memoPayload = subscriptionRequired && typeof serviceRequirement === "object" ? preparePayload({
5638
+ ...serviceRequirement,
5639
+ priceValue: 0,
5640
+ priceType: "subscription" /* SUBSCRIPTION */
5641
+ }) : preparePayload(serviceRequirement);
5642
+ const isPrivate = typeof serviceRequirement === "object" && "isPrivate" in serviceRequirement && serviceRequirement.isPrivate;
5643
+ let content = memoPayload;
5644
+ if (isPrivate) {
5645
+ const memoContent = await this.createMemoContent(jobId, memoPayload);
5646
+ content = memoContent.url;
5245
5647
  }
5246
5648
  payloads.push(
5247
5649
  this.acpContractClient.createMemo(
5248
5650
  jobId,
5249
- preparePayload(serviceRequirement),
5250
- 0 /* MESSAGE */,
5651
+ isPrivate ? content : memoPayload,
5652
+ isPrivate ? 4 /* OBJECT_URL */ : 0 /* MESSAGE */,
5251
5653
  true,
5252
5654
  1 /* NEGOTIATION */
5253
5655
  )
@@ -5305,10 +5707,7 @@ var AcpClient = class {
5305
5707
  if (!memo) {
5306
5708
  return null;
5307
5709
  }
5308
- return this._hydrateMemo(
5309
- memo,
5310
- this.contractClientByAddress(memo.contractAddress)
5311
- );
5710
+ return this._hydrateMemo(memo);
5312
5711
  }
5313
5712
  async getAgent(walletAddress, options = {}) {
5314
5713
  const params = {
@@ -5336,32 +5735,195 @@ var AcpClient = class {
5336
5735
  account.id,
5337
5736
  account.clientAddress,
5338
5737
  account.providerAddress,
5339
- account.metadata
5738
+ account.metadata,
5739
+ account.expiryAt
5340
5740
  );
5341
5741
  }
5342
- async getByClientAndProvider(clientAddress, providerAddress, acpContractClient) {
5343
- const response = await this._fetch(
5344
- `/accounts/client/${clientAddress}/provider/${providerAddress}`,
5345
- "GET",
5346
- {},
5347
- {},
5348
- (err) => {
5349
- if (err.response?.status === 404) {
5350
- return;
5351
- }
5352
- throw new acpError_default("Failed to get account by client and provider", err);
5742
+ /**
5743
+ * Gets account or subscription data for a client–provider pair.
5744
+ * When offeringName is provided, the backend may return subscription tiers and accounts
5745
+ * (ISubscriptionCheckResponse). When not provided, returns a single AcpAccount or null.
5746
+ */
5747
+ async getByClientAndProvider(clientAddress, providerAddress, acpContractClient, offeringName) {
5748
+ let endpoint = `/accounts/client/${clientAddress}/provider/${providerAddress}`;
5749
+ if (offeringName) {
5750
+ endpoint = `/accounts/sub/client/${clientAddress}/provider/${providerAddress}`;
5751
+ }
5752
+ const response = await this._fetch(endpoint, "GET", {}, {}, (err) => {
5753
+ if (err.response?.status === 404) {
5754
+ return;
5353
5755
  }
5354
- );
5756
+ throw new acpError_default("Failed to get account by client and provider", err);
5757
+ });
5355
5758
  if (!response) {
5356
5759
  return null;
5357
5760
  }
5761
+ if (typeof response === "object" && "accounts" in response && Array.isArray(response.accounts)) {
5762
+ const sub = response;
5763
+ sub.accounts = sub.accounts.map((a) => ({
5764
+ ...a,
5765
+ expiryAt: a.expiryAt ?? a.expiry
5766
+ }));
5767
+ return sub;
5768
+ }
5769
+ const account = response;
5770
+ const expiryAt = account.expiryAt ?? account.expiry;
5358
5771
  return new AcpAccount(
5359
5772
  acpContractClient || this.contractClients[0],
5360
- response.id,
5361
- response.clientAddress,
5362
- response.providerAddress,
5363
- response.metadata
5773
+ account.id,
5774
+ account.clientAddress,
5775
+ account.providerAddress,
5776
+ account.metadata,
5777
+ expiryAt
5778
+ );
5779
+ }
5780
+ /**
5781
+ * Narrows a backend response to ISubscriptionCheckResponse if it has an accounts array.
5782
+ */
5783
+ _asSubscriptionCheck(raw) {
5784
+ return raw && typeof raw === "object" && "accounts" in raw ? raw : null;
5785
+ }
5786
+ /**
5787
+ * Resolve the account to use for the job.
5788
+ *
5789
+ * For subscription jobs, priority:
5790
+ * 1. Valid account matching preferred tier
5791
+ * 2. Any valid (non-expired) account
5792
+ * 3. Unactivated account (expiryAt = 0) to reuse
5793
+ * 4. null — createJob will create a new one
5794
+ */
5795
+ async _resolveSubscriptionAccount(providerAddress, offeringName, preferredSubscriptionTier) {
5796
+ if (!offeringName) return { account: null };
5797
+ const raw = await this.getByClientAndProvider(
5798
+ this.walletAddress,
5799
+ providerAddress,
5800
+ this.acpContractClient,
5801
+ offeringName
5802
+ );
5803
+ const subscriptionCheck = raw && typeof raw === "object" && "accounts" in raw ? raw : null;
5804
+ if (!subscriptionCheck) return { account: null };
5805
+ const now = Math.floor(Date.now() / 1e3);
5806
+ const allAccounts = subscriptionCheck.accounts ?? [];
5807
+ const matchedAccount = this._findPreferredAccount(allAccounts, preferredSubscriptionTier, now) ?? allAccounts.find((a) => a.expiryAt != null && a.expiryAt > now) ?? allAccounts.find((a) => a.expiryAt == null || a.expiryAt === 0);
5808
+ if (!matchedAccount) return { account: null };
5809
+ return {
5810
+ account: new AcpAccount(
5811
+ this.acpContractClient,
5812
+ matchedAccount.id,
5813
+ matchedAccount.clientAddress ?? this.walletAddress,
5814
+ matchedAccount.providerAddress ?? providerAddress,
5815
+ matchedAccount.metadata,
5816
+ matchedAccount.expiryAt
5817
+ )
5818
+ };
5819
+ }
5820
+ _findPreferredAccount(accounts, preferredTier, now) {
5821
+ if (!preferredTier) return void 0;
5822
+ return accounts.find((a) => {
5823
+ if (a.expiryAt == null || a.expiryAt <= now) return false;
5824
+ const meta = typeof a.metadata === "string" ? (() => {
5825
+ try {
5826
+ return JSON.parse(a.metadata);
5827
+ } catch {
5828
+ return {};
5829
+ }
5830
+ })() : a.metadata ?? {};
5831
+ return meta?.name === preferredTier;
5832
+ });
5833
+ }
5834
+ /**
5835
+ * Returns the first subscription account with expiryAt > now, or null.
5836
+ */
5837
+ _getValidSubscriptionAccountFromResponse(response, acpContractClient) {
5838
+ const now = Math.floor(Date.now() / 1e3);
5839
+ const valid = response.accounts?.find(
5840
+ (a) => a.expiryAt != null && a.expiryAt > now
5841
+ );
5842
+ if (!valid) return null;
5843
+ return new AcpAccount(
5844
+ acpContractClient,
5845
+ valid.id,
5846
+ valid.clientAddress,
5847
+ valid.providerAddress,
5848
+ valid.metadata,
5849
+ valid.expiryAt
5850
+ );
5851
+ }
5852
+ /**
5853
+ * Seller-facing: determines whether to create a subscription payment request memo.
5854
+ * Call this when handling a new job (e.g. in REQUEST phase); then branch on
5855
+ * needsSubscriptionPayment and use tier when true.
5856
+ */
5857
+ async getSubscriptionPaymentRequirement(clientAddress, providerAddress, offeringName) {
5858
+ let raw;
5859
+ try {
5860
+ raw = await this.getByClientAndProvider(
5861
+ clientAddress,
5862
+ providerAddress,
5863
+ void 0,
5864
+ offeringName
5865
+ );
5866
+ } catch {
5867
+ return {
5868
+ needsSubscriptionPayment: false,
5869
+ action: "no_subscription_required"
5870
+ };
5871
+ }
5872
+ const response = this._asSubscriptionCheck(raw);
5873
+ if (!response?.accounts?.length) {
5874
+ return {
5875
+ needsSubscriptionPayment: false,
5876
+ action: "no_subscription_required"
5877
+ };
5878
+ }
5879
+ const now = Math.floor(Date.now() / 1e3);
5880
+ const hasValidSubscription = response.accounts.some(
5881
+ (a) => a.expiryAt != null && a.expiryAt > now
5364
5882
  );
5883
+ if (hasValidSubscription) {
5884
+ return {
5885
+ needsSubscriptionPayment: false,
5886
+ action: "valid_subscription"
5887
+ };
5888
+ }
5889
+ const firstAccount = response.accounts[0];
5890
+ const tier = {
5891
+ name: firstAccount.metadata?.name ?? "",
5892
+ price: firstAccount.metadata?.price ?? 0,
5893
+ duration: firstAccount.metadata?.duration ?? 0
5894
+ };
5895
+ return {
5896
+ needsSubscriptionPayment: true,
5897
+ tier
5898
+ };
5899
+ }
5900
+ async getValidSubscriptionAccount(providerAddress, offeringName, clientAddress, acpContractClient) {
5901
+ const raw = await this.getByClientAndProvider(
5902
+ clientAddress,
5903
+ providerAddress,
5904
+ acpContractClient,
5905
+ offeringName
5906
+ );
5907
+ const subscriptionCheck = this._asSubscriptionCheck(raw);
5908
+ if (!subscriptionCheck) return null;
5909
+ const contractClient = acpContractClient || this.contractClients[0];
5910
+ const account = this._getValidSubscriptionAccountFromResponse(
5911
+ subscriptionCheck,
5912
+ contractClient
5913
+ );
5914
+ if (account) return account;
5915
+ const legacy = subscriptionCheck;
5916
+ if (legacy.subscriptionRequired && legacy.hasValidSubscription && legacy.account) {
5917
+ return new AcpAccount(
5918
+ contractClient,
5919
+ legacy.account.id,
5920
+ legacy.account.clientAddress,
5921
+ legacy.account.providerAddress,
5922
+ legacy.account.metadata,
5923
+ legacy.account.expiryAt
5924
+ );
5925
+ }
5926
+ return null;
5365
5927
  }
5366
5928
  async createMemoContent(jobId, content) {
5367
5929
  const response = await this._fetch(
@@ -5677,9 +6239,7 @@ var AcpContractClient = class _AcpContractClient extends baseAcpContractClient_d
5677
6239
  throw new acpError_default(`Failed to send user operation`, finalError);
5678
6240
  }
5679
6241
  async getJobId(createJobUserOpHash, clientAddress, providerAddress) {
5680
- const result = await this.sessionKeyClient.getUserOperationReceipt(
5681
- createJobUserOpHash
5682
- );
6242
+ const result = await this.sessionKeyClient.getUserOperationReceipt(createJobUserOpHash);
5683
6243
  if (!result) {
5684
6244
  throw new acpError_default("Failed to get user operation receipt");
5685
6245
  }
@@ -6551,6 +7111,7 @@ var MEMO_MANAGER_ABI = [
6551
7111
  { inputs: [], name: "InvalidMemoState", type: "error" },
6552
7112
  { inputs: [], name: "InvalidMemoStateTransition", type: "error" },
6553
7113
  { inputs: [], name: "InvalidMemoType", type: "error" },
7114
+ { inputs: [], name: "InvalidSubscriptionDuration", type: "error" },
6554
7115
  { inputs: [], name: "JobAlreadyCompleted", type: "error" },
6555
7116
  { inputs: [], name: "JobDoesNotExist", type: "error" },
6556
7117
  { inputs: [], name: "MemoAlreadyApproved", type: "error" },
@@ -6586,6 +7147,7 @@ var MEMO_MANAGER_ABI = [
6586
7147
  { inputs: [], name: "ZeroAddressToken", type: "error" },
6587
7148
  { inputs: [], name: "ZeroAssetManagerAddress", type: "error" },
6588
7149
  { inputs: [], name: "ZeroJobManagerAddress", type: "error" },
7150
+ { inputs: [], name: "ZeroPaymentManagerAddress", type: "error" },
6589
7151
  {
6590
7152
  anonymous: false,
6591
7153
  inputs: [
@@ -6858,6 +7420,31 @@ var MEMO_MANAGER_ABI = [
6858
7420
  name: "RoleRevoked",
6859
7421
  type: "event"
6860
7422
  },
7423
+ {
7424
+ anonymous: false,
7425
+ inputs: [
7426
+ {
7427
+ indexed: true,
7428
+ internalType: "uint256",
7429
+ name: "memoId",
7430
+ type: "uint256"
7431
+ },
7432
+ {
7433
+ indexed: true,
7434
+ internalType: "uint256",
7435
+ name: "accountId",
7436
+ type: "uint256"
7437
+ },
7438
+ {
7439
+ indexed: false,
7440
+ internalType: "uint256",
7441
+ name: "duration",
7442
+ type: "uint256"
7443
+ }
7444
+ ],
7445
+ name: "SubscriptionActivated",
7446
+ type: "event"
7447
+ },
6861
7448
  {
6862
7449
  anonymous: false,
6863
7450
  inputs: [
@@ -6925,17 +7512,6 @@ var MEMO_MANAGER_ABI = [
6925
7512
  stateMutability: "view",
6926
7513
  type: "function"
6927
7514
  },
6928
- {
6929
- inputs: [
6930
- { internalType: "uint256[]", name: "memoIds", type: "uint256[]" },
6931
- { internalType: "bool", name: "approved", type: "bool" },
6932
- { internalType: "string", name: "reason", type: "string" }
6933
- ],
6934
- name: "bulkApproveMemos",
6935
- outputs: [],
6936
- stateMutability: "nonpayable",
6937
- type: "function"
6938
- },
6939
7515
  {
6940
7516
  inputs: [
6941
7517
  { internalType: "uint256", name: "memoId", type: "uint256" },
@@ -7013,9 +7589,40 @@ var MEMO_MANAGER_ABI = [
7013
7589
  type: "function"
7014
7590
  },
7015
7591
  {
7016
- inputs: [{ internalType: "uint256", name: "memoId", type: "uint256" }],
7017
- name: "emergencyApproveMemo",
7018
- outputs: [],
7592
+ inputs: [
7593
+ { internalType: "uint256", name: "jobId", type: "uint256" },
7594
+ { internalType: "address", name: "sender", type: "address" },
7595
+ { internalType: "string", name: "content", type: "string" },
7596
+ {
7597
+ components: [
7598
+ { internalType: "address", name: "token", type: "address" },
7599
+ { internalType: "uint256", name: "amount", type: "uint256" },
7600
+ { internalType: "address", name: "recipient", type: "address" },
7601
+ { internalType: "uint256", name: "feeAmount", type: "uint256" },
7602
+ {
7603
+ internalType: "enum ACPTypes.FeeType",
7604
+ name: "feeType",
7605
+ type: "uint8"
7606
+ },
7607
+ { internalType: "bool", name: "isExecuted", type: "bool" },
7608
+ { internalType: "uint256", name: "expiredAt", type: "uint256" },
7609
+ { internalType: "uint32", name: "lzSrcEid", type: "uint32" },
7610
+ { internalType: "uint32", name: "lzDstEid", type: "uint32" }
7611
+ ],
7612
+ internalType: "struct ACPTypes.PayableDetails",
7613
+ name: "payableDetails_",
7614
+ type: "tuple"
7615
+ },
7616
+ { internalType: "uint256", name: "duration", type: "uint256" },
7617
+ { internalType: "uint256", name: "expiredAt", type: "uint256" },
7618
+ {
7619
+ internalType: "enum ACPTypes.JobPhase",
7620
+ name: "nextPhase",
7621
+ type: "uint8"
7622
+ }
7623
+ ],
7624
+ name: "createSubscriptionMemo",
7625
+ outputs: [{ internalType: "uint256", name: "memoId", type: "uint256" }],
7019
7626
  stateMutability: "nonpayable",
7020
7627
  type: "function"
7021
7628
  },
@@ -7026,13 +7633,6 @@ var MEMO_MANAGER_ABI = [
7026
7633
  stateMutability: "nonpayable",
7027
7634
  type: "function"
7028
7635
  },
7029
- {
7030
- inputs: [],
7031
- name: "getAssetManager",
7032
- outputs: [{ internalType: "address", name: "", type: "address" }],
7033
- stateMutability: "view",
7034
- type: "function"
7035
- },
7036
7636
  {
7037
7637
  inputs: [
7038
7638
  { internalType: "uint256", name: "jobId", type: "uint256" },
@@ -7229,17 +7829,6 @@ var MEMO_MANAGER_ABI = [
7229
7829
  stateMutability: "view",
7230
7830
  type: "function"
7231
7831
  },
7232
- {
7233
- inputs: [{ internalType: "uint256", name: "memoId", type: "uint256" }],
7234
- name: "getMemoApprovalStatus",
7235
- outputs: [
7236
- { internalType: "bool", name: "isApproved", type: "bool" },
7237
- { internalType: "address", name: "approvedBy", type: "address" },
7238
- { internalType: "uint256", name: "approvedAt", type: "uint256" }
7239
- ],
7240
- stateMutability: "view",
7241
- type: "function"
7242
- },
7243
7832
  {
7244
7833
  inputs: [{ internalType: "uint256", name: "memoId", type: "uint256" }],
7245
7834
  name: "getMemoWithPayableDetails",
@@ -7302,34 +7891,6 @@ var MEMO_MANAGER_ABI = [
7302
7891
  stateMutability: "view",
7303
7892
  type: "function"
7304
7893
  },
7305
- {
7306
- inputs: [{ internalType: "uint256", name: "memoId", type: "uint256" }],
7307
- name: "getPayableDetails",
7308
- outputs: [
7309
- {
7310
- components: [
7311
- { internalType: "address", name: "token", type: "address" },
7312
- { internalType: "uint256", name: "amount", type: "uint256" },
7313
- { internalType: "address", name: "recipient", type: "address" },
7314
- { internalType: "uint256", name: "feeAmount", type: "uint256" },
7315
- {
7316
- internalType: "enum ACPTypes.FeeType",
7317
- name: "feeType",
7318
- type: "uint8"
7319
- },
7320
- { internalType: "bool", name: "isExecuted", type: "bool" },
7321
- { internalType: "uint256", name: "expiredAt", type: "uint256" },
7322
- { internalType: "uint32", name: "lzSrcEid", type: "uint32" },
7323
- { internalType: "uint32", name: "lzDstEid", type: "uint32" }
7324
- ],
7325
- internalType: "struct ACPTypes.PayableDetails",
7326
- name: "",
7327
- type: "tuple"
7328
- }
7329
- ],
7330
- stateMutability: "view",
7331
- type: "function"
7332
- },
7333
7894
  {
7334
7895
  inputs: [{ internalType: "bytes32", name: "role", type: "bytes32" }],
7335
7896
  name: "getRoleAdmin",
@@ -7368,16 +7929,6 @@ var MEMO_MANAGER_ABI = [
7368
7929
  stateMutability: "nonpayable",
7369
7930
  type: "function"
7370
7931
  },
7371
- {
7372
- inputs: [
7373
- { internalType: "uint256", name: "jobId", type: "uint256" },
7374
- { internalType: "address", name: "user", type: "address" }
7375
- ],
7376
- name: "isJobEvaluator",
7377
- outputs: [{ internalType: "bool", name: "", type: "bool" }],
7378
- stateMutability: "view",
7379
- type: "function"
7380
- },
7381
7932
  {
7382
7933
  inputs: [
7383
7934
  { internalType: "uint256", name: "memoId", type: "uint256" },
@@ -7549,23 +8100,16 @@ var MEMO_MANAGER_ABI = [
7549
8100
  },
7550
8101
  {
7551
8102
  inputs: [
7552
- {
7553
- internalType: "enum ACPTypes.MemoType",
7554
- name: "memoType",
7555
- type: "uint8"
7556
- },
7557
- { internalType: "uint256", name: "requiredApprovals_", type: "uint256" }
8103
+ { internalType: "address", name: "assetManager_", type: "address" }
7558
8104
  ],
7559
- name: "setApprovalRequirements",
8105
+ name: "setAssetManager",
7560
8106
  outputs: [],
7561
8107
  stateMutability: "nonpayable",
7562
8108
  type: "function"
7563
8109
  },
7564
8110
  {
7565
- inputs: [
7566
- { internalType: "address", name: "assetManager_", type: "address" }
7567
- ],
7568
- name: "setAssetManager",
8111
+ inputs: [{ internalType: "uint256", name: "memoId", type: "uint256" }],
8112
+ name: "setPayableDetailsExecuted",
7569
8113
  outputs: [],
7570
8114
  stateMutability: "nonpayable",
7571
8115
  type: "function"
@@ -7861,6 +8405,37 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
7861
8405
  }
7862
8406
  return Number(createdJobEvent.args.jobId);
7863
8407
  }
8408
+ async getAccountIdFromUserOpHash(userOpHash) {
8409
+ const result = await this.sessionKeyClient.getUserOperationReceipt(
8410
+ userOpHash,
8411
+ "pending"
8412
+ );
8413
+ if (!result || !result.logs?.length) {
8414
+ return null;
8415
+ }
8416
+ const contractAddresses = [
8417
+ this.contractAddress.toLowerCase(),
8418
+ this.accountManagerAddress.toLowerCase()
8419
+ ];
8420
+ for (const log of result.logs) {
8421
+ if (!contractAddresses.includes(log.address?.toLowerCase())) {
8422
+ continue;
8423
+ }
8424
+ try {
8425
+ const decoded = decodeEventLog2({
8426
+ abi: this.abi,
8427
+ data: log.data,
8428
+ topics: log.topics
8429
+ });
8430
+ if (decoded.eventName === "AccountCreated") {
8431
+ const args = decoded.args;
8432
+ if (args?.accountId != null) return Number(args.accountId);
8433
+ }
8434
+ } catch {
8435
+ }
8436
+ }
8437
+ return null;
8438
+ }
7864
8439
  async updateJobX402Nonce(jobId, nonce) {
7865
8440
  return await this.acpX402.updateJobNonce(jobId, nonce);
7866
8441
  }
@@ -7914,6 +8489,7 @@ var acpContractClientV2_default = AcpContractClientV2;
7914
8489
  var index_default = acpClient_default;
7915
8490
  export {
7916
8491
  acpAbi_default as ACP_ABI,
8492
+ AcpAccount,
7917
8493
  acpAgent_default as AcpAgent,
7918
8494
  AcpAgentSort,
7919
8495
  acpContractClient_default as AcpContractClient,
@@ -7932,6 +8508,7 @@ export {
7932
8508
  FareAmount,
7933
8509
  FareBigInt,
7934
8510
  MemoType,
8511
+ PriceType,
7935
8512
  baseAcpConfig,
7936
8513
  baseAcpConfigV2,
7937
8514
  baseAcpX402Config,