Skip to main content

defi-savings

Deposit USDC into Aave v3 on Base and let it accrue yield. The library is wallet-agnostic: bring your own signer.

Install

pip install defi-savings
# or
uv add defi-savings

Requires Python 3.11+.

Signers

The library separates what to call on Aave from how to sign the transaction. Pick the signer that matches your setup.

EOA

Single private key. Submits approve and supply as two sequential transactions.

from defi_savings import AaveProvider, EOASigner

provider = AaveProvider(
    EOASigner(
        private_key="0x...",
        rpc_url="https://mainnet.base.org",
    )
)

Gnosis Safe

2-of-N multisig. Batches approve and supply into one atomic MultiSend transaction. No gnosis-py dependency required.

from defi_savings import AaveProvider, GnosisSafeSigner

provider = AaveProvider(
    GnosisSafeSigner(
        safe_address="0x...",
        signer1_key="0x...",
        signer2_key="0x...",
        rpc_url="https://mainnet.base.org",
    )
)

Custom wallet

Implement three methods to support any signing setup: Coinbase MPC, Fireblocks, hardware signers, or anything else that can sign an Ethereum transaction.

from defi_savings import Signer, Call

class MyCoinbaseWalletSigner(Signer):
    @property
    def address(self) -> str:
        return "0x..."          # where the USDC lives

    @property
    def w3(self):
        return self._w3         # Web3 instance used for read-only calls

    def execute(self, calls: list[Call]) -> str:
        # sign and submit however your wallet works
        # return the tx hash
        ...

Usage

from decimal import Decimal

# Deposit $1000 USDC from the signer address into Aave
tx = provider.deposit(Decimal("1000"))

# Balance includes principal and all accrued yield
balance = provider.position_balance()   # Decimal("1004.823100")

# Live APY
apy = provider.current_apy()            # Decimal("4.82")

# Withdraw $500 back to the signer address
tx = provider.withdraw(Decimal("500"))

Provider methods are synchronous (Web3.py). In async code, wrap with asyncio.to_thread().

balance = await asyncio.to_thread(provider.position_balance)

Yield distribution

If multiple users share a single treasury, use distribute_yield to split accrued interest proportionally. It is a pure function with no I/O.

from defi_savings import AccountSnapshot, distribute_yield
from decimal import Decimal

snapshots = [
    AccountSnapshot("alice", balance=Decimal("1000"), last_snapshot=Decimal("1000")),
    AccountSnapshot("bob",   balance=Decimal("3000"), last_snapshot=Decimal("3000")),
]

distributions = distribute_yield(snapshots, provider.position_balance())
# [("alice", Decimal("25.000000")), ("bob", Decimal("75.000000"))]

After crediting each user, set last_snapshot = balance + yield_amt so the next run only measures new growth.

Custom protocols

Implement YieldProvider to use Morpho, Compound, or any other protocol. The signer stays the same.

from defi_savings import YieldProvider, Signer
from decimal import Decimal

class MorphoProvider(YieldProvider):
    name = "morpho-base"

    def __init__(self, signer: Signer): ...
    def deposit(self, amount_usdc: Decimal) -> str: ...
    def withdraw(self, amount_usdc: Decimal) -> str: ...
    def position_balance(self) -> Decimal: ...
    def current_apy(self) -> Decimal: ...

Running tests

uv sync --dev
pytest

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

defi_savings-0.1.0.tar.gz (11.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

defi_savings-0.1.0-py3-none-any.whl (12.6 kB view details)

Uploaded Python 3

File details

Details for the file defi_savings-0.1.0.tar.gz.

File metadata

  • Download URL: defi_savings-0.1.0.tar.gz
  • Upload date:
  • Size: 11.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.4

File hashes

Hashes for defi_savings-0.1.0.tar.gz
Algorithm Hash digest
SHA256 35598a9f6723602d1273dbdda339f82689af6156d03402f75ce78a7f68ef94b3
MD5 72347f21011d60157e3d072426332652
BLAKE2b-256 71cf92532d26e4222060f46ee7d52f1a848934571ad837140974dcf4b22c7e86

See more details on using hashes here.

File details

Details for the file defi_savings-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for defi_savings-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f3a15527ed4b76797694a76d98a2eff60d8ea652a5f7e396a3c75f8aaa6e14b9
MD5 c14bec6633bea6d8bba12f43ff813608
BLAKE2b-256 8641a3223c8fe53b8aea9276facdf64bf16e0d1a67a199c520ea45aec9913246

See more details on using hashes here.

Release history Release notifications | RSS feed

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page