@virtuals-protocol/acp-node 0.3.0-beta.16 → 0.3.0-beta.18

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.js CHANGED
@@ -35,12 +35,13 @@ var require_package = __commonJS({
35
35
  "package.json"(exports2, module2) {
36
36
  module2.exports = {
37
37
  name: "@virtuals-protocol/acp-node",
38
- version: "0.3.0-beta.16",
38
+ version: "0.3.0-beta.18",
39
39
  main: "./dist/index.js",
40
40
  module: "./dist/index.mjs",
41
41
  types: "./dist/index.d.ts",
42
42
  scripts: {
43
43
  test: "jest",
44
+ "test:ci": "jest --ci --reporters=default --reporters=jest-junit",
44
45
  "test:watch": "jest --watch",
45
46
  "test:coverage": "jest --coverage",
46
47
  tsup: "tsup src/index.ts --dts --format cjs,esm --out-dir dist"
@@ -56,6 +57,7 @@ var require_package = __commonJS({
56
57
  "babel-jest": "^30.2.0",
57
58
  dotenv: "^17.2.3",
58
59
  jest: "^30.2.0",
60
+ "jest-junit": "^16.0.0",
59
61
  "ts-jest": "^29.4.5",
60
62
  typescript: "^5.8.3"
61
63
  },
@@ -89,6 +91,7 @@ __export(index_exports, {
89
91
  AcpJob: () => acpJob_default,
90
92
  AcpJobPhases: () => AcpJobPhases,
91
93
  AcpMemo: () => acpMemo_default,
94
+ AcpMemoState: () => AcpMemoState,
92
95
  AcpMemoStatus: () => AcpMemoStatus,
93
96
  AcpOnlineStatus: () => AcpOnlineStatus,
94
97
  BaseAcpContractClient: () => baseAcpContractClient_default,
@@ -1282,7 +1285,7 @@ var ACP_ABI = [
1282
1285
  var acpAbi_default = ACP_ABI;
1283
1286
 
1284
1287
  // src/acpClient.ts
1285
- var import_viem4 = require("viem");
1288
+ var import_viem6 = require("viem");
1286
1289
  var import_socket = require("socket.io-client");
1287
1290
 
1288
1291
  // src/contractClients/baseAcpContractClient.ts
@@ -1311,27 +1314,42 @@ var acpError_default = AcpError;
1311
1314
 
1312
1315
  // src/acpFare.ts
1313
1316
  var Fare = class _Fare {
1314
- constructor(contractAddress, decimals) {
1317
+ constructor(contractAddress, decimals, chainId) {
1315
1318
  this.contractAddress = contractAddress;
1316
1319
  this.decimals = decimals;
1320
+ this.chainId = chainId;
1317
1321
  }
1318
1322
  formatAmount(amount) {
1319
1323
  return (0, import_viem.parseUnits)(amount.toString(), this.decimals);
1320
1324
  }
1321
- static async fromContractAddress(contractAddress, config = baseAcpConfig) {
1325
+ static async fromContractAddress(contractAddress, config = baseAcpConfig, chainId = config.chain.id) {
1322
1326
  if (contractAddress === config.baseFare.contractAddress) {
1323
1327
  return config.baseFare;
1324
1328
  }
1329
+ let chainConfig = config.chain;
1330
+ let rpcUrl = config.rpcEndpoint;
1331
+ if (chainId !== config.chain.id) {
1332
+ const selectedConfig = config.chains?.find(
1333
+ (chain) => chain.chain.id === chainId
1334
+ );
1335
+ if (!selectedConfig) {
1336
+ throw new acpError_default(
1337
+ `Chain configuration for chainId ${chainId} not found.`
1338
+ );
1339
+ }
1340
+ chainConfig = selectedConfig.chain;
1341
+ rpcUrl = selectedConfig.rpcUrl;
1342
+ }
1325
1343
  const publicClient = (0, import_viem.createPublicClient)({
1326
- chain: config.chain,
1327
- transport: (0, import_viem.http)(config.rpcEndpoint)
1344
+ chain: chainConfig,
1345
+ transport: (0, import_viem.http)(rpcUrl)
1328
1346
  });
1329
1347
  const decimals = await publicClient.readContract({
1330
1348
  address: contractAddress,
1331
1349
  abi: import_viem.erc20Abi,
1332
1350
  functionName: "decimals"
1333
1351
  });
1334
- return new _Fare(contractAddress, decimals);
1352
+ return new _Fare(contractAddress, decimals, chainId);
1335
1353
  }
1336
1354
  };
1337
1355
  var FareAmountBase = class {
@@ -1750,6 +1768,34 @@ var ACP_V2_ABI = [
1750
1768
  stateMutability: "nonpayable",
1751
1769
  type: "function"
1752
1770
  },
1771
+ {
1772
+ inputs: [
1773
+ { internalType: "uint256", name: "jobId", type: "uint256" },
1774
+ { internalType: "string", name: "content", type: "string" },
1775
+ { internalType: "address", name: "token", type: "address" },
1776
+ { internalType: "uint256", name: "amount", type: "uint256" },
1777
+ { internalType: "address", name: "recipient", type: "address" },
1778
+ { internalType: "uint256", name: "feeAmount", type: "uint256" },
1779
+ { internalType: "enum ACPTypes.FeeType", name: "feeType", type: "uint8" },
1780
+ {
1781
+ internalType: "enum ACPTypes.MemoType",
1782
+ name: "memoType",
1783
+ type: "uint8"
1784
+ },
1785
+ { internalType: "uint256", name: "expiredAt", type: "uint256" },
1786
+ { internalType: "bool", name: "isSecured", type: "bool" },
1787
+ {
1788
+ internalType: "enum ACPTypes.JobPhase",
1789
+ name: "nextPhase",
1790
+ type: "uint8"
1791
+ },
1792
+ { internalType: "uint32", name: "lzDstEid", type: "uint32" }
1793
+ ],
1794
+ name: "createCrossChainPayableMemo",
1795
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
1796
+ stateMutability: "nonpayable",
1797
+ type: "function"
1798
+ },
1753
1799
  {
1754
1800
  inputs: [
1755
1801
  { internalType: "address", name: "provider", type: "address" },
@@ -1934,7 +1980,12 @@ var ACP_V2_ABI = [
1934
1980
  name: "nextPhase",
1935
1981
  type: "uint8"
1936
1982
  },
1937
- { internalType: "uint256", name: "expiredAt", type: "uint256" }
1983
+ { internalType: "uint256", name: "expiredAt", type: "uint256" },
1984
+ {
1985
+ internalType: "enum ACPTypes.MemoState",
1986
+ name: "state",
1987
+ type: "uint8"
1988
+ }
1938
1989
  ],
1939
1990
  internalType: "struct ACPTypes.Memo[]",
1940
1991
  name: "memos",
@@ -1981,7 +2032,12 @@ var ACP_V2_ABI = [
1981
2032
  name: "nextPhase",
1982
2033
  type: "uint8"
1983
2034
  },
1984
- { internalType: "uint256", name: "expiredAt", type: "uint256" }
2035
+ { internalType: "uint256", name: "expiredAt", type: "uint256" },
2036
+ {
2037
+ internalType: "enum ACPTypes.MemoState",
2038
+ name: "state",
2039
+ type: "uint8"
2040
+ }
1985
2041
  ],
1986
2042
  internalType: "struct ACPTypes.Memo[]",
1987
2043
  name: "memos",
@@ -2024,7 +2080,12 @@ var ACP_V2_ABI = [
2024
2080
  name: "nextPhase",
2025
2081
  type: "uint8"
2026
2082
  },
2027
- { internalType: "uint256", name: "expiredAt", type: "uint256" }
2083
+ { internalType: "uint256", name: "expiredAt", type: "uint256" },
2084
+ {
2085
+ internalType: "enum ACPTypes.MemoState",
2086
+ name: "state",
2087
+ type: "uint8"
2088
+ }
2028
2089
  ],
2029
2090
  internalType: "struct ACPTypes.Memo[]",
2030
2091
  name: "memos",
@@ -2280,7 +2341,7 @@ var acpAbiV2_default = ACP_V2_ABI;
2280
2341
  var V1_MAX_RETRIES = 10;
2281
2342
  var V2_MAX_RETRIES = 3;
2282
2343
  var AcpContractConfig2 = class {
2283
- constructor(chain, contractAddress, baseFare, alchemyRpcUrl, acpUrl, abi, maxRetries, rpcEndpoint, x402Config) {
2344
+ constructor(chain, contractAddress, baseFare, alchemyRpcUrl, acpUrl, abi, maxRetries, rpcEndpoint, x402Config, chains = []) {
2284
2345
  this.chain = chain;
2285
2346
  this.contractAddress = contractAddress;
2286
2347
  this.baseFare = baseFare;
@@ -2290,6 +2351,7 @@ var AcpContractConfig2 = class {
2290
2351
  this.maxRetries = maxRetries;
2291
2352
  this.rpcEndpoint = rpcEndpoint;
2292
2353
  this.x402Config = x402Config;
2354
+ this.chains = chains;
2293
2355
  }
2294
2356
  };
2295
2357
  var baseSepoliaAcpConfig = new AcpContractConfig2(
@@ -3535,6 +3597,16 @@ var HTTP_STATUS_CODES = {
3535
3597
  PAYMENT_REQUIRED: 402
3536
3598
  };
3537
3599
  var SINGLE_SIGNER_VALIDATION_MODULE_ADDRESS = "0x00000000000099DE0BF6fA90dEB851E2A2df7d83";
3600
+ var ASSET_MANAGER_ADDRESSES = {
3601
+ [import_chains.bscTestnet.id]: "0xfCf52B02936623852dd5132007E9414f9060168b",
3602
+ [import_chains.bsc.id]: "",
3603
+ [import_chains.polygonAmoy.id]: "0xfCf52B02936623852dd5132007E9414f9060168b",
3604
+ [import_chains.polygon.id]: "",
3605
+ [import_chains.arbitrum.id]: "",
3606
+ [import_chains.arbitrumSepolia.id]: "0xfCf52B02936623852dd5132007E9414f9060168b",
3607
+ [import_chains.sepolia.id]: "0xfCf52B02936623852dd5132007E9414f9060168b",
3608
+ [import_chains.mainnet.id]: ""
3609
+ };
3538
3610
 
3539
3611
  // src/contractClients/baseAcpContractClient.ts
3540
3612
  var MemoType = /* @__PURE__ */ ((MemoType3) => {
@@ -3549,6 +3621,7 @@ var MemoType = /* @__PURE__ */ ((MemoType3) => {
3549
3621
  MemoType3[MemoType3["PAYABLE_TRANSFER_ESCROW"] = 8] = "PAYABLE_TRANSFER_ESCROW";
3550
3622
  MemoType3[MemoType3["NOTIFICATION"] = 9] = "NOTIFICATION";
3551
3623
  MemoType3[MemoType3["PAYABLE_NOTIFICATION"] = 10] = "PAYABLE_NOTIFICATION";
3624
+ MemoType3[MemoType3["TRANSFER_EVENT"] = 11] = "TRANSFER_EVENT";
3552
3625
  return MemoType3;
3553
3626
  })(MemoType || {});
3554
3627
  var AcpJobPhases = /* @__PURE__ */ ((AcpJobPhases3) => {
@@ -3565,6 +3638,7 @@ var BaseAcpContractClient = class {
3565
3638
  constructor(agentWalletAddress, config = baseAcpConfig) {
3566
3639
  this.agentWalletAddress = agentWalletAddress;
3567
3640
  this.config = config;
3641
+ this.publicClients = {};
3568
3642
  this.chain = config.chain;
3569
3643
  this.abi = config.abi;
3570
3644
  this.contractAddress = config.contractAddress;
@@ -3664,12 +3738,12 @@ ${JSON.stringify(
3664
3738
  throw new acpError_default("Failed to create job", error);
3665
3739
  }
3666
3740
  }
3667
- approveAllowance(amountBaseUnit, paymentTokenAddress = this.config.baseFare.contractAddress) {
3741
+ approveAllowance(amountBaseUnit, paymentTokenAddress = this.config.baseFare.contractAddress, targetAddress) {
3668
3742
  try {
3669
3743
  const data = (0, import_viem2.encodeFunctionData)({
3670
3744
  abi: import_viem2.erc20Abi,
3671
3745
  functionName: "approve",
3672
- args: [this.contractAddress, amountBaseUnit]
3746
+ args: [targetAddress ?? this.contractAddress, amountBaseUnit]
3673
3747
  });
3674
3748
  const payload = {
3675
3749
  data,
@@ -3708,6 +3782,35 @@ ${JSON.stringify(
3708
3782
  throw new acpError_default("Failed to create payable memo", error);
3709
3783
  }
3710
3784
  }
3785
+ createCrossChainPayableMemo(jobId, content, token, amountBaseUnit, recipient, feeAmountBaseUnit, feeType, type, expiredAt, nextPhase, destinationEid, secured = true) {
3786
+ try {
3787
+ const data = (0, import_viem2.encodeFunctionData)({
3788
+ abi: this.abi,
3789
+ functionName: "createCrossChainPayableMemo",
3790
+ args: [
3791
+ jobId,
3792
+ content,
3793
+ token,
3794
+ amountBaseUnit,
3795
+ recipient,
3796
+ feeAmountBaseUnit,
3797
+ feeType,
3798
+ type,
3799
+ expiredAt,
3800
+ secured,
3801
+ nextPhase,
3802
+ destinationEid
3803
+ ]
3804
+ });
3805
+ const payload = {
3806
+ data,
3807
+ contractAddress: this.contractAddress
3808
+ };
3809
+ return payload;
3810
+ } catch (error) {
3811
+ throw new acpError_default("Failed to create cross chain payable memo", error);
3812
+ }
3813
+ }
3711
3814
  createMemo(jobId, content, type, isSecured, nextPhase) {
3712
3815
  try {
3713
3816
  const data = (0, import_viem2.encodeFunctionData)({
@@ -3724,6 +3827,22 @@ ${JSON.stringify(
3724
3827
  throw new acpError_default("Failed to create memo", error);
3725
3828
  }
3726
3829
  }
3830
+ createMemoWithMetadata(jobId, content, type, isSecured, nextPhase, metadata) {
3831
+ try {
3832
+ const data = (0, import_viem2.encodeFunctionData)({
3833
+ abi: this.abi,
3834
+ functionName: "createMemoWithMetadata",
3835
+ args: [jobId, content, type, isSecured, nextPhase, metadata]
3836
+ });
3837
+ const payload = {
3838
+ data,
3839
+ contractAddress: this.contractAddress
3840
+ };
3841
+ return payload;
3842
+ } catch (error) {
3843
+ throw new acpError_default("Failed to create memo with metadata", error);
3844
+ }
3845
+ }
3727
3846
  signMemo(memoId, isApproved, reason) {
3728
3847
  try {
3729
3848
  const data = (0, import_viem2.encodeFunctionData)({
@@ -3809,9 +3928,47 @@ ${JSON.stringify(
3809
3928
  throw new acpError_default("Failed to submit TransferWithAuthorization", error);
3810
3929
  }
3811
3930
  }
3931
+ async getERC20Balance(chainId, tokenAddress, walletAddress) {
3932
+ const publicClient = this.publicClients[chainId];
3933
+ if (!publicClient) {
3934
+ throw new acpError_default(`Public client for chainId ${chainId} not found`);
3935
+ }
3936
+ return await publicClient.readContract({
3937
+ address: tokenAddress,
3938
+ abi: import_viem2.erc20Abi,
3939
+ functionName: "balanceOf",
3940
+ args: [walletAddress]
3941
+ });
3942
+ }
3943
+ async getERC20Allowance(chainId, tokenAddress, walletAddress, spenderAddress) {
3944
+ const publicClient = this.publicClients[chainId];
3945
+ if (!publicClient) {
3946
+ throw new acpError_default(`Public client for chainId ${chainId} not found`);
3947
+ }
3948
+ return await publicClient.readContract({
3949
+ address: tokenAddress,
3950
+ abi: import_viem2.erc20Abi,
3951
+ functionName: "allowance",
3952
+ args: [walletAddress, spenderAddress]
3953
+ });
3954
+ }
3955
+ async getERC20Symbol(chainId, tokenAddress) {
3956
+ const publicClient = this.publicClients[chainId];
3957
+ if (!publicClient) {
3958
+ throw new acpError_default(`Public client for chainId ${chainId} not found`);
3959
+ }
3960
+ return await publicClient.readContract({
3961
+ address: tokenAddress,
3962
+ abi: import_viem2.erc20Abi,
3963
+ functionName: "symbol"
3964
+ });
3965
+ }
3812
3966
  };
3813
3967
  var baseAcpContractClient_default = BaseAcpContractClient;
3814
3968
 
3969
+ // src/acpJob.ts
3970
+ var import_viem5 = require("viem");
3971
+
3815
3972
  // src/interfaces.ts
3816
3973
  var AcpMemoStatus = /* @__PURE__ */ ((AcpMemoStatus2) => {
3817
3974
  AcpMemoStatus2["PENDING"] = "PENDING";
@@ -3819,6 +3976,15 @@ var AcpMemoStatus = /* @__PURE__ */ ((AcpMemoStatus2) => {
3819
3976
  AcpMemoStatus2["REJECTED"] = "REJECTED";
3820
3977
  return AcpMemoStatus2;
3821
3978
  })(AcpMemoStatus || {});
3979
+ var AcpMemoState = /* @__PURE__ */ ((AcpMemoState2) => {
3980
+ AcpMemoState2["NONE"] = "NONE";
3981
+ AcpMemoState2["PENDING"] = "PENDING";
3982
+ AcpMemoState2["IN_PROGRESS"] = "IN_PROGRESS";
3983
+ AcpMemoState2["READY"] = "READY";
3984
+ AcpMemoState2["COMPLETED"] = "COMPLETED";
3985
+ AcpMemoState2["REJECTED"] = "REJECTED";
3986
+ return AcpMemoState2;
3987
+ })(AcpMemoState || {});
3822
3988
  var AcpAgentSort = /* @__PURE__ */ ((AcpAgentSort2) => {
3823
3989
  AcpAgentSort2["SUCCESSFUL_JOB_COUNT"] = "successfulJobCount";
3824
3990
  AcpAgentSort2["SUCCESS_RATE"] = "successRate";
@@ -3857,6 +4023,8 @@ var PositionDirection = /* @__PURE__ */ ((PositionDirection2) => {
3857
4023
  })(PositionDirection || {});
3858
4024
 
3859
4025
  // src/utils.ts
4026
+ var import_viem3 = require("viem");
4027
+ var import_chains2 = require("viem/chains");
3860
4028
  function tryParseJson(content) {
3861
4029
  try {
3862
4030
  return JSON.parse(content);
@@ -3873,9 +4041,34 @@ function safeBase64Encode(data) {
3873
4041
  }
3874
4042
  return Buffer.from(data).toString("base64");
3875
4043
  }
4044
+ function getDestinationEndpointId(chainId) {
4045
+ switch (chainId) {
4046
+ case import_chains2.baseSepolia.id:
4047
+ return 40245;
4048
+ case import_chains2.sepolia.id:
4049
+ return 40161;
4050
+ case import_chains2.polygonAmoy.id:
4051
+ return 40267;
4052
+ case import_chains2.arbitrumSepolia.id:
4053
+ return 40231;
4054
+ case import_chains2.bscTestnet.id:
4055
+ return 40102;
4056
+ case import_chains2.base.id:
4057
+ return 30184;
4058
+ case import_chains2.mainnet.id:
4059
+ return 30101;
4060
+ case import_chains2.polygon.id:
4061
+ return 30109;
4062
+ case import_chains2.arbitrum.id:
4063
+ return 30110;
4064
+ case import_chains2.bsc.id:
4065
+ return 30102;
4066
+ }
4067
+ throw new Error(`Unsupported chain ID: ${chainId}`);
4068
+ }
3876
4069
 
3877
4070
  // src/acpJobOffering.ts
3878
- var import_viem3 = require("viem");
4071
+ var import_viem4 = require("viem");
3879
4072
  var import_ajv = __toESM(require("ajv"));
3880
4073
  var AcpJobOffering = class {
3881
4074
  constructor(acpClient, acpContractClient, providerAddress, name, price, priceType = "fixed" /* FIXED */, requirement) {
@@ -3934,7 +4127,7 @@ var AcpJobOffering = class {
3934
4127
  } else {
3935
4128
  createJobPayload = this.acpContractClient.createJobWithAccount(
3936
4129
  account.id,
3937
- evaluatorAddress || import_viem3.zeroAddress,
4130
+ evaluatorAddress || import_viem4.zeroAddress,
3938
4131
  fareAmount.amount,
3939
4132
  fareAmount.fare.contractAddress,
3940
4133
  expiredAt,
@@ -4075,20 +4268,38 @@ var AcpJob = class {
4075
4268
  }
4076
4269
  const feeAmount = new FareAmount(0, this.acpContractClient.config.baseFare);
4077
4270
  const isPercentagePricing = this.priceType === "percentage" /* PERCENTAGE */;
4078
- operations.push(
4079
- this.acpContractClient.createPayableMemo(
4080
- this.id,
4081
- content,
4082
- amount.amount,
4083
- recipient,
4084
- isPercentagePricing ? BigInt(Math.round(this.priceValue * 1e4)) : feeAmount.amount,
4085
- isPercentagePricing ? 3 /* PERCENTAGE_FEE */ : 0 /* NO_FEE */,
4086
- 2 /* TRANSACTION */,
4087
- type,
4088
- expiredAt,
4089
- amount.fare.contractAddress
4090
- )
4091
- );
4271
+ if (amount.fare.chainId && amount.fare.chainId !== this.acpContractClient.config.chain.id) {
4272
+ operations.push(
4273
+ this.acpContractClient.createCrossChainPayableMemo(
4274
+ this.id,
4275
+ content,
4276
+ amount.fare.contractAddress,
4277
+ amount.amount,
4278
+ recipient,
4279
+ isPercentagePricing ? BigInt(Math.round(this.priceValue * 1e4)) : feeAmount.amount,
4280
+ isPercentagePricing ? 3 /* PERCENTAGE_FEE */ : 0 /* NO_FEE */,
4281
+ type,
4282
+ expiredAt,
4283
+ 2 /* TRANSACTION */,
4284
+ getDestinationEndpointId(amount.fare.chainId)
4285
+ )
4286
+ );
4287
+ } else {
4288
+ operations.push(
4289
+ this.acpContractClient.createPayableMemo(
4290
+ this.id,
4291
+ content,
4292
+ amount.amount,
4293
+ recipient,
4294
+ isPercentagePricing ? BigInt(Math.round(this.priceValue * 1e4)) : feeAmount.amount,
4295
+ isPercentagePricing ? 3 /* PERCENTAGE_FEE */ : 0 /* NO_FEE */,
4296
+ 2 /* TRANSACTION */,
4297
+ type,
4298
+ expiredAt,
4299
+ amount.fare.contractAddress
4300
+ )
4301
+ );
4302
+ }
4092
4303
  return await this.acpContractClient.handleOperation(operations);
4093
4304
  }
4094
4305
  async payAndAcceptRequirement(reason) {
@@ -4130,9 +4341,11 @@ var AcpJob = class {
4130
4341
  3 /* EVALUATION */
4131
4342
  )
4132
4343
  );
4133
- const x402PaymentDetails = await this.acpContractClient.getX402PaymentDetails(this.id);
4134
- if (x402PaymentDetails.isX402) {
4135
- await this.performX402Payment(this.price);
4344
+ if (this.price > 0) {
4345
+ const x402PaymentDetails = await this.acpContractClient.getX402PaymentDetails(this.id);
4346
+ if (x402PaymentDetails.isX402) {
4347
+ await this.performX402Payment(this.price);
4348
+ }
4136
4349
  }
4137
4350
  return await this.acpContractClient.handleOperation(operations);
4138
4351
  }
@@ -4219,6 +4432,9 @@ var AcpJob = class {
4219
4432
  if (this.latestMemo?.nextPhase !== 3 /* EVALUATION */) {
4220
4433
  throw new acpError_default("No transaction memo found");
4221
4434
  }
4435
+ if (amount.fare.chainId !== this.acpContractClient.config.chain.id) {
4436
+ return await this.deliverCrossChainPayable(this.clientAddress, amount);
4437
+ }
4222
4438
  const operations = [];
4223
4439
  operations.push(
4224
4440
  this.acpContractClient.approveAllowance(
@@ -4349,6 +4565,56 @@ var AcpJob = class {
4349
4565
  waitMs = Math.min(waitMs * 2, maxWaitMs);
4350
4566
  }
4351
4567
  }
4568
+ async deliverCrossChainPayable(recipient, amount) {
4569
+ if (!amount.fare.chainId) {
4570
+ throw new acpError_default("Chain ID is required for cross chain payable");
4571
+ }
4572
+ const chainId = amount.fare.chainId;
4573
+ const tokenBalance = await this.acpContractClient.getERC20Balance(
4574
+ chainId,
4575
+ amount.fare.contractAddress,
4576
+ this.acpContractClient.agentWalletAddress
4577
+ );
4578
+ if (tokenBalance < amount.amount) {
4579
+ throw new acpError_default("Insufficient token balance for cross chain payable");
4580
+ }
4581
+ const currentAllowance = await this.acpContractClient.getERC20Allowance(
4582
+ chainId,
4583
+ amount.fare.contractAddress,
4584
+ this.acpContractClient.agentWalletAddress,
4585
+ ASSET_MANAGER_ADDRESSES[chainId]
4586
+ );
4587
+ const approveAllowanceOperation = this.acpContractClient.approveAllowance(
4588
+ amount.amount + currentAllowance,
4589
+ amount.fare.contractAddress,
4590
+ ASSET_MANAGER_ADDRESSES[chainId]
4591
+ );
4592
+ await this.acpContractClient.handleOperation(
4593
+ [approveAllowanceOperation],
4594
+ chainId
4595
+ );
4596
+ const tokenSymbol = await this.acpContractClient.getERC20Symbol(
4597
+ chainId,
4598
+ amount.fare.contractAddress
4599
+ );
4600
+ const createMemoOperation = this.acpContractClient.createCrossChainPayableMemo(
4601
+ this.id,
4602
+ `Performing cross chain payable transfer of ${(0, import_viem5.formatUnits)(
4603
+ amount.amount,
4604
+ amount.fare.decimals
4605
+ )} ${tokenSymbol} to ${recipient}`,
4606
+ amount.fare.contractAddress,
4607
+ amount.amount,
4608
+ recipient,
4609
+ BigInt(0),
4610
+ 0 /* NO_FEE */,
4611
+ 7 /* PAYABLE_TRANSFER */,
4612
+ new Date(Date.now() + 1e3 * 60 * 5),
4613
+ 4 /* COMPLETED */,
4614
+ getDestinationEndpointId(chainId)
4615
+ );
4616
+ await this.acpContractClient.handleOperation([createMemoOperation]);
4617
+ }
4352
4618
  [util.inspect.custom]() {
4353
4619
  return {
4354
4620
  id: this.id,
@@ -4372,7 +4638,7 @@ var acpJob_default = AcpJob;
4372
4638
  // src/acpMemo.ts
4373
4639
  var import_util = __toESM(require("util"));
4374
4640
  var AcpMemo = class {
4375
- constructor(contractClient, id, type, content, nextPhase, status, senderAddress, signedReason, expiry, payableDetails, txHash, signedTxHash) {
4641
+ constructor(contractClient, id, type, content, nextPhase, status, senderAddress, signedReason, expiry, payableDetails, txHash, signedTxHash, state) {
4376
4642
  this.contractClient = contractClient;
4377
4643
  this.id = id;
4378
4644
  this.type = type;
@@ -4385,6 +4651,7 @@ var AcpMemo = class {
4385
4651
  this.payableDetails = payableDetails;
4386
4652
  this.txHash = txHash;
4387
4653
  this.signedTxHash = signedTxHash;
4654
+ this.state = state;
4388
4655
  if (this.payableDetails) {
4389
4656
  this.payableDetails.amount = BigInt(this.payableDetails.amount);
4390
4657
  this.payableDetails.feeAmount = BigInt(this.payableDetails.feeAmount);
@@ -4535,7 +4802,8 @@ var AcpClient = class {
4535
4802
  memo.expiry ? new Date(parseInt(memo.expiry) * 1e3) : void 0,
4536
4803
  memo.payableDetails,
4537
4804
  memo.txHash,
4538
- memo.signedTxHash
4805
+ memo.signedTxHash,
4806
+ memo.state
4539
4807
  );
4540
4808
  }),
4541
4809
  data.phase,
@@ -4573,7 +4841,8 @@ var AcpClient = class {
4573
4841
  memo.expiry ? new Date(parseInt(memo.expiry) * 1e3) : void 0,
4574
4842
  memo.payableDetails,
4575
4843
  memo.txHash,
4576
- memo.signedTxHash
4844
+ memo.signedTxHash,
4845
+ memo.state
4577
4846
  );
4578
4847
  }),
4579
4848
  data.phase,
@@ -4598,7 +4867,14 @@ var AcpClient = class {
4598
4867
  process.on("SIGTERM", cleanup);
4599
4868
  }
4600
4869
  async browseAgents(keyword, options) {
4601
- let { cluster, sort_by, top_k, graduationStatus, onlineStatus, showHiddenOfferings } = options;
4870
+ let {
4871
+ cluster,
4872
+ sort_by,
4873
+ top_k,
4874
+ graduationStatus,
4875
+ onlineStatus,
4876
+ showHiddenOfferings
4877
+ } = options;
4602
4878
  top_k = top_k ?? 5;
4603
4879
  let url = `${this.acpUrl}/api/agents/v4/search?search=${keyword}`;
4604
4880
  if (sort_by && sort_by.length > 0) {
@@ -4680,7 +4956,7 @@ var AcpClient = class {
4680
4956
  baseAcpConfig.contractAddress,
4681
4957
  baseAcpX402Config.contractAddress
4682
4958
  ].includes(this.acpContractClient.config.contractAddress);
4683
- const defaultEvaluatorAddress = isV1 && !evaluatorAddress ? this.walletAddress : import_viem4.zeroAddress;
4959
+ const defaultEvaluatorAddress = isV1 && !evaluatorAddress ? this.walletAddress : import_viem6.zeroAddress;
4684
4960
  const chainId = this.acpContractClient.config.chain.id;
4685
4961
  const isUsdcPaymentToken = USDC_TOKEN_ADDRESS[chainId].toLowerCase() === fareAmount.fare.contractAddress.toLowerCase();
4686
4962
  const isX402Job = this.acpContractClient.config.x402Config && isUsdcPaymentToken;
@@ -4789,7 +5065,8 @@ var AcpClient = class {
4789
5065
  memo.expiry ? new Date(parseInt(memo.expiry) * 1e3) : void 0,
4790
5066
  memo.payableDetails,
4791
5067
  memo.txHash,
4792
- memo.signedTxHash
5068
+ memo.signedTxHash,
5069
+ memo.state
4793
5070
  )
4794
5071
  );
4795
5072
  jobs.push(
@@ -4863,7 +5140,8 @@ var AcpClient = class {
4863
5140
  memo.expiry ? new Date(parseInt(memo.expiry) * 1e3) : void 0,
4864
5141
  memo.payableDetails,
4865
5142
  memo.txHash,
4866
- memo.signedTxHash
5143
+ memo.signedTxHash,
5144
+ memo.state
4867
5145
  )
4868
5146
  );
4869
5147
  return new acpJob_default(
@@ -4922,7 +5200,8 @@ var AcpClient = class {
4922
5200
  memo.expiry ? new Date(parseInt(memo.expiry) * 1e3) : void 0,
4923
5201
  memo.payableDetails,
4924
5202
  memo.txHash,
4925
- memo.signedTxHash
5203
+ memo.signedTxHash,
5204
+ memo.state
4926
5205
  );
4927
5206
  } catch (err) {
4928
5207
  throw new acpError_default(
@@ -4986,10 +5265,10 @@ var acpClient_default = AcpClient;
4986
5265
  var import_core = require("@aa-sdk/core");
4987
5266
  var import_infra2 = require("@account-kit/infra");
4988
5267
  var import_smart_contracts = require("@account-kit/smart-contracts");
4989
- var import_viem6 = require("viem");
5268
+ var import_viem8 = require("viem");
4990
5269
 
4991
5270
  // src/acpX402.ts
4992
- var import_viem5 = require("viem");
5271
+ var import_viem7 = require("viem");
4993
5272
  var import_crypto = require("crypto");
4994
5273
  var AcpX402 = class {
4995
5274
  constructor(config, sessionKeyClient, publicClient) {
@@ -5031,6 +5310,9 @@ var AcpX402 = class {
5031
5310
  const acpJob = await response.json();
5032
5311
  return acpJob;
5033
5312
  } catch (error) {
5313
+ if (error instanceof acpError_default) {
5314
+ throw error;
5315
+ }
5034
5316
  throw new acpError_default("Failed to update job X402 nonce", error);
5035
5317
  }
5036
5318
  }
@@ -5044,7 +5326,7 @@ var AcpX402 = class {
5044
5326
  contracts: [
5045
5327
  {
5046
5328
  address: USDC_CONTRACT,
5047
- abi: import_viem5.erc20Abi,
5329
+ abi: import_viem7.erc20Abi,
5048
5330
  functionName: "name"
5049
5331
  },
5050
5332
  {
@@ -5119,6 +5401,9 @@ var AcpX402 = class {
5119
5401
  data
5120
5402
  };
5121
5403
  } catch (error) {
5404
+ if (error instanceof acpError_default) {
5405
+ throw error;
5406
+ }
5122
5407
  throw new acpError_default("Failed to perform X402 request", error);
5123
5408
  }
5124
5409
  }
@@ -5244,7 +5529,7 @@ var AcpContractClient = class _AcpContractClient extends baseAcpContractClient_d
5244
5529
  const contractLogs = result.logs.filter((log) => {
5245
5530
  return log.address.toLowerCase() === this.contractAddress.toLowerCase();
5246
5531
  }).map(
5247
- (log) => (0, import_viem6.decodeEventLog)({
5532
+ (log) => (0, import_viem8.decodeEventLog)({
5248
5533
  abi: this.abi,
5249
5534
  data: log.data,
5250
5535
  topics: log.topics
@@ -5260,7 +5545,7 @@ var AcpContractClient = class _AcpContractClient extends baseAcpContractClient_d
5260
5545
  }
5261
5546
  createJob(providerAddress, evaluatorAddress, expireAt, paymentTokenAddress, budgetBaseUnit, metadata, isX402Job) {
5262
5547
  try {
5263
- const data = (0, import_viem6.encodeFunctionData)({
5548
+ const data = (0, import_viem8.encodeFunctionData)({
5264
5549
  abi: this.abi,
5265
5550
  functionName: isX402Job ? "createJobWithX402" : "createJob",
5266
5551
  args: [
@@ -5280,7 +5565,7 @@ var AcpContractClient = class _AcpContractClient extends baseAcpContractClient_d
5280
5565
  }
5281
5566
  setBudgetWithPaymentToken(jobId, budgetBaseUnit, paymentTokenAddress = this.config.baseFare.contractAddress) {
5282
5567
  try {
5283
- const data = (0, import_viem6.encodeFunctionData)({
5568
+ const data = (0, import_viem8.encodeFunctionData)({
5284
5569
  abi: this.abi,
5285
5570
  functionName: "setBudgetWithPaymentToken",
5286
5571
  args: [jobId, budgetBaseUnit, paymentTokenAddress]
@@ -5296,7 +5581,7 @@ var AcpContractClient = class _AcpContractClient extends baseAcpContractClient_d
5296
5581
  }
5297
5582
  createPayableMemo(jobId, content, amountBaseUnit, recipient, feeAmountBaseUnit, feeType, nextPhase, type, expiredAt, token = this.config.baseFare.contractAddress, secured = true) {
5298
5583
  try {
5299
- const data = (0, import_viem6.encodeFunctionData)({
5584
+ const data = (0, import_viem8.encodeFunctionData)({
5300
5585
  abi: this.abi,
5301
5586
  functionName: "createPayableMemo",
5302
5587
  args: [
@@ -5346,7 +5631,7 @@ var acpContractClient_default = AcpContractClient;
5346
5631
  var import_core2 = require("@aa-sdk/core");
5347
5632
  var import_infra3 = require("@account-kit/infra");
5348
5633
  var import_smart_contracts2 = require("@account-kit/smart-contracts");
5349
- var import_viem7 = require("viem");
5634
+ var import_viem9 = require("viem");
5350
5635
 
5351
5636
  // src/abis/jobManagerAbi.ts
5352
5637
  var JOB_MANAGER_ABI = [
@@ -6050,6 +6335,7 @@ var JOB_MANAGER_ABI = [
6050
6335
  var jobManagerAbi_default = JOB_MANAGER_ABI;
6051
6336
 
6052
6337
  // src/contractClients/acpContractClientV2.ts
6338
+ var import_chains3 = require("viem/chains");
6053
6339
  var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClient_default {
6054
6340
  constructor(jobManagerAddress, memoManagerAddress, accountManagerAddress, agentWalletAddress, config = baseAcpConfigV2) {
6055
6341
  super(agentWalletAddress, config);
@@ -6059,11 +6345,20 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6059
6345
  this.PRIORITY_FEE_MULTIPLIER = 2;
6060
6346
  this.MAX_FEE_PER_GAS = 2e7;
6061
6347
  this.MAX_PRIORITY_FEE_PER_GAS = 21e6;
6348
+ this.GAS_FEE_MULTIPLIER = 0.5;
6349
+ this._sessionKeyClients = {};
6062
6350
  }
6063
6351
  static async build(walletPrivateKey, sessionEntityKeyId, agentWalletAddress, config = baseAcpConfigV2) {
6064
- const publicClient = (0, import_viem7.createPublicClient)({
6352
+ const publicClients = {};
6353
+ for (const chain of config.chains) {
6354
+ publicClients[chain.chain.id] = (0, import_viem9.createPublicClient)({
6355
+ chain: chain.chain,
6356
+ transport: (0, import_viem9.http)(chain.rpcUrl)
6357
+ });
6358
+ }
6359
+ const publicClient = (0, import_viem9.createPublicClient)({
6065
6360
  chain: config.chain,
6066
- transport: (0, import_viem7.http)(config.rpcEndpoint)
6361
+ transport: (0, import_viem9.http)(config.rpcEndpoint)
6067
6362
  });
6068
6363
  const [jobManagerAddress, memoManagerAddress, accountManagerAddress] = await publicClient.multicall({
6069
6364
  contracts: [
@@ -6096,6 +6391,7 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6096
6391
  agentWalletAddress,
6097
6392
  config
6098
6393
  );
6394
+ acpContractClient.publicClients = publicClients;
6099
6395
  await acpContractClient.init(walletPrivateKey, sessionEntityKeyId);
6100
6396
  return acpContractClient;
6101
6397
  }
@@ -6114,6 +6410,21 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6114
6410
  isGlobalValidation: true
6115
6411
  }
6116
6412
  });
6413
+ for (const chain of this.config.chains) {
6414
+ this._sessionKeyClients[chain.chain.id] = await (0, import_smart_contracts2.createModularAccountV2Client)({
6415
+ chain: chain.chain,
6416
+ transport: (0, import_infra3.alchemy)({
6417
+ rpcUrl: `${this.config.alchemyRpcUrl}?chainId=${chain.chain.id}`
6418
+ }),
6419
+ signer: sessionKeySigner,
6420
+ policyId: "186aaa4a-5f57-4156-83fb-e456365a8820",
6421
+ accountAddress: this.agentWalletAddress,
6422
+ signerEntity: {
6423
+ entityId: sessionEntityKeyId,
6424
+ isGlobalValidation: true
6425
+ }
6426
+ });
6427
+ }
6117
6428
  this._acpX402 = new AcpX402(
6118
6429
  this.config,
6119
6430
  this.sessionKeyClient,
@@ -6126,7 +6437,10 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6126
6437
  `ACP Contract Client validation failed: agent account ${this.agentWalletAddress} is not deployed on-chain`
6127
6438
  );
6128
6439
  }
6129
- await this.validateSessionKeyOnChain(sessionSignerAddress, sessionEntityKeyId);
6440
+ await this.validateSessionKeyOnChain(
6441
+ sessionSignerAddress,
6442
+ sessionEntityKeyId
6443
+ );
6130
6444
  console.log("Connected to ACP:", {
6131
6445
  agentWalletAddress: this.agentWalletAddress,
6132
6446
  whitelistedWalletAddress: sessionSignerAddress,
@@ -6154,11 +6468,20 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6154
6468
  }
6155
6469
  return this._acpX402;
6156
6470
  }
6157
- async calculateGasFees() {
6471
+ async calculateGasFees(chainId) {
6472
+ if (chainId) {
6473
+ const { maxFeePerGas } = await this.publicClients[chainId].estimateFeesPerGas();
6474
+ const increasedMaxFeePerGas = BigInt(maxFeePerGas) + BigInt(maxFeePerGas) * BigInt(this.GAS_FEE_MULTIPLIER * 100) / BigInt(100);
6475
+ return increasedMaxFeePerGas;
6476
+ }
6158
6477
  const finalMaxFeePerGas = BigInt(this.MAX_FEE_PER_GAS) + BigInt(this.MAX_PRIORITY_FEE_PER_GAS) * BigInt(Math.max(0, this.PRIORITY_FEE_MULTIPLIER - 1));
6159
6478
  return finalMaxFeePerGas;
6160
6479
  }
6161
- async handleOperation(operations) {
6480
+ async handleOperation(operations, chainId) {
6481
+ const sessionKeyClient = chainId ? this._sessionKeyClients[chainId] : this.sessionKeyClient;
6482
+ if (!sessionKeyClient) {
6483
+ throw new acpError_default("Session key client not initialized");
6484
+ }
6162
6485
  const payload = {
6163
6486
  uo: operations.map((operation) => ({
6164
6487
  target: operation.contractAddress,
@@ -6179,16 +6502,21 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6179
6502
  maxFeePerGas: `0x${gasFees.toString(16)}`
6180
6503
  };
6181
6504
  }
6182
- const { hash } = await this.sessionKeyClient.sendUserOperation(payload);
6183
- const txnHash = await this.sessionKeyClient.waitForUserOperationTransaction({
6505
+ const { hash } = await sessionKeyClient.sendUserOperation(payload);
6506
+ const checkTransactionConfig = {
6184
6507
  hash,
6185
- tag: "pending",
6186
6508
  retries: {
6187
6509
  intervalMs: 200,
6188
6510
  multiplier: 1.1,
6189
6511
  maxRetries: 10
6190
6512
  }
6191
- });
6513
+ };
6514
+ if (!chainId || chainId === import_chains3.baseSepolia.id || chainId === import_chains3.base.id) {
6515
+ checkTransactionConfig["tag"] = "pending";
6516
+ }
6517
+ const txnHash = await sessionKeyClient.waitForUserOperationTransaction(
6518
+ checkTransactionConfig
6519
+ );
6192
6520
  return { userOpHash: hash, txnHash };
6193
6521
  } catch (error) {
6194
6522
  retries -= 1;
@@ -6212,7 +6540,7 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6212
6540
  const contractLogs = result.logs.filter((log) => {
6213
6541
  return log.address.toLowerCase() === this.jobManagerAddress.toLowerCase();
6214
6542
  }).map(
6215
- (log) => (0, import_viem7.decodeEventLog)({
6543
+ (log) => (0, import_viem9.decodeEventLog)({
6216
6544
  abi: jobManagerAbi_default,
6217
6545
  data: log.data,
6218
6546
  topics: log.topics
@@ -6271,6 +6599,7 @@ var index_default = acpClient_default;
6271
6599
  AcpJob,
6272
6600
  AcpJobPhases,
6273
6601
  AcpMemo,
6602
+ AcpMemoState,
6274
6603
  AcpMemoStatus,
6275
6604
  AcpOnlineStatus,
6276
6605
  BaseAcpContractClient,