Using Proton Drive's CLI For Automated Cloud Sync
I use a tool of my own crafting (cryptonabber-txn-sync) to keep my budgeting software in sync with onchain transactions. I normally do this on my laptop, but recently tried to use the app on my desktop in anticipation of replacing my laptop in the near future. The tool ran fine, but I ran into an issue when I tried to run it on my laptop: the work I had done on my desktop was invisible to my laptop.
See, cryptonabber-txn-sync uses a file to track what transactions it's seen and processed (or been told to permanently skip). My desktop had a copy of that file with entries that my laptop didn't - the file is stored locally, so there's no central database for the two machines to synchronize their data with. The outcome of this wasn't terrible - I just had to replay some transactions on my laptop and tell the tool to ignore them permanently - but it was still annoying and, also, error-prone: how likely am I to remember, when I run this tool again on my desktop (or even my new laptop) what transactions I have and haven't synchronized?
I tooled around with the idea of creating some kind of database storage option in the tool - I run a Postgres instance on my local network, so I could use that - but I decided that that was too invasive into the app. Right now, it does what it needs to do - synchronize transactions into YNAB - and I didn't want to overload it with every bell and whistle. Simple tools lend themselves to being able to be composed into more-complex workflows.
Composability, it turns out, is the key to the solution here. See, I use Proton for a number of things, including their Proton Drive storage offering. Proton Drive's desktop experience - especially on Linux - may not be as polished as OneDrive or Google Drive, but their privacy offerings are pretty much top-notch. Further, they provide a command-line interface (CLI) tool - which means that I can build a script to upload and download files programmatically.
I already have a shell script that runs cryptonabber-txn-sync across the accounts I want to track, so adding in the Proton Drive CLI was just a matter of dropping in a few commands, yielding a script like:
set -euo pipefail
source .env
echo "Downloading ignored transaction list"
proton-drive auth login
proton-drive filesystem download '/my-files/apps/cryptonabber-txn-sync/transaction_hash.ignorelist' . -f remove
echo "Synchronizing Hot Storage"
./cryptonabber-txn-sync --ynab-access-token="$YNAB_ACCESS_TOKEN" \
--wallet-address="$HOT_STORAGE_ADDRESS" \
--ynab-account-name="Hot Storage" \
--blockscout-api-key=$BLOCKSCOUT_API_KEY
echo "Synchronizing Cold Storage wallet"
./cryptonabber-txn-sync --ynab-access-token="$YNAB_ACCESS_TOKEN" \
--wallet-address="$COLD_STORAGE_ADDRESS" \
--ynab-account-name="Cold Storage" \
--blockscout-api-key=$BLOCKSCOUT_API_KEY
echo "Uploading ignored transaction list"
proton-drive filesystem upload ./transaction_hash.ignorelist '/my-files/apps/cryptonabber-txn-sync/' -f replace
The key additions are the calls to proton-drive - first, to authenticate, then to download the file as it exists to replace whatever's stored locally, and then, after all is said and done, upload it to Proton Drive. Now, when I run this shell script on my desktop machine, it'll download everything that I last uploaded from my laptop and I won't have to replay any of the transactions that I processed on my laptop!
There are a couple of caveats with this script:
- I had to manually upload the file I had on my local machine to seed the file on Proton Drive. I'm sure I could have made the script smart enough to check to see if the file exists before trying to download it, but sometimes the non-programmatic, simple solution is the best solution.
- If either of the calls to
cryptonabber-txn-syncfail (maybe Blockscout is down; maybe YNAB is down; maybe there's a bug in the tool), then any changes to the transaction ignore list will be lost. Again, I could probably make the script resilient to this, but the risk of having to occasionally reconstitue the last five minutes' of work is low enough and the consequences of such a rebuild are low enough that it doesn't warrant that kind of complexity in the script - complexity that I would have to maintain in the long-term.
I was rather delighted with the ease with which I was able to add in cross-device synchronization with zero changes to my tool. It all really speaks to the value of being able to compose different tools together to create something that, while not greater than the sum of its parts, still yields an appreciable sum.
Attributions
The sync logo used for this was sourced from Magnific.