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/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

Gemini Changed their withdrawal fees, which broke the previous withdrawal script. Below is the updated code that works for BTC or any other static fee crypto. For ETH and dynamic fee crypto check out this blog post: https://www.rhett.blog/automatically-withdrawal-bitcoin-from-gemini-updated

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

import json
import gemini
from math import floor

public_key = ""  
private_key = ""
symbol = 'BATBTC'
tick_size = 6
quote_currency_price_increment = 8
#update symbol based on what crypto/fiat pair you want to buy. Default is BATBTC, change to BATETH for ETH or BATUSD for USD (for example) - see all possibilities down in symbols and minimums link
#update tick size based on what crypto-pair you are buying. All BAT pairs are 6. Check out the API link below to see what you need for your pair
#update you quote_currency_price_increment based on the BAT pair you're trading. BTC is 8, ETH is 7, USD is 5
#<https://docs.gemini.com/rest-api/#symbols-and-minimums>

def _convertBAT(pub_key, priv_key, sell_size=0):
    bat_balance = 0
    trader = gemini.PrivateClient(pub_key, priv_key)
    if(list((type['available'] for type in  trader.get_balance() if type['currency'] == 'BAT'))):
        bat_balance = str(list((type['available'] for type in  trader.get_balance() if type['currency'] == 'BAT'))[0])
        print(f"BAT balance = {bat_balance}")
    if sell_size == 0:
        sell_size = (floor(float(bat_balance)*(10**(tick_size))))/(10**(tick_size))
        print(f"Sell size = {sell_size}")

    price = str(round(float(trader.get_ticker(symbol)['ask'])*0.998,quote_currency_price_increment))
    print(f"Price: {price}")

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

def lambda_handler(event, context):
    #Provide optional third parameter sell size to _convertBAT to only convert a BTC sized portion of your BAT
    #ie. _convertBAT(public_key, private_key, .00001) to sell .00001 BTC of your BAT stack
    message = _convertBAT(public_key, private_key)
    return {
        'statusCode': 200,
        'body': json.dumps(f'Placed maker sell order for {symbol}.')
    }