RPC bundled simulations
Node RPC आपको blockchain डेटा पढ़ने और transactions भेजने की अनुमति देता है। लेकिन आप एक ही RPC URL के माध्यम से Node पर bundled transactions का simulation भी कर सकते हैं। RPC के माध्यम से Simulations केवल समर्थित नेटवर्क पर उपलब्ध हैं। यदि आपका नेटवर्क Node पर समर्थित नहीं है, तो इसके बजाय Simulation API के माध्यम से bundled simulations चलाएँ। RPC URL को Dashboard से प्राप्त करें। Node > इच्छित नेटवर्क का Copy HTTPS URL पर जाएँ।example
https://mainnet.gateway.tenderly.co/$TENDERLY_NODE_ACCESS_KEY
tenderly_simulateBundle विधि को कॉल करें। यह कस्टम विधि आपको कई transactions को एक array के रूप में पास करके simulation करने की अनुमति देती है। RPC reference देखें।
Transactions एक ही block में एक के बाद एक simulation किए जाते हैं।
- example
- response.json
example
curl https://mainnet.gateway.tenderly.co/$TENDERLY_NODE_ACCESS_KEY \
-X POST \
-H "Content-Type: application/json" \
-d \
'{
"id": 0,
"jsonrpc": "2.0",
"method": "tenderly_simulateBundle",
"params": [
[
{
"from": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"data": "0x40c10f19000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce10000000000000000000000000000000000000000000000001bc16d674ec80000"
},
{
"from": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"gas": "0x7a1200",
"data": "0x095ea7b3000000000000000000000000f7ddedc66b1d482e5c38e4730b3357d32411e5dd0000000000000000000000000000000000000000000000000de0b6b3a7640000"
},
{
"from": "0xf7ddedc66b1d482e5c38e4730b3357d32411e5dd",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"gas": "0x7a1200",
"data": "0x23b872dd000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce1000000000000000000000000bd8daa414fda8a8a129f7035e7496759c5af8570000000000000000000000000000000000000000000000000006a94d74f430000"
}
],
"latest",
{
"0x6b175474e89094c44da98b954eedeac495271d0f": {
"stateDiff": {
"0xedd7d04419e9c48ceb6055956cbb4e2091ae310313a4d1fa7cbcfe7561616e03": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
}
}
]
}'
response.json
{
"id": 0,
"jsonrpc": "2.0",
"result": [
{
"status": true,
"gasUsed": "0xd0d9",
"cumulativeGasUsed": "0x0",
"blockNumber": "0x121c950",
"type": "0x0",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000010000000020000000000000000000800000000000000000000000010000000000000000000004000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000020000000002000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000",
"logs": [
{
"name": "Transfer",
"anonymous": false,
"inputs": [
{
"value": "0x0000000000000000000000000000000000000000",
"type": "address",
"name": "src"
},
{
"value": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"type": "address",
"name": "dst"
},
{
"value": "2000000000000000000",
"type": "uint256",
"name": "wad"
}
],
"raw": {
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce1"
],
"data": "0x0000000000000000000000000000000000000000000000001bc16d674ec80000"
}
}
],
"trace": [
{
"type": "CALL",
"from": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"gas": "0xbeb6d8c",
"gasUsed": "0x7c65",
"value": "0x0",
"input": "0x40c10f19000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce10000000000000000000000000000000000000000000000001bc16d674ec80000",
"decodedInput": [
{
"value": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"type": "address",
"name": "usr"
},
{
"value": "2000000000000000000",
"type": "uint256",
"name": "wad"
}
],
"method": "mint",
"output": "0x",
"subtraces": 0,
"traceAddress": []
}
],
"assetChanges": [
{
"assetInfo": {
"standard": "ERC20",
"type": "Fungible",
"contractAddress": "0x6b175474e89094c44da98b954eedeac495271d0f",
"symbol": "dai",
"name": "Dai",
"logo": "https://assets.coingecko.com/coins/images/9956/large/Badge_Dai.webp?1696509996",
"decimals": 18,
"dollarValue": "0.9996880292892456"
},
"type": "Mint",
"to": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"rawAmount": "0x1bc16d674ec80000",
"amount": "2",
"dollarValue": "1.9993760585784912109"
}
],
"balanceChanges": [
{
"address": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"dollarValue": "1.9993760585784912109",
"transfers": [
0
]
}
]
},
{
"status": true,
"gasUsed": "0xb442",
"cumulativeGasUsed": "0x0",
"blockNumber": "0x121c950",
"type": "0x0",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000200000000000000000000000000008000000000000000000000000000000000000000010000000000000000000020000000000000000000000000000000000000000000000000000004000800000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000002000000000000000000000000100010000000000000000000000000000000000000000000000000000000000000",
"logs": [
{
"name": "Approval",
"anonymous": false,
"inputs": [
{
"value": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"type": "address",
"name": "src"
},
{
"value": "0xf7ddedc66b1d482e5c38e4730b3357d32411e5dd",
"type": "address",
"name": "guy"
},
{
"value": "1000000000000000000",
"type": "uint256",
"name": "wad"
}
],
"raw": {
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"topics": [
"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925",
"0x000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce1",
"0x000000000000000000000000f7ddedc66b1d482e5c38e4730b3357d32411e5dd"
],
"data": "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000"
}
}
],
"trace": [
{
"type": "CALL",
"from": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"gas": "0x79bd80",
"gasUsed": "0x5fc2",
"value": "0x0",
"input": "0x095ea7b3000000000000000000000000f7ddedc66b1d482e5c38e4730b3357d32411e5dd0000000000000000000000000000000000000000000000000de0b6b3a7640000",
"decodedInput": [
{
"value": "0xf7ddedc66b1d482e5c38e4730b3357d32411e5dd",
"type": "address",
"name": "usr"
},
{
"value": "1000000000000000000",
"type": "uint256",
"name": "wad"
}
],
"method": "approve",
"output": "0x0000000000000000000000000000000000000000000000000000000000000001",
"decodedOutput": [
{
"value": true,
"type": "bool",
"name": ""
}
],
"subtraces": 0,
"traceAddress": []
}
]
},
{
"status": true,
"gasUsed": "0xe38b",
"cumulativeGasUsed": "0x0",
"blockNumber": "0x121c950",
"type": "0x0",
"logsBloom": "0x00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000004000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000002000000000000000000020000000002000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000",
"logs": [
{
"name": "Transfer",
"anonymous": false,
"inputs": [
{
"value": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"type": "address",
"name": "src"
},
{
"value": "0xbd8daa414fda8a8a129f7035e7496759c5af8570",
"type": "address",
"name": "dst"
},
{
"value": "30000000000000000",
"type": "uint256",
"name": "wad"
}
],
"raw": {
"address": "0x6b175474e89094c44da98b954eedeac495271d0f",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce1",
"0x000000000000000000000000bd8daa414fda8a8a129f7035e7496759c5af8570"
],
"data": "0x000000000000000000000000000000000000000000000000006a94d74f430000"
}
}
],
"trace": [
{
"type": "CALL",
"from": "0xf7ddedc66b1d482e5c38e4730b3357d32411e5dd",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"gas": "0x79bc28",
"gasUsed": "0x8db3",
"value": "0x0",
"input": "0x23b872dd000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce1000000000000000000000000bd8daa414fda8a8a129f7035e7496759c5af8570000000000000000000000000000000000000000000000000006a94d74f430000",
"decodedInput": [
{
"value": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"type": "address",
"name": "src"
},
{
"value": "0xbd8daa414fda8a8a129f7035e7496759c5af8570",
"type": "address",
"name": "dst"
},
{
"value": "30000000000000000",
"type": "uint256",
"name": "wad"
}
],
"method": "transferFrom",
"output": "0x0000000000000000000000000000000000000000000000000000000000000001",
"decodedOutput": [
{
"value": true,
"type": "bool",
"name": ""
}
],
"subtraces": 0,
"traceAddress": []
}
],
"assetChanges": [
{
"assetInfo": {
"standard": "ERC20",
"type": "Fungible",
"contractAddress": "0x6b175474e89094c44da98b954eedeac495271d0f",
"symbol": "dai",
"name": "Dai",
"logo": "https://assets.coingecko.com/coins/images/9956/large/Badge_Dai.webp?1696509996",
"decimals": 18,
"dollarValue": "0.9996880292892456"
},
"type": "Transfer",
"from": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"to": "0xbd8daa414fda8a8a129f7035e7496759c5af8570",
"rawAmount": "0x6a94d74f430000",
"amount": "0.03",
"dollarValue": "0.029990640878677368163"
}
],
"balanceChanges": [
{
"address": "0xbd8daa414fda8a8a129f7035e7496759c5af8570",
"dollarValue": "0.029990640878677368163",
"transfers": [
0
]
},
{
"address": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"dollarValue": "-0.029990640878677368163",
"transfers": [
0
]
}
]
}
]
}
API bundled simulations
एक ही बार में कई लगातार transactions का simulation करने के लिएsimulate-bundle API एंडपॉइंट का उपयोग करें। API reference देखें।
example
https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_SLUG}/project/${TENDERLY_PROJECT_SLUG}/simulate-bundle
- Shell
- request.ts
curl --request POST \
--url https://api.tenderly.co/api/v1/account/me/project/project/simulate-bundle \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header "X-Access-Key: $TENDERLY_ACCESS_KEY" \
--data '{
"simulations": [
{
"network_id": "1",
"save": true,
"save_if_fails": true,
"simulation_type": "full",
"from": "0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"input": "0x40c10f19000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce10000000000000000000000000000000000000000000000001bc16d674ec80000",
"state_objects": {
"0x6b175474e89094c44da98b954eedeac495271d0f": {
"storage": {
"0xedd7d04419e9c48ceb6055956cbb4e2091ae310313a4d1fa7cbcfe7561616e03": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
}
}
},
{
"network_id": "1",
"save": true,
"save_if_fails": true,
"simulation_type": "full",
"from": "0xe58b9ee93700a616b50509c8292977fa7a0f8ce1",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"input": "0x095ea7b3000000000000000000000000f7ddedc66b1d482e5c38e4730b3357d32411e5dd0000000000000000000000000000000000000000000000000de0b6b3a7640000"
},
{
"network_id": "1",
"save": true,
"save_if_fails": true,
"simulation_type": "full",
"from": "0xf7ddedc66b1d482e5c38e4730b3357d32411e5dd",
"to": "0x6b175474e89094c44da98b954eedeac495271d0f",
"input": "0x23b872dd000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce1000000000000000000000000bd8daa414fda8a8a129f7035e7496759c5af8570000000000000000000000000000000000000000000000000006a94d74f430000"
}
]
}'
request.ts
dotenv.config();
// assuming environment variables TENDERLY_ACCOUNT_SLUG, TENDERLY_PROJECT_SLUG and TENDERLY_ACCESS_KEY are set
const { TENDERLY_ACCOUNT_SLUG, TENDERLY_PROJECT_SLUG, TENDERLY_ACCESS_KEY } = process.env;
const batchedSimulations = async () => {
console.time('Batch Simulation');
const daiSequence = (
await axios.post(
`https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_SLUG}/project/${TENDERLY_PROJECT_SLUG}/simulate-bundle`,
// the transaction
{
simulations: getTxSequence().map((transaction) => ({
network_id: '1', // network to simulate on
save: true,
save_if_fails: true,
simulation_type: 'full',
...transaction,
})),
},
{
headers: {
'X-Access-Key': TENDERLY_ACCESS_KEY as string,
},
},
)
).data;
console.timeEnd('Batch Simulation');
console.log(JSON.stringify(daiSequence, null, 2));
};
function getTxSequence() {
const fakeWardAddress = '0xe2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2e2';
const daiOwner = 'e58b9ee93700a616b50509c8292977fa7a0f8ce1';
const daiSpend = 'f7ddedc66b1d482e5c38e4730b3357d32411e5dd';
const daiRecip = 'e58b9ee93700a616b50509c8292977fa7a0f8ce1';
const daiContract = '0x6b175474e89094c44da98b954eedeac495271d0f';
return [
// TX1: Mint 2 DAI for e58b9ee93700a616b50509c8292977fa7a0f8ce1.
// Must do state override so sender (from) is considered a ward for this simulation
{
from: fakeWardAddress,
to: '0x6b175474e89094c44da98b954eedeac495271d0f',
input:
'0x40c10f19000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce10000000000000000000000000000000000000000000000001bc16d674ec80000',
// make 0xcace477c66b1f2e151974eeada9ac8b95a31c50593ae1db2f048f0a2b54c1424 a ward
state_objects: {
'0x6b175474e89094c44da98b954eedeac495271d0f': {
storage: {
'0xedd7d04419e9c48ceb6055956cbb4e2091ae310313a4d1fa7cbcfe7561616e03':
'0x0000000000000000000000000000000000000000000000000000000000000001',
},
},
},
},
// TX2: e58b9ee93700a616b50509c8292977fa7a0f8ce1 approves 1 DAI to f7ddedc66b1d482e5c38e4730b3357d32411e5dd
{
from: '0xe58b9ee93700a616b50509c8292977fa7a0f8ce1',
to: '0x6b175474e89094c44da98b954eedeac495271d0f',
input:
'0x095ea7b3000000000000000000000000f7ddedc66b1d482e5c38e4730b3357d32411e5dd0000000000000000000000000000000000000000000000000de0b6b3a7640000',
},
{
// TX3: 0xf7ddedc66b1d482e5c38e4730b3357d32411e5dd calls transferFrom to transfer 0.5 DAI belonging to e58b9ee93700a616b50509c8292977fa7a0f8ce1, sending them to e58b9ee93700a616b50509c8292977fa7a0f8ce1
from: '0xf7ddedc66b1d482e5c38e4730b3357d32411e5dd',
to: '0x6b175474e89094c44da98b954eedeac495271d0f',
input:
'0x23b872dd000000000000000000000000e58b9ee93700a616b50509c8292977fa7a0f8ce1000000000000000000000000bd8daa414fda8a8a129f7035e7496759c5af8570000000000000000000000000000000000000000000000000006a94d74f430000',
},
];
}
function getWardStorageLocation(wardAddress: string) {
// calculate the storage location of `wards[wardAddress]`
// yields 0xedd7d04419e9c48ceb6055956cbb4e2091ae310313a4d1fa7cbcfe7561616e03
return ethers.utils.keccak256(
ethers.utils.concat([
ethers.utils.hexZeroPad(wardAddress, 32), // the ward address (address 0x000..0) - mapping key
ethers.utils.hexZeroPad('0x0', 32), // the wards slot is 0th in the DAI contract - the mapping variable
]),
);
}
batchedSimulations();
उपयोग के मामले जानें
- Asset और balance परिवर्तन: होने वाले सभी balance और asset परिवर्तनों के लिए सटीक डॉलर मूल्य प्राप्त करें।
- Gas अनुमान: transaction भेजने से पहले gas लागतों की सटीक भविष्यवाणी करें।
- State overrides: विभिन्न परिदृश्यों का परीक्षण करने के लिए timestamps और contract डेटा जैसी blockchain स्थितियों को संशोधित करें।
- Transaction परिणामों का पूर्वावलोकन: उन समस्याओं की पहचान करें और उन्हें ठीक करें जो transactions को विफल कर सकती हैं।