@virtuals-protocol/acp-node 0.3.0-beta.17 → 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.mjs CHANGED
@@ -8,12 +8,13 @@ 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.17",
11
+ version: "0.3.0-beta.18",
12
12
  main: "./dist/index.js",
13
13
  module: "./dist/index.mjs",
14
14
  types: "./dist/index.d.ts",
15
15
  scripts: {
16
16
  test: "jest",
17
+ "test:ci": "jest --ci --reporters=default --reporters=jest-junit",
17
18
  "test:watch": "jest --watch",
18
19
  "test:coverage": "jest --coverage",
19
20
  tsup: "tsup src/index.ts --dts --format cjs,esm --out-dir dist"
@@ -29,6 +30,7 @@ var require_package = __commonJS({
29
30
  "babel-jest": "^30.2.0",
30
31
  dotenv: "^17.2.3",
31
32
  jest: "^30.2.0",
33
+ "jest-junit": "^16.0.0",
32
34
  "ts-jest": "^29.4.5",
33
35
  typescript: "^5.8.3"
34
36
  },
@@ -1236,7 +1238,10 @@ import {
1236
1238
  } from "viem";
1237
1239
 
1238
1240
  // src/configs/acpConfigs.ts
1239
- import { baseSepolia, base } from "@account-kit/infra";
1241
+ import {
1242
+ baseSepolia,
1243
+ base
1244
+ } from "@account-kit/infra";
1240
1245
 
1241
1246
  // src/acpFare.ts
1242
1247
  import {
@@ -1264,27 +1269,42 @@ var acpError_default = AcpError;
1264
1269
 
1265
1270
  // src/acpFare.ts
1266
1271
  var Fare = class _Fare {
1267
- constructor(contractAddress, decimals) {
1272
+ constructor(contractAddress, decimals, chainId) {
1268
1273
  this.contractAddress = contractAddress;
1269
1274
  this.decimals = decimals;
1275
+ this.chainId = chainId;
1270
1276
  }
1271
1277
  formatAmount(amount) {
1272
1278
  return parseUnits(amount.toString(), this.decimals);
1273
1279
  }
1274
- static async fromContractAddress(contractAddress, config = baseAcpConfig) {
1280
+ static async fromContractAddress(contractAddress, config = baseAcpConfig, chainId = config.chain.id) {
1275
1281
  if (contractAddress === config.baseFare.contractAddress) {
1276
1282
  return config.baseFare;
1277
1283
  }
1284
+ let chainConfig = config.chain;
1285
+ let rpcUrl = config.rpcEndpoint;
1286
+ if (chainId !== config.chain.id) {
1287
+ const selectedConfig = config.chains?.find(
1288
+ (chain) => chain.chain.id === chainId
1289
+ );
1290
+ if (!selectedConfig) {
1291
+ throw new acpError_default(
1292
+ `Chain configuration for chainId ${chainId} not found.`
1293
+ );
1294
+ }
1295
+ chainConfig = selectedConfig.chain;
1296
+ rpcUrl = selectedConfig.rpcUrl;
1297
+ }
1278
1298
  const publicClient = createPublicClient({
1279
- chain: config.chain,
1280
- transport: http(config.rpcEndpoint)
1299
+ chain: chainConfig,
1300
+ transport: http(rpcUrl)
1281
1301
  });
1282
1302
  const decimals = await publicClient.readContract({
1283
1303
  address: contractAddress,
1284
1304
  abi: erc20Abi,
1285
1305
  functionName: "decimals"
1286
1306
  });
1287
- return new _Fare(contractAddress, decimals);
1307
+ return new _Fare(contractAddress, decimals, chainId);
1288
1308
  }
1289
1309
  };
1290
1310
  var FareAmountBase = class {
@@ -1703,6 +1723,34 @@ var ACP_V2_ABI = [
1703
1723
  stateMutability: "nonpayable",
1704
1724
  type: "function"
1705
1725
  },
1726
+ {
1727
+ inputs: [
1728
+ { internalType: "uint256", name: "jobId", type: "uint256" },
1729
+ { internalType: "string", name: "content", type: "string" },
1730
+ { internalType: "address", name: "token", type: "address" },
1731
+ { internalType: "uint256", name: "amount", type: "uint256" },
1732
+ { internalType: "address", name: "recipient", type: "address" },
1733
+ { internalType: "uint256", name: "feeAmount", type: "uint256" },
1734
+ { internalType: "enum ACPTypes.FeeType", name: "feeType", type: "uint8" },
1735
+ {
1736
+ internalType: "enum ACPTypes.MemoType",
1737
+ name: "memoType",
1738
+ type: "uint8"
1739
+ },
1740
+ { internalType: "uint256", name: "expiredAt", type: "uint256" },
1741
+ { internalType: "bool", name: "isSecured", type: "bool" },
1742
+ {
1743
+ internalType: "enum ACPTypes.JobPhase",
1744
+ name: "nextPhase",
1745
+ type: "uint8"
1746
+ },
1747
+ { internalType: "uint32", name: "lzDstEid", type: "uint32" }
1748
+ ],
1749
+ name: "createCrossChainPayableMemo",
1750
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
1751
+ stateMutability: "nonpayable",
1752
+ type: "function"
1753
+ },
1706
1754
  {
1707
1755
  inputs: [
1708
1756
  { internalType: "address", name: "provider", type: "address" },
@@ -1887,7 +1935,12 @@ var ACP_V2_ABI = [
1887
1935
  name: "nextPhase",
1888
1936
  type: "uint8"
1889
1937
  },
1890
- { internalType: "uint256", name: "expiredAt", type: "uint256" }
1938
+ { internalType: "uint256", name: "expiredAt", type: "uint256" },
1939
+ {
1940
+ internalType: "enum ACPTypes.MemoState",
1941
+ name: "state",
1942
+ type: "uint8"
1943
+ }
1891
1944
  ],
1892
1945
  internalType: "struct ACPTypes.Memo[]",
1893
1946
  name: "memos",
@@ -1934,7 +1987,12 @@ var ACP_V2_ABI = [
1934
1987
  name: "nextPhase",
1935
1988
  type: "uint8"
1936
1989
  },
1937
- { internalType: "uint256", name: "expiredAt", type: "uint256" }
1990
+ { internalType: "uint256", name: "expiredAt", type: "uint256" },
1991
+ {
1992
+ internalType: "enum ACPTypes.MemoState",
1993
+ name: "state",
1994
+ type: "uint8"
1995
+ }
1938
1996
  ],
1939
1997
  internalType: "struct ACPTypes.Memo[]",
1940
1998
  name: "memos",
@@ -1977,7 +2035,12 @@ var ACP_V2_ABI = [
1977
2035
  name: "nextPhase",
1978
2036
  type: "uint8"
1979
2037
  },
1980
- { internalType: "uint256", name: "expiredAt", type: "uint256" }
2038
+ { internalType: "uint256", name: "expiredAt", type: "uint256" },
2039
+ {
2040
+ internalType: "enum ACPTypes.MemoState",
2041
+ name: "state",
2042
+ type: "uint8"
2043
+ }
1981
2044
  ],
1982
2045
  internalType: "struct ACPTypes.Memo[]",
1983
2046
  name: "memos",
@@ -2233,7 +2296,7 @@ var acpAbiV2_default = ACP_V2_ABI;
2233
2296
  var V1_MAX_RETRIES = 10;
2234
2297
  var V2_MAX_RETRIES = 3;
2235
2298
  var AcpContractConfig2 = class {
2236
- constructor(chain, contractAddress, baseFare, alchemyRpcUrl, acpUrl, abi, maxRetries, rpcEndpoint, x402Config) {
2299
+ constructor(chain, contractAddress, baseFare, alchemyRpcUrl, acpUrl, abi, maxRetries, rpcEndpoint, x402Config, chains = []) {
2237
2300
  this.chain = chain;
2238
2301
  this.contractAddress = contractAddress;
2239
2302
  this.baseFare = baseFare;
@@ -2243,6 +2306,7 @@ var AcpContractConfig2 = class {
2243
2306
  this.maxRetries = maxRetries;
2244
2307
  this.rpcEndpoint = rpcEndpoint;
2245
2308
  this.x402Config = x402Config;
2309
+ this.chains = chains;
2246
2310
  }
2247
2311
  };
2248
2312
  var baseSepoliaAcpConfig = new AcpContractConfig2(
@@ -3470,7 +3534,18 @@ var SINGLE_SIGNER_VALIDATION_MODULE_ABI = [
3470
3534
  var singleSignerValidationModuleAbi_default = SINGLE_SIGNER_VALIDATION_MODULE_ABI;
3471
3535
 
3472
3536
  // src/constants.ts
3473
- import { base as base2, baseSepolia as baseSepolia2 } from "viem/chains";
3537
+ import {
3538
+ arbitrum as arbitrum2,
3539
+ arbitrumSepolia as arbitrumSepolia2,
3540
+ base as base2,
3541
+ baseSepolia as baseSepolia2,
3542
+ bsc as bsc2,
3543
+ bscTestnet as bscTestnet2,
3544
+ mainnet as mainnet2,
3545
+ polygon as polygon2,
3546
+ polygonAmoy as polygonAmoy2,
3547
+ sepolia as sepolia2
3548
+ } from "viem/chains";
3474
3549
  var USDC_TOKEN_ADDRESS = {
3475
3550
  [baseSepolia2.id]: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
3476
3551
  [base2.id]: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
@@ -3488,6 +3563,16 @@ var HTTP_STATUS_CODES = {
3488
3563
  PAYMENT_REQUIRED: 402
3489
3564
  };
3490
3565
  var SINGLE_SIGNER_VALIDATION_MODULE_ADDRESS = "0x00000000000099DE0BF6fA90dEB851E2A2df7d83";
3566
+ var ASSET_MANAGER_ADDRESSES = {
3567
+ [bscTestnet2.id]: "0xfCf52B02936623852dd5132007E9414f9060168b",
3568
+ [bsc2.id]: "",
3569
+ [polygonAmoy2.id]: "0xfCf52B02936623852dd5132007E9414f9060168b",
3570
+ [polygon2.id]: "",
3571
+ [arbitrum2.id]: "",
3572
+ [arbitrumSepolia2.id]: "0xfCf52B02936623852dd5132007E9414f9060168b",
3573
+ [sepolia2.id]: "0xfCf52B02936623852dd5132007E9414f9060168b",
3574
+ [mainnet2.id]: ""
3575
+ };
3491
3576
 
3492
3577
  // src/contractClients/baseAcpContractClient.ts
3493
3578
  var MemoType = /* @__PURE__ */ ((MemoType3) => {
@@ -3502,6 +3587,7 @@ var MemoType = /* @__PURE__ */ ((MemoType3) => {
3502
3587
  MemoType3[MemoType3["PAYABLE_TRANSFER_ESCROW"] = 8] = "PAYABLE_TRANSFER_ESCROW";
3503
3588
  MemoType3[MemoType3["NOTIFICATION"] = 9] = "NOTIFICATION";
3504
3589
  MemoType3[MemoType3["PAYABLE_NOTIFICATION"] = 10] = "PAYABLE_NOTIFICATION";
3590
+ MemoType3[MemoType3["TRANSFER_EVENT"] = 11] = "TRANSFER_EVENT";
3505
3591
  return MemoType3;
3506
3592
  })(MemoType || {});
3507
3593
  var AcpJobPhases = /* @__PURE__ */ ((AcpJobPhases3) => {
@@ -3518,6 +3604,7 @@ var BaseAcpContractClient = class {
3518
3604
  constructor(agentWalletAddress, config = baseAcpConfig) {
3519
3605
  this.agentWalletAddress = agentWalletAddress;
3520
3606
  this.config = config;
3607
+ this.publicClients = {};
3521
3608
  this.chain = config.chain;
3522
3609
  this.abi = config.abi;
3523
3610
  this.contractAddress = config.contractAddress;
@@ -3617,12 +3704,12 @@ ${JSON.stringify(
3617
3704
  throw new acpError_default("Failed to create job", error);
3618
3705
  }
3619
3706
  }
3620
- approveAllowance(amountBaseUnit, paymentTokenAddress = this.config.baseFare.contractAddress) {
3707
+ approveAllowance(amountBaseUnit, paymentTokenAddress = this.config.baseFare.contractAddress, targetAddress) {
3621
3708
  try {
3622
3709
  const data = encodeFunctionData({
3623
3710
  abi: erc20Abi2,
3624
3711
  functionName: "approve",
3625
- args: [this.contractAddress, amountBaseUnit]
3712
+ args: [targetAddress ?? this.contractAddress, amountBaseUnit]
3626
3713
  });
3627
3714
  const payload = {
3628
3715
  data,
@@ -3661,6 +3748,35 @@ ${JSON.stringify(
3661
3748
  throw new acpError_default("Failed to create payable memo", error);
3662
3749
  }
3663
3750
  }
3751
+ createCrossChainPayableMemo(jobId, content, token, amountBaseUnit, recipient, feeAmountBaseUnit, feeType, type, expiredAt, nextPhase, destinationEid, secured = true) {
3752
+ try {
3753
+ const data = encodeFunctionData({
3754
+ abi: this.abi,
3755
+ functionName: "createCrossChainPayableMemo",
3756
+ args: [
3757
+ jobId,
3758
+ content,
3759
+ token,
3760
+ amountBaseUnit,
3761
+ recipient,
3762
+ feeAmountBaseUnit,
3763
+ feeType,
3764
+ type,
3765
+ expiredAt,
3766
+ secured,
3767
+ nextPhase,
3768
+ destinationEid
3769
+ ]
3770
+ });
3771
+ const payload = {
3772
+ data,
3773
+ contractAddress: this.contractAddress
3774
+ };
3775
+ return payload;
3776
+ } catch (error) {
3777
+ throw new acpError_default("Failed to create cross chain payable memo", error);
3778
+ }
3779
+ }
3664
3780
  createMemo(jobId, content, type, isSecured, nextPhase) {
3665
3781
  try {
3666
3782
  const data = encodeFunctionData({
@@ -3677,6 +3793,22 @@ ${JSON.stringify(
3677
3793
  throw new acpError_default("Failed to create memo", error);
3678
3794
  }
3679
3795
  }
3796
+ createMemoWithMetadata(jobId, content, type, isSecured, nextPhase, metadata) {
3797
+ try {
3798
+ const data = encodeFunctionData({
3799
+ abi: this.abi,
3800
+ functionName: "createMemoWithMetadata",
3801
+ args: [jobId, content, type, isSecured, nextPhase, metadata]
3802
+ });
3803
+ const payload = {
3804
+ data,
3805
+ contractAddress: this.contractAddress
3806
+ };
3807
+ return payload;
3808
+ } catch (error) {
3809
+ throw new acpError_default("Failed to create memo with metadata", error);
3810
+ }
3811
+ }
3680
3812
  signMemo(memoId, isApproved, reason) {
3681
3813
  try {
3682
3814
  const data = encodeFunctionData({
@@ -3762,9 +3894,47 @@ ${JSON.stringify(
3762
3894
  throw new acpError_default("Failed to submit TransferWithAuthorization", error);
3763
3895
  }
3764
3896
  }
3897
+ async getERC20Balance(chainId, tokenAddress, walletAddress) {
3898
+ const publicClient = this.publicClients[chainId];
3899
+ if (!publicClient) {
3900
+ throw new acpError_default(`Public client for chainId ${chainId} not found`);
3901
+ }
3902
+ return await publicClient.readContract({
3903
+ address: tokenAddress,
3904
+ abi: erc20Abi2,
3905
+ functionName: "balanceOf",
3906
+ args: [walletAddress]
3907
+ });
3908
+ }
3909
+ async getERC20Allowance(chainId, tokenAddress, walletAddress, spenderAddress) {
3910
+ const publicClient = this.publicClients[chainId];
3911
+ if (!publicClient) {
3912
+ throw new acpError_default(`Public client for chainId ${chainId} not found`);
3913
+ }
3914
+ return await publicClient.readContract({
3915
+ address: tokenAddress,
3916
+ abi: erc20Abi2,
3917
+ functionName: "allowance",
3918
+ args: [walletAddress, spenderAddress]
3919
+ });
3920
+ }
3921
+ async getERC20Symbol(chainId, tokenAddress) {
3922
+ const publicClient = this.publicClients[chainId];
3923
+ if (!publicClient) {
3924
+ throw new acpError_default(`Public client for chainId ${chainId} not found`);
3925
+ }
3926
+ return await publicClient.readContract({
3927
+ address: tokenAddress,
3928
+ abi: erc20Abi2,
3929
+ functionName: "symbol"
3930
+ });
3931
+ }
3765
3932
  };
3766
3933
  var baseAcpContractClient_default = BaseAcpContractClient;
3767
3934
 
3935
+ // src/acpJob.ts
3936
+ import { formatUnits } from "viem";
3937
+
3768
3938
  // src/interfaces.ts
3769
3939
  var AcpMemoStatus = /* @__PURE__ */ ((AcpMemoStatus2) => {
3770
3940
  AcpMemoStatus2["PENDING"] = "PENDING";
@@ -3772,6 +3942,15 @@ var AcpMemoStatus = /* @__PURE__ */ ((AcpMemoStatus2) => {
3772
3942
  AcpMemoStatus2["REJECTED"] = "REJECTED";
3773
3943
  return AcpMemoStatus2;
3774
3944
  })(AcpMemoStatus || {});
3945
+ var AcpMemoState = /* @__PURE__ */ ((AcpMemoState2) => {
3946
+ AcpMemoState2["NONE"] = "NONE";
3947
+ AcpMemoState2["PENDING"] = "PENDING";
3948
+ AcpMemoState2["IN_PROGRESS"] = "IN_PROGRESS";
3949
+ AcpMemoState2["READY"] = "READY";
3950
+ AcpMemoState2["COMPLETED"] = "COMPLETED";
3951
+ AcpMemoState2["REJECTED"] = "REJECTED";
3952
+ return AcpMemoState2;
3953
+ })(AcpMemoState || {});
3775
3954
  var AcpAgentSort = /* @__PURE__ */ ((AcpAgentSort2) => {
3776
3955
  AcpAgentSort2["SUCCESSFUL_JOB_COUNT"] = "successfulJobCount";
3777
3956
  AcpAgentSort2["SUCCESS_RATE"] = "successRate";
@@ -3810,6 +3989,19 @@ var PositionDirection = /* @__PURE__ */ ((PositionDirection2) => {
3810
3989
  })(PositionDirection || {});
3811
3990
 
3812
3991
  // src/utils.ts
3992
+ import { decodeAbiParameters, encodeAbiParameters } from "viem";
3993
+ import {
3994
+ arbitrum as arbitrum3,
3995
+ arbitrumSepolia as arbitrumSepolia3,
3996
+ base as base3,
3997
+ baseSepolia as baseSepolia3,
3998
+ bsc as bsc3,
3999
+ bscTestnet as bscTestnet3,
4000
+ mainnet as mainnet3,
4001
+ polygon as polygon3,
4002
+ polygonAmoy as polygonAmoy3,
4003
+ sepolia as sepolia3
4004
+ } from "viem/chains";
3813
4005
  function tryParseJson(content) {
3814
4006
  try {
3815
4007
  return JSON.parse(content);
@@ -3826,6 +4018,31 @@ function safeBase64Encode(data) {
3826
4018
  }
3827
4019
  return Buffer.from(data).toString("base64");
3828
4020
  }
4021
+ function getDestinationEndpointId(chainId) {
4022
+ switch (chainId) {
4023
+ case baseSepolia3.id:
4024
+ return 40245;
4025
+ case sepolia3.id:
4026
+ return 40161;
4027
+ case polygonAmoy3.id:
4028
+ return 40267;
4029
+ case arbitrumSepolia3.id:
4030
+ return 40231;
4031
+ case bscTestnet3.id:
4032
+ return 40102;
4033
+ case base3.id:
4034
+ return 30184;
4035
+ case mainnet3.id:
4036
+ return 30101;
4037
+ case polygon3.id:
4038
+ return 30109;
4039
+ case arbitrum3.id:
4040
+ return 30110;
4041
+ case bsc3.id:
4042
+ return 30102;
4043
+ }
4044
+ throw new Error(`Unsupported chain ID: ${chainId}`);
4045
+ }
3829
4046
 
3830
4047
  // src/acpJobOffering.ts
3831
4048
  import { zeroAddress as zeroAddress2 } from "viem";
@@ -4028,20 +4245,38 @@ var AcpJob = class {
4028
4245
  }
4029
4246
  const feeAmount = new FareAmount(0, this.acpContractClient.config.baseFare);
4030
4247
  const isPercentagePricing = this.priceType === "percentage" /* PERCENTAGE */;
4031
- operations.push(
4032
- this.acpContractClient.createPayableMemo(
4033
- this.id,
4034
- content,
4035
- amount.amount,
4036
- recipient,
4037
- isPercentagePricing ? BigInt(Math.round(this.priceValue * 1e4)) : feeAmount.amount,
4038
- isPercentagePricing ? 3 /* PERCENTAGE_FEE */ : 0 /* NO_FEE */,
4039
- 2 /* TRANSACTION */,
4040
- type,
4041
- expiredAt,
4042
- amount.fare.contractAddress
4043
- )
4044
- );
4248
+ if (amount.fare.chainId && amount.fare.chainId !== this.acpContractClient.config.chain.id) {
4249
+ operations.push(
4250
+ this.acpContractClient.createCrossChainPayableMemo(
4251
+ this.id,
4252
+ content,
4253
+ amount.fare.contractAddress,
4254
+ amount.amount,
4255
+ recipient,
4256
+ isPercentagePricing ? BigInt(Math.round(this.priceValue * 1e4)) : feeAmount.amount,
4257
+ isPercentagePricing ? 3 /* PERCENTAGE_FEE */ : 0 /* NO_FEE */,
4258
+ type,
4259
+ expiredAt,
4260
+ 2 /* TRANSACTION */,
4261
+ getDestinationEndpointId(amount.fare.chainId)
4262
+ )
4263
+ );
4264
+ } else {
4265
+ operations.push(
4266
+ this.acpContractClient.createPayableMemo(
4267
+ this.id,
4268
+ content,
4269
+ amount.amount,
4270
+ recipient,
4271
+ isPercentagePricing ? BigInt(Math.round(this.priceValue * 1e4)) : feeAmount.amount,
4272
+ isPercentagePricing ? 3 /* PERCENTAGE_FEE */ : 0 /* NO_FEE */,
4273
+ 2 /* TRANSACTION */,
4274
+ type,
4275
+ expiredAt,
4276
+ amount.fare.contractAddress
4277
+ )
4278
+ );
4279
+ }
4045
4280
  return await this.acpContractClient.handleOperation(operations);
4046
4281
  }
4047
4282
  async payAndAcceptRequirement(reason) {
@@ -4174,6 +4409,9 @@ var AcpJob = class {
4174
4409
  if (this.latestMemo?.nextPhase !== 3 /* EVALUATION */) {
4175
4410
  throw new acpError_default("No transaction memo found");
4176
4411
  }
4412
+ if (amount.fare.chainId !== this.acpContractClient.config.chain.id) {
4413
+ return await this.deliverCrossChainPayable(this.clientAddress, amount);
4414
+ }
4177
4415
  const operations = [];
4178
4416
  operations.push(
4179
4417
  this.acpContractClient.approveAllowance(
@@ -4304,6 +4542,56 @@ var AcpJob = class {
4304
4542
  waitMs = Math.min(waitMs * 2, maxWaitMs);
4305
4543
  }
4306
4544
  }
4545
+ async deliverCrossChainPayable(recipient, amount) {
4546
+ if (!amount.fare.chainId) {
4547
+ throw new acpError_default("Chain ID is required for cross chain payable");
4548
+ }
4549
+ const chainId = amount.fare.chainId;
4550
+ const tokenBalance = await this.acpContractClient.getERC20Balance(
4551
+ chainId,
4552
+ amount.fare.contractAddress,
4553
+ this.acpContractClient.agentWalletAddress
4554
+ );
4555
+ if (tokenBalance < amount.amount) {
4556
+ throw new acpError_default("Insufficient token balance for cross chain payable");
4557
+ }
4558
+ const currentAllowance = await this.acpContractClient.getERC20Allowance(
4559
+ chainId,
4560
+ amount.fare.contractAddress,
4561
+ this.acpContractClient.agentWalletAddress,
4562
+ ASSET_MANAGER_ADDRESSES[chainId]
4563
+ );
4564
+ const approveAllowanceOperation = this.acpContractClient.approveAllowance(
4565
+ amount.amount + currentAllowance,
4566
+ amount.fare.contractAddress,
4567
+ ASSET_MANAGER_ADDRESSES[chainId]
4568
+ );
4569
+ await this.acpContractClient.handleOperation(
4570
+ [approveAllowanceOperation],
4571
+ chainId
4572
+ );
4573
+ const tokenSymbol = await this.acpContractClient.getERC20Symbol(
4574
+ chainId,
4575
+ amount.fare.contractAddress
4576
+ );
4577
+ const createMemoOperation = this.acpContractClient.createCrossChainPayableMemo(
4578
+ this.id,
4579
+ `Performing cross chain payable transfer of ${formatUnits(
4580
+ amount.amount,
4581
+ amount.fare.decimals
4582
+ )} ${tokenSymbol} to ${recipient}`,
4583
+ amount.fare.contractAddress,
4584
+ amount.amount,
4585
+ recipient,
4586
+ BigInt(0),
4587
+ 0 /* NO_FEE */,
4588
+ 7 /* PAYABLE_TRANSFER */,
4589
+ new Date(Date.now() + 1e3 * 60 * 5),
4590
+ 4 /* COMPLETED */,
4591
+ getDestinationEndpointId(chainId)
4592
+ );
4593
+ await this.acpContractClient.handleOperation([createMemoOperation]);
4594
+ }
4307
4595
  [util.inspect.custom]() {
4308
4596
  return {
4309
4597
  id: this.id,
@@ -4327,7 +4615,7 @@ var acpJob_default = AcpJob;
4327
4615
  // src/acpMemo.ts
4328
4616
  import util2 from "util";
4329
4617
  var AcpMemo = class {
4330
- constructor(contractClient, id, type, content, nextPhase, status, senderAddress, signedReason, expiry, payableDetails, txHash, signedTxHash) {
4618
+ constructor(contractClient, id, type, content, nextPhase, status, senderAddress, signedReason, expiry, payableDetails, txHash, signedTxHash, state) {
4331
4619
  this.contractClient = contractClient;
4332
4620
  this.id = id;
4333
4621
  this.type = type;
@@ -4340,6 +4628,7 @@ var AcpMemo = class {
4340
4628
  this.payableDetails = payableDetails;
4341
4629
  this.txHash = txHash;
4342
4630
  this.signedTxHash = signedTxHash;
4631
+ this.state = state;
4343
4632
  if (this.payableDetails) {
4344
4633
  this.payableDetails.amount = BigInt(this.payableDetails.amount);
4345
4634
  this.payableDetails.feeAmount = BigInt(this.payableDetails.feeAmount);
@@ -4490,7 +4779,8 @@ var AcpClient = class {
4490
4779
  memo.expiry ? new Date(parseInt(memo.expiry) * 1e3) : void 0,
4491
4780
  memo.payableDetails,
4492
4781
  memo.txHash,
4493
- memo.signedTxHash
4782
+ memo.signedTxHash,
4783
+ memo.state
4494
4784
  );
4495
4785
  }),
4496
4786
  data.phase,
@@ -4528,7 +4818,8 @@ var AcpClient = class {
4528
4818
  memo.expiry ? new Date(parseInt(memo.expiry) * 1e3) : void 0,
4529
4819
  memo.payableDetails,
4530
4820
  memo.txHash,
4531
- memo.signedTxHash
4821
+ memo.signedTxHash,
4822
+ memo.state
4532
4823
  );
4533
4824
  }),
4534
4825
  data.phase,
@@ -4553,7 +4844,14 @@ var AcpClient = class {
4553
4844
  process.on("SIGTERM", cleanup);
4554
4845
  }
4555
4846
  async browseAgents(keyword, options) {
4556
- let { cluster, sort_by, top_k, graduationStatus, onlineStatus, showHiddenOfferings } = options;
4847
+ let {
4848
+ cluster,
4849
+ sort_by,
4850
+ top_k,
4851
+ graduationStatus,
4852
+ onlineStatus,
4853
+ showHiddenOfferings
4854
+ } = options;
4557
4855
  top_k = top_k ?? 5;
4558
4856
  let url = `${this.acpUrl}/api/agents/v4/search?search=${keyword}`;
4559
4857
  if (sort_by && sort_by.length > 0) {
@@ -4744,7 +5042,8 @@ var AcpClient = class {
4744
5042
  memo.expiry ? new Date(parseInt(memo.expiry) * 1e3) : void 0,
4745
5043
  memo.payableDetails,
4746
5044
  memo.txHash,
4747
- memo.signedTxHash
5045
+ memo.signedTxHash,
5046
+ memo.state
4748
5047
  )
4749
5048
  );
4750
5049
  jobs.push(
@@ -4818,7 +5117,8 @@ var AcpClient = class {
4818
5117
  memo.expiry ? new Date(parseInt(memo.expiry) * 1e3) : void 0,
4819
5118
  memo.payableDetails,
4820
5119
  memo.txHash,
4821
- memo.signedTxHash
5120
+ memo.signedTxHash,
5121
+ memo.state
4822
5122
  )
4823
5123
  );
4824
5124
  return new acpJob_default(
@@ -4877,7 +5177,8 @@ var AcpClient = class {
4877
5177
  memo.expiry ? new Date(parseInt(memo.expiry) * 1e3) : void 0,
4878
5178
  memo.payableDetails,
4879
5179
  memo.txHash,
4880
- memo.signedTxHash
5180
+ memo.signedTxHash,
5181
+ memo.state
4881
5182
  );
4882
5183
  } catch (err) {
4883
5184
  throw new acpError_default(
@@ -4990,6 +5291,9 @@ var AcpX402 = class {
4990
5291
  const acpJob = await response.json();
4991
5292
  return acpJob;
4992
5293
  } catch (error) {
5294
+ if (error instanceof acpError_default) {
5295
+ throw error;
5296
+ }
4993
5297
  throw new acpError_default("Failed to update job X402 nonce", error);
4994
5298
  }
4995
5299
  }
@@ -5078,6 +5382,9 @@ var AcpX402 = class {
5078
5382
  data
5079
5383
  };
5080
5384
  } catch (error) {
5385
+ if (error instanceof acpError_default) {
5386
+ throw error;
5387
+ }
5081
5388
  throw new acpError_default("Failed to perform X402 request", error);
5082
5389
  }
5083
5390
  }
@@ -6011,6 +6318,7 @@ var JOB_MANAGER_ABI = [
6011
6318
  var jobManagerAbi_default = JOB_MANAGER_ABI;
6012
6319
 
6013
6320
  // src/contractClients/acpContractClientV2.ts
6321
+ import { base as base4, baseSepolia as baseSepolia4 } from "viem/chains";
6014
6322
  var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClient_default {
6015
6323
  constructor(jobManagerAddress, memoManagerAddress, accountManagerAddress, agentWalletAddress, config = baseAcpConfigV2) {
6016
6324
  super(agentWalletAddress, config);
@@ -6020,8 +6328,17 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6020
6328
  this.PRIORITY_FEE_MULTIPLIER = 2;
6021
6329
  this.MAX_FEE_PER_GAS = 2e7;
6022
6330
  this.MAX_PRIORITY_FEE_PER_GAS = 21e6;
6331
+ this.GAS_FEE_MULTIPLIER = 0.5;
6332
+ this._sessionKeyClients = {};
6023
6333
  }
6024
6334
  static async build(walletPrivateKey, sessionEntityKeyId, agentWalletAddress, config = baseAcpConfigV2) {
6335
+ const publicClients = {};
6336
+ for (const chain of config.chains) {
6337
+ publicClients[chain.chain.id] = createPublicClient4({
6338
+ chain: chain.chain,
6339
+ transport: http3(chain.rpcUrl)
6340
+ });
6341
+ }
6025
6342
  const publicClient = createPublicClient4({
6026
6343
  chain: config.chain,
6027
6344
  transport: http3(config.rpcEndpoint)
@@ -6057,6 +6374,7 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6057
6374
  agentWalletAddress,
6058
6375
  config
6059
6376
  );
6377
+ acpContractClient.publicClients = publicClients;
6060
6378
  await acpContractClient.init(walletPrivateKey, sessionEntityKeyId);
6061
6379
  return acpContractClient;
6062
6380
  }
@@ -6075,6 +6393,21 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6075
6393
  isGlobalValidation: true
6076
6394
  }
6077
6395
  });
6396
+ for (const chain of this.config.chains) {
6397
+ this._sessionKeyClients[chain.chain.id] = await createModularAccountV2Client2({
6398
+ chain: chain.chain,
6399
+ transport: alchemy2({
6400
+ rpcUrl: `${this.config.alchemyRpcUrl}?chainId=${chain.chain.id}`
6401
+ }),
6402
+ signer: sessionKeySigner,
6403
+ policyId: "186aaa4a-5f57-4156-83fb-e456365a8820",
6404
+ accountAddress: this.agentWalletAddress,
6405
+ signerEntity: {
6406
+ entityId: sessionEntityKeyId,
6407
+ isGlobalValidation: true
6408
+ }
6409
+ });
6410
+ }
6078
6411
  this._acpX402 = new AcpX402(
6079
6412
  this.config,
6080
6413
  this.sessionKeyClient,
@@ -6087,7 +6420,10 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6087
6420
  `ACP Contract Client validation failed: agent account ${this.agentWalletAddress} is not deployed on-chain`
6088
6421
  );
6089
6422
  }
6090
- await this.validateSessionKeyOnChain(sessionSignerAddress, sessionEntityKeyId);
6423
+ await this.validateSessionKeyOnChain(
6424
+ sessionSignerAddress,
6425
+ sessionEntityKeyId
6426
+ );
6091
6427
  console.log("Connected to ACP:", {
6092
6428
  agentWalletAddress: this.agentWalletAddress,
6093
6429
  whitelistedWalletAddress: sessionSignerAddress,
@@ -6115,11 +6451,20 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6115
6451
  }
6116
6452
  return this._acpX402;
6117
6453
  }
6118
- async calculateGasFees() {
6454
+ async calculateGasFees(chainId) {
6455
+ if (chainId) {
6456
+ const { maxFeePerGas } = await this.publicClients[chainId].estimateFeesPerGas();
6457
+ const increasedMaxFeePerGas = BigInt(maxFeePerGas) + BigInt(maxFeePerGas) * BigInt(this.GAS_FEE_MULTIPLIER * 100) / BigInt(100);
6458
+ return increasedMaxFeePerGas;
6459
+ }
6119
6460
  const finalMaxFeePerGas = BigInt(this.MAX_FEE_PER_GAS) + BigInt(this.MAX_PRIORITY_FEE_PER_GAS) * BigInt(Math.max(0, this.PRIORITY_FEE_MULTIPLIER - 1));
6120
6461
  return finalMaxFeePerGas;
6121
6462
  }
6122
- async handleOperation(operations) {
6463
+ async handleOperation(operations, chainId) {
6464
+ const sessionKeyClient = chainId ? this._sessionKeyClients[chainId] : this.sessionKeyClient;
6465
+ if (!sessionKeyClient) {
6466
+ throw new acpError_default("Session key client not initialized");
6467
+ }
6123
6468
  const payload = {
6124
6469
  uo: operations.map((operation) => ({
6125
6470
  target: operation.contractAddress,
@@ -6140,16 +6485,21 @@ var AcpContractClientV2 = class _AcpContractClientV2 extends baseAcpContractClie
6140
6485
  maxFeePerGas: `0x${gasFees.toString(16)}`
6141
6486
  };
6142
6487
  }
6143
- const { hash } = await this.sessionKeyClient.sendUserOperation(payload);
6144
- const txnHash = await this.sessionKeyClient.waitForUserOperationTransaction({
6488
+ const { hash } = await sessionKeyClient.sendUserOperation(payload);
6489
+ const checkTransactionConfig = {
6145
6490
  hash,
6146
- tag: "pending",
6147
6491
  retries: {
6148
6492
  intervalMs: 200,
6149
6493
  multiplier: 1.1,
6150
6494
  maxRetries: 10
6151
6495
  }
6152
- });
6496
+ };
6497
+ if (!chainId || chainId === baseSepolia4.id || chainId === base4.id) {
6498
+ checkTransactionConfig["tag"] = "pending";
6499
+ }
6500
+ const txnHash = await sessionKeyClient.waitForUserOperationTransaction(
6501
+ checkTransactionConfig
6502
+ );
6153
6503
  return { userOpHash: hash, txnHash };
6154
6504
  } catch (error) {
6155
6505
  retries -= 1;
@@ -6231,6 +6581,7 @@ export {
6231
6581
  acpJob_default as AcpJob,
6232
6582
  AcpJobPhases,
6233
6583
  acpMemo_default as AcpMemo,
6584
+ AcpMemoState,
6234
6585
  AcpMemoStatus,
6235
6586
  AcpOnlineStatus,
6236
6587
  baseAcpContractClient_default as BaseAcpContractClient,