sdk-triggerx 0.1.28 → 0.1.29

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.
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.checkTgBalance = void 0;
7
7
  const ethers_1 = require("ethers");
8
8
  const GasRegistry_json_1 = __importDefault(require("../contracts/abi/GasRegistry.json"));
9
- const config_1 = require("../config");
9
+ const contractUtils_1 = require("../contracts/contractUtils");
10
10
  const errors_1 = require("../utils/errors");
11
11
  /**
12
12
  * Check TG balance for a given signer using SDK-provided RPC
@@ -22,36 +22,31 @@ const checkTgBalance = async (signer, chainId) => {
22
22
  return (0, errors_1.createErrorResponse)(new errors_1.ValidationError('signer', 'Signer is required'), 'Validation error');
23
23
  }
24
24
  try {
25
- // Try to get chainId from signer's provider if not provided
26
- // If signer's provider fails, we'll use the provided chainId or return error
27
- let resolvedChainId = chainId?.toString();
28
- if (!resolvedChainId) {
29
- try {
30
- const network = await signer.provider?.getNetwork();
31
- resolvedChainId = network?.chainId ? network.chainId.toString() : undefined;
32
- }
33
- catch (providerError) {
34
- // If user's RPC fails, we can't get chainId from it
35
- // This is expected in cases where user's RPC is down
36
- console.warn('Could not get network from signer provider, using provided chainId or will fail:', providerError);
25
+ // Resolve chain ID (use provided chainId or resolve from signer)
26
+ let resolvedChainId;
27
+ try {
28
+ resolvedChainId = await (0, contractUtils_1.resolveChainId)(signer, chainId);
29
+ }
30
+ catch (configError) {
31
+ if (configError instanceof errors_1.ConfigurationError) {
32
+ return (0, errors_1.createErrorResponse)(configError, 'Configuration error');
37
33
  }
34
+ return (0, errors_1.createErrorResponse)(new errors_1.ConfigurationError('Failed to resolve chain ID', { originalError: configError }), 'Configuration error');
38
35
  }
39
- if (!resolvedChainId) {
40
- return (0, errors_1.createErrorResponse)(new errors_1.ConfigurationError('Chain ID is required. Please provide chainId parameter or ensure signer has a working provider.'), 'Configuration error');
36
+ // Get contract address
37
+ let gasRegistryContractAddress;
38
+ try {
39
+ gasRegistryContractAddress = (0, contractUtils_1.getContractAddress)(resolvedChainId, 'gasRegistry');
41
40
  }
42
- const { gasRegistry } = (0, config_1.getChainAddresses)(resolvedChainId);
43
- const gasRegistryContractAddress = gasRegistry;
44
- if (!gasRegistryContractAddress) {
45
- return (0, errors_1.createErrorResponse)(new errors_1.ConfigurationError(`GasRegistry address not configured for chain ID: ${resolvedChainId}`), 'Configuration error');
41
+ catch (configError) {
42
+ if (configError instanceof errors_1.ConfigurationError) {
43
+ return (0, errors_1.createErrorResponse)(configError, 'Configuration error');
44
+ }
45
+ return (0, errors_1.createErrorResponse)(new errors_1.ConfigurationError('Failed to get contract address', { originalError: configError }), 'Configuration error');
46
46
  }
47
- // Use SDK-provided RPC provider instead of user's provider
47
+ // Create contract instance with SDK RPC provider (read-only)
48
48
  // This ensures we can read balance even if user's RPC fails
49
- const rpcProvider = (0, config_1.getRpcProvider)(resolvedChainId);
50
- if (!rpcProvider) {
51
- return (0, errors_1.createErrorResponse)(new errors_1.ConfigurationError(`RPC URL not configured for chain ID: ${resolvedChainId}. Cannot check balance without RPC provider.`), 'Configuration error');
52
- }
53
- // Create contract instance with our RPC provider (read-only)
54
- const contract = new ethers_1.ethers.Contract(gasRegistryContractAddress, GasRegistry_json_1.default, rpcProvider);
49
+ const contract = await (0, contractUtils_1.createContractWithSdkRpc)(gasRegistryContractAddress, GasRegistry_json_1.default, resolvedChainId, signer);
55
50
  // Get address from signer (this doesn't require provider)
56
51
  const address = await signer.getAddress();
57
52
  // Read balance using our RPC provider
package/dist/api/jobs.js CHANGED
@@ -372,7 +372,9 @@ async function createJob(client, params) {
372
372
  noOfExecutions = jobInput.timeFrame / (jobInput.timeInterval ?? 0);
373
373
  }
374
374
  // Set job_cost_prediction
375
- let job_cost_prediction = 0.1 * noOfExecutions; // default for static
375
+ // ethers.parseEther expects a string, so we construct the ether amount string safely
376
+ let job_cost_prediction = Number(ethers_1.ethers.parseEther((0.1 * noOfExecutions).toString()).toString()); // default for static
377
+ // console.log('job_cost_prediction', job_cost_prediction);
376
378
  if (argType === 2) {
377
379
  // Dynamic: call backend API to get fee
378
380
  const ipfs_url = jobInput.dynamicArgumentsScriptUrl;
@@ -383,6 +385,10 @@ async function createJob(client, params) {
383
385
  let fee = 0;
384
386
  try {
385
387
  const feeRes = await client.get('/api/fees', { params: { ipfs_url } });
388
+ // console.log('feeRes', feeRes);
389
+ // console.log('feeRes.total_fee', feeRes.total_fee);
390
+ // console.log('typeof feeRes', typeof feeRes);
391
+ // console.log('typeof feeRes.total_fee', typeof feeRes.total_fee);
386
392
  // The API now returns { total_fee: number }
387
393
  if (feeRes && typeof feeRes.total_fee === 'number') {
388
394
  fee = feeRes.total_fee;
@@ -399,8 +405,11 @@ async function createJob(client, params) {
399
405
  const errorCode = (0, errors_1.determineErrorCode)(err, httpStatusCode);
400
406
  return (0, errors_1.createErrorResponse)(new errors_1.ApiError('Failed to fetch job cost prediction', { originalError: err, ipfs_url }, httpStatusCode), 'API error');
401
407
  }
408
+ // console.log('fee', fee);
409
+ // console.log('noOfExecutions', noOfExecutions);
402
410
  job_cost_prediction = fee * noOfExecutions;
403
411
  }
412
+ // console.log('job_cost_prediction', job_cost_prediction);
404
413
  // Ask user if they want to proceed
405
414
  // Since this is a library, we can't prompt in Node.js directly.
406
415
  // We'll throw an error with the fee and let the caller handle the prompt/confirmation.
@@ -419,7 +428,7 @@ async function createJob(client, params) {
419
428
  catch (err) {
420
429
  return (0, errors_1.createErrorResponse)(new errors_1.BalanceError('Failed to check TG balance', { originalError: err }), 'Balance check error');
421
430
  }
422
- if (Number(tgBalance) < job_cost_prediction) {
431
+ if (Number(tgBalanceWei) < job_cost_prediction) {
423
432
  // Check if user has enabled auto topup
424
433
  // For each job type, autotopupTG should be present in jobInput
425
434
  const autoTopupTG = jobInput.autotopupTG === true;
@@ -434,6 +443,7 @@ async function createJob(client, params) {
434
443
  // autotopupTG is true, automatically top up
435
444
  const requiredTG = Math.ceil(job_cost_prediction); // 1 TG = 0.001 ETH
436
445
  try {
446
+ console.log('topping up TG balance', requiredTG);
437
447
  const topupResult = await (0, topupTg_1.topupTg)(requiredTG, signer);
438
448
  if (!topupResult.success) {
439
449
  return (0, errors_1.createErrorResponse)(new errors_1.BalanceError('Failed to top up TG balance', topupResult.details), 'Top-up error');
@@ -4,11 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.topupTg = void 0;
7
- const ethers_1 = require("ethers");
8
7
  const GasRegistry_json_1 = __importDefault(require("../contracts/abi/GasRegistry.json"));
9
- const config_1 = require("../config");
8
+ const contractUtils_1 = require("../contracts/contractUtils");
10
9
  const errors_1 = require("../utils/errors");
11
10
  const topupTg = async (tgAmount, signer) => {
11
+ console.log('topping up TG balance', tgAmount);
12
12
  // Validate inputs
13
13
  if (!tgAmount || tgAmount <= 0) {
14
14
  return (0, errors_1.createErrorResponse)(new errors_1.ValidationError('tgAmount', 'TG amount must be a positive number'), 'Validation error');
@@ -17,20 +17,66 @@ const topupTg = async (tgAmount, signer) => {
17
17
  return (0, errors_1.createErrorResponse)(new errors_1.ValidationError('signer', 'Signer is required'), 'Validation error');
18
18
  }
19
19
  try {
20
- const network = await signer.provider?.getNetwork();
21
- const chainId = network?.chainId ? network.chainId.toString() : undefined;
22
- const { gasRegistry } = (0, config_1.getChainAddresses)(chainId);
23
- const gasRegistryContractAddress = gasRegistry;
24
- if (!gasRegistryContractAddress) {
25
- return (0, errors_1.createErrorResponse)(new errors_1.ConfigurationError(`GasRegistry address not configured for chain ID: ${chainId}`), 'Configuration error');
20
+ // Get contract address and create contract instances with SDK RPC provider
21
+ // This ensures we can interact with the contract even if user's RPC fails
22
+ let gasRegistryContractAddress;
23
+ let contract;
24
+ let contractWithSigner;
25
+ let resolvedChainId;
26
+ let signerAddress;
27
+ try {
28
+ // Get signer address (this doesn't require the signer's provider to work)
29
+ signerAddress = await signer.getAddress();
30
+ // Resolve chain ID from signer
31
+ resolvedChainId = await (0, contractUtils_1.resolveChainId)(signer);
32
+ // Get contract address
33
+ gasRegistryContractAddress = (0, contractUtils_1.getContractAddress)(resolvedChainId, 'gasRegistry');
34
+ // Create contract instances with SDK RPC provider
35
+ const contractInstances = await (0, contractUtils_1.createContractWithSdkRpcAndSigner)(gasRegistryContractAddress, GasRegistry_json_1.default, signer, resolvedChainId);
36
+ contract = contractInstances.contract;
37
+ contractWithSigner = contractInstances.contractWithSigner;
38
+ }
39
+ catch (configError) {
40
+ if (configError instanceof errors_1.ConfigurationError) {
41
+ return (0, errors_1.createErrorResponse)(configError, 'Configuration error');
42
+ }
43
+ return (0, errors_1.createErrorResponse)(new errors_1.ConfigurationError('Failed to initialize contract', { originalError: configError }), 'Configuration error');
26
44
  }
27
- const contract = new ethers_1.ethers.Contract(gasRegistryContractAddress, GasRegistry_json_1.default, signer);
28
45
  // Each TG costs 0.001 ETH, so calculate the ETH required for the given TG amount
46
+ console.log('tgAmount', tgAmount);
29
47
  const amountInEthWei = tgAmount;
30
48
  // const amountInEthWei = ethers.parseEther(amountInEth.toString());
31
- const tx = await contract.purchaseTG(amountInEthWei, { value: amountInEthWei });
32
- await tx.wait();
33
- return { success: true, data: tx };
49
+ console.log('amountInEthWei', amountInEthWei);
50
+ // Estimate gas for the transaction using SDK RPC provider
51
+ // This ensures gas estimation works even if user's RPC fails
52
+ let estimatedGas;
53
+ try {
54
+ console.log('Estimating gas using SDK RPC provider...');
55
+ // Use contract instance with SDK RPC provider for estimation
56
+ // Specify the signer's address in the estimation options
57
+ estimatedGas = await contract.purchaseTG.estimateGas(amountInEthWei, {
58
+ value: amountInEthWei,
59
+ from: signerAddress // Specify the sender address for accurate estimation
60
+ });
61
+ console.log('Estimated gas (using SDK RPC):', estimatedGas.toString());
62
+ // Add 10% buffer to ensure transaction doesn't fail
63
+ const gasWithBuffer = (estimatedGas * BigInt(110)) / BigInt(100);
64
+ console.log('Gas with 10% buffer:', gasWithBuffer.toString());
65
+ // Execute transaction using signer (for signing)
66
+ const tx = await contractWithSigner.purchaseTG(amountInEthWei, {
67
+ value: amountInEthWei,
68
+ gasLimit: gasWithBuffer
69
+ });
70
+ await tx.wait();
71
+ return { success: true, data: tx };
72
+ }
73
+ catch (gasEstimateError) {
74
+ // If gas estimation fails, try without gas limit (let provider estimate)
75
+ console.warn('Gas estimation failed (using SDK RPC), proceeding without gas limit:', gasEstimateError);
76
+ const tx = await contractWithSigner.purchaseTG(amountInEthWei, { value: amountInEthWei });
77
+ await tx.wait();
78
+ return { success: true, data: tx };
79
+ }
34
80
  }
35
81
  catch (error) {
36
82
  console.error('Error topping up TG:', error);
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.withdrawTg = void 0;
7
7
  const ethers_1 = require("ethers");
8
8
  const GasRegistry_json_1 = __importDefault(require("../contracts/abi/GasRegistry.json"));
9
- const config_1 = require("../config");
9
+ const contractUtils_1 = require("../contracts/contractUtils");
10
10
  const errors_1 = require("../utils/errors");
11
11
  /**
12
12
  * Withdraw ETH in exchange for TG tokens.
@@ -23,17 +23,27 @@ const withdrawTg = async (signer, amountTG) => {
23
23
  return (0, errors_1.createErrorResponse)(new errors_1.ValidationError('amountTG', 'Amount must be a positive number'), 'Validation error');
24
24
  }
25
25
  try {
26
- const network = await signer.provider?.getNetwork();
27
- const chainId = network?.chainId ? network.chainId.toString() : undefined;
28
- const { gasRegistry } = (0, config_1.getChainAddresses)(chainId);
29
- const gasRegistryContractAddress = gasRegistry;
30
- if (!gasRegistryContractAddress) {
31
- return (0, errors_1.createErrorResponse)(new errors_1.ConfigurationError(`GasRegistry address not configured for chain ID: ${chainId}`), 'Configuration error');
26
+ // Resolve chain ID and create contract instances with SDK RPC provider
27
+ let resolvedChainId;
28
+ let contractWithSigner;
29
+ try {
30
+ // Resolve chain ID from signer
31
+ resolvedChainId = await (0, contractUtils_1.resolveChainId)(signer);
32
+ // Get contract address
33
+ const gasRegistryContractAddress = (0, contractUtils_1.getContractAddress)(resolvedChainId, 'gasRegistry');
34
+ // Create contract instances with SDK RPC provider
35
+ const contractInstances = await (0, contractUtils_1.createContractWithSdkRpcAndSigner)(gasRegistryContractAddress, GasRegistry_json_1.default, signer, resolvedChainId);
36
+ contractWithSigner = contractInstances.contractWithSigner;
37
+ }
38
+ catch (configError) {
39
+ if (configError instanceof errors_1.ConfigurationError) {
40
+ return (0, errors_1.createErrorResponse)(configError, 'Configuration error');
41
+ }
42
+ return (0, errors_1.createErrorResponse)(new errors_1.ConfigurationError('Failed to initialize contract', { originalError: configError }), 'Configuration error');
32
43
  }
33
- const contract = new ethers_1.ethers.Contract(gasRegistryContractAddress, GasRegistry_json_1.default, signer);
34
44
  // Assumes the contract has a function: claimEthForTg(uint256 amount)
35
45
  const amountTGWei = ethers_1.ethers.parseEther(amountTG.toString());
36
- const tx = await contract.claimETHForTG(amountTGWei);
46
+ const tx = await contractWithSigner.claimETHForTG(amountTGWei);
37
47
  await tx.wait();
38
48
  return { success: true, data: tx };
39
49
  }
package/dist/config.js CHANGED
@@ -75,7 +75,19 @@ function getRpcProvider(chainId) {
75
75
  if (!rpcUrl) {
76
76
  return null;
77
77
  }
78
- return new ethers_1.ethers.JsonRpcProvider(rpcUrl);
78
+ // Convert chainId to number for network configuration
79
+ const chainIdNum = chainId ? Number(chainId) : undefined;
80
+ if (!chainIdNum) {
81
+ // If no chainId, create provider without network (will auto-detect)
82
+ return new ethers_1.ethers.JsonRpcProvider(rpcUrl);
83
+ }
84
+ // Create a Network object with the chainId to explicitly set the network
85
+ // This prevents the provider from trying to auto-detect the network,
86
+ // which can cause timeouts when the RPC is slow or unresponsive
87
+ const network = ethers_1.ethers.Network.from(chainIdNum);
88
+ // Create provider with explicit network to skip network detection
89
+ // This prevents timeout issues when RPC is slow or unresponsive
90
+ return new ethers_1.ethers.JsonRpcProvider(rpcUrl, network);
79
91
  }
80
92
  function getChainAddresses(chainId) {
81
93
  const chainKey = String(chainId ?? '');
@@ -2,12 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createJobOnChain = createJobOnChain;
4
4
  exports.deleteJobOnChain = deleteJobOnChain;
5
- const ethers_1 = require("ethers");
5
+ const contractUtils_1 = require("./contractUtils");
6
6
  async function createJobOnChain({ jobTitle, jobType, timeFrame, targetContractAddress, encodedData, contractAddress, abi, signer, }) {
7
- const contract = new ethers_1.ethers.Contract(contractAddress, abi, signer);
8
- const tx = await contract.createJob(jobTitle, jobType, timeFrame, targetContractAddress, encodedData);
7
+ // Resolve chain ID and create contract with SDK RPC provider
8
+ const chainId = await (0, contractUtils_1.resolveChainId)(signer);
9
+ const { contract, contractWithSigner } = await (0, contractUtils_1.createContractWithSdkRpcAndSigner)(contractAddress, abi, signer, chainId);
10
+ // Use contractWithSigner for transaction (signing)
11
+ // Use contract for reading/parsing logs (SDK RPC)
12
+ const tx = await contractWithSigner.createJob(jobTitle, jobType, timeFrame, targetContractAddress, encodedData);
9
13
  const receipt = await tx.wait();
10
14
  // Try to extract jobId from event logs (assume event is JobCreated(jobId,...))
15
+ // Use contract (with SDK RPC) for parsing logs
11
16
  const event = receipt.logs
12
17
  .map((log) => {
13
18
  try {
@@ -24,7 +29,9 @@ async function createJobOnChain({ jobTitle, jobType, timeFrame, targetContractAd
24
29
  throw new Error('Job ID not found in contract events');
25
30
  }
26
31
  async function deleteJobOnChain({ jobId, contractAddress, abi, signer, }) {
27
- const contract = new ethers_1.ethers.Contract(contractAddress, abi.abi, signer);
28
- const tx = await contract.deleteJob(jobId);
32
+ // Resolve chain ID and create contract with SDK RPC provider
33
+ const chainId = await (0, contractUtils_1.resolveChainId)(signer);
34
+ const { contractWithSigner } = await (0, contractUtils_1.createContractWithSdkRpcAndSigner)(contractAddress, abi.abi || abi, signer, chainId);
35
+ const tx = await contractWithSigner.deleteJob(jobId);
29
36
  await tx.wait();
30
37
  }
@@ -0,0 +1,54 @@
1
+ import { ethers, Contract } from 'ethers';
2
+ /**
3
+ * Get SDK RPC provider for a given chain ID
4
+ * This ensures reliable connection even if user's RPC fails
5
+ * @param chainId - Chain ID as string or number
6
+ * @returns ethers.JsonRpcProvider instance
7
+ * @throws ConfigurationError if RPC provider is not available
8
+ */
9
+ export declare function getSdkRpcProvider(chainId: string | number | undefined): ethers.JsonRpcProvider;
10
+ /**
11
+ * Resolve chain ID from signer's provider or use provided chainId
12
+ * @param signer - ethers.Signer instance
13
+ * @param chainId - Optional chain ID (takes precedence if provided)
14
+ * @returns Resolved chain ID as string
15
+ * @throws ConfigurationError if chain ID cannot be resolved
16
+ */
17
+ export declare function resolveChainId(signer: ethers.Signer, chainId?: string | number): Promise<string>;
18
+ /**
19
+ * Create a contract instance with SDK RPC provider for read operations and gas estimation
20
+ * This ensures reliable contract interaction even if user's RPC fails
21
+ * @param contractAddress - Contract address
22
+ * @param abi - Contract ABI
23
+ * @param chainId - Chain ID (will be resolved if not provided)
24
+ * @param signer - Optional signer (used to resolve chainId if not provided)
25
+ * @returns Contract instance connected to SDK RPC provider
26
+ */
27
+ export declare function createContractWithSdkRpc(contractAddress: string, abi: any, chainId: string | number | undefined, signer?: ethers.Signer): Promise<Contract>;
28
+ /**
29
+ * Create a contract instance with SDK RPC provider and connect signer for transactions
30
+ * This pattern is used for operations that need:
31
+ * - SDK RPC for reads/estimations (reliable even if user's RPC fails)
32
+ * - User's signer for transaction signing
33
+ * @param contractAddress - Contract address
34
+ * @param abi - Contract ABI
35
+ * @param signer - Signer instance (used for signing transactions)
36
+ * @param chainId - Optional chain ID (will be resolved from signer if not provided)
37
+ * @returns Object containing:
38
+ * - contract: Contract instance with SDK RPC (for reads/estimations)
39
+ * - contractWithSigner: Contract instance connected to signer (for transactions)
40
+ * - chainId: Resolved chain ID
41
+ */
42
+ export declare function createContractWithSdkRpcAndSigner(contractAddress: string, abi: any, signer: ethers.Signer, chainId?: string | number): Promise<{
43
+ contract: Contract;
44
+ contractWithSigner: Contract;
45
+ chainId: string;
46
+ }>;
47
+ /**
48
+ * Get contract address for a given chain ID
49
+ * @param chainId - Chain ID as string or number
50
+ * @param contractType - Type of contract ('gasRegistry' | 'jobRegistry')
51
+ * @returns Contract address
52
+ * @throws ConfigurationError if contract address is not configured
53
+ */
54
+ export declare function getContractAddress(chainId: string | number | undefined, contractType: 'gasRegistry' | 'jobRegistry'): string;
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSdkRpcProvider = getSdkRpcProvider;
4
+ exports.resolveChainId = resolveChainId;
5
+ exports.createContractWithSdkRpc = createContractWithSdkRpc;
6
+ exports.createContractWithSdkRpcAndSigner = createContractWithSdkRpcAndSigner;
7
+ exports.getContractAddress = getContractAddress;
8
+ const ethers_1 = require("ethers");
9
+ const config_1 = require("../config");
10
+ const errors_1 = require("../utils/errors");
11
+ /**
12
+ * Get SDK RPC provider for a given chain ID
13
+ * This ensures reliable connection even if user's RPC fails
14
+ * @param chainId - Chain ID as string or number
15
+ * @returns ethers.JsonRpcProvider instance
16
+ * @throws ConfigurationError if RPC provider is not available
17
+ */
18
+ function getSdkRpcProvider(chainId) {
19
+ if (!chainId) {
20
+ throw new errors_1.ConfigurationError('Chain ID is required to get RPC provider');
21
+ }
22
+ const rpcProvider = (0, config_1.getRpcProvider)(chainId);
23
+ if (!rpcProvider) {
24
+ throw new errors_1.ConfigurationError(`RPC URL not configured for chain ID: ${chainId}`);
25
+ }
26
+ return rpcProvider;
27
+ }
28
+ /**
29
+ * Resolve chain ID from signer's provider or use provided chainId
30
+ * @param signer - ethers.Signer instance
31
+ * @param chainId - Optional chain ID (takes precedence if provided)
32
+ * @returns Resolved chain ID as string
33
+ * @throws ConfigurationError if chain ID cannot be resolved
34
+ */
35
+ async function resolveChainId(signer, chainId) {
36
+ // If chainId is provided, use it
37
+ if (chainId) {
38
+ return chainId.toString();
39
+ }
40
+ // Try to get chainId from signer's provider
41
+ try {
42
+ const network = await signer.provider?.getNetwork();
43
+ if (network?.chainId) {
44
+ return network.chainId.toString();
45
+ }
46
+ }
47
+ catch (providerError) {
48
+ // If user's RPC fails, we can't get chainId from it
49
+ console.warn('Could not get network from signer provider:', providerError);
50
+ }
51
+ throw new errors_1.ConfigurationError('Chain ID is required. Please provide chainId parameter or ensure signer has a working provider.');
52
+ }
53
+ /**
54
+ * Create a contract instance with SDK RPC provider for read operations and gas estimation
55
+ * This ensures reliable contract interaction even if user's RPC fails
56
+ * @param contractAddress - Contract address
57
+ * @param abi - Contract ABI
58
+ * @param chainId - Chain ID (will be resolved if not provided)
59
+ * @param signer - Optional signer (used to resolve chainId if not provided)
60
+ * @returns Contract instance connected to SDK RPC provider
61
+ */
62
+ async function createContractWithSdkRpc(contractAddress, abi, chainId, signer) {
63
+ // Resolve chain ID
64
+ let resolvedChainId;
65
+ if (chainId) {
66
+ resolvedChainId = chainId.toString();
67
+ }
68
+ else if (signer) {
69
+ resolvedChainId = await resolveChainId(signer);
70
+ }
71
+ else {
72
+ throw new errors_1.ConfigurationError('Chain ID or signer is required to create contract');
73
+ }
74
+ // Get SDK RPC provider
75
+ const rpcProvider = getSdkRpcProvider(resolvedChainId);
76
+ // Create contract instance with SDK RPC provider
77
+ return new ethers_1.ethers.Contract(contractAddress, abi, rpcProvider);
78
+ }
79
+ /**
80
+ * Create a contract instance with SDK RPC provider and connect signer for transactions
81
+ * This pattern is used for operations that need:
82
+ * - SDK RPC for reads/estimations (reliable even if user's RPC fails)
83
+ * - User's signer for transaction signing
84
+ * @param contractAddress - Contract address
85
+ * @param abi - Contract ABI
86
+ * @param signer - Signer instance (used for signing transactions)
87
+ * @param chainId - Optional chain ID (will be resolved from signer if not provided)
88
+ * @returns Object containing:
89
+ * - contract: Contract instance with SDK RPC (for reads/estimations)
90
+ * - contractWithSigner: Contract instance connected to signer (for transactions)
91
+ * - chainId: Resolved chain ID
92
+ */
93
+ async function createContractWithSdkRpcAndSigner(contractAddress, abi, signer, chainId) {
94
+ // Resolve chain ID
95
+ const resolvedChainId = await resolveChainId(signer, chainId);
96
+ // Get SDK RPC provider
97
+ const rpcProvider = getSdkRpcProvider(resolvedChainId);
98
+ // Create contract instance with SDK RPC provider (for reads/estimations)
99
+ const contract = new ethers_1.ethers.Contract(contractAddress, abi, rpcProvider);
100
+ // Connect signer to contract (for transactions)
101
+ const contractWithSigner = contract.connect(signer);
102
+ return {
103
+ contract,
104
+ contractWithSigner,
105
+ chainId: resolvedChainId,
106
+ };
107
+ }
108
+ /**
109
+ * Get contract address for a given chain ID
110
+ * @param chainId - Chain ID as string or number
111
+ * @param contractType - Type of contract ('gasRegistry' | 'jobRegistry')
112
+ * @returns Contract address
113
+ * @throws ConfigurationError if contract address is not configured
114
+ */
115
+ function getContractAddress(chainId, contractType) {
116
+ if (!chainId) {
117
+ throw new errors_1.ConfigurationError('Chain ID is required to get contract address');
118
+ }
119
+ const addresses = (0, config_1.getChainAddresses)(chainId);
120
+ const address = contractType === 'gasRegistry' ? addresses.gasRegistry : addresses.jobRegistry;
121
+ if (!address) {
122
+ throw new errors_1.ConfigurationError(`${contractType} address not configured for chain ID: ${chainId}`);
123
+ }
124
+ return address;
125
+ }
@@ -2,3 +2,4 @@ export * from './JobRegistry';
2
2
  export * from './safe/SafeFactory';
3
3
  export * from './safe/SafeWallet';
4
4
  export * from './TriggerXContract';
5
+ export * from './contractUtils';
@@ -19,3 +19,5 @@ __exportStar(require("./JobRegistry"), exports);
19
19
  __exportStar(require("./safe/SafeFactory"), exports);
20
20
  __exportStar(require("./safe/SafeWallet"), exports);
21
21
  __exportStar(require("./TriggerXContract"), exports);
22
+ // Contract utilities for RPC provider management
23
+ __exportStar(require("./contractUtils"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdk-triggerx",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "description": "SDK for interacting with the TriggerX backend and smart contracts.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",