Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions scripts/compare-balance-logs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/bin/bash
# Compare two FinancialDataLog entries to find asset changes

set -e

if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: $0 <log_id_1> <log_id_2>"
exit 1
fi

LOG_ID_1="$1"
LOG_ID_2="$2"

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/../.env"

if [ ! -f "$ENV_FILE" ]; then
echo "Error: Environment file not found: $ENV_FILE"
exit 1
fi

DEBUG_ADDRESS=$(grep -E "^DEBUG_ADDRESS=" "$ENV_FILE" | cut -d'=' -f2-)
DEBUG_SIGNATURE=$(grep -E "^DEBUG_SIGNATURE=" "$ENV_FILE" | cut -d'=' -f2-)
DEBUG_API_URL=$(grep -E "^DEBUG_API_URL=" "$ENV_FILE" | cut -d'=' -f2-)

if [ -z "$DEBUG_ADDRESS" ] || [ -z "$DEBUG_SIGNATURE" ]; then
echo "Error: DEBUG_ADDRESS and DEBUG_SIGNATURE must be set in .env"
exit 1
fi

API_URL="${DEBUG_API_URL:-https://api.dfx.swiss/v1}"

# Authenticate
TOKEN_RESPONSE=$(curl -s -X POST "$API_URL/auth" \
-H "Content-Type: application/json" \
-d "{\"address\":\"$DEBUG_ADDRESS\",\"signature\":\"$DEBUG_SIGNATURE\"}")

TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.accessToken' 2>/dev/null)

if [ "$TOKEN" == "null" ] || [ -z "$TOKEN" ]; then
echo "Authentication failed"
exit 1
fi

# Get both log entries
SQL="SELECT id, created, message FROM log WHERE id IN ($LOG_ID_1, $LOG_ID_2) ORDER BY id"
RESULT=$(curl -s -X POST "$API_URL/gs/debug" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"sql\":\"$SQL\"}")

# Parse with jq
echo "$RESULT" | jq -r '
# Extract both entries
.[0] as $entry1 |
.[1] as $entry2 |

# Parse message JSON
($entry1.message | fromjson) as $msg1 |
($entry2.message | fromjson) as $msg2 |

"=== Balance Comparison ===",
"",
"Entry 1: ID \($entry1.id) at \($entry1.created)",
" plusBalance: \($msg1.balancesTotal.plusBalanceChf)",
" minusBalance: \($msg1.balancesTotal.minusBalanceChf)",
" totalBalance: \($msg1.balancesTotal.plusBalanceChf - $msg1.balancesTotal.minusBalanceChf | tostring | .[0:12])",
"",
"Entry 2: ID \($entry2.id) at \($entry2.created)",
" plusBalance: \($msg2.balancesTotal.plusBalanceChf)",
" minusBalance: \($msg2.balancesTotal.minusBalanceChf)",
" totalBalance: \($msg2.balancesTotal.plusBalanceChf - $msg2.balancesTotal.minusBalanceChf | tostring | .[0:12])",
"",
"=== Changes ===",
" Δ plusBalance: \($msg2.balancesTotal.plusBalanceChf - $msg1.balancesTotal.plusBalanceChf | tostring | .[0:12])",
" Δ minusBalance: \($msg2.balancesTotal.minusBalanceChf - $msg1.balancesTotal.minusBalanceChf | tostring | .[0:12])",
" Δ totalBalance: \(($msg2.balancesTotal.plusBalanceChf - $msg2.balancesTotal.minusBalanceChf) - ($msg1.balancesTotal.plusBalanceChf - $msg1.balancesTotal.minusBalanceChf) | tostring | .[0:12])",
"",
"=== Top Asset Changes (by CHF impact) ===",
"",
# Get all asset IDs from both messages
([($msg1.assets | keys[]), ($msg2.assets | keys[])] | unique) as $all_assets |

# Calculate changes for each asset
[
$all_assets[] | . as $asset_id |
{
assetId: $asset_id,
plus1: ($msg1.assets[$asset_id].plusBalance.total // 0),
plus2: ($msg2.assets[$asset_id].plusBalance.total // 0),
minus1: ($msg1.assets[$asset_id].minusBalance.total // 0),
minus2: ($msg2.assets[$asset_id].minusBalance.total // 0),
price1: ($msg1.assets[$asset_id].priceChf // 0),
price2: ($msg2.assets[$asset_id].priceChf // 0)
} |
. + {
deltaPlus: (.plus2 - .plus1),
deltaMinus: (.minus2 - .minus1),
price: (if .price2 > 0 then .price2 else .price1 end)
} |
. + {
deltaPlusChf: (.deltaPlus * .price),
deltaMinusChf: (.deltaMinus * .price),
deltaNetChf: ((.deltaPlus - .deltaMinus) * .price)
}
] |

# Filter out zero changes
map(select((.deltaNetChf | if . < 0 then -. else . end) > 10)) |

# Sort by absolute net CHF change
sort_by(-.deltaNetChf | if . < 0 then -. else . end) |

# Take top 20
.[0:20][] |

"Asset \(.assetId): Δnet=\(.deltaNetChf) CHF (Δplus: \(.deltaPlus) units, Δminus: \(.deltaMinus) units, price: \(.price) CHF)"
'
114 changes: 114 additions & 0 deletions scripts/inspect-asset-balance.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/bin/bash
# Inspect detailed balance structure for a specific asset

set -e

if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: $0 <log_id> <asset_id>"
exit 1
fi

LOG_ID="$1"
ASSET_ID="$2"

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/../.env"

if [ ! -f "$ENV_FILE" ]; then
echo "Error: Environment file not found: $ENV_FILE"
exit 1
fi

DEBUG_ADDRESS=$(grep -E "^DEBUG_ADDRESS=" "$ENV_FILE" | cut -d'=' -f2-)
DEBUG_SIGNATURE=$(grep -E "^DEBUG_SIGNATURE=" "$ENV_FILE" | cut -d'=' -f2-)
DEBUG_API_URL=$(grep -E "^DEBUG_API_URL=" "$ENV_FILE" | cut -d'=' -f2-)

if [ -z "$DEBUG_ADDRESS" ] || [ -z "$DEBUG_SIGNATURE" ]; then
echo "Error: DEBUG_ADDRESS and DEBUG_SIGNATURE must be set in .env"
exit 1
fi

API_URL="${DEBUG_API_URL:-https://api.dfx.swiss/v1}"

# Authenticate
TOKEN_RESPONSE=$(curl -s -X POST "$API_URL/auth" \
-H "Content-Type: application/json" \
-d "{\"address\":\"$DEBUG_ADDRESS\",\"signature\":\"$DEBUG_SIGNATURE\"}")

TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.accessToken' 2>/dev/null)

if [ "$TOKEN" == "null" ] || [ -z "$TOKEN" ]; then
echo "Authentication failed"
exit 1
fi

# Get log entry
SQL="SELECT id, created, message FROM log WHERE id = $LOG_ID"
RESULT=$(curl -s -X POST "$API_URL/gs/debug" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"sql\":\"$SQL\"}")

# Parse with jq
echo "$RESULT" | jq -r --arg asset_id "$ASSET_ID" '
.[0] as $entry |
($entry.message | fromjson) as $msg |
$msg.assets[$asset_id] as $asset |

if $asset then
"=== Asset \($asset_id) Balance Details ===",
"",
"Log Entry: \($entry.id) at \($entry.created)",
"Price CHF: \($asset.priceChf)",
"",
"=== Plus Balance ===",
"Total: \($asset.plusBalance.total)",
"",
if $asset.plusBalance.liquidity then
"Liquidity: \($asset.plusBalance.liquidity.total)",
(if $asset.plusBalance.liquidity.liquidityBalance then
" - liquidityBalance.total: \($asset.plusBalance.liquidity.liquidityBalance.total)",
($asset.plusBalance.liquidity.liquidityBalance | to_entries[] | select(.key != "total") | " [\(.key)]: \(.value)")
else empty end),
(if $asset.plusBalance.liquidity.paymentDepositBalance then
" - paymentDepositBalance.total: \($asset.plusBalance.liquidity.paymentDepositBalance.total)"
else empty end),
(if $asset.plusBalance.liquidity.manualLiqPosition then
" - manualLiqPosition.total: \($asset.plusBalance.liquidity.manualLiqPosition.total)"
else empty end)
else
"Liquidity: N/A"
end,
"",
if $asset.plusBalance.custom then
"Custom: \($asset.plusBalance.custom.total)",
($asset.plusBalance.custom | to_entries[] | select(.key != "total") | " - \(.key): \(.value)")
else
"Custom: N/A"
end,
"",
if $asset.plusBalance.pending then
"Pending: \($asset.plusBalance.pending.total)",
(if $asset.plusBalance.pending.cryptoInput then " - cryptoInput: \($asset.plusBalance.pending.cryptoInput)" else empty end),
(if $asset.plusBalance.pending.exchangeOrder then " - exchangeOrder: \($asset.plusBalance.pending.exchangeOrder)" else empty end),
(if $asset.plusBalance.pending.bridgeOrder then " - bridgeOrder: \($asset.plusBalance.pending.bridgeOrder)" else empty end),
(if $asset.plusBalance.pending.fromOlky then " - fromOlky: \($asset.plusBalance.pending.fromOlky)" else empty end),
(if $asset.plusBalance.pending.fromKraken then " - fromKraken: \($asset.plusBalance.pending.fromKraken)" else empty end),
(if $asset.plusBalance.pending.toKraken then " - toKraken: \($asset.plusBalance.pending.toKraken)" else empty end),
(if $asset.plusBalance.pending.fromScrypt then " - fromScrypt: \($asset.plusBalance.pending.fromScrypt)" else empty end),
(if $asset.plusBalance.pending.toScrypt then " - toScrypt: \($asset.plusBalance.pending.toScrypt)" else empty end)
else
"Pending: N/A"
end,
"",
"=== Minus Balance ===",
"Total: \($asset.minusBalance.total)",
"",
(if $asset.minusBalance.debt then "Debt: \($asset.minusBalance.debt)" else empty end),
(if $asset.minusBalance.pending then
"Pending: \($asset.minusBalance.pending.total)"
else empty end)
else
"Asset \($asset_id) not found in log entry \($entry.id)"
end
'
112 changes: 112 additions & 0 deletions scripts/sum-asset-balances.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/bin/bash
# Sum plusBalance.total for assets of a specific financialType

set -e

if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: $0 <log_id> <financial_type>"
exit 1
fi

LOG_ID="$1"
FINANCIAL_TYPE="$2"

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/../.env"

if [ ! -f "$ENV_FILE" ]; then
echo "Error: Environment file not found: $ENV_FILE"
exit 1
fi

DEBUG_ADDRESS=$(grep -E "^DEBUG_ADDRESS=" "$ENV_FILE" | cut -d'=' -f2-)
DEBUG_SIGNATURE=$(grep -E "^DEBUG_SIGNATURE=" "$ENV_FILE" | cut -d'=' -f2-)
DEBUG_API_URL=$(grep -E "^DEBUG_API_URL=" "$ENV_FILE" | cut -d'=' -f2-)

if [ -z "$DEBUG_ADDRESS" ] || [ -z "$DEBUG_SIGNATURE" ]; then
echo "Error: DEBUG_ADDRESS and DEBUG_SIGNATURE must be set in .env"
exit 1
fi

API_URL="${DEBUG_API_URL:-https://api.dfx.swiss/v1}"

# Authenticate
TOKEN_RESPONSE=$(curl -s -X POST "$API_URL/auth" \
-H "Content-Type: application/json" \
-d "{\"address\":\"$DEBUG_ADDRESS\",\"signature\":\"$DEBUG_SIGNATURE\"}")

TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r '.accessToken' 2>/dev/null)

if [ "$TOKEN" == "null" ] || [ -z "$TOKEN" ]; then
echo "Authentication failed"
exit 1
fi

# Get asset IDs for this financial type
ASSET_IDS=$(curl -s -X POST "$API_URL/gs/debug" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"sql\":\"SELECT id FROM asset WHERE financialType = '$FINANCIAL_TYPE'\"}" | \
jq -r '.[].id' | tr '\n' ',' | sed 's/,$//')

echo "=== Asset Balance Sum for Financial Type: $FINANCIAL_TYPE ==="
echo "Log ID: $LOG_ID"
echo "Asset IDs: $ASSET_IDS"
echo ""

# Get log entry
SQL="SELECT id, created, message FROM log WHERE id = $LOG_ID"
RESULT=$(curl -s -X POST "$API_URL/gs/debug" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"sql\":\"$SQL\"}")

# Parse with jq
echo "$RESULT" | jq -r --arg asset_ids "$ASSET_IDS" '
.[0] as $entry |
($entry.message | fromjson) as $msg |

# Split asset IDs
($asset_ids | split(",") | map(tonumber)) as $ids |

"Log Entry: \($entry.id) at \($entry.created)",
"",
"Individual Asset Balances:",
"",

# Process each asset
[
$ids[] | . as $id |
$msg.assets[($id | tostring)] as $asset |
if $asset then
{
id: $id,
plusTotal: ($asset.plusBalance.total // 0),
minusTotal: ($asset.minusBalance.total // 0),
priceChf: ($asset.priceChf // 0),
plusChf: (($asset.plusBalance.total // 0) * ($asset.priceChf // 0)),
minusChf: (($asset.minusBalance.total // 0) * ($asset.priceChf // 0)),
netChf: ((($asset.plusBalance.total // 0) - ($asset.minusBalance.total // 0)) * ($asset.priceChf // 0))
}
else
{
id: $id,
plusTotal: 0,
minusTotal: 0,
priceChf: 0,
plusChf: 0,
minusChf: 0,
netChf: 0
}
end
] as $balances |

# Print details
($balances[] | "Asset \(.id): plus=\(.plusTotal | tostring | .[0:12]) minus=\(.minusTotal | tostring | .[0:12]) price=\(.priceChf | tostring | .[0:10]) → plusChf=\(.plusChf | tostring | .[0:12]) netChf=\(.netChf | tostring | .[0:12])"),
"",
"=== Summary ===",
"",
"Total Plus CHF: \($balances | map(.plusChf) | add)",
"Total Minus CHF: \($balances | map(.minusChf) | add)",
"Total Net CHF: \($balances | map(.netChf) | add)"
'
Loading