Skip to content

LinkageDevTeam/linkage-finance-python-tool

Repository files navigation

Linkage Finance Python Tool

A comprehensive Python tool for interacting with Linkage Finance smart contracts on Cardano. This tool enables developers to create funds, manage deposits and withdrawals, collect royalties, and perform other operations directly with the Linkage Finance protocol without depending on the Linkage Finance web interface.

What is Linkage Finance?

Linkage Finance is a decentralized protocol on Cardano that allows users to create index funds (baskets of tokens) with automatic rebalancing and royalty collection. Users can deposit tokens into funds and receive fund tokens representing their share, while fund creators earn royalties from trading activity.

Features

  • Fund Creation: Create custom index funds with your own token baskets and weights
  • Deposits & Withdrawals: Easily deposit tokens into funds and withdraw your share
  • Royalty Collection: Fund creators can collect accumulated royalties
  • Multiple Networks: Support for Mainnet, Preprod, and local Devnet
  • Wallet Integration: Multiple wallet loading options (mnemonic, keys, files)
  • Error Handling: Comprehensive error handling and transaction result reporting
  • Type Safety: Full type annotations for better development experience

Installation

Prerequisites

  • Python 3.8 or higher
  • Cardano node access (via Blockfrost for mainnet/preprod or local node for devnet)
  • Smart contract CBOR files (provided by Linkage Finance team)

Install from Source

  1. Clone this repository:
git clone https://github.com/linkage-finance/linkage-python-tool.git
cd linkage-python-tool
  1. Install dependencies:
pip install -r requirements.txt
  1. Install the package:
pip install -e .

Install from PyPI (when available)

pip install linkage-finance-tool

Setup

1. Get Smart Contract Files

Contact the Linkage Finance team to obtain the smart contract CBOR files. Create a contracts directory and organize them like this:

contracts/
├── free_mint/
│   └── script.cbor
├── linkage_authenticator_compressed/
│   └── script.cbor
├── linkage_factory_compressed/
│   └── script.cbor
└── linkage_authenticated_compressed/
    └── script.cbor

2. Get Blockfrost API Key (for Mainnet/Preprod)

  1. Go to blockfrost.io
  2. Create an account
  3. Create a new project
  4. Copy your API key

3. Prepare Your Wallet

You can use the tool with:

  • Mnemonic phrase (12-24 words)
  • Signing key (hex format)
  • Key files (cardano-cli format)
  • Generate new wallet (tool will create one for you)

Quick Start

Here's a simple example to get you started:

from linkage_tool import LinkageClient, NetworkConfig

# 1. Initialize client
client = LinkageClient(
    network=NetworkConfig.PREPROD,
    blockfrost_api_key="your_api_key_here",
    contracts_dir="./contracts"
)

# 2. Load your wallet
wallet = client.load_wallet_from_mnemonic(
    "your twelve word mnemonic phrase here for the wallet access"
)
print(f"Wallet address: {client.wallet_address}")

# 3. Set reference script address (provided by Linkage team)
client.set_reference_script_address("addr_test1qz...")

# 4. Create factory (one-time setup)
result = client.create_factory()
if result.success:
    print(f"Factory created! TX: {result.transaction_id}")

# 5. Mint test tokens
result = client.mint_test_tokens(num_tokens=5)
if result.success:
    print(f"Tokens minted! TX: {result.transaction_id}")

# 6. Create a fund
tokens = ["policy_id_hex" + "token1".encode().hex()]  # Your token list
result = client.create_fund(
    fund_name="MyFirstFund",
    tokens=tokens,
    factors=[1000],  # Token weights
    royalty_factor=3  # 3% royalty
)
if result.success:
    print(f"Fund created! TX: {result.transaction_id}")

Detailed Usage Guide

Setting Up the Client

from linkage_tool import LinkageClient, NetworkConfig

# For Preprod testnet (recommended for testing)
client = LinkageClient(
    network=NetworkConfig.PREPROD,
    blockfrost_api_key="preprod_api_key",
    contracts_dir="./contracts"
)

# For Mainnet (production)
client = LinkageClient(
    network=NetworkConfig.MAINNET,
    blockfrost_api_key="mainnet_api_key",
    contracts_dir="./contracts"
)

# For local devnet (development)
client = LinkageClient(
    network=NetworkConfig.DEVNET,
    contracts_dir="./contracts"
)

Loading Wallets

From Mnemonic Phrase

wallet = client.load_wallet_from_mnemonic(
    "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
)

From Signing Key

wallet = client.load_wallet_from_keys("your_signing_key_in_hex_format")

From Files (cardano-cli format)

wallet = client.load_wallet_from_files(
    skey_path="path/to/wallet.skey",
    vkey_path="path/to/wallet.vkey"  # optional
)

Generate New Wallet

wallet, mnemonic = client.generate_new_wallet()
print(f"New wallet created: {wallet}")
print(f"Mnemonic (save this!): {mnemonic}")

Working with Funds

Create a Fund

# Define your token basket
tokens = [
    "policy1_hex" + "btc".encode().hex(),
    "policy1_hex" + "eth".encode().hex(),
    "policy1_hex" + "ada".encode().hex(),
]

# Define token weights/factors
factors = [1000, 800, 2000]  # BTC: 1000, ETH: 800, ADA: 2000

# Create the fund
result = client.create_fund(
    fund_name="CryptoBasket",
    tokens=tokens,
    factors=factors,
    fund_token_factor=1000,  # Base factor for fund tokens
    royalty_factor=3  # 3% royalty on deposits
)

if result.success:
    print(f"Fund created successfully!")
    print(f"Transaction ID: {result.transaction_id}")
    fund_tx_id = result.transaction_id
else:
    print(f"Fund creation failed: {result.error_message}")

Deposit into a Fund

result = client.deposit_to_fund(
    fund_tx_hash=fund_tx_id,  # TX hash from fund creation
    deposit_multiple=1000  # Deposit 1000x the minimum amount
)

if result.success:
    print(f"Deposit successful! TX: {result.transaction_id}")
    new_fund_tx_id = result.transaction_id  # Fund UTXO moves to new TX

Withdraw from a Fund

result = client.withdraw_from_fund(
    fund_tx_hash=current_fund_tx_id,
    withdraw_multiple=500  # Withdraw 500x the minimum amount
)

if result.success:
    print(f"Withdrawal successful! TX: {result.transaction_id}")

Collect Royalties (Fund Creator Only)

# Check current balance first
balance = client.get_fund_balance(current_fund_tx_id)
if balance and balance.accrued_royalty > 0:
    result = client.collect_royalties(
        fund_tx_hash=current_fund_tx_id,
        collect_amount=balance.accrued_royalty  # Collect all royalties
    )
    
    if result.success:
        print(f"Royalties collected! TX: {result.transaction_id}")

Monitoring Funds

# Get fund balance and state
balance = client.get_fund_balance(fund_tx_id)
if balance:
    print(f"Fund tokens: {balance.fund_tokens}")
    print(f"Accrued royalties: {balance.accrued_royalty}")
    print(f"Underlying tokens: {balance.underlying_tokens}")

Error Handling

All operations return a TransactionResult object:

result = client.create_fund(...)

if result.success:
    print(f"Success! TX: {result.transaction_id}")
    print(f"Fee paid: {result.fee} lovelace")
else:
    print(f"Failed: {result.error_message}")

Advanced Features

Custom Token Configurations

# Create a fund with custom configuration
result = client.create_fund(
    fund_name="AdvancedFund",
    tokens=your_token_list,
    factors=your_custom_factors,
    fund_token_factor=2000,  # Custom fund token factor
    royalty_factor=5  # 5% royalty instead of default 3%
)

Network Information

info = client.get_network_info()
print(f"Network: {info['network']}")
print(f"Wallet: {info['wallet_address']}")
print(f"Reference scripts: {info['ref_script_address']}")

Contract Addresses

# Get the address of any contract
factory_addr = client.get_contract_address("linkage_factory", compressed=True)
fund_addr = client.get_contract_address("linkage_authenticated", compressed=True)

Examples

Basic Usage

See examples/basic_usage.py for a complete step-by-step example covering:

  • Setting up the client
  • Creating a factory
  • Minting test tokens
  • Creating and managing funds

Advanced Usage

See examples/advanced_usage.py for advanced patterns including:

  • Managing multiple funds
  • Batch operations
  • Error handling strategies
  • Portfolio monitoring
  • Automatic royalty collection

Network Considerations

  • Use PREPROD for testing and development
  • Only use MAINNET for production applications
  • Be aware of transaction fees and network congestion

Troubleshooting

Common Issues

"Reference script UTXO not found"

  • Make sure you've set the correct reference script address
  • Ensure the smart contracts have been deployed to that address
  • Check that you're on the correct network

"Insufficient funds"

  • Ensure your wallet has enough ADA for transaction fees
  • Check that you have the required tokens for deposits
  • Verify minimum UTXO requirements are met

Blockfrost API errors

  • Verify your API key is correct and active
  • Check you haven't exceeded rate limits
  • Ensure you're using the right API key for your network

Contributing

We welcome contributions! Please see our contributing guidelines for:

  • Code style requirements
  • Testing procedures
  • Pull request process
  • Bug reporting

About

Open Source Python Tool for Linkage Finance Smart Contract Interaction

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages