Gemini

[Layer.zip (updated for deposits) generated from Docker allows you to use gemini Python library when uploaded as a Layer in AWS - instructions for how to generate your own here: https://dev.to/mmascioni/using-external-python-packages-with-aws-lambda-layers-526o](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/04373a20-8a41-41e1-aff3-97ec40c278a2/layer.zip)

Layer.zip (updated for deposits) generated from Docker allows you to use gemini Python library when uploaded as a Layer in AWS - instructions for how to generate your own here: https://dev.to/mmascioni/using-external-python-packages-with-aws-lambda-layers-526o

FAQs: https://rhett.blog/2021/07/08/gemini-api-faqs/

Extra Code for DEVS: https://github.com/TheTallMan67/Gemini-API-Functions-for-AWS

Original Python Library: https://github.com/mtusman/gemini-python

Buy Bitcoin from Gemini

import json
import gemini

public_key = ""  
private_key = ""
symbol = "BTCUSD"
tick_size = 8
quote_currency_price_increment = 2
#update symbol based on what crypto/fiat pair you want to buy. Default is BTCUSD, change to BTCEUR for Euros or ETHUSD for Ethereum (for example) - see all possibilities down in symbols and minimums link
#update tick_size and quote_currency_price_increment based on what crypto-pair you are buying. BTC is 8 - in the doc it says 1e-8 you want the number after e-. Or in the case of .01 you want 2 (because .01 is 1e-2) 
#Check out the API link below to see what you need for your pair
#<https://docs.gemini.com/rest-api/#symbols-and-minimums>

def _buyBitcoin(buy_size,pub_key, priv_key):
    # Set up a buy for 0.999 times the current price add more decimals for a higher price and faster fill, if the price is too close to spot your order won't post. 
    # Lower factor makes the order cheaper but fills quickly (0.5 would set an order for half the price and so your order could take months/years/never to fill)
    trader = gemini.PrivateClient(pub_key, priv_key)
    symbol_spot_price = float(trader.get_ticker(symbol)['ask'])
    print(symbol_spot_price)
    factor = 0.999
    #to set a limit order at a fixed price (ie. $55,525) set execution_price = "55525.00" or execution_price = str(55525.00)
    execution_price = str(round(symbol_spot_price*factor,quote_currency_price_increment))

    #set amount to the most precise rounding (tick_size) and multiply by 0.998 for fee inclusion - if you make an order for $20.00 there should be $19.96 coin bought and $0.04 (0.20% fee)
    amount = round((buy_size*0.998)/float(execution_price),tick_size)
		
    #execute maker buy with the appropriate symbol, amount, and calculated price
    buy = trader.new_order(symbol, str(amount), execution_price, "buy", ["maker-or-cancel"])
    print(f'Maker Buy: {buy}')

def lambda_handler(event, context):
    _buyBitcoin(20, public_key, private_key)
    return {
        'statusCode': 200,
        'body': json.dumps('End of script')
    }

Buy ETH from Gemini

import json
import gemini

public_key = ""  
private_key = ""
symbol = "ETHUSD"
tick_size = 6
quote_currency_price_increment = 2
#update symbol based on what crypto/fiat pair you want to buy. Default is BTCUSD, change to BTCEUR for Euros or ETHUSD for Ethereum (for example) - see all possibilities down in symbols and minimums link
#update tick_size and quote_currency_price_increment based on what crypto-pair you are buying. BTC is 8 - in the doc it says 1e-8 you want the number after e-. Or in the case of .01 you want 2 (because .01 is 1e-2) 
#Check out the API link below to see what you need for your pair
#<https://docs.gemini.com/rest-api/#symbols-and-minimums>

def _buyEtherium(buy_size,pub_key, priv_key):
    # Set up a buy for the current price
    trader = gemini.PrivateClient(pub_key, priv_key)
    factor = 0.998
    #to set a limit order at a fixed price (ie. $55,525) set execution_price = "55525.00" or execution_price = str(55525.00)
    price = str(round(float(trader.get_ticker(symbol)['ask'])*factor,quote_currency_price_increment))

    #set amount to the most precise rounding (tick_size) and multiply by 0.998 for fee inclusion - if you make an order for $20.00 there should be $19.96 coin bought and $0.04 (0.20% fee)
    eth_amount = round((buy_size*factor)/float(price),tick_size)

    #execute maker buy, round to 8 decimal places for precision, multiply price by 2 so your limit order always gets fully filled
    buy = trader.new_order(symbol, str(eth_amount), price, "buy", ["maker-or-cancel"])
    print(f'Maker Buy: {buy}')

def lambda_handler(event, context):
    _buyEtherium(10, public_key, private_key)
    return {
        'statusCode': 200,
        'body': json.dumps('End of script')
    }

Withdraw From Gemini to One Address

import json
import gemini

public_key = ""  
private_key = ""
trader = gemini.PrivateClient(public_key, private_key)

#withdraws full available balance of specified coin to given address
def _withdrawFullCoinBalance(coin, address):
    amount = "0"
    for currency in trader.get_balance():
        if(currency['currency'] == coin):
            amount = currency['availableForWithdrawal']
            print(f'Amount Available for Withdrawal: {amount}')
    
    #Replace the amount variable below with ".001" to withdraw .001 BTC - change the amount if you want to withdraw some static amount
    withdraw = trader.withdraw_to_address(coin, address, amount)
    print(withdraw)

def lambda_handler(event, context):
    #Add addresses below 
    #MAKE SURE THAT YOUR WALLET ADDRESS IS FOR THE SAME TOKEN AS THE WITHDRAWAL SYMBOL OR YOU COULD LOSE FUNDS
    #(ie. in _withdrawPartialCoinBalance(bitcoin_withdrawal_symbol, btc_address, .75) both btc_address and bitcoin_withdrawal_symbol reference the same coin (BTC))

    bitcoin_withdrawal_symbol = "BTC"
    ethereum_withdrawal_symbol = "ETH"
    btc_address = ''
    eth_address = ''
    _withdrawFullCoinBalance(bitcoin_withdrawal_symbol, btc_address)
    _withdrawFullCoinBalance(ethereum_withdrawal_symbol, eth_address)

    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

Withdraw to One Random Address from a List of Addresses

import json
import gemini
import random

public_key=''
private_key=''
trader = gemini.PrivateClient(public_key, private_key)

#withdraws full available balance of specified coin to given address
def _withdrawFullCoinBalance(coin, address):

    amount = "0"
    for currency in trader.get_balance():
        if(currency['currency'] == coin):
            amount = str(float(currency['availableForWithdrawal']))
            print(f'Amount Available for Withdrawal: {amount}')
            
    withdraw = trader.withdraw_to_address(coin, address, amount)
    return amount

def lambda_handler(event, context):
    #Edit these addresses to whatever you want
    btc_BlockFi = ''
    btc_multisig = ''
    btc_multisig2 = ''
    #Add the addresses to this list
    btc_addresses = [btc_BlockFi,btc_multisig, btc_multisig2, btc_multisig3]
    eth_BlockFi = ''
    eth_addresses = [eth_BlockFi]
    btc_withdraw = _withdrawFullCoinBalance("BTC", random.choice(btc_addresses))

    return {
        'statusCode': 200,
        'body': json.dumps(f'{btc_withdraw} BTC withdrawn.')
    }

Sell Bitcoin - Gemini

import json
import gemini

public_key = ""  
private_key = ""
symbol = 'BTCUSD'
tick_size = 8
quote_currency_price_increment = 2
#update symbol based on what crypto/fiat pair you want to buy. Default is BTCUSD, change to BTCEUR for Euros or ETHUSD for Ethereum (for example) - see all possibilities down in symbols and minimums link
#update tick_size and quote_currency_price_increment based on what crypto-pair you are buying. BTC is 8 - in the doc it says 1e-8 you want the number after e-. Or in the case of .01 you want 2 (because .01 is 1e-2) 
#Check out the API link below to see what you need for your pair
#<https://docs.gemini.com/rest-api/#symbols-and-minimums>

def _sellBitcoin(sell_size,pub_key, priv_key):
    # Set up a sell for 1.001X above the current price
    # Higher factor makes the order price higher but fills slower (2 would set an order for double the price and so your order could take months/years/never to fill)
    trader = gemini.PrivateClient(pub_key, priv_key)
    symbol_spot_price = float(trader.get_ticker(symbol)['ask'])
    factor = 1.001
    #to set a limit order at a fixed price (ie. $55,525) set execution_price = "55525.00" or execution_price = str(55525.00)
    execution_price = str(round(symbol_spot_price*factor,quote_currency_price_increment))

    #most precise rounding + *.998 for fee inclusion
    amount = round((sell_size*.998)/float(execution_price),tick_size)

    sell = trader.new_order(symbol, str(amount), execution_price, "sell", ["maker-or-cancel"])
    print(f'Maker Sell: {sell}')
    return [amount, execution_price]

def lambda_handler(event, context):
    message = _sellBitcoin(20, public_key, private_key)
    return {
        'statusCode': 200,
        'body': json.dumps(f'You sold {message[0]} Bitcoin for {message[1]}. You monster.')
    }

Convert GUSD to USD (For Automating Deposits)

import json
import gemini

public_key = ''
private_key = ''

#This function converts all your GUSD to USD
def _convertGUSDtoUSD(pub_key, priv_key):
    gusd_balance = 0
    trader = gemini.PrivateClient(pub_key, priv_key)
    if(list((type['available'] for type in  trader.get_balance() if type['currency'] == 'GUSD'))):
        gusd_balance = str(list((type['available'] for type in  trader.get_balance() if type['currency'] == 'GUSD'))[0])
    #use "buy" to convert USD to GUSD
    #use "sell" to convert GUSD into USD
    #replace gusd_balance below to transfer a static amount, use gusd_balance to transfer all your GUSD to USD
    results = trader.wrap_order(gusd_balance, "sell")
    print(results)

def lambda_handler(event, context):
    _convertGUSDtoUSD(public_key, private_key)
    return {
        'statusCode': 200,
        'body': json.dumps('End of script')
    }

Update Bitcoin GSheet - Gemini

import json
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from datetime import datetime
import gemini

public_key = ""  
private_key = ""

def _addTransaction(transaction):
    #populate transaction details
    transaction_date = str(datetime.fromtimestamp(transaction['timestamp']).date())
    transaction_id = float(transaction['tid'])
    provider = "Gemini"
    quantity = float(transaction['amount'])
    btc_price = float(transaction['price'])
    fee = float(transaction['fee_amount'])
    usd_amount = quantity * btc_price + fee

    #populate with new row
    return [transaction_date, transaction_id, provider, quantity, btc_price, usd_amount, fee]
    
def _authenticateSpreadsheet():
    #Set up access to the spreadsheet
    scope = ["<https://spreadsheets.google.com/feeds>",
            '<https://www.googleapis.com/auth/spreadsheets>',
            "<https://www.googleapis.com/auth/drive.file>",
            "<https://www.googleapis.com/auth/drive>"]
    creds = ServiceAccountCredentials.from_json_keyfile_name("sheets_creds.json", scope)
    client = gspread.authorize(creds)
    return client.open("The Public Definitive Bitcoin Sheet").worksheet("BTC Buy Audit File")

def populateBTC(pub_key, priv_key):
    audit_file = _authenticateSpreadsheet()
    num_rows_added = 0
    trader = gemini.PrivateClient(pub_key, private_key)
    buys = trader.get_past_trades("BTCUSD")[::-1]
    last_gemini_transaction = (list(filter(lambda gemini: gemini['Provider'] == 'Gemini', audit_file.get_all_records()[-50:]))[-1]['Transaction ID'])
    for buy in buys:
        if(buy['tid'] > last_gemini_transaction):
            audit_file.append_row(_addTransaction(buy), value_input_option="USER_ENTERED")
            num_rows_added += 1
    return num_rows_added
    
def lambda_handler(event, context):
    num = populateBTC(public_key, private_key)
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps(f'{num} transactions added!')
    }

Convert BAT to BTC - Gemini