sdk-triggerx 0.1.27 → 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.
- package/dist/api/checkTgBalance.d.ts +9 -1
- package/dist/api/checkTgBalance.js +37 -10
- package/dist/api/jobs.js +17 -8
- package/dist/api/topupTg.js +58 -12
- package/dist/api/withdrawTg.js +19 -9
- package/dist/config.d.ts +10 -0
- package/dist/config.js +33 -0
- package/dist/contracts/JobRegistry.js +12 -5
- package/dist/contracts/contractUtils.d.ts +54 -0
- package/dist/contracts/contractUtils.js +125 -0
- package/dist/contracts/index.d.ts +1 -0
- package/dist/contracts/index.js +2 -0
- package/package.json +1 -1
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { ethers } from 'ethers';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Check TG balance for a given signer using SDK-provided RPC
|
|
4
|
+
* This function uses our own RPC provider to ensure reliable connection
|
|
5
|
+
* even if the user's RPC fails
|
|
6
|
+
* @param signer - ethers.Signer instance (used to get wallet address)
|
|
7
|
+
* @param chainId - Optional chain ID. If not provided, will try to get from signer's provider
|
|
8
|
+
* @returns Balance information or error response
|
|
9
|
+
*/
|
|
10
|
+
export declare const checkTgBalance: (signer: ethers.Signer, chainId?: string | number) => Promise<{
|
|
3
11
|
success: boolean;
|
|
4
12
|
data?: {
|
|
5
13
|
tgBalanceWei: bigint;
|
|
@@ -6,23 +6,50 @@ 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
|
|
9
|
+
const contractUtils_1 = require("../contracts/contractUtils");
|
|
10
10
|
const errors_1 = require("../utils/errors");
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Check TG balance for a given signer using SDK-provided RPC
|
|
13
|
+
* This function uses our own RPC provider to ensure reliable connection
|
|
14
|
+
* even if the user's RPC fails
|
|
15
|
+
* @param signer - ethers.Signer instance (used to get wallet address)
|
|
16
|
+
* @param chainId - Optional chain ID. If not provided, will try to get from signer's provider
|
|
17
|
+
* @returns Balance information or error response
|
|
18
|
+
*/
|
|
19
|
+
const checkTgBalance = async (signer, chainId) => {
|
|
12
20
|
// Validate inputs
|
|
13
21
|
if (!signer) {
|
|
14
22
|
return (0, errors_1.createErrorResponse)(new errors_1.ValidationError('signer', 'Signer is required'), 'Validation error');
|
|
15
23
|
}
|
|
16
24
|
try {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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');
|
|
33
|
+
}
|
|
34
|
+
return (0, errors_1.createErrorResponse)(new errors_1.ConfigurationError('Failed to resolve chain ID', { originalError: configError }), 'Configuration error');
|
|
35
|
+
}
|
|
36
|
+
// Get contract address
|
|
37
|
+
let gasRegistryContractAddress;
|
|
38
|
+
try {
|
|
39
|
+
gasRegistryContractAddress = (0, contractUtils_1.getContractAddress)(resolvedChainId, 'gasRegistry');
|
|
40
|
+
}
|
|
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
|
+
}
|
|
47
|
+
// Create contract instance with SDK RPC provider (read-only)
|
|
48
|
+
// This ensures we can read balance even if user's RPC fails
|
|
49
|
+
const contract = await (0, contractUtils_1.createContractWithSdkRpc)(gasRegistryContractAddress, GasRegistry_json_1.default, resolvedChainId, signer);
|
|
50
|
+
// Get address from signer (this doesn't require provider)
|
|
25
51
|
const address = await signer.getAddress();
|
|
52
|
+
// Read balance using our RPC provider
|
|
26
53
|
const balance = await contract.balances(address);
|
|
27
54
|
// balance is likely an array or object with ethSpent and TGbalance, both in wei
|
|
28
55
|
// We'll convert TGbalance from wei to ETH
|
package/dist/api/jobs.js
CHANGED
|
@@ -16,8 +16,6 @@ const config_1 = require("../config");
|
|
|
16
16
|
const validation_1 = require("../utils/validation");
|
|
17
17
|
const errors_1 = require("../utils/errors");
|
|
18
18
|
const SafeWallet_1 = require("../contracts/safe/SafeWallet");
|
|
19
|
-
const JOB_ID = '300949528249665590178224313442040528409305273634097553067152835846309150732';
|
|
20
|
-
const DYNAMIC_ARGS_URL = 'https://teal-random-koala-993.mypinata.cloud/ipfs/bafkreif426p7t7takzhw3g6we2h6wsvf27p5jxj3gaiynqf22p3jvhx4la';
|
|
21
19
|
// Helper function to encode multisend batch transactions
|
|
22
20
|
function encodeMultisendData(transactions) {
|
|
23
21
|
// Multisend format: for each transaction, encode as:
|
|
@@ -55,7 +53,7 @@ function encodeMultisendData(transactions) {
|
|
|
55
53
|
}
|
|
56
54
|
function toCreateJobDataFromTime(input, balances, userAddress, jobCostPrediction) {
|
|
57
55
|
return {
|
|
58
|
-
job_id:
|
|
56
|
+
job_id: "",
|
|
59
57
|
user_address: userAddress,
|
|
60
58
|
ether_balance: balances.etherBalance,
|
|
61
59
|
token_balance: balances.tokenBalanceWei,
|
|
@@ -87,7 +85,7 @@ function toCreateJobDataFromTime(input, balances, userAddress, jobCostPrediction
|
|
|
87
85
|
}
|
|
88
86
|
function toCreateJobDataFromEvent(input, balances, userAddress, jobCostPrediction) {
|
|
89
87
|
return {
|
|
90
|
-
job_id:
|
|
88
|
+
job_id: "",
|
|
91
89
|
user_address: userAddress,
|
|
92
90
|
ether_balance: balances.etherBalance,
|
|
93
91
|
token_balance: balances.tokenBalanceWei,
|
|
@@ -118,7 +116,7 @@ function toCreateJobDataFromEvent(input, balances, userAddress, jobCostPredictio
|
|
|
118
116
|
}
|
|
119
117
|
function toCreateJobDataFromCondition(input, balances, userAddress, jobCostPrediction) {
|
|
120
118
|
return {
|
|
121
|
-
job_id:
|
|
119
|
+
job_id: "",
|
|
122
120
|
user_address: userAddress,
|
|
123
121
|
ether_balance: balances.etherBalance,
|
|
124
122
|
token_balance: balances.tokenBalanceWei,
|
|
@@ -374,7 +372,9 @@ async function createJob(client, params) {
|
|
|
374
372
|
noOfExecutions = jobInput.timeFrame / (jobInput.timeInterval ?? 0);
|
|
375
373
|
}
|
|
376
374
|
// Set job_cost_prediction
|
|
377
|
-
|
|
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);
|
|
378
378
|
if (argType === 2) {
|
|
379
379
|
// Dynamic: call backend API to get fee
|
|
380
380
|
const ipfs_url = jobInput.dynamicArgumentsScriptUrl;
|
|
@@ -385,6 +385,10 @@ async function createJob(client, params) {
|
|
|
385
385
|
let fee = 0;
|
|
386
386
|
try {
|
|
387
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);
|
|
388
392
|
// The API now returns { total_fee: number }
|
|
389
393
|
if (feeRes && typeof feeRes.total_fee === 'number') {
|
|
390
394
|
fee = feeRes.total_fee;
|
|
@@ -401,16 +405,20 @@ async function createJob(client, params) {
|
|
|
401
405
|
const errorCode = (0, errors_1.determineErrorCode)(err, httpStatusCode);
|
|
402
406
|
return (0, errors_1.createErrorResponse)(new errors_1.ApiError('Failed to fetch job cost prediction', { originalError: err, ipfs_url }, httpStatusCode), 'API error');
|
|
403
407
|
}
|
|
408
|
+
// console.log('fee', fee);
|
|
409
|
+
// console.log('noOfExecutions', noOfExecutions);
|
|
404
410
|
job_cost_prediction = fee * noOfExecutions;
|
|
405
411
|
}
|
|
412
|
+
// console.log('job_cost_prediction', job_cost_prediction);
|
|
406
413
|
// Ask user if they want to proceed
|
|
407
414
|
// Since this is a library, we can't prompt in Node.js directly.
|
|
408
415
|
// We'll throw an error with the fee and let the caller handle the prompt/confirmation.
|
|
409
416
|
// If you want to automate, you can add a `proceed` flag to params in the future.
|
|
410
417
|
// Check if the user has enough TG to cover the job cost prediction
|
|
418
|
+
// Use chainId if available, so we can use SDK RPC provider even if user's RPC fails
|
|
411
419
|
let tgBalanceWei, tgBalance;
|
|
412
420
|
try {
|
|
413
|
-
const balanceResult = await (0, checkTgBalance_1.checkTgBalance)(signer);
|
|
421
|
+
const balanceResult = await (0, checkTgBalance_1.checkTgBalance)(signer, chainIdStr);
|
|
414
422
|
if (!balanceResult.success || !balanceResult.data) {
|
|
415
423
|
return (0, errors_1.createErrorResponse)(new errors_1.BalanceError('Failed to check TG balance', balanceResult.details), 'Balance check error');
|
|
416
424
|
}
|
|
@@ -420,7 +428,7 @@ async function createJob(client, params) {
|
|
|
420
428
|
catch (err) {
|
|
421
429
|
return (0, errors_1.createErrorResponse)(new errors_1.BalanceError('Failed to check TG balance', { originalError: err }), 'Balance check error');
|
|
422
430
|
}
|
|
423
|
-
if (Number(
|
|
431
|
+
if (Number(tgBalanceWei) < job_cost_prediction) {
|
|
424
432
|
// Check if user has enabled auto topup
|
|
425
433
|
// For each job type, autotopupTG should be present in jobInput
|
|
426
434
|
const autoTopupTG = jobInput.autotopupTG === true;
|
|
@@ -435,6 +443,7 @@ async function createJob(client, params) {
|
|
|
435
443
|
// autotopupTG is true, automatically top up
|
|
436
444
|
const requiredTG = Math.ceil(job_cost_prediction); // 1 TG = 0.001 ETH
|
|
437
445
|
try {
|
|
446
|
+
console.log('topping up TG balance', requiredTG);
|
|
438
447
|
const topupResult = await (0, topupTg_1.topupTg)(requiredTG, signer);
|
|
439
448
|
if (!topupResult.success) {
|
|
440
449
|
return (0, errors_1.createErrorResponse)(new errors_1.BalanceError('Failed to top up TG balance', topupResult.details), 'Top-up error');
|
package/dist/api/topupTg.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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);
|
package/dist/api/withdrawTg.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
46
|
+
const tx = await contractWithSigner.claimETHForTG(amountTGWei);
|
|
37
47
|
await tx.wait();
|
|
38
48
|
return { success: true, data: tx };
|
|
39
49
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
1
2
|
export interface SDKConfig {
|
|
2
3
|
apiKey: string;
|
|
3
4
|
apiUrl: string;
|
|
@@ -9,8 +10,16 @@ export declare const CONTRACT_ADDRESSES_BY_CHAIN: Record<string, {
|
|
|
9
10
|
safeModule?: string;
|
|
10
11
|
safeSingleton?: string;
|
|
11
12
|
multisendCallOnly?: string;
|
|
13
|
+
rpcUrl?: string;
|
|
12
14
|
}>;
|
|
13
15
|
export declare function getConfig(): SDKConfig;
|
|
16
|
+
/**
|
|
17
|
+
* Get RPC provider for a given chain ID using SDK-configured RPC URLs
|
|
18
|
+
* This ensures reliable connection even if user's RPC fails
|
|
19
|
+
* @param chainId - Chain ID as string or number
|
|
20
|
+
* @returns ethers.JsonRpcProvider instance or null if chain not supported
|
|
21
|
+
*/
|
|
22
|
+
export declare function getRpcProvider(chainId: string | number | undefined): ethers.JsonRpcProvider | null;
|
|
14
23
|
export declare function getChainAddresses(chainId: string | number | undefined): {
|
|
15
24
|
gasRegistry: string;
|
|
16
25
|
jobRegistry: string;
|
|
@@ -18,4 +27,5 @@ export declare function getChainAddresses(chainId: string | number | undefined):
|
|
|
18
27
|
safeModule: string | undefined;
|
|
19
28
|
safeSingleton: string | undefined;
|
|
20
29
|
multisendCallOnly: string | undefined;
|
|
30
|
+
rpcUrl: string | undefined;
|
|
21
31
|
};
|
package/dist/config.js
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.CONTRACT_ADDRESSES_BY_CHAIN = void 0;
|
|
6
6
|
exports.getConfig = getConfig;
|
|
7
|
+
exports.getRpcProvider = getRpcProvider;
|
|
7
8
|
exports.getChainAddresses = getChainAddresses;
|
|
9
|
+
const ethers_1 = require("ethers");
|
|
8
10
|
// Contract addresses per chain
|
|
9
11
|
// Keyed by chainId as string to avoid bigint conversions throughout the SDK
|
|
10
12
|
exports.CONTRACT_ADDRESSES_BY_CHAIN = {
|
|
@@ -16,6 +18,7 @@ exports.CONTRACT_ADDRESSES_BY_CHAIN = {
|
|
|
16
18
|
safeFactory: '0x04359eDC46Cd6C6BD7F6359512984222BE10F8Be',
|
|
17
19
|
safeModule: '0xa0bC1477cfc452C05786262c377DE51FB8bc4669',
|
|
18
20
|
multisendCallOnly: '0x9641d764fc13c8B624c04430C7356C1C7C8102e2',
|
|
21
|
+
rpcUrl: 'https://sepolia.optimism.io',
|
|
19
22
|
},
|
|
20
23
|
// Ethereum Sepolia (11155111) - Ethereum Sepolia Testnet
|
|
21
24
|
'11155111': {
|
|
@@ -24,6 +27,7 @@ exports.CONTRACT_ADDRESSES_BY_CHAIN = {
|
|
|
24
27
|
safeFactory: '0xdf76E2A796a206D877086c717979054544B1D9Bc',
|
|
25
28
|
safeModule: '0xa0bC1477cfc452C05786262c377DE51FB8bc4669',
|
|
26
29
|
multisendCallOnly: '0x9641d764fc13c8B624c04430C7356C1C7C8102e2',
|
|
30
|
+
rpcUrl: 'https://rpc.sepolia.org',
|
|
27
31
|
},
|
|
28
32
|
// Arbitrum Sepolia (421614) - Arbitrum Sepolia Testnet
|
|
29
33
|
'421614': {
|
|
@@ -32,6 +36,7 @@ exports.CONTRACT_ADDRESSES_BY_CHAIN = {
|
|
|
32
36
|
safeFactory: '0x04359eDC46Cd6C6BD7F6359512984222BE10F8Be',
|
|
33
37
|
safeModule: '0xa0bC1477cfc452C05786262c377DE51FB8bc4669',
|
|
34
38
|
multisendCallOnly: '0x9641d764fc13c8B624c04430C7356C1C7C8102e2',
|
|
39
|
+
rpcUrl: 'https://sepolia-rollup.arbitrum.io/rpc',
|
|
35
40
|
// safeSingleton can be provided per deployment (Safe or SafeL2)
|
|
36
41
|
},
|
|
37
42
|
// Base Sepolia (84532) - Base Sepolia Testnet
|
|
@@ -41,6 +46,7 @@ exports.CONTRACT_ADDRESSES_BY_CHAIN = {
|
|
|
41
46
|
safeFactory: '0x04359eDC46Cd6C6BD7F6359512984222BE10F8Be',
|
|
42
47
|
safeModule: '0xa0bC1477cfc452C05786262c377DE51FB8bc4669',
|
|
43
48
|
multisendCallOnly: '0x9641d764fc13c8B624c04430C7356C1C7C8102e2',
|
|
49
|
+
rpcUrl: 'https://sepolia.base.org',
|
|
44
50
|
},
|
|
45
51
|
// MAINNET CONFIGURATIONS
|
|
46
52
|
// Arbitrum One (42161) - Mainnet
|
|
@@ -48,6 +54,7 @@ exports.CONTRACT_ADDRESSES_BY_CHAIN = {
|
|
|
48
54
|
gasRegistry: '0x93dDB2307F3Af5df85F361E5Cddd898Acd3d132d',
|
|
49
55
|
jobRegistry: '0xAf1189aFd1F1880F09AeC3Cbc32cf415c735C710',
|
|
50
56
|
multisendCallOnly: '0x9641d764fc13c8B624c04430C7356C1C7C8102e2',
|
|
57
|
+
rpcUrl: 'https://arb1.arbitrum.io/rpc',
|
|
51
58
|
},
|
|
52
59
|
// Default/fallbacks can be extended as needed for other networks
|
|
53
60
|
};
|
|
@@ -57,6 +64,31 @@ function getConfig() {
|
|
|
57
64
|
apiUrl: '',
|
|
58
65
|
};
|
|
59
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Get RPC provider for a given chain ID using SDK-configured RPC URLs
|
|
69
|
+
* This ensures reliable connection even if user's RPC fails
|
|
70
|
+
* @param chainId - Chain ID as string or number
|
|
71
|
+
* @returns ethers.JsonRpcProvider instance or null if chain not supported
|
|
72
|
+
*/
|
|
73
|
+
function getRpcProvider(chainId) {
|
|
74
|
+
const { rpcUrl } = getChainAddresses(chainId);
|
|
75
|
+
if (!rpcUrl) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
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);
|
|
91
|
+
}
|
|
60
92
|
function getChainAddresses(chainId) {
|
|
61
93
|
const chainKey = String(chainId ?? '');
|
|
62
94
|
const mapped = exports.CONTRACT_ADDRESSES_BY_CHAIN[chainKey];
|
|
@@ -67,5 +99,6 @@ function getChainAddresses(chainId) {
|
|
|
67
99
|
safeModule: mapped ? mapped.safeModule : '',
|
|
68
100
|
safeSingleton: mapped ? mapped.safeSingleton : '',
|
|
69
101
|
multisendCallOnly: mapped ? mapped.multisendCallOnly : '',
|
|
102
|
+
rpcUrl: mapped ? mapped.rpcUrl : '',
|
|
70
103
|
};
|
|
71
104
|
}
|
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createJobOnChain = createJobOnChain;
|
|
4
4
|
exports.deleteJobOnChain = deleteJobOnChain;
|
|
5
|
-
const
|
|
5
|
+
const contractUtils_1 = require("./contractUtils");
|
|
6
6
|
async function createJobOnChain({ jobTitle, jobType, timeFrame, targetContractAddress, encodedData, contractAddress, abi, signer, }) {
|
|
7
|
-
|
|
8
|
-
const
|
|
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
|
-
|
|
28
|
-
const
|
|
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
|
+
}
|
package/dist/contracts/index.js
CHANGED
|
@@ -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);
|