We make
DeFi accessible
through Python
DeFi accessible
through Python
From data-sourcing over backtesting strategies to analytics — we cover your infrastructure needs in one simple Python package. No Solidity required.
Introducing Dojo
A Python interface for DeFi, enabling users to build and simulate strategies and contracts entirely on-premises before real-world deployment.
Use the this tool to explore the simulation. You can plot any 2 quantities against each other over time.
What does Dojo offer?
Data accessibility
Decipher history.
Access on-chain data of any smart contract and any historic block for data ingestion and strategy evaluation.
Python Interface
Smart contracts, simplified. Develop strategies in pure Python.
Seamlessly access DeFi with simple Python functions like aave_flashloan
or uniswap_trade
. Run arbitrary Python code, make API calls, and incorporate external data feeds, leveraging the full power of Python's ecosystem. No need to run a node or manage data pipelines — everything you need is readily available and easy to use.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@aave/protocol-v2/contracts/interfaces/IFlashLoanReceiver.sol";
import "@aave/protocol-v2/contracts/interfaces/ILendingPool.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract FlashLoanReceiver is IFlashLoanReceiver {
ILendingPool public lendingPool;
constructor(address _lendingPool) {
lendingPool = ILendingPool(_lendingPool);
}
function executeOperation(
address[] memory assets,
uint256[] memory amounts,
uint256[] memory premiums,
address initiator,
bytes memory params
) external override {
(address recipient) = abi.decode(params, (address));
for (uint256 i = 0; i < assets.length; i++) {
IERC20(assets[i]).transfer(recipient, amounts[i]);
}
for (uint256 i = 0; i < assets.length; i++) {
uint256 amountOwing = amounts[i] + premiums[i];
IERC20(assets[i]).approve(address(lendingPool), amountOwing);
}
}
function initiateFlashLoan(address[] memory assets, uint256[] memory amounts, bytes memory params) external {
lendingPool.flashLoan(address(this), assets, amounts, params);
}
}
const axios = require('axios');
async function fetchHistoricPrices(token0, token1, startTime, endTime) {
const query = `
{
pair(id: "${token0}-${token1}") {
token0 {
symbol
}
token1 {
symbol
}
token0Price
token1Price
token0PriceHistory(first: 1000, where: { timestamp_gte: ${startTime}, timestamp_lte: ${endTime} }, orderBy: timestamp, orderDirection: asc) {
price
timestamp
}
token1PriceHistory(first: 1000, where: { timestamp_gte: ${startTime}, timestamp_lte: ${endTime} }, orderBy: timestamp, orderDirection: asc) {
price
timestamp
}
}
}
`;
try {
const response = await axios.post('https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2', {
query: query
});
return response.data.data.pair;
} catch (error) {
console.error('Error fetching historic prices:', error);
return null;
}
}
// Example usage
const token0 = '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984'; // Token0 address (e.g., ETH)
const token1 = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'; // Token1 address (e.g., DAI)
const startTime = Math.floor((Date.now() - 7 * 24 * 60 * 60 * 1000) / 1000); // 7 days ago in Unix timestamp
const endTime = Math.floor(Date.now() / 1000); // Current time in Unix timestamp
fetchHistoricPrices(token0, token1, startTime, endTime)
.then(pairData => {
console.log(pairData);
})
.catch(error => {
console.error('Error:', error);
});
env = UniV3Env(
data_range = (2021-06-01, 2023-03-04)
)
env.load_data()
policy = [
AAVEv3FlashLoan(amount = 1_000_000),
Univ3Trade(pool = 'USDC-WETH', amount = 1_000_000),
Balv2Trade(pool = 'USDC-WETH', amount = 'max'),
AAVEv3FlashLoanRepay(amount = 1_000_000),
]
testnet.backtest_run(env, [policy])
sandbox.live_run(private_key = '0x0..', env, [policy])
Simulation Platform
Practice before you preach.
Test and train strategies and smart contracts through dojo’s agent-based simulator to simulate transactions at the EVM smart contract level.