• Stars
    star
    193
  • Rank 201,081 (Top 4 %)
  • Language
    Python
  • License
    GNU Affero Genera...
  • Created over 7 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Python API for Maker contracts

pymaker

Python API for Maker contracts.

Build Status

https://chat.makerdao.com/channel/keeper

Introduction

The DAI Stablecoin System incentivizes external agents, called keepers, to automate certain operations around the Ethereum blockchain. In order to ease their development, an API around most of the Maker contracts has been created. It can be used not only by keepers, but may also be found useful by authors of some other, unrelated utilities aiming to interact with these contracts.

Based on this API, a set of reference Maker keepers is being developed. They all used to reside in this repository, but now each of them has an individual one: bite-keeper (SCD only), arbitrage-keeper, auction-keeper (MCD only), cdp-keeper (SCD only), market-maker-keeper.

You only need to install this project directly if you want to build your own keepers, or if you want to play with this API library itself. If you just want to install one of reference keepers, go to one of the repositories linked above and start from there. Each of these keepers references some version of pymaker via a Git submodule.

Installation

This project uses Python 3.6.6.

In order to clone the project and install required third-party packages please execute:

git clone https://github.com/makerdao/pymaker.git
cd pymaker
pip3 install -r requirements.txt

Known Ubuntu issues

In order for the secp256k Python dependency to compile properly, following packages will need to be installed:

sudo apt-get install build-essential automake libtool pkg-config libffi-dev python-dev python-pip libsecp256k1-dev

(for Ubuntu 18.04 Server)

Known macOS issues

In order for the Python requirements to install correctly on macOS, please install openssl, libtool, pkg-config and automake using Homebrew:

brew install openssl libtool pkg-config automake

and set the LDFLAGS environment variable before you run pip3 install -r requirements.txt:

export LDFLAGS="-L$(brew --prefix openssl)/lib" CFLAGS="-I$(brew --prefix openssl)/include" 

Known node issues

  • pymaker has been tested against Parity/OpenEthereum and Geth. It has not been tested against Hyperledger Besu.
  • Many Ethereum node providers do not support the full JSON-RPC API. As such, certain JSON-RPC calls in __init__.py may not function properly.
  • Some node providers only support certain calls using websocket endpoints. Unfortunately, Web3.py's WebsocketProvider does not support multiple threads awaiting a response from the websocket, breaking some core pymaker functionality in Lifecycle and Transact classes.
  • When using an Infura node to pull event logs, ensure your requests are batched into a small enough chunks such that no more than 10,000 results will be returned for each request.
  • Asynchronous submission of simultaneous transactions often doesn't work on third-party node providers because RPC calls to parity_nextNonce and getTransactionCount are inappropriately proxied, cached, or just plain not supported. To remedy this, a serial-incrementing nonce is used for these providers' URLs. The downside to a serial- incrementing nonce is that transactions submitted for the same account from another wallet or keeper will bring the next nonce out-of-alignment, causing transaction failures or unexpected replacements. To work around this, stop the application, wait for pending transactions for the account to be mined, and then restart the application.
  • Recovery of pending transactions does not work on certain third-party node providers.

Available APIs

The current version provides APIs around:

APIs around the following functionality have not been implemented:

  • Governance (DSAuth, DSGuard, DSSpell, Mom)

Contributions from the community are appreciated.

Code samples

Below you can find some code snippets demonstrating how the API can be used both for developing your own keepers and for creating some other utilities interacting with the DAI Stablecoin ecosystem contracts.

Token transfer

This snippet demonstrates how to transfer some SAI from our default address. The SAI token address is discovered by querying the Tub, so all we need as a Tub address:

from web3 import HTTPProvider, Web3

from pymaker import Address
from pymaker.token import ERC20Token
from pymaker.numeric import Wad
from pymaker.sai import Tub


web3 = Web3(HTTPProvider(endpoint_uri="http://localhost:8545"))

tub = Tub(web3=web3, address=Address('0xb7ae5ccabd002b5eebafe6a8fad5499394f67980'))
sai = ERC20Token(web3=web3, address=tub.sai())

sai.transfer(address=Address('0x0000000000111111111100000000001111111111'),
             value=Wad.from_number(10)).transact()

Updating a DSValue

This snippet demonstrates how to update a DSValue with the ETH/USD rate pulled from CryptoCompare:

import json
import urllib.request

from web3 import HTTPProvider, Web3

from pymaker import Address
from pymaker.feed import DSValue
from pymaker.numeric import Wad


def cryptocompare_rate() -> Wad:
    with urllib.request.urlopen("https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD") as url:
        data = json.loads(url.read().decode())
        return Wad.from_number(data['USD'])


web3 = Web3(HTTPProvider(endpoint_uri="http://localhost:8545"))

dsvalue = DSValue(web3=web3, address=Address('0x038b3d8288df582d57db9be2106a27be796b0daf'))
dsvalue.poke_with_int(cryptocompare_rate().value).transact()

SAI introspection

This snippet demonstrates how to fetch data from Tub and Tap contracts:

from web3 import HTTPProvider, Web3

from pymaker import Address
from pymaker.token import ERC20Token
from pymaker.numeric import Ray
from pymaker.sai import Tub, Tap


web3 = Web3(HTTPProvider(endpoint_uri="http://localhost:8545"))

tub = Tub(web3=web3, address=Address('0x448a5065aebb8e423f0896e6c5d525c040f59af3'))
tap = Tap(web3=web3, address=Address('0xbda109309f9fafa6dd6a9cb9f1df4085b27ee8ef'))
sai = ERC20Token(web3=web3, address=tub.sai())
skr = ERC20Token(web3=web3, address=tub.skr())
gem = ERC20Token(web3=web3, address=tub.gem())

print(f"")
print(f"Token summary")
print(f"-------------")
print(f"SAI total supply       : {sai.total_supply()} SAI")
print(f"SKR total supply       : {skr.total_supply()} SKR")
print(f"GEM total supply       : {gem.total_supply()} GEM")
print(f"")
print(f"Collateral summary")
print(f"------------------")
print(f"GEM collateral         : {tub.pie()} GEM")
print(f"SKR collateral         : {tub.air()} SKR")
print(f"SKR pending liquidation: {tap.fog()} SKR")
print(f"")
print(f"Debt summary")
print(f"------------")
print(f"Debt ceiling           : {tub.cap()} SAI")
print(f"Good debt              : {tub.din()} SAI")
print(f"Bad debt               : {tap.woe()} SAI")
print(f"Surplus                : {tap.joy()} SAI")
print(f"")
print(f"Feed summary")
print(f"------------")
print(f"REF per GEM feed       : {tub.pip()}")
print(f"REF per SKR price      : {tub.tag()}")
print(f"GEM per SKR price      : {tub.per()}")
print(f"")
print(f"Tub parameters")
print(f"--------------")
print(f"Liquidation ratio      : {tub.mat()*100} %")
print(f"Liquidation penalty    : {tub.axe()*100 - Ray.from_number(100)} %")
print(f"Stability fee          : {tub.tax()} %")
print(f"")
print(f"All cups")
print(f"--------")
for cup_id in range(1, tub.cupi()+1):
    cup = tub.cups(cup_id)
    print(f"Cup #{cup_id}, lad={cup.lad}, ink={cup.ink} SKR, tab={tub.tab(cup_id)} SAI, safe={tub.safe(cup_id)}")

Multi-collateral Dai

This snippet demonstrates how to create a CDP and draw Dai.

import sys
from web3 import Web3, HTTPProvider

from pymaker import Address
from pymaker.deployment import DssDeployment
from pymaker.keys import register_keys
from pymaker.numeric import Wad


web3 = Web3(HTTPProvider(endpoint_uri="https://localhost:8545",
                         request_kwargs={"timeout": 10}))
web3.eth.defaultAccount = sys.argv[1]   # ex: 0x0000000000000000000000000000000aBcdef123
register_keys(web3, [sys.argv[2]])      # ex: key_file=~keys/default-account.json,pass_file=~keys/default-account.pass

mcd = DssDeployment.from_json(web3=web3, conf=open("tests/config/kovan-addresses.json", "r").read())
our_address = Address(web3.eth.defaultAccount)


# Choose the desired collateral; in this case we'll wrap some Eth
collateral = mcd.collaterals['ETH-A']
ilk = collateral.ilk
collateral.gem.deposit(Wad.from_number(3)).transact()

# Add collateral and allocate the desired amount of Dai
collateral.approve(our_address)
collateral.adapter.join(our_address, Wad.from_number(3)).transact()
mcd.vat.frob(ilk, our_address, dink=Wad.from_number(3), dart=Wad.from_number(153)).transact()
print(f"CDP Dai balance before withdrawal: {mcd.vat.dai(our_address)}")

# Mint and withdraw our Dai
mcd.approve_dai(our_address)
mcd.dai_adapter.exit(our_address, Wad.from_number(153)).transact()
print(f"CDP Dai balance after withdrawal:  {mcd.vat.dai(our_address)}")

# Repay (and burn) our Dai
assert mcd.dai_adapter.join(our_address, Wad.from_number(153)).transact()
print(f"CDP Dai balance after repayment:   {mcd.vat.dai(our_address)}")

# Withdraw our collateral
mcd.vat.frob(ilk, our_address, dink=Wad(0), dart=Wad.from_number(-153)).transact()
mcd.vat.frob(ilk, our_address, dink=Wad.from_number(-3), dart=Wad(0)).transact()
collateral.adapter.exit(our_address, Wad.from_number(3)).transact()
print(f"CDP Dai balance w/o collateral:    {mcd.vat.dai(our_address)}")

Asynchronous invocation of Ethereum transactions

This snippet demonstrates how multiple token transfers can be executed asynchronously:

from web3 import HTTPProvider
from web3 import Web3

from pymaker import Address, synchronize
from pymaker.numeric import Wad
from pymaker.sai import Tub
from pymaker.token import ERC20Token


web3 = Web3(HTTPProvider(endpoint_uri="http://localhost:8545"))

tub = Tub(web3=web3, address=Address('0x448a5065aebb8e423f0896e6c5d525c040f59af3'))
sai = ERC20Token(web3=web3, address=tub.sai())
skr = ERC20Token(web3=web3, address=tub.skr())

synchronize([sai.transfer(Address('0x0101010101020202020203030303030404040404'), Wad.from_number(1.5)).transact_async(),
             skr.transfer(Address('0x0303030303040404040405050505050606060606'), Wad.from_number(2.5)).transact_async()])

Multiple invocations in one Ethereum transaction

This snippet demonstrates how multiple token transfers can be executed in one Ethereum transaction. A TxManager instance has to be deployed and owned by the caller.

from web3 import HTTPProvider
from web3 import Web3

from pymaker import Address
from pymaker.approval import directly
from pymaker.numeric import Wad
from pymaker.sai import Tub
from pymaker.token import ERC20Token
from pymaker.transactional import TxManager


web3 = Web3(HTTPProvider(endpoint_uri="http://localhost:8545"))

tub = Tub(web3=web3, address=Address('0x448a5065aebb8e423f0896e6c5d525c040f59af3'))
sai = ERC20Token(web3=web3, address=tub.sai())
skr = ERC20Token(web3=web3, address=tub.skr())

tx = TxManager(web3=web3, address=Address('0x57bFE16ae8fcDbD46eDa9786B2eC1067cd7A8f48'))
tx.approve([sai, skr], directly())

tx.execute([sai.address, skr.address],
           [sai.transfer(Address('0x0101010101020202020203030303030404040404'), Wad.from_number(1.5)).invocation(),
            skr.transfer(Address('0x0303030303040404040405050505050606060606'), Wad.from_number(2.5)).invocation()]).transact()

Ad-hoc increasing of gas price for asynchronous transactions

import asyncio
from random import randint

from web3 import Web3, HTTPProvider

from pymaker import Address
from pymaker.gas import FixedGasPrice
from pymaker.oasis import SimpleMarket


web3 = Web3(HTTPProvider(endpoint_uri=f"http://localhost:8545"))
otc = SimpleMarket(web3=web3, address=Address('0x375d52588c3f39ee7710290237a95C691d8432E7'))


async def bump_with_increasing_gas_price(order_id):
    gas_price = FixedGasPrice(gas_price=1000000000)
    task = asyncio.ensure_future(otc.bump(order_id).transact_async(gas_price=gas_price))

    while not task.done():
        await asyncio.sleep(1)
        gas_price.update_gas_price(gas_price.gas_price + randint(0, gas_price.gas_price))

    return task.result()


bump_task = asyncio.ensure_future(bump_with_increasing_gas_price(otc.get_orders()[-1].order_id))
event_loop = asyncio.get_event_loop()
bump_result = event_loop.run_until_complete(bump_task)

print(bump_result)
print(bump_result.transaction_hash)

Testing

Prerequisites:

This project uses pytest for unit testing. Testing of Multi-collateral Dai is performed on a Dockerized local testchain included in tests\config.

In order to be able to run tests, please install development dependencies first by executing:

pip3 install -r requirements-dev.txt

You can then run all tests with:

./test.sh

By default, pymaker will not send a transaction to the chain if gas estimation fails, because this means the transaction would revert. For testing purposes, it is sometimes useful to send bad transactions to the chain. To accomplish this, set class variable gas_estimate_for_bad_txs in your application. For example:

from pymaker import Transact
Transact.gas_estimate_for_bad_txs = 200000

License

See COPYING file.

More Repositories

1

multicall

Multicall: Aggregate multiple constant function call results into one
Solidity
811
star
2

awesome-makerdao

A collection of tools, documents, articles, blog posts, interviews, and videos related to MakerDAO and the Dai stablecoin.
688
star
3

dss

Dai Stablecoin System
Solidity
673
star
4

developerguides

Developer guides to integrate with MakerDAO's smart contracts, SDKs, APIs, products, and partners
Shell
641
star
5

market-maker-keeper

Maker Keeper Framework: Market maker keepers for OasisDEX, EtherDelta, 0x (RadarRelay, ERCdEX), Paradex, DDEX, IDEX, Bibox, Ethfinex, GoPax, HitBTC, TheOcean, OKEX and Gate.io.
Python
452
star
6

multicall.js

Multicall.js: A JavaScript blockchain state management library for dapps
JavaScript
410
star
7

community

Contains current and historical governance polls and executives used in the governance of the Maker Protocol. Previously contained a lot of other content which remains in the 'prior-cleanup' branch.
MDX
183
star
8

sai

Single Collateral Dai
Solidity
160
star
9

auction-keeper

Maker Keeper Framework: Keeper to participate in `flip`, `flop` and `flap` auctions in multicollateral Dai.
Python
120
star
10

arbitrage-keeper

Maker Keeper Framework: Keeper to arbitrage on OasisDEX, `join`, `exit`, `boom` and `bust`. Efficiently handles both bad debt liquidations and surplus Dai.
Python
115
star
11

spells-mainnet

Staging repo for MakerDAO weekly executive spells
Solidity
114
star
12

starknet-dai-bridge

TypeScript
98
star
13

dai.js

JavaScript
97
star
14

simple-arbitrage-keeper

Arbitrage Keeper on OasisDEX and Uniswap V1
Python
88
star
15

dss-teleport

Solidity
81
star
16

pyexchange

Python API for some cryptocurrency exchanges
Python
75
star
17

optimism-dai-bridge

Optimism Dai and upgradable token bridge
TypeScript
72
star
18

dss-proxy-actions

Set of proxy functions for MCD (using mcd-cdp-handler)
Solidity
72
star
19

dss-deploy

Set of smart contracts and bash scripts to deploy Multi collateral DAI
Solidity
66
star
20

tx-manager

Solidity contract to make multiple calls in one Ethereum transaction. Used by Maker keepers.
Makefile
66
star
21

mips

Maker Improvement Proposals (MIPs)
63
star
22

spells-goerli

Solidity
58
star
23

dss-direct-deposit

Solidity
57
star
24

integration-examples

A set of examples of how to use the DAI.js library with various purposes and configs
JavaScript
56
star
25

oracles-v2

Nix
50
star
26

bite-keeper

Maker Keeper Framework: Keeper to bite undercollateralized cups.
Python
49
star
27

dss-deploy-scripts

Shell
47
star
28

dss-flash

MakerDAO Flash Mint Module
Solidity
47
star
29

governance-portal-v2

Governance Portal V2
TypeScript
46
star
30

mips-best-practices

A collection of best practices and code samples for technical Maker Improvement Proposals (MIPs).
Solidity
44
star
31

endgame-toolkit

Smart contract modules to enable MakerDAO Endgame.
Solidity
42
star
32

dss-exec-lib

DSS Executive Spellcrafting Library Contracts
Solidity
37
star
33

market-maker-stats

Maker Keeper Framework: Set of tools to analyze market maker keepers performance.
Python
33
star
34

testchain

Start a local test chain with the MakerDAO contracts deployed on it, quickly and easily.
Shell
33
star
35

dss-conduits

Solidity
33
star
36

dss-kiln

Slow burner for protocol assets.
Solidity
33
star
37

dss-interfaces

Abstract developer interfaces to the Dai Stablecoin System core contracts.
Solidity
33
star
38

price-feed

price feed, with expiration and medianizer poke
Solidity
32
star
39

sdai

A tokenized wrapper around the DSR.
Solidity
31
star
40

univ3-lp-oracle

Solidity
31
star
41

dss-vest

Solidity
31
star
42

exchange-callees

Exchange Callee contracts for LIQ2.0 Flash Loans
Solidity
30
star
43

uniswap-price-feed

Python
30
star
44

auction-demo-keeper

JavaScript
30
star
45

evm

Shell
28
star
46

cdp-keeper

Maker Keeper Framework: Keeper to actively manage open CDPs.
Python
28
star
47

lockstake

Solidity
27
star
48

btc-market

Trade bitcoins for tokens via btc-relay
27
star
49

mkr-mcd-spec

High level KSpecification for the MCD System by Runtime Verification and Maker Foundation
Python
27
star
50

dss-gem-joins

Solidity
25
star
51

arbitrum-dai-bridge

TypeScript
25
star
52

dss-cdp-manager

Solidity
25
star
53

dss-allocator

Solidity
24
star
54

governance-portal

Governance Portal
JavaScript
24
star
55

mcd-changelog

Multi-Collateral DAI Public Releases Page
HTML
24
star
56

univ2-lp-oracle

Solidity
23
star
57

ilk-registry

A publicly-modifiable registry of ilks in the Dai Stablecoin System.
Solidity
22
star
58

scd-cdp-portal

Single-Collateral Dai CDP Portal
JavaScript
21
star
59

dss-proxy

Solidity
21
star
60

dockerized-auction-keeper

Shell
21
star
61

token-auction

Continuous Splitting Token Auction
Makefile
21
star
62

osm

Feed with 1 hour delay
Solidity
21
star
63

simplecoin1

Something to play with while we wait
Makefile
20
star
64

setzer

manipulate feeds
Shell
20
star
65

sky

Python
19
star
66

xdomain

TypeScript
19
star
67

medianizer

Returns median value of several DSValue, DSCache or other Medianizers
Solidity
18
star
68

mcd-cli

MCD Command-line interface
Shell
18
star
69

dss-bridge

18
star
70

curve-lp-oracle

Solidity
17
star
71

dai-ui

JavaScript
16
star
72

dss-crop-join

Solidity
16
star
73

petrometer

Tool which summarizes daily and total gas consumption of all transactions sent from a specified Ethereum address.
Python
16
star
74

plunger

Tool for overriding Ethereum transactions stuck in the pool
Python
16
star
75

esm

Emergency Shutdown Module
Solidity
16
star
76

governance-manual

Welcome to the Maker Operational Manual. This set of documents intends to acquaint MKR Holders with the voting process and to serve as reference material for them to consult during the day-to-day operation of the protocol.
16
star
77

median

Medianizer 2
Solidity
15
star
78

MIP21-RWA-Example

MIP21 example
Solidity
14
star
79

dss-lite-psm

14
star
80

dss-charter

Solidity
13
star
81

spells-kovan

Solidity
12
star
82

dai-cli

SCD Command-line interface
Shell
12
star
83

redeem

UI for redeeming MKR tokens
JavaScript
12
star
84

rwa-toolkit

SW Repo; Content Manager: CES-001; MIP21 Toolkit: Equipment for Off-chain Asset Backed Lending in MakerDAO
Solidity
12
star
85

dss-cron

Solidity
12
star
86

dss-chain-log

Simple way to track the mcd changelog on-chain.
Solidity
12
star
87

proxy-registry

This Registry deploys new proxy instances through DSProxyFactory and keeps a registry of owner => proxy
Solidity
12
star
88

oracle-suite

Go
11
star
89

dss-test

Solidity
11
star
90

univ2-pool-migrator

Solidity
11
star
91

megapoker

Smart contract to poke and drip
Solidity
10
star
92

token-faucet

Mostly well behaved ERC20s faucet
Solidity
10
star
93

vote-proxy

ds-chief mkr proxy voting with a hot/cold wallet
Solidity
10
star
94

scd-mcd-migration

Solidity
9
star
95

dss-darkspell

spell to conceal bug fix source and bytecode during pause delay
Solidity
9
star
96

nst

Ruby
9
star
97

protego

Solidity
9
star
98

wormhole-integration-tests

Gathers all related repos and runs a suite of integration tests using forked networks.
TypeScript
9
star
99

mcd-security

The Maker Foundation's highest priority is the security of the Maker protocol. This repository is dedicated to providing transparency to our community with respect to the results of our MCD Audits and our Bug Bounty Program results.
9
star
100

vulcan0x

SCD GraphQL API
PLpgSQL
8
star