├── .github
├── FUNDING.yml
└── workflows
│ ├── main.yml
│ └── release.yml
├── .gitignore
├── .gitmodules
├── App.org
├── App.pdf
├── App.txt
├── COPYING
├── GNUmakefile
├── LICENSE
├── MANIFEST.in
├── README.org
├── README.pdf
├── README.txt
├── SLIP-39-macOS.spec
├── SLIP-39-win32.spec
├── SLIP-39.metadata
├── check-signature
└── entitlements.plist
├── SLIP-39.py
├── default.nix
├── dkim-setup
├── fonts_list.py
├── images
├── 1x1-ffffff3f.png
├── 1x1-ffffff7f.png
├── 1x1-ffffffbf.png
├── BIP-39-backup-entropy.png
├── BSC.png
├── BSC.svg
├── BTC.png
├── BTC.svg
├── CRO.png
├── CRO.svg
├── DOGE.png
├── DOGE.svg
├── ETH.png
├── ETH.svg
├── LTC.png
├── LTC.svg
├── SLIP-39.icns
├── SLIP-39.ico
├── SLIP-39.png
├── SLIP-39.svg
├── SLIP39 - Screen Shot 1.png
├── SLIP39 - Screen Shot 1.xcf
├── SLIP39-Example.pdf
├── SLIP39-backup-BIP39.png
├── SLIP39-recover-BIP39-entropy.png
├── SLIP39-recover-BIP39-mnemonic.png
├── XRP.png
├── XRP.svg
├── boo.svg
├── boo2.svg
├── guilloche-center.png
├── guilloche-center.svg
├── paper-wallet-background.svg
├── slip39-cards.png
├── slip39-overview-youtube.png
├── slip39-wallets.png
└── slip39.png
├── nixpkgs.nix
├── pyproject.toml
├── pytest.ini
├── requirements-dev.txt
├── requirements-gui.txt
├── requirements-invoice.txt
├── requirements-serial.txt
├── requirements-tests.txt
├── requirements-wallet.txt
├── requirements.txt
├── setup.py
├── shell.nix
└── slip39
├── __init__.py
├── __main__.py
├── api.py
├── api_passphrase_test.py
├── api_test.py
├── cli
├── __init__.py
└── __main__.py
├── communications.py
├── communications_test.py
├── defaults.py
├── dependency_test.py
├── generator
├── __init__.py
├── __main__.py
└── main.py
├── generator_test.py
├── gui
├── SLIP-39-AS-BIP.org
├── SLIP-39-AS-BIP.txt
├── SLIP-39-CRYPTO.org
├── SLIP-39-CRYPTO.txt
├── SLIP-39-CS.org
├── SLIP-39-CS.txt
├── SLIP-39-EXTENDABLE.org
├── SLIP-39-EXTENDABLE.txt
├── SLIP-39-G-NAME.org
├── SLIP-39-G-NAME.txt
├── SLIP-39-G.org
├── SLIP-39-G.txt
├── SLIP-39-LO.org
├── SLIP-39-LO.txt
├── SLIP-39-PASSPHRASE.org
├── SLIP-39-PASSPHRASE.txt
├── SLIP-39-PF.org
├── SLIP-39-PF.txt
├── SLIP-39-SD.org
├── SLIP-39-SD.txt
├── SLIP-39-SE-SIGS.org
├── SLIP-39-SE-SIGS.txt
├── SLIP-39-SE.org
├── SLIP-39-SE.txt
├── SLIP-39-THRESHOLD.org
├── SLIP-39-THRESHOLD.txt
├── SLIP-39-WALLET.org
├── SLIP-39-WALLET.txt
├── SLIP-39.txt
├── __init__.py
├── __main__.py
└── main.py
├── invoice
├── Cryptos
│ ├── BNB_32.png
│ ├── BTC_32.png
│ ├── CRO_32.png
│ ├── DOGE_32.png
│ ├── ETH_32.png
│ ├── LTC_32.png
│ └── XRP_32.png
├── MultiSend-solc-v0-4-11.sol
├── MultiSend-solc-v0-5-15.sol
├── MultiTransferEther-solc-v0-5-16.sol
├── Tokens-Ethereum.json
├── Tokens-Goerli.json
├── Tokens.py
├── Tokens
│ ├── 1INCH_32.webp
│ ├── AGIX_28.webp
│ ├── AMB_28.webp
│ ├── AMP_32.webp
│ ├── ANY_32.webp
│ ├── AOA_28.webp
│ ├── APE_32.webp
│ ├── BAL_32.webp
│ ├── BAND_32.webp
│ ├── BAT.webp
│ ├── BDG.webp
│ ├── BIT_32.webp
│ ├── BNB_2.webp
│ ├── BNT_32.webp
│ ├── BTT_32.webp
│ ├── BUSD_32.webp
│ ├── CEL_28.webp
│ ├── CHSB_3.png
│ ├── CHZ_28.webp
│ ├── CNN_28.webp
│ ├── COFI_28.webp
│ ├── COMP_32.webp
│ ├── CRO_32.webp
│ ├── CVX_32.webp
│ ├── DACC.png
│ ├── DAI_32.webp
│ ├── DATx_28.webp
│ ├── DENT.webp
│ ├── DFI_32.png
│ ├── DYDX_32.webp
│ ├── ELEC_28.webp
│ ├── ELON_32.webp
│ ├── ENJ_2.webp
│ ├── ENS_32.webp
│ ├── EURT_32.webp
│ ├── FAIR_28.webp
│ ├── FEG_32.webp
│ ├── FET_32.webp
│ ├── FLOKI_32.webp
│ ├── FRAX_32.webp
│ ├── FTI_28.png
│ ├── FTM_32.webp
│ ├── FUEL_28.webp
│ ├── FUN_32.webp
│ ├── FXS_32.webp
│ ├── GALA_32.webp
│ ├── GLM_32.webp
│ ├── GMT_32.webp
│ ├── GNO_32.webp
│ ├── GRT_32.webp
│ ├── GSE_28.webp
│ ├── GTO.webp
│ ├── GUSD_28.webp
│ ├── HAND_28.png
│ ├── HBTC_32.png
│ ├── HEX_32.webp
│ ├── HOGE_32.webp
│ ├── HOT_28.webp
│ ├── HT_28.webp
│ ├── IHT_28.webp
│ ├── IIC_28.png
│ ├── IMT_28.png
│ ├── IND_28.webp
│ ├── IONC_28.png
│ ├── IOST_28.webp
│ ├── IOTX_28.webp
│ ├── IOV_28.webp
│ ├── KAN.webp
│ ├── KCS_32.webp
│ ├── KNC_32.webp
│ ├── KUB_28.png
│ ├── LDO_32.webp
│ ├── LEND_28.webp
│ ├── LEO_2.webp
│ ├── LINK_32.webp
│ ├── LPT_28.webp
│ ├── LRC_32.webp
│ ├── LXT_28.webp
│ ├── LYM_28.webp
│ ├── MASK_32.webp
│ ├── MATIC_32.webp
│ ├── MCO_28.webp
│ ├── MITx_32.webp
│ ├── MKR.webp
│ ├── MWAT_28.webp
│ ├── NEAR_32.webp
│ ├── NEXO_32.webp
│ ├── NXM_32.webp
│ ├── OCN_28.webp
│ ├── OHM_32.webp
│ ├── OKB_28.webp
│ ├── OMG_32.webp
│ ├── ONE_32.png
│ ├── PAI_28.png
│ ├── PAXG_32.webp
│ ├── PAY_28.webp
│ ├── POLY_28.webp
│ ├── POWR_2.webp
│ ├── PTT_32.png
│ ├── QNT_2.webp
│ ├── REV_32.webp
│ ├── RFR.png
│ ├── RNDR_32.webp
│ ├── RNT_28.png
│ ├── RPL_32.webp
│ ├── RSR_32.webp
│ ├── SAITAMA_32.webp
│ ├── SALT_28.webp
│ ├── SAND_32.webp
│ ├── SAT_28.png
│ ├── SHIB_32.webp
│ ├── SLP_32.webp
│ ├── SNT.webp
│ ├── SNX_32.webp
│ ├── SRM_32.webp
│ ├── STORJ_32.webp
│ ├── STQ_28.webp
│ ├── SUSHI_32.webp
│ ├── SYN_32.webp
│ ├── TEL_28.webp
│ ├── THETA_28.webp
│ ├── TOS_28.webp
│ ├── TUSD_32.webp
│ ├── UCASH_28.png
│ ├── UNI_32.webp
│ ├── USDC_28.webp
│ ├── USDD_32.webp
│ ├── USDP_32.webp
│ ├── USDT_32.webp
│ ├── VEN_28.webp
│ ├── VIN_28.webp
│ ├── WBTC_28.webp
│ ├── WETH_28.webp
│ ├── WOO_32.webp
│ ├── WQTUM_28.png
│ ├── XAUt_32.webp
│ ├── XCN_32.webp
│ ├── XDCE_28.webp
│ ├── XEN_32.webp
│ ├── XMX_28.webp
│ ├── XNN_28.webp
│ ├── XYO_2.webp
│ ├── YEE_28.png
│ ├── YFI_2.webp
│ ├── ZIL_2.webp
│ ├── ZRX_28.webp
│ ├── ZSC_28.png
│ ├── aAAVE_32.webp
│ ├── anyLTC_32.webp
│ ├── cDAI_32.webp
│ ├── cETH_28.webp
│ ├── cUSDC_28.webp
│ ├── cUSDT_32.webp
│ ├── nCash_28.webp
│ ├── rETH_32.webp
│ ├── stETH_32.webp
│ ├── stkAAVE_32.webp
│ ├── wCELO_32.png
│ └── wMANA_32.webp
├── __init__.py
├── artifact.py
├── artifact_test.py
├── artifact_test
│ ├── dominionrnd-invoice.png
│ ├── dominionrnd-invoice.svg
│ ├── dominionrnd-logo.png
│ └── dominionrnd-logo.svg
├── bitquery_test.py
├── contracts
│ ├── ForwarderERC20.sol
│ ├── MultiPayoutERC20.sol
│ ├── MultiPayoutERC20.sol-B52FD4-v0.8.17-o100
│ ├── MultiPayoutERC20Base.sol
│ └── MultiPayoutERC20Forwarder.sol
├── ethereum.py
├── ethereum_test.py
├── multipayout.py
├── multipayout_test.crypto-keypair-plaintext
├── multipayout_test.machine-id
├── multipayout_test.py
├── payments.py
├── payments_test.py
└── payments_test
│ └── payments_test.machine-id
├── layout
├── 1x1-ffffff3f.png
├── 1x1-ffffff54.png
├── 1x1-ffffffbf.png
├── BNB.png
├── BTC.png
├── COVER-BIP-39.org
├── COVER-BIP-39.txt
├── COVER-SLIP-39.org
├── COVER-SLIP-39.txt
├── COVER.txt
├── CRO.png
├── DOGE.png
├── ETH.png
├── LTC.png
├── SLIP-39.png
├── XRP.png
├── __init__.py
├── components.py
├── font
│ ├── DejaVuSansMono-Bold.ttf
│ ├── DejaVuSansMono-BoldOblique.ttf
│ ├── DejaVuSansMono-Oblique.ttf
│ ├── DejaVuSansMono.ttf
│ ├── Inconsolata-Bold.ttf
│ ├── Inconsolata-Regular.ttf
│ ├── NotoSansMono-Bold.ttf
│ ├── NotoSansMono-Regular.ttf
│ ├── OFL.txt
│ ├── OverpassMono-Bold.ttf
│ ├── OverpassMono-Regular.ttf
│ ├── SourceCodePro-Bold.ttf
│ ├── SourceCodePro-BoldItalic.ttf
│ ├── SourceCodePro-Italic.ttf
│ └── SourceCodePro-Regular.ttf
├── paper-wallet-background.png
├── pdf.py
└── printer.py
├── main.py
├── output_test.py
├── recovery
├── __init__.py
├── __main__.py
├── entropy.py
└── main.py
├── recovery_test.csv
├── recovery_test.py
├── util.py
├── util_test.py
└── version.py
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: [pjkundert]
2 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3 |
4 | name: Python package
5 |
6 | on:
7 | push:
8 | branches:
9 | - master
10 | - feature-**
11 | - fix-**
12 | pull_request:
13 | branches:
14 | - master
15 |
16 | jobs:
17 | build:
18 |
19 | runs-on: ubuntu-24.04
20 | strategy:
21 | matrix:
22 | # Requires Python3 w/ Type Annotations
23 | python-version: ['3.9', '3.10', '3.11', '3.12']
24 |
25 | steps:
26 | - name: Checkout repository code
27 | uses: actions/checkout@master
28 | - name: Update openssl
29 | run: |
30 | #sudo apt-get update
31 | #sudo apt-get -y install openssl
32 | openssl version
33 | openssl
34 | - name: Set up Python ${{ matrix.python-version }}
35 | uses: actions/setup-python@master
36 | with:
37 | python-version: ${{ matrix.python-version }}
38 | - name: Install dependencies
39 | run: |
40 | python3 -m pip install .[all,tests]
41 | - name: Lint with flake8
42 | run: |
43 | make analyze
44 | - name: Test with pytest
45 | run: |
46 | make test
47 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | pypi-publish:
10 | if: startsWith(github.ref, 'refs/tags')
11 | name: Upload release to PyPI
12 | runs-on: ubuntu-latest
13 | environment:
14 | name: pypi
15 | url: https://pypi.org/p/python-slip39
16 | permissions:
17 | id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
18 | steps:
19 | - name: Checkout
20 | uses: actions/checkout@v3
21 | - name: Set up Python
22 | uses: actions/setup-python@v4
23 | - name: Build
24 | run: |
25 | python -m pip install -r requirements-dev.txt
26 | python -m build .
27 | - name: Publish package distributions to PyPI
28 | uses: pypa/gh-action-pypi-publish@release/v1
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.log.*
3 | *.log
4 |
5 | # Archive files
6 | *.tgz
7 | *.tar
8 |
9 | # Editor temporaries
10 | *~
11 | .#*
12 |
13 | # System generated files
14 | .DS_Store
15 |
16 | *.tex
17 | *.aux
18 | *.toc
19 | auto/
20 | *.out
21 | build/
22 | MANIFEST
23 | dist/
24 | *.egg-info/
25 | .vagrant
26 | .pytest_cache/
27 | .cache/
28 | .eggs
29 | private_keys
30 | images/SLIP-39.iconset
31 | .coverage*
32 | /SLIP39-20*.pdf
33 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "slip39/invoice/openzeppelin-contracts"]
2 | path = slip39/invoice/openzeppelin-contracts
3 | url = https://github.com/OpenZeppelin/openzeppelin-contracts.git
4 |
--------------------------------------------------------------------------------
/App.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/App.pdf
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Slip39 is distributed under the GNU General Public License version 3 (or later)
2 | and is also available under alternative licenses negotiated directly with
3 | Dominion Research & Development Corp. If you obtained slip39 under the GPL,
4 | then the GPL applies to all slip39 modules used on your system as well, except
5 | as defined below. The GPL (version 3) is included in this source tree in the
6 | file COPYING.
7 |
8 | Dominion Research & Development Corp. holds copyright and/or sufficient
9 | licenses to all components of the slip39 package, and therefore can grant, at
10 | its sole discretion, the ability for companies, individuals, or organizations
11 | to create proprietary or Open Source (even if not GPL) modules which may use at
12 | runtime the portions of slip39 which fall under our copyright/license umbrella,
13 | or are distributed under more flexible licenses than GPL.
14 |
15 | If you wish to use our code in other GPL programs, don't worry -- there is no
16 | requirement that you provide the same exception in your GPL'd products.
17 |
18 | If you have any questions regarding our licensing policy, please contact us:
19 |
20 | +1.780.970.8148
21 | perry@dominionrnd.com
22 | Dominion Research & Development Corp.
23 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | # Both sdist and bdist include these files
2 | include LICENSE
3 | include COPYING
4 | include README.org
5 | include README.pdf
6 | include README.txt
7 | include requirements*.txt
8 | global-exclude *~
9 |
--------------------------------------------------------------------------------
/README.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/README.pdf
--------------------------------------------------------------------------------
/SLIP-39-macOS.spec:
--------------------------------------------------------------------------------
1 | # -*- mode: python ; coding: utf-8 -*-
2 | from PyInstaller.utils.hooks import collect_data_files
3 |
4 | datas = []
5 | datas += collect_data_files('shamir_mnemonic')
6 | datas += collect_data_files('slip39')
7 |
8 | block_cipher = None
9 |
10 | a = Analysis(
11 | ['SLIP-39.py'],
12 | pathex=[],
13 | binaries=[],
14 | datas=datas,
15 | hiddenimports=['slip39'],
16 | hookspath=[],
17 | hooksconfig={},
18 | runtime_hooks=[],
19 | excludes=[],
20 | win_no_prefer_redirects=False,
21 | win_private_assemblies=False,
22 | cipher=block_cipher,
23 | noarchive=False,
24 | )
25 |
26 | pyz = PYZ(
27 | a.pure,
28 | a.zipped_data,
29 | cipher=block_cipher,
30 | )
31 |
32 | exe = EXE(
33 | pyz,
34 | a.scripts,
35 | a.binaries,
36 | a.datas,
37 | [],
38 | name='SLIP-39',
39 | debug=False,
40 | bootloader_ignore_signals=False,
41 | strip=False,
42 | upx=True,
43 | upx_exclude=[],
44 | runtime_tmpdir=None,
45 | console=False,
46 | disable_windowed_traceback=False,
47 | argv_emulation=False,
48 | target_arch=None,
49 | codesign_identity='EAA134BE299C43D27E33E2B8645FF4CF55DE8A92',
50 | entitlements_file=None,
51 | icon='images/SLIP-39.icns',
52 | )
53 |
54 | app = BUNDLE(
55 | exe,
56 | name='SLIP-39.app',
57 | icon='images/SLIP-39.icns',
58 | version='11.2.1',
59 | info_plist={
60 | 'NSPrincipalClass': 'NSApplication',
61 | 'NSAppleScriptEnabled': False,
62 | 'LSBackgroundOnly': False,
63 | 'NSRequiresAquaSystemAppearance': 'No',
64 | 'CFBundleSupportedPlatforms': ['MacOSX'],
65 | 'CFBundleIdentifier': 'ca.kundert.perry.SLIP39',
66 | 'CFBundleVersion':'11.2.1',
67 | 'CFBundlePackageType':'APPL',
68 | 'LSApplicationCategoryType':'public.app-category.utilities',
69 | 'LSMinimumSystemVersion':'10.15',
70 | 'NSHumanReadableCopyright':"Copyright © 2023 Perry Kundert.",
71 | 'ITSAppUsesNonExemptEncryption': False,
72 | },
73 | bundle_identifier='ca.kundert.perry.SLIP39',
74 | )
75 |
--------------------------------------------------------------------------------
/SLIP-39-win32.spec:
--------------------------------------------------------------------------------
1 | # -*- mode: python ; coding: utf-8 -*-
2 | from PyInstaller.utils.hooks import collect_data_files
3 |
4 | datas = []
5 | datas += collect_data_files('shamir_mnemonic')
6 | datas += collect_data_files('slip39')
7 |
8 | block_cipher = None
9 |
10 | a = Analysis(
11 | ['SLIP-39.py'],
12 | pathex=[],
13 | binaries=[],
14 | datas=datas,
15 | hiddenimports=['slip39'],
16 | hookspath=[],
17 | hooksconfig={},
18 | runtime_hooks=[],
19 | excludes=[],
20 | win_no_prefer_redirects=False,
21 | win_private_assemblies=False,
22 | cipher=block_cipher,
23 | noarchive=False,
24 | )
25 |
26 | pyz = PYZ(
27 | a.pure,
28 | a.zipped_data,
29 | cipher=block_cipher,
30 | )
31 |
32 | exe = EXE(
33 | pyz,
34 | a.scripts,
35 | a.binaries,
36 | a.zipfiles,
37 | a.datas,
38 | [],
39 | name='SLIP-39',
40 | debug=False,
41 | bootloader_ignore_signals=False,
42 | strip=False,
43 | upx=True,
44 | upx_exclude=[],
45 | runtime_tmpdir=None,
46 | console=False,
47 | disable_windowed_traceback=False,
48 | argv_emulation=False,
49 | target_arch=None,
50 | codesign_identity=None,
51 | entitlements_file=None,
52 | )
53 |
--------------------------------------------------------------------------------
/SLIP-39.metadata/check-signature:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
4 |
5 | # IMPORTANT NOTE: This file is licensed only for use on Apple-branded
6 | # computers and is subject to the terms and conditions of the Apple Software
7 | # License Agreement accompanying the package this file is a part of.
8 | # You may not port this file to another platform without Apple's written consent.
9 |
10 | >&2 echo "(c) 2014 Apple Inc. All rights reserved."
11 |
12 | bundle_installer_requirements='(anchor apple generic and
13 | certificate 1[subject.CN] = "Apple Software Update Certification Authority") or
14 | (anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.10] exists) or
15 | (anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists and
16 | (certificate leaf[field.1.2.840.113635.100.6.1.14] or
17 | certificate leaf[field.1.2.840.113635.100.6.1.13]))'
18 |
19 | app_requirements='(anchor apple) or
20 | (anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9] exists) or
21 | (anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] exists
22 | and certificate leaf[field.1.2.840.113635.100.6.1.13] exists)'
23 |
24 | codesign=/usr/bin/codesign
25 |
26 | build_version=$(sw_vers -buildVersion)
27 | v1=$(sed 's/^\([0-9]*\).*/\1/' <<< $build_version)
28 | v2=$(sed 's/^[0-9]*\([A-Z]\).*/\1/' <<< $build_version)
29 |
30 | if [[ "$v1" -lt 13 || ( "$v1" -eq 13 && "$v2" < "F" ) ]]; then
31 | >&2 echo "This tool requires OS X Version 10.9.5 or higher."
32 | exit 3
33 | fi
34 |
35 | ok=1
36 | for target; do
37 | use_codesign=1
38 |
39 | if [[ $target == *.pkg || $target == *.mpkg ]]; then
40 | if [[ -d $target ]]; then
41 | >&2 echo "${target}: Warning: bundle installers are deprecated, please use regular installer packages."
42 | requirements=$bundle_installer_requirements
43 | else
44 | use_codesign=0
45 |
46 | pkgutil_output=$(pkgutil --check-signature "$target" 2>&1)
47 | result=$?
48 |
49 | [ $result -ne 0 ] && >&2 echo $pkgutil_output
50 | fi
51 | else
52 | requirements=$app_requirements
53 | fi
54 |
55 | if [[ $use_codesign -eq 1 ]]; then
56 | $codesign -v --deep -R="${requirements}" "$target"
57 | result=$?
58 |
59 | if [[ $result -eq 3 ]]; then
60 | >&2 echo "${target}: The target is not signed with Developer ID or by the Mac App Store."
61 | fi
62 | fi
63 |
64 | [ $# -ne 1 ] && echo -n "${target}: "
65 | if [[ $result -eq 0 ]]; then
66 | echo YES
67 | else
68 | echo NO
69 | ok=0
70 | fi
71 | done
72 |
73 | [ $ok -eq 1 ] && exit 0 || exit 2
74 |
--------------------------------------------------------------------------------
/SLIP-39.metadata/entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.files.user-selected.read-write
6 |
7 |
10 | com.apple.security.cs.allow-jit
11 | com.apple.security.cs.allow-unsigned-executable-memory
12 | com.apple.security.cs.disable-library-validation
13 |
14 |
15 |
--------------------------------------------------------------------------------
/SLIP-39.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env python3
2 |
3 | import sys
4 |
5 | from slip39.gui.main import main
6 |
7 | sys.exit( main() )
8 |
--------------------------------------------------------------------------------
/default.nix:
--------------------------------------------------------------------------------
1 | { pkgs ? import ./nixpkgs.nix {} }:
2 |
3 | with pkgs;
4 |
5 | let
6 | in
7 | {
8 | py313 = stdenv.mkDerivation rec {
9 | name = "python313-with-pytest";
10 |
11 | buildInputs = [
12 | cacert
13 | git
14 | gnumake
15 | openssh
16 | python313Full
17 | python313Packages.pytest
18 | python313Packages.tkinter
19 | ];
20 | };
21 |
22 | py312 = stdenv.mkDerivation rec {
23 | name = "python312-with-pytest";
24 |
25 | buildInputs = [
26 | cacert
27 | git
28 | gnumake
29 | openssh
30 | python312Full
31 | python312Packages.pytest
32 | python312Packages.tkinter
33 | ];
34 | };
35 |
36 | py311 = stdenv.mkDerivation rec {
37 | name = "python311-with-pytest";
38 |
39 | buildInputs = [
40 | cacert
41 | git
42 | gnumake
43 | openssh
44 | python311Full
45 | python311Packages.pytest
46 | python311Packages.tkinter
47 | ];
48 | };
49 |
50 | py310 = stdenv.mkDerivation rec {
51 | name = "python310-with-pytest";
52 |
53 | buildInputs = [
54 | cacert
55 | git
56 | gnumake
57 | openssh
58 | python310Full
59 | python310Packages.pytest
60 | python310Packages.tkinter
61 | ];
62 | };
63 |
64 | py39 = stdenv.mkDerivation rec {
65 | name = "python39-with-pytest";
66 |
67 | buildInputs = [
68 | cacert
69 | git
70 | gnumake
71 | openssh
72 | python39Full
73 | python39Packages.pytest
74 | python39Packages.tkinter
75 | ];
76 | };
77 | }
78 |
--------------------------------------------------------------------------------
/dkim-setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | #
4 | # dkim-setup
5 | #
6 | # See: https://russell.ballestrini.net/quickstart-to-dkim-sign-email-with-python/
7 | #
8 | # Create a new Email DKIM key for your company's licensing... subdomin, eg.
9 | #
10 | # licensing.awesome-inc.com
11 | #
12 |
13 | # This sub-domain exists solely to host a DKIM key to validate emails
14 | # generated by the company's product's Licensing verification code.
15 |
16 | # Signs an Email envelope for the singular purpose of sending Licensing
17 | # messages. This allows your software to send an SMTP email claiming to be from
18 | # the domain licensing.awesome-inc.com; DKIM-signed fields are indicated
19 | # by >:
20 |
21 | #
22 | # > From: no-reply@licensing.awesome-inc.com
23 | # > To: licensing@awesome-inc.com
24 | # Reply-To: some.client@example.com
25 | # > Subject: "Something Awesome" License: 123456
26 | #
27 | # > Dear Something Awesome Client;
28 | # >
29 | # > Your unique Client ID the Subject: line of this email.
30 | # >
31 | # > Please enter this Client ID when prompted, to complete your Licensing
32 | # > procedure for Example Inc's Awesome Product. Once you've entered
33 | # > the Client ID above, you will be authorized to use Something Awesome.
34 | # >
35 | # > Thanks,
36 | # > --
37 | # > Something Awesome
38 | # > Product Support
39 | # > support@awesome-inc.com
40 | #
41 |
42 | # The From/To and body are signed, the the Subject: is not, because we must
43 | # send a different Client ID in each email's Subject: line. An auto-responder
44 | # must be set up on your Company's (eg. awesome-inc.com) email server, for the
45 | # new "licensing" recipient email address:
46 |
47 | #
48 | # licensing@awesome-inc.com
49 | #
50 |
51 |
52 |
53 | # Each email arriving at licensing@awesome-inc.com must simply be bounced
54 | # back to the Reply-To: address indicated. This accomplishes:
55 |
56 | # 1) Informs licensing@awesome-inc.com of the potential new client's email
57 | # address + Client ID, which are used to generate the MultiPayoutERC20
58 | # contract's .forwarder_address(), generating the unique Cryptocurrency
59 | # account address into which the client will deposit their payment.
60 |
61 | # 2) Ensures that the client has personal control over the indicated email
62 | # address, preventing the generation of "Spam" installations and allow
63 | # communications with the client. Even though your product itself generates
64 | # the unique ID, it demands that the client receive it via email to complete
65 | # the verification, because the email address is used as part of the hash,
66 | # and we do not want people using the same email address, or other people's
67 | # email addresses.
68 |
69 | KTYPE="rsa" # "ed25519" # but not well supported yet; even by Cloudflare
70 |
71 | COMPANY=""
72 | while [ "${COMPANY}" == "" ]; do
73 | echo -n "What is your company's name: "
74 | read COMPANY
75 | done
76 |
77 | DOMAIN=""
78 | while [ "${DOMAIN}" == "" ]; do
79 | echo -n "What is your domain name: "
80 | read DOMAIN
81 | done
82 |
83 | SUB="licensing"
84 |
85 | # See if we've already got a DKIM .dns/.key pair w/ a certain "selector";
86 | # If not, create one with the present date
87 | SELECTOR=""
88 | for f in $( ls -1 ${SUB}.${DOMAIN}.*.dns | sort | tail -1 ); do
89 | f=${f%.dns}
90 | SELECTOR=${f#${SUB}.${DOMAIN}.}
91 | done
92 | if [ -z "${SELECTOR}" ]; then
93 | SELECTOR=$( date +%Y%m%d )
94 | fi
95 | TXTFILE="${SUB}.${DOMAIN}.${SELECTOR}.dns"
96 | if [ ! -r "${TXTFILE}" ]; then
97 | dknewkey --ktype ${KTYPE} ${SUB}.${DOMAIN}.${SELECTOR}
98 | fi
99 | ls -l ${TXTFILE}
100 |
101 | echo "Found DKIM key: $( cat ${TXTFILE} )"
102 |
103 | # See if it's installed in DNS. Dig always returns TXT as string literals: "..."
104 | TXTREC="${SELECTOR}._domainkey.${SUB}.${DOMAIN}"
105 | echo -n "Checking DNS at ${TXTREC} ..."
106 | TXT=$( python3 -m crypto_licensing.licensing.doh --no-json dig ${TXTREC} TXT )
107 | echo ${TXT}
108 |
109 | if (( $? )); then
110 | echo "Failed attempting to query DNS for ${TXTREC}";
111 | exit 1
112 | elif [ -z "${TXT}" ]; then
113 | echo "No TXT record found at ${TXTREC}"
114 | exit 1
115 | elif ! echo -n ${TXT//\"} | diff ${TXTFILE} -; then
116 | echo "${TXTFILE} doesn't match ${TXTREC} TXT record"
117 | exit 1
118 | fi
119 |
120 | echo "DKIM properly set up for ${TXTREC}: ${TXT}"
121 |
--------------------------------------------------------------------------------
/fonts_list.py:
--------------------------------------------------------------------------------
1 | from tkinter import Tk, font
2 | import PySimpleGUI as sg
3 | root = Tk()
4 | font_tuple = font.families()
5 | #Creates a Empty list to hold font names
6 | FontList=[]
7 | fonts = [font.Font(family=f) for f in font.families()]
8 | monospace = (f for f in fonts if f.metrics("fixed"))
9 | # for font in font_tuple:
10 | # FontList.append(font)
11 | for font in monospace:
12 | FontList.append(font.actual('family'))
13 | root.destroy()
14 | print( '\n'.join( FontList ))
15 |
16 | #size 28, 28 is optimized for my Android phone please tweak as per your screen
17 | #Scrolled popup to accommodate big list
18 | sg.popup_scrolled(FontList, title='All fonts installed using PySimpleGUI', size=(28,28), grab_anywhere=True)
19 |
20 |
--------------------------------------------------------------------------------
/images/1x1-ffffff3f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/1x1-ffffff3f.png
--------------------------------------------------------------------------------
/images/1x1-ffffff7f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/1x1-ffffff7f.png
--------------------------------------------------------------------------------
/images/1x1-ffffffbf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/1x1-ffffffbf.png
--------------------------------------------------------------------------------
/images/BIP-39-backup-entropy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/BIP-39-backup-entropy.png
--------------------------------------------------------------------------------
/images/BSC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/BSC.png
--------------------------------------------------------------------------------
/images/BSC.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
105 |
--------------------------------------------------------------------------------
/images/BTC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/BTC.png
--------------------------------------------------------------------------------
/images/BTC.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
53 |
--------------------------------------------------------------------------------
/images/CRO.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/CRO.png
--------------------------------------------------------------------------------
/images/CRO.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
26 |
--------------------------------------------------------------------------------
/images/DOGE.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/DOGE.png
--------------------------------------------------------------------------------
/images/DOGE.svg:
--------------------------------------------------------------------------------
1 |
2 |
54 |
--------------------------------------------------------------------------------
/images/ETH.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/ETH.png
--------------------------------------------------------------------------------
/images/ETH.svg:
--------------------------------------------------------------------------------
1 |
2 |
82 |
--------------------------------------------------------------------------------
/images/LTC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/LTC.png
--------------------------------------------------------------------------------
/images/LTC.svg:
--------------------------------------------------------------------------------
1 |
2 |
72 |
--------------------------------------------------------------------------------
/images/SLIP-39.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/SLIP-39.icns
--------------------------------------------------------------------------------
/images/SLIP-39.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/SLIP-39.ico
--------------------------------------------------------------------------------
/images/SLIP-39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/SLIP-39.png
--------------------------------------------------------------------------------
/images/SLIP39 - Screen Shot 1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/SLIP39 - Screen Shot 1.png
--------------------------------------------------------------------------------
/images/SLIP39 - Screen Shot 1.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/SLIP39 - Screen Shot 1.xcf
--------------------------------------------------------------------------------
/images/SLIP39-Example.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/SLIP39-Example.pdf
--------------------------------------------------------------------------------
/images/SLIP39-backup-BIP39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/SLIP39-backup-BIP39.png
--------------------------------------------------------------------------------
/images/SLIP39-recover-BIP39-entropy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/SLIP39-recover-BIP39-entropy.png
--------------------------------------------------------------------------------
/images/SLIP39-recover-BIP39-mnemonic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/SLIP39-recover-BIP39-mnemonic.png
--------------------------------------------------------------------------------
/images/XRP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/XRP.png
--------------------------------------------------------------------------------
/images/XRP.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
81 |
--------------------------------------------------------------------------------
/images/boo.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/images/boo2.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/images/guilloche-center.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/guilloche-center.png
--------------------------------------------------------------------------------
/images/slip39-cards.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/slip39-cards.png
--------------------------------------------------------------------------------
/images/slip39-overview-youtube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/slip39-overview-youtube.png
--------------------------------------------------------------------------------
/images/slip39-wallets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/slip39-wallets.png
--------------------------------------------------------------------------------
/images/slip39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/images/slip39.png
--------------------------------------------------------------------------------
/nixpkgs.nix:
--------------------------------------------------------------------------------
1 | import (fetchTarball {
2 | url = "https://github.com/NixOS/nixpkgs/archive/refs/tags/23.11.tar.gz";
3 | sha256 = "1ndiv385w1qyb3b18vw13991fzb9wg4cl21wglk89grsfsnra41k";
4 | })
5 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools >= 40.9.0", "wheel"]
3 | build-backend = "setuptools.build_meta"
4 |
--------------------------------------------------------------------------------
/pytest.ini:
--------------------------------------------------------------------------------
1 | [pytest]
2 | testpaths = slip39
3 | addopts = -v --ignore-glob=**/__main__.py --ignore-glob=**/main.py --ignore-glob=**/ethereum.py --cov=slip39 --cov-config=.coveragerc
4 |
--------------------------------------------------------------------------------
/requirements-dev.txt:
--------------------------------------------------------------------------------
1 | build
2 | cx_Freeze >=6.12
3 | setuptools
4 | wheel
5 |
--------------------------------------------------------------------------------
/requirements-gui.txt:
--------------------------------------------------------------------------------
1 | pysimplegui >=5.0.7,<5.1
2 |
--------------------------------------------------------------------------------
/requirements-invoice.txt:
--------------------------------------------------------------------------------
1 | eth-account >=0.8.0,<0.9
2 | py-solc-x >=1.1.1,<1.2
3 | pycryptodome >=3.16, <4
4 | requests >=2.20, <3
5 |
6 | dkimpy[ed25519] >=1.0.5,<2
7 |
8 | # These versions are very brittle; must be upgraded in lock-step (see web3.py/setup.py)
9 | # 6.0.0b9
10 | #web3[tester] ==6.0.0b9
11 | #eth-tester[py-evm] ==v0.8.0-b.3
12 | # Until ethpm upgrade to avoid dependency
13 | #ipfshttpclient ; python_version >= "3.11"
14 |
15 | # 6.6.1
16 | web3[tester] ==6.8.0
17 | eth-tester[py-evm] ==v0.9.1-b.1
18 | # Until ethpm upgrade to avoid dependency
19 | #ipfshttpclient = 0.8.0a2
20 |
--------------------------------------------------------------------------------
/requirements-serial.txt:
--------------------------------------------------------------------------------
1 | pyserial >=3.5
2 |
--------------------------------------------------------------------------------
/requirements-tests.txt:
--------------------------------------------------------------------------------
1 | aiosmtpd >=1.4, <2
2 | build
3 | cx_Freeze >=6.12
4 | flake8
5 | pyinstaller >=6.1
6 | pytest >=7.4.2,<8
7 | pytest-cov >=4.1.0,<5
8 | setuptools
9 | wheel
10 |
--------------------------------------------------------------------------------
/requirements-wallet.txt:
--------------------------------------------------------------------------------
1 | eth-account >=0.8.0,<0.9
2 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | base58 >=2.0.1,<3
2 | chacha20poly1305 >=0.0.3
3 | click >=8.1.3,<9
4 | crypto-licensing >=3.3.2,<4
5 | cx_Freeze >=6.12 ; sys_platform == "win32"
6 | fpdf2 >=2.7.6,<3
7 | #hdwallet >=2.3.0,<3
8 | hdwallet-slip39 >=2.3.0,<3
9 | #tabulate >=0.10.0
10 | tabulate-slip39 >=0.10.0
11 | mnemonic >=0.21, <1
12 | qrcode >=7.3
13 | #shamir-mnemonic >=0.3.0,<0.4
14 | shamir-mnemonic-slip39 >=0.4.0,<0.5
15 |
--------------------------------------------------------------------------------
/shell.nix:
--------------------------------------------------------------------------------
1 | { pkgs ? import ./nixpkgs.nix {} }:
2 |
3 | let
4 | targets = import ./default.nix {
5 | inherit pkgs;
6 | };
7 | targeted = builtins.getEnv "TARGET";
8 | selected = targeted + pkgs.lib.optionalString (targeted == "") "py312";
9 | in
10 |
11 | with pkgs;
12 |
13 | mkShell {
14 | buildInputs = lib.getAttrFromPath [ selected "buildInputs" ] targets;
15 |
16 | shellHook = ''
17 | echo "Welcome to the Python ${selected} environment!"
18 | '';
19 | }
20 |
--------------------------------------------------------------------------------
/slip39/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | #
3 | # Python-slip39 -- Ethereum SLIP-39 Account Generation and Recovery
4 | #
5 | # Copyright (c) 2022, Dominion Research & Development Corp.
6 | #
7 | # Python-slip39 is free software: you can redistribute it and/or modify it under
8 | # the terms of the GNU General Public License as published by the Free Software
9 | # Foundation, either version 3 of the License, or (at your option) any later
10 | # version. It is also available under alternative (eg. Commercial) licenses, at
11 | # your option. See the LICENSE file at the top of the source tree.
12 | #
13 | # Python-slip39 is distributed in the hope that it will be useful, but WITHOUT
14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 | #
17 |
18 | from __future__ import annotations
19 |
20 | __author__ = "Perry Kundert"
21 | __email__ = "perry@dominionrnd.com"
22 | __copyright__ = "Copyright (c) 2022 Dominion Research & Development Corp."
23 | __license__ = "Dual License: GPLv3 (or later) and Commercial (see LICENSE)"
24 |
25 | from .version import __version__, __version_info__ # noqa F401
26 | from .api import * # noqa F403
27 | from .layout import * # noqa F403
28 | from .recovery import * # noqa F403
29 |
--------------------------------------------------------------------------------
/slip39/__main__.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | from .main import main
4 |
5 | sys.exit( main() )
6 |
--------------------------------------------------------------------------------
/slip39/cli/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | #
3 | # Python-slip39 -- Ethereum SLIP-39 Account Generation and Recovery
4 | #
5 | # Copyright (c) 2022, Dominion Research & Development Corp.
6 | #
7 | # Python-slip39 is free software: you can redistribute it and/or modify it under
8 | # the terms of the GNU General Public License as published by the Free Software
9 | # Foundation, either version 3 of the License, or (at your option) any later
10 | # version. It is also available under alternative (eg. Commercial) licenses, at
11 | # your option. See the LICENSE file at the top of the source tree.
12 | #
13 | # Python-slip39 is distributed in the hope that it will be useful, but WITHOUT
14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 | #
17 |
18 | from __future__ import annotations
19 |
20 | import click
21 | import json
22 | import logging
23 | import string
24 |
25 | from .. import addresses as slip39_addresses
26 | from ..util import commas, log_cfg, log_level, input_secure
27 | from ..defaults import BITS
28 |
29 | __author__ = "Perry Kundert"
30 | __email__ = "perry@dominionrnd.com"
31 | __copyright__ = "Copyright (c) 2022 Dominion Research & Development Corp."
32 | __license__ = "Dual License: GPLv3 (or later) and Commercial (see LICENSE)"
33 |
34 | """
35 | Provide basic CLI access to the slip39 API.
36 |
37 | Output generally defaults to JSON. Use -v for more details, and --no-json to emit standard text output instead.
38 | """
39 |
40 | log = logging.getLogger( __package__ )
41 |
42 |
43 | @click.group()
44 | @click.option('-v', '--verbose', count=True)
45 | @click.option('-q', '--quiet', count=True)
46 | @click.option( '--json/--no-json', default=True, help="Output JSON (the default)")
47 | def cli( verbose, quiet, json ):
48 | cli.verbosity = verbose - quiet
49 | log_cfg['level'] = log_level( cli.verbosity )
50 | logging.basicConfig( **log_cfg )
51 | if verbose or quiet:
52 | logging.getLogger().setLevel( log_cfg['level'] )
53 | cli.json = json
54 | cli.verbosity = 0 # noqa: E305
55 | cli.json = False
56 |
57 |
58 | @click.command()
59 | @click.option( "--crypto", help="The cryptocurrency address to generate (default: BTC)" )
60 | @click.option( "--paths", help="The HD wallet derivation path (default: the standard path for the cryptocurrency; if xpub, omits leading hardened segments by default)" )
61 | @click.option( "--secret", required=True, help="A hex seed or '{x,y,z}{pub,prv}...' x-public/private key to derive HD wallet addresses from; '-' reads it from stdin" )
62 | @click.option( "--format", help="legacy, segwit, bech32 (default: standard for cryptocurrency or '{x,y,z}{pub/prv}...' key)" )
63 | @click.option( '--unbounded/--no-unbounded', default=False, help="Allow unbounded sequences of addresses")
64 | def addresses( crypto, paths, secret, format, unbounded ):
65 | if secret == '-':
66 | secret = input_secure( 'Master secret hex: ', secret=True )
67 | elif secret and ( secret.lower().startswith( '0x' )
68 | or all( c in string.hexdigits for c in secret )):
69 | log.warning( "It is recommended to not use '-s|--secret '; specify '-' to read from input" )
70 | if secret and secret.lower().startswith('0x'):
71 | secret = secret[2:]
72 | if not secret:
73 | log.error( f"Provide a random {commas( BITS, final='or' )}-bit Seed via --secret" )
74 | if cli.json:
75 | click.echo( "[" )
76 | for i,(cry,pth,adr) in enumerate( slip39_addresses(
77 | master_secret = secret,
78 | crypto = crypto,
79 | paths = paths,
80 | format = format,
81 | allow_unbounded = unbounded
82 | )):
83 | if cli.json:
84 | if i:
85 | click.echo( "," )
86 | if cli.verbosity > 0:
87 | click.echo( f" [{json.dumps( cry )+',':6} {json.dumps( pth )+',':21} {json.dumps( adr )}]", nl=False )
88 | else:
89 | click.echo( f" {json.dumps( adr )}", nl=False )
90 | else:
91 | if cli.verbosity > 0:
92 | click.echo( f"{cry:5} {pth:20} {adr}" )
93 | else:
94 | click.echo( f"{adr}" )
95 | if cli.json:
96 | click.echo( "\n]" )
97 |
98 |
99 | cli.add_command( addresses )
100 |
--------------------------------------------------------------------------------
/slip39/cli/__main__.py:
--------------------------------------------------------------------------------
1 |
2 | #
3 | # Python-slip39 -- Ethereum SLIP-39 Account Generation and Recovery
4 | #
5 | # Copyright (c) 2022, Dominion Research & Development Corp.
6 | #
7 | # Python-slip39 is free software: you can redistribute it and/or modify it under
8 | # the terms of the GNU General Public License as published by the Free Software
9 | # Foundation, either version 3 of the License, or (at your option) any later
10 | # version. It is also available under alternative (eg. Commercial) licenses, at
11 | # your option. See the LICENSE file at the top of the source tree.
12 | #
13 | # Python-slip39 is distributed in the hope that it will be useful, but WITHOUT
14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 | #
17 |
18 | from __future__ import annotations
19 |
20 | from . import cli
21 |
22 | __author__ = "Perry Kundert"
23 | __email__ = "perry@dominionrnd.com"
24 | __copyright__ = "Copyright (c) 2022 Dominion Research & Development Corp."
25 | __license__ = "Dual License: GPLv3 (or later) and Commercial (see LICENSE)"
26 |
27 | cli()
28 |
--------------------------------------------------------------------------------
/slip39/generator/__main__.py:
--------------------------------------------------------------------------------
1 |
2 | #
3 | # Python-slip39 -- Ethereum SLIP-39 Account Generation and Recovery
4 | #
5 | # Copyright (c) 2022, Dominion Research & Development Corp.
6 | #
7 | # Python-slip39 is free software: you can redistribute it and/or modify it under
8 | # the terms of the GNU General Public License as published by the Free Software
9 | # Foundation, either version 3 of the License, or (at your option) any later
10 | # version. It is also available under alternative (eg. Commercial) licenses, at
11 | # your option. See the LICENSE file at the top of the source tree.
12 | #
13 | # Python-slip39 is distributed in the hope that it will be useful, but WITHOUT
14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 | #
17 |
18 | from __future__ import annotations
19 |
20 | import sys
21 |
22 | from .main import main
23 |
24 | __author__ = "Perry Kundert"
25 | __email__ = "perry@dominionrnd.com"
26 | __copyright__ = "Copyright (c) 2022 Dominion Research & Development Corp."
27 | __license__ = "Dual License: GPLv3 (or later) and Commercial (see LICENSE)"
28 |
29 | sys.exit( main() )
30 |
--------------------------------------------------------------------------------
/slip39/generator_test.py:
--------------------------------------------------------------------------------
1 | import os
2 | import logging
3 | import threading
4 |
5 | import pytest
6 |
7 | try:
8 | import pty
9 | from serial import Serial
10 | except ImportError:
11 | Serial = None
12 |
13 | from .api import random_secret, accountgroups
14 | from .generator import chacha20poly1305, accountgroups_output, accountgroups_input
15 |
16 | log = logging.getLogger( __package__ )
17 |
18 |
19 | def listener(port):
20 | # continuously listen to commands on the master device
21 | while True:
22 | res = b""
23 | while not res.endswith(b"\r\n"):
24 | # keep reading one byte at a time until we have a full line
25 | res += os.read(port, 1)
26 | #print("command: %s" % res)
27 |
28 | # write back the response
29 | if res == b'QPGS\r\n':
30 | os.write(port, b"correct result\r\n")
31 | else:
32 | os.write(port, b"I don't understand\r\n")
33 |
34 |
35 | @pytest.mark.skipif( not Serial,
36 | reason="Serial testing needs pyserial" )
37 | def test_serial():
38 | """Start the testing"""
39 | master,slave = pty.openpty() # open the pseudoterminal
40 | s_name = os.ttyname(slave) # translate the slave fd to a filename
41 |
42 | log.info( f"Pty name: {s_name}" )
43 |
44 | # create a separate thread that listens on the master device for commands
45 | thread = threading.Thread(target=listener, args=[master])
46 | thread.daemon = True
47 | thread.start()
48 |
49 | # open a pySerial connection to the slave. Receiver can signal sender to stop/start
50 | ser = Serial(s_name, 2400, timeout=1)
51 |
52 | ser.write(b'test2\r\n') # write the first command
53 | res = b""
54 | while not res.endswith(b'\r\n'):
55 | # read the response
56 | res += ser.read()
57 | log.info("result: %s" % res)
58 | assert res.startswith( b"I don't understand" )
59 |
60 | ser.write(b'QPGS\r\n') # write a second command
61 | res = b""
62 | while not res.endswith(b'\r\n'):
63 | # read the response
64 | res += ser.read()
65 | log.info("result: %s" % res)
66 | assert res.startswith( b"correct result" )
67 |
68 |
69 | def generator( password, cryptopaths, fd ):
70 | """Generate a sequence of Accounts to the given file descriptor."""
71 | fdout = os.fdopen( fd, "w" )
72 | nonce = random_secret( 12 )
73 | cipher = chacha20poly1305( password=password )
74 | for index,group in enumerate( accountgroups(
75 | master_secret = b'\xff' * 16,
76 | cryptopaths = cryptopaths,
77 | )):
78 | log.info( f"Sending: {group}" )
79 | accountgroups_output(
80 | group = group,
81 | index = index,
82 | cipher = cipher,
83 | nonce = nonce,
84 | corrupt = .01,
85 | file = fdout,
86 | )
87 |
88 |
89 | @pytest.mark.skipif( not Serial,
90 | reason="Serial testing needs pyserial" )
91 | def test_groups_pty():
92 | password = "password"
93 | master,slave = pty.openpty()
94 | slave_name = os.ttyname( slave )
95 |
96 | cryptopaths = [
97 | ("ETH", "m/44'/60'/0'/0/-10"),
98 | ("ETH", "m/44'/ 0'/0'/0/-10"),
99 | ]
100 |
101 | gen = threading.Thread(
102 | target = generator,
103 | args = [password, cryptopaths, master] )
104 | gen.daemon = True
105 | gen.start()
106 |
107 | class SerialEOF( Serial ):
108 | """Convert any SerialException to an EOFError, for compatibility with PTY. In real serial
109 | ports, we'll handle detection of counterparty readiness with DTR/DSR, and flow control with
110 | RTS/CTS.
111 |
112 | """
113 | def read( self, size=1 ):
114 | while True:
115 | try:
116 | return super( SerialEOF, self ).read( size=size )
117 | except Exception as exc: # SerialError as exc:
118 | # if "readiness" in str(exc):
119 | # time.sleep( .1 )
120 | # continue
121 | raise EOFError( str( exc ))
122 |
123 | ser = SerialEOF( slave_name, timeout=1)
124 | for group in accountgroups_input(
125 | cipher = chacha20poly1305( password=password ),
126 | encoding = 'UTF-8',
127 | file = ser
128 | ):
129 | log.info( f"Receive: {group}" )
130 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-AS-BIP.org:
--------------------------------------------------------------------------------
1 | #+title: Using BIP-39
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | SLIP-39 Mnemonics can be used directly on a Trezor to backup/restore the Seed.
6 |
7 | Also supports other Hardware Wallets that require a BIP-39 Mnemonic for Seed recovery, such as to
8 | your Ledger Nano. Recover your BIP-39 Seed Phrase from these SLIP-39 cards using the GUI (or
9 | command-line, or [[https://iancoleman.io/slip39/]]) whenever you need it, to restore your Crypto
10 | accounts to your hardware wallet.
11 |
12 | | Controls | Description |
13 | |----------+---------------------------------------------------------------------|
14 | | Backup | Already using a BIP-39 Seed Phrase? Back it up using SLIP-39 Cards |
15 | | Create | Generate SLIP-39 Cards, even if using a BIP-39 hardware wallet |
16 | | Recover | Use SLIP-39/BIP-39 to recover Seed, supports using BIP-39 on wallet |
17 | | Pro | Convert existing BIP-39 Seed to SLIP-39 for "Paper Wallet" backup |
18 | #+END_ABSTRACT
19 |
20 | * Using BIP-39
21 |
22 | To support older or less expensive existing hardware wallets that *only* support BIP-39 recovery,
23 | *or* to backup existing BIP-39 Mnemonic phrases to SLIP-39 (to avoid moving all of your old
24 | BIP-39 Seed derived wallets to new SLIP-39 Seed derived wallets), click the "Using BIP-39"
25 | checkbox (this is the default). This will do two things:
26 |
27 | ** Output BIP-39 Mnemonics
28 |
29 | You will see your BIP-39 Mnemonic, which encodes the Seed Source (and optionally any Seed Extra
30 | Randomness) you've specified.
31 |
32 | We'll even include one BIP-39 card in the output PDF. You can store this card (very safely and
33 | securely), but we recommend you destroy it, and instead use the SLIP-39 App with your SLIP-39
34 | Mnemonic Cards to recover the BIP-39 Mnemonic phrase when needed.
35 |
36 | ** Use BIP-39 Seed Generation
37 |
38 | Any Cryptocurrency wallet QR codes and Paper Wallets will be derived using standard BIP-39 Seed generation.
39 |
40 | Since BIP-39 uses the Seed Entropy *differently* than SLIP-39 does, this produces *different*
41 | wallets in the hardware wallet device! In other words, exactly the same 128- or 256-bit entropy
42 | produces different wallets in a [[https://affil.trezor.io/SHdv][Trezor Safe 3]] recovered directly from SLIP-39 Mnemonics, compared
43 | to the same Trezor or [[https://shop.ledger.com/pages/ledger-nano-x?r=2cd1cb6ae51f][Ledger Nano X]] recovered from BIP-39.
44 |
45 | This is usually not a problem: just ensure that if you're intending to use a hardware wallet that
46 | natively supports SLIP-39 (like the Trezor), *do not select* "Using BIP-39". Then, the QR codes
47 | and Paper Wallets printed will match those produced in the hardware wallet after SLIP-39
48 | recovery.
49 |
50 | If your hardware wallet only supports BIP-39 (or you're just backing up the Seed Entropy of an
51 | existing BIP-39 Mnemonic using SLIP-39, and you want to continue using the original BIP-39
52 | wallets), then *do select* "Using BIP-39". Then, when you recover your Trezor or Ledger from
53 | BIP-39, the printed QR codes and Paper Wallets will use the BIP-39 Seed generation standard, and
54 | will match those produced in the hardware after BIP-39 recovery.
55 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-AS-BIP.txt:
--------------------------------------------------------------------------------
1 | SLIP-39 Mnemonics can be used directly on a Trezor to backup/restore the
2 | Seed.
3 |
4 | Also supports other Hardware Wallets that require a BIP-39 Mnemonic for
5 | Seed recovery, such as to your Ledger Nano. Recover your BIP-39 Seed
6 | Phrase from these SLIP-39 cards using the GUI (or command-line, or
7 | ) whenever you need it, to restore your
8 | Crypto accounts to your hardware wallet.
9 |
10 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
11 | Controls Description
12 | ───────────────────────────────────────────────────────────────────────────────
13 | Backup Already using a BIP-39 Seed Phrase? Back it up using SLIP-39 Cards
14 | Create Generate SLIP-39 Cards, even if using a BIP-39 hardware wallet
15 | Recover Use SLIP-39/BIP-39 to recover Seed, supports using BIP-39 on wallet
16 | Pro Convert existing BIP-39 Seed to SLIP-39 for "Paper Wallet" backup
17 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
18 |
19 |
20 | 1 Using BIP-39
21 | ══════════════
22 |
23 | To support older or less expensive existing hardware wallets that
24 | *only* support BIP-39 recovery, *or* to backup existing BIP-39
25 | Mnemonic phrases to SLIP-39 (to avoid moving all of your old BIP-39
26 | Seed derived wallets to new SLIP-39 Seed derived wallets), click the
27 | "Using BIP-39" checkbox (this is the default). This will do two
28 | things:
29 |
30 |
31 | 1.1 Output BIP-39 Mnemonics
32 | ───────────────────────────
33 |
34 | You will see your BIP-39 Mnemonic, which encodes the Seed Source (and
35 | optionally any Seed Extra Randomness) you've specified.
36 |
37 | We'll even include one BIP-39 card in the output PDF. You can store
38 | this card (very safely and securely), but we recommend you destroy it,
39 | and instead use the SLIP-39 App with your SLIP-39 Mnemonic Cards to
40 | recover the BIP-39 Mnemonic phrase when needed.
41 |
42 |
43 | 1.2 Use BIP-39 Seed Generation
44 | ──────────────────────────────
45 |
46 | Any Cryptocurrency wallet QR codes and Paper Wallets will be derived
47 | using standard BIP-39 Seed generation.
48 |
49 | Since BIP-39 uses the Seed Entropy *differently* than SLIP-39 does,
50 | this produces *different* wallets in the hardware wallet device! In
51 | other words, exactly the same 128- or 256-bit entropy produces
52 | different wallets in a [Trezor Safe 3] recovered directly from SLIP-39
53 | Mnemonics, compared to the same Trezor or [Ledger Nano X] recovered
54 | from BIP-39.
55 |
56 | This is usually not a problem: just ensure that if you're intending to
57 | use a hardware wallet that natively supports SLIP-39 (like the
58 | Trezor), *do not select* "Using BIP-39". Then, the QR codes and Paper
59 | Wallets printed will match those produced in the hardware wallet after
60 | SLIP-39 recovery.
61 |
62 | If your hardware wallet only supports BIP-39 (or you're just backing
63 | up the Seed Entropy of an existing BIP-39 Mnemonic using SLIP-39, and
64 | you want to continue using the original BIP-39 wallets), then *do
65 | select* "Using BIP-39". Then, when you recover your Trezor or Ledger
66 | from BIP-39, the printed QR codes and Paper Wallets will use the
67 | BIP-39 Seed generation standard, and will match those produced in the
68 | hardware after BIP-39 recovery.
69 |
70 |
71 | [Trezor Safe 3]
72 |
73 | [Ledger Nano X]
74 |
75 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-CRYPTO.org:
--------------------------------------------------------------------------------
1 | #+title: Cryptocurrencies
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | Cryptocurrencies Wallet addresses to display, and the Paper Wallets to produce (if a password is
6 | supplied). The cryptocurrencies supported, and the standard BIP-44 derivation paths (Trezor,
7 | Ledger, etc. compatible) displayed are:
8 |
9 | | Controls | Crypto | Semantic | Path | Address | Support |
10 | |-----------+--------+----------+-------------------+---------+---------|
11 | | (default) | ETH | Legacy | m/44'/ 60'/0'/0/0 | 0x... | |
12 | | (default) | BTC | Bech32 | m/84'/ 0'/0'/0/0 | bc1... | |
13 | | | | SegWit | m/49'/ 0'/0'/0/0 | 3... | |
14 | | | | Legacy | m/44'/ 0'/0'/0/0 | 1... | |
15 | | Recover | LTC | Bech32 | m/84'/ 2'/0'/0/0 | ltc1... | |
16 | | | | SegWit | m/49'/ 2'/0'/0/0 | M... | |
17 | | | | Legacy | m/44'/ 2'/0'/0/0 | L... | |
18 | | Recover | DOGE | Legacy | m/44'/ 3'/0'/0/0 | D... | |
19 | | Pro | BSC | Legacy | m/44'/ 60'/0'/0/0 | 0x... | Beta |
20 | | Pro | XRP | Legacy | m/44'/144'/0'/0/0 | r... | |
21 |
22 | On each SLIP-39 card, up to 2 Wallet addresses and QR codes will be displayed, for information
23 | purposes only, to illustrate *which* Wallets are derived from this Seed.
24 | #+END_ABSTRACT
25 |
26 | * Semantics
27 |
28 | By default, we produce address semantics compatible with what the Trezor hardware wallet produces
29 | (ie. Bech32, for =BTC= and =LTC=). The underlying =slip39= library is capable of producing the
30 | Legacy and SegWit forms of these addresses, if necessary.
31 |
32 | * Cryptocurrencies In Beta Testing
33 |
34 | XRP and BSC wallet addresses are also supported, if desired (currently in Beta testing quality).
35 | Generated Paper Wallets should be /tested/ to ensure that generated and recovered private keys are
36 | valid.
37 |
38 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-CRYPTO.txt:
--------------------------------------------------------------------------------
1 | Cryptocurrencies Wallet addresses to display, and the Paper Wallets to
2 | produce (if a password is supplied). The cryptocurrencies supported,
3 | and the standard BIP-44 derivation paths (Trezor, Ledger, etc.
4 | compatible) displayed are:
5 |
6 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
7 | Controls Crypto Semantic Path Address Support
8 | ──────────────────────────────────────────────────────────────────
9 | (default) ETH Legacy m/44'/ 60'/0'/0/0 0x…
10 | (default) BTC Bech32 m/84'/ 0'/0'/0/0 bc1…
11 | SegWit m/49'/ 0'/0'/0/0 3…
12 | Legacy m/44'/ 0'/0'/0/0 1…
13 | Recover LTC Bech32 m/84'/ 2'/0'/0/0 ltc1…
14 | SegWit m/49'/ 2'/0'/0/0 M…
15 | Legacy m/44'/ 2'/0'/0/0 L…
16 | Recover DOGE Legacy m/44'/ 3'/0'/0/0 D…
17 | Pro BSC Legacy m/44'/ 60'/0'/0/0 0x… Beta
18 | Pro XRP Legacy m/44'/144'/0'/0/0 r…
19 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
20 |
21 | On each SLIP-39 card, up to 2 Wallet addresses and QR codes will be
22 | displayed, for information purposes only, to illustrate *which* Wallets
23 | are derived from this Seed.
24 |
25 |
26 | 1 Semantics
27 | ═══════════
28 |
29 | By default, we produce address semantics compatible with what the
30 | Trezor hardware wallet produces (ie. Bech32, for `BTC' and `LTC').
31 | The underlying `slip39' library is capable of producing the Legacy and
32 | SegWit forms of these addresses, if necessary.
33 |
34 |
35 | 2 Cryptocurrencies In Beta Testing
36 | ══════════════════════════════════
37 |
38 | XRP and BSC wallet addresses are also supported, if desired (currently
39 | in Beta testing quality). Generated Paper Wallets should be /tested/
40 | to ensure that generated and recovered private keys are valid.
41 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-CS.org:
--------------------------------------------------------------------------------
1 | #+title: SLIP-39 Card Sizes
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | Select the desired SLIP-39 card size.
6 |
7 | | Controls | Card Size | Width | Height |
8 | |-----------+-----------+--------+--------|
9 | | (default) | Business | 3-1/2" | 2" |
10 | | All | Credit | 3-3/8" | 2-1/4" |
11 | | All | Index | 5" | 3" |
12 | | Recover | Half | 8" | 4.5" |
13 | | Recover | Third | 8" | 3-3/8" |
14 | | Recover | Quarter | 8" | 2-5/8" |
15 | | Pro | Photo | 5-1/2" | 3-1/5" |
16 |
17 | #+END_ABSTRACT
18 |
19 | * Orientation
20 |
21 | SLIP-39 Cards will be laid out on the desired paper size in the most optimal
22 | orientation, to fit the most Cards on the selected paper.
23 |
24 | ** Paper Wallets
25 |
26 | If Cryptocurrency "Paper Wallet" are printed, the selected Paper will always be printed in Portrait
27 | orientation.
28 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-CS.txt:
--------------------------------------------------------------------------------
1 | Select the desired SLIP-39 card size.
2 |
3 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4 | Controls Card Size Width Height
5 | ──────────────────────────────────────
6 | (default) Business 3-1/2" 2"
7 | All Credit 3-3/8" 2-1/4"
8 | All Index 5" 3"
9 | Recover Half 8" 4.5"
10 | Recover Third 8" 3-3/8"
11 | Recover Quarter 8" 2-5/8"
12 | Pro Photo 5-1/2" 3-1/5"
13 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
14 |
15 |
16 | 1 Orientation
17 | ═════════════
18 |
19 | SLIP-39 Cards will be laid out on the desired paper size in the most
20 | optimal orientation, to fit the most Cards on the selected paper.
21 |
22 |
23 | 1.1 Paper Wallets
24 | ─────────────────
25 |
26 | If Cryptocurrency "Paper Wallet" are printed, the selected Paper will
27 | always be printed in Portrait orientation.
28 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-EXTENDABLE.org:
--------------------------------------------------------------------------------
1 | #+title: Extendable
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | SLIP-39 Mnemonics recover a unique (but "valid") Seed and derived wallets, no matter what
6 | /alternative/ passphrase you use! Your /original/ Seed can only be recovered with the originally
7 | specified "correct" passphrase.
8 |
9 | Extendable SLIP-39 Mnemonics ensures that all SLIP-39 Mnemonic sets generated from the /original/
10 | Seed and original "correct" passphrase will /always/ result in the same unique Seed for each
11 | /alternative/ passphrase.
12 |
13 | Non-Extendable SLIP-39 Mnemonics recover the /original/ Seed with the "correct" passphrase, but
14 | *different* unique Seeds for all /alternative/ passphrases.
15 | #+END_ABSTRACT
16 |
17 | * Extendable
18 |
19 | The default is now /Extendable/ -- does /not/ use the Identifier to salt the encryption passphrase.
20 |
21 | ** The Purpose for Multiple Passphrases
22 |
23 | Recovering different Seeds for different passphrases is a valuable feature, because you may use
24 | the same SLIP-39 Mnemonic cards, and supply different passphrases to recover different (but valid)
25 | Seeds and sets of derived HD wallets!
26 |
27 | - You could have a "distress" passphrase that recovers a decoy wallet containing a
28 | small amount of sacrificial funds, while your real savings are under a different passphrase.
29 | - One password for your personal accounts and another for business accounts.
30 |
31 | ** Non-Extendable Encoding
32 |
33 | Historically, the SLIP-39 encoding used the randomly assigned Identifier to both 1) associate groups
34 | of Mnemonics belonging to the same set, but /also/ 2) to salt the Seed encryption.
35 |
36 | This meant that: if you created 2 sets of SLIP-39 Mnemonics for the same Seed -- each set would
37 | lead to */same/* Seed with the "correct" original passphrase, but to */different/* Seeds with
38 | each "distress" passphrase!
39 |
40 | Unless all sets of SLIP-39 Mnemonics lead to the same Seeds for each passphrase, you are
41 | restricted to ever issue /only one/ set of SLIP-39 Mnemonics for each Seed! You lose the ability
42 | to recover other "distress" passphrase Seeds from the new sets of Mnemonics!
43 |
44 | ** Issuing Multiple SLIP-39 Mnemonic Sets
45 |
46 | You may want to issue a simple set of SLIP-39 Mnemonics for your Seed to begin with, and then
47 | (later) decide to issue a more elaborate set of SLIP-39 Mnenmonic cards.
48 |
49 | Only with Extendable SLIP-39 Mnemonics, will the /alternative/ passphrase Seeds and derived
50 | wallets be consistent.
51 |
52 | * Recovery
53 |
54 | The SLIP-39 App supports recovery from both Extendable and (historic) non-Extendable SLIP-39
55 | Mnemonics.
56 |
57 | ** Using [[https://iancoleman.io/slip39]]
58 |
59 | Until the website is updated, you cannot (as of Dec 2024) use it to recover your Seed from
60 | Extendable SLIP-39 Mnemonics.
61 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-EXTENDABLE.txt:
--------------------------------------------------------------------------------
1 | SLIP-39 Mnemonics recover a unique (but "valid") Seed and derived
2 | wallets, no matter what /alternative/ passphrase you use! Your
3 | /original/ Seed can only be recovered with the originally specified
4 | "correct" passphrase.
5 |
6 | Extendable SLIP-39 Mnemonics ensures that all SLIP-39 Mnemonic sets
7 | generated from the /original/ Seed and original "correct" passphrase
8 | will /always/ result in the same unique Seed for each /alternative/
9 | passphrase.
10 |
11 | Non-Extendable SLIP-39 Mnemonics recover the /original/ Seed with the
12 | "correct" passphrase, but *different* unique Seeds for all /alternative/
13 | passphrases.
14 |
15 |
16 | 1 Extendable
17 | ════════════
18 |
19 | The default is now /Extendable/ – does /not/ use the Identifier to
20 | salt the encryption passphrase.
21 |
22 |
23 | 1.1 The Purpose for Multiple Passphrases
24 | ────────────────────────────────────────
25 |
26 | Recovering different Seeds for different passphrases is a valuable
27 | feature, because you may use the same SLIP-39 Mnemonic cards, and
28 | supply different passphrases to recover different (but valid) Seeds
29 | and sets of derived HD wallets!
30 |
31 | • You could have a "distress" passphrase that recovers a decoy wallet
32 | containing a small amount of sacrificial funds, while your real
33 | savings are under a different passphrase.
34 | • One password for your personal accounts and another for business
35 | accounts.
36 |
37 |
38 | 1.2 Non-Extendable Encoding
39 | ───────────────────────────
40 |
41 | Historically, the SLIP-39 encoding used the randomly assigned
42 | Identifier to both 1) associate groups of Mnemonics belonging to the
43 | same set, but /also/ 2) to salt the Seed encryption.
44 |
45 | This meant that: if you created 2 sets of SLIP-39 Mnemonics for the
46 | same Seed – each set would lead to */same/* Seed with the "correct"
47 | original passphrase, but to */different/* Seeds with each "distress"
48 | passphrase!
49 |
50 | Unless all sets of SLIP-39 Mnemonics lead to the same Seeds for each
51 | passphrase, you are restricted to ever issue /only one/ set of SLIP-39
52 | Mnemonics for each Seed! You lose the ability to recover other
53 | "distress" passphrase Seeds from the new sets of Mnemonics!
54 |
55 |
56 | 1.3 Issuing Multiple SLIP-39 Mnemonic Sets
57 | ──────────────────────────────────────────
58 |
59 | You may want to issue a simple set of SLIP-39 Mnemonics for your Seed
60 | to begin with, and then (later) decide to issue a more elaborate set
61 | of SLIP-39 Mnenmonic cards.
62 |
63 | Only with Extendable SLIP-39 Mnemonics, will the /alternative/
64 | passphrase Seeds and derived wallets be consistent.
65 |
66 |
67 | 2 Recovery
68 | ══════════
69 |
70 | The SLIP-39 App supports recovery from both Extendable and (historic)
71 | non-Extendable SLIP-39 Mnemonics.
72 |
73 |
74 | 2.1 Using
75 | ────────────────────────────────────────
76 |
77 | Until the website is updated, you cannot (as of Dec 2024) use it to
78 | recover your Seed from Extendable SLIP-39 Mnemonics.
79 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-G-NAME.org:
--------------------------------------------------------------------------------
1 | #+title: SLIP-39 Group Names
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | Name each Group according to "who" or "where" you plan to distribute it.
6 |
7 | The default Group names and their intended usages are:
8 |
9 | | First | A 1-card group stored in the First safe place |
10 | | Second | A 1-card group stored in the First safe place |
11 | | Fam | A smaller group of Family members |
12 | | Fren | A larger group of Friends; increase Needed |
13 | #+END_ABSTRACT
14 |
15 | * 1-Card Groups
16 |
17 | Useful for the direct owners of the Seed. Just one Card for these groups must be collected;
18 | ensure that 2+ of these Groups are created, and a "Requires recovery" threshold of least 2 is
19 | specified.
20 |
21 | If /less than/ the threshold amount of these cards is found by an attacker, the Seed /cannot/ be
22 | recovered (unless other Groups are also recovered).
23 |
24 | * Multi-Card Groups
25 |
26 | If you have a group of people (or places) that may be lost or destroyed, or where some Mnemonics
27 | (cards) may be found and fall into hostile hands, use a multi-card group.
28 |
29 | ** Hostile Groups
30 |
31 | The more /hostile/ (untrustworthy) the group (ie. the more likely that any card(s) may be stolen
32 | by an attacker) -- make the Group's Needed/#-in-Group ratio larger. Then, the attacker must
33 | collect more cards to defeat the Group.
34 |
35 | ** Fragile Groups
36 |
37 | The more /fragile/ (unreliable) the group (ie. the more likely that any card(s) may be lost or
38 | destroyed) -- make the Group's Needed/#-in-Group ratio smaller. Thus, more cards may be
39 | lost/destroyed before the Group can no longer be recovered (an *other* Group(s) must be
40 | colledted, instead, to recover the Seed).
41 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-G-NAME.txt:
--------------------------------------------------------------------------------
1 | Name each Group according to "who" or "where" you plan to distribute it.
2 |
3 | The default Group names and their intended usages are:
4 |
5 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
6 | First A 1-card group stored in the First safe place
7 | Second A 1-card group stored in the First safe place
8 | Fam A smaller group of Family members
9 | Fren A larger group of Friends; increase Needed
10 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
11 |
12 |
13 | 1 1-Card Groups
14 | ═══════════════
15 |
16 | Useful for the direct owners of the Seed. Just one Card for these
17 | groups must be collected; ensure that 2+ of these Groups are created,
18 | and a "Requires recovery" threshold of least 2 is specified.
19 |
20 | If /less than/ the threshold amount of these cards is found by an
21 | attacker, the Seed /cannot/ be recovered (unless other Groups are also
22 | recovered).
23 |
24 |
25 | 2 Multi-Card Groups
26 | ═══════════════════
27 |
28 | If you have a group of people (or places) that may be lost or
29 | destroyed, or where some Mnemonics (cards) may be found and fall into
30 | hostile hands, use a multi-card group.
31 |
32 |
33 | 2.1 Hostile Groups
34 | ──────────────────
35 |
36 | The more /hostile/ (untrustworthy) the group (ie. the more likely that
37 | any card(s) may be stolen by an attacker) – make the Group's
38 | Needed/#-in-Group ratio larger. Then, the attacker must collect more
39 | cards to defeat the Group.
40 |
41 |
42 | 2.2 Fragile Groups
43 | ──────────────────
44 |
45 | The more /fragile/ (unreliable) the group (ie. the more likely that
46 | any card(s) may be lost or destroyed) – make the Group's
47 | Needed/#-in-Group ratio smaller. Thus, more cards may be
48 | lost/destroyed before the Group can no longer be recovered (an *other*
49 | Group(s) must be colledted, instead, to recover the Seed).
50 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-G.org:
--------------------------------------------------------------------------------
1 | #+title: SLIP-39 Group Needed/#-in-Group
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | Increase "# in Group" as your target group locations or members grows.
6 |
7 | Increase "# Needed", the more Hostile/Untrustorthy the Group is.
8 |
9 | Decrease "# Needed", the less Fragile/Unreliable the Group is.
10 |
11 | #+END_ABSTRACT
12 |
13 | * 1-Card Groups
14 |
15 | Useful for the direct owners of the Seed. Just one Card for these groups must be collected;
16 | ensure that 2+ of these Groups are created, and a "Requires recovery" threshold of least 2 is
17 | specified.
18 |
19 | If /less than/ the threshold amount of these cards is found by an attacker, the Seed /cannot/ be
20 | recovered (unless other Groups are also recovered).
21 |
22 | * Multi-Card Groups
23 |
24 | If you have a group of people (or places) that may be lost or destroyed, or where some Mnemonics
25 | (cards) may be found and fall into hostile hands, use a multi-card group.
26 |
27 | ** Hostile Groups
28 |
29 | The more /hostile/ (untrustworthy) the group (ie. the more likely that any card(s) may be stolen
30 | by an attacker) -- make the Group's Needed/#-in-Group ratio larger. Then, the attacker must
31 | collect more cards to defeat the Group.
32 |
33 | ** Fragile Groups
34 |
35 | The more /fragile/ (unreliable) the group (ie. the more likely that any card(s) may be lost or
36 | destroyed) -- make the Group's Needed/#-in-Group ratio smaller. Thus, more cards may be
37 | lost/destroyed before the Group can no longer be recovered (an *other* Group(s) must be
38 | colledted, instead, to recover the Seed).
39 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-G.txt:
--------------------------------------------------------------------------------
1 | Increase "# in Group" as your target group locations or members grows.
2 |
3 | Increase "# Needed", the more Hostile/Untrustorthy the Group is.
4 |
5 | Decrease "# Needed", the less Fragile/Unreliable the Group is.
6 |
7 |
8 | 1 1-Card Groups
9 | ═══════════════
10 |
11 | Useful for the direct owners of the Seed. Just one Card for these
12 | groups must be collected; ensure that 2+ of these Groups are created,
13 | and a "Requires recovery" threshold of least 2 is specified.
14 |
15 | If /less than/ the threshold amount of these cards is found by an
16 | attacker, the Seed /cannot/ be recovered (unless other Groups are also
17 | recovered).
18 |
19 |
20 | 2 Multi-Card Groups
21 | ═══════════════════
22 |
23 | If you have a group of people (or places) that may be lost or
24 | destroyed, or where some Mnemonics (cards) may be found and fall into
25 | hostile hands, use a multi-card group.
26 |
27 |
28 | 2.1 Hostile Groups
29 | ──────────────────
30 |
31 | The more /hostile/ (untrustworthy) the group (ie. the more likely that
32 | any card(s) may be stolen by an attacker) – make the Group's
33 | Needed/#-in-Group ratio larger. Then, the attacker must collect more
34 | cards to defeat the Group.
35 |
36 |
37 | 2.2 Fragile Groups
38 | ──────────────────
39 |
40 | The more /fragile/ (unreliable) the group (ie. the more likely that
41 | any card(s) may be lost or destroyed) – make the Group's
42 | Needed/#-in-Group ratio smaller. Thus, more cards may be
43 | lost/destroyed before the Group can no longer be recovered (an *other*
44 | Group(s) must be colledted, instead, to recover the Seed).
45 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-LO.org:
--------------------------------------------------------------------------------
1 | #+title: Controls
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | Select an appropriate level of Controls detail.
6 |
7 | | Backup | Create SLIP-39 Mnemonics from existing BIP-39 Seed Phrase |
8 | | Create | SLIP-39 Mnemonic creation, "Using BIP-39" wallet support |
9 | | Recover | Enhanced SLIP-39 creation and SLIP-39/BIP-39 recovery |
10 | | Pro | Advanced Seeds, conversion of BIP-39 Phrase + passphrase to SLIP-39 |
11 | #+END_ABSTRACT
12 |
13 | * Backup
14 |
15 | The simplest mode, to "back up" a BIP-39 Seed Phrase Mnemonic to SLIP-39 Mnemonic Card Groups.
16 |
17 | Once you print, test recovery and distribute the SLIP-39 Mnemonic Cards, you can safely destroy
18 | your unreliable and insecure BIP-39 Seed Phrase Mnemonic backups; you can securely and reliably
19 | recover your BIP-39 Seed Phrase whenever you need it, by collecting a sufficient number of the
20 | SLIP-39 Cards.
21 |
22 | * Create
23 |
24 | A basic SLIP-39 Mnemonic creation interface. Default support for [[https://affil.trezor.io/SHdv][Trezor Safe 3]] with native
25 | SLIP-39 Mnemonics recovery.
26 |
27 | Select "Using BIP-39" for a traditional BIP-39 Seed Phrase Mnemonic, to use any other hardware
28 | wallets such as the [[https://shop.ledger.com/pages/ledger-nano-x?r=2cd1cb6ae51f][Ledger Nano]] (or even the Trezor, in BIP-39 Recovery mode).
29 |
30 | * Recovery
31 |
32 | Greater control over the Mnemonic creation process. Recovery of Seed Entropy from SLIP-39
33 | Mnemonics.
34 |
35 | Recover Seed Entropy from existing BIP-39 Mnemonic phrases by selecting "BIP-39 Entropy" in Seed
36 | Source.
37 |
38 | ** Extra Seed Randomness
39 |
40 | Probably most importantly, Extra Seed Entropy can be supplied. Any data supplied (Dice rolls,
41 | for example, add about 2.5 bits of entropy per roll) is hashed with a standard SHA-512 hash
42 | function, which can be independently confirmed.
43 |
44 | Finally, you can visually confirm that the Entropy is correctly applied via XOR to the Seed Data
45 | Source, to produce the Master Secret Seed.
46 |
47 | At no point do you need to "Trust" that the SLIP-39 program is producing a Master Secret Seed
48 | from known data!
49 |
50 | ** SLIP-39
51 |
52 | Supports input of existing SLIP-39 mnemonics to recover the original Seed Entropy.
53 |
54 | *** Recover From Lost SLIP-39 Mnemonic Cards
55 |
56 | If you know that some of your original SLIP-39 Mnemonic cards have been lost, you can
57 | re-issue /another/ set of SLIP-39 cards containing the same, original Seed Entropy.
58 |
59 | * Pro
60 |
61 | Advanced SLIP-39 creation and recovery, and recovery (and conversion) of BIP-39 Mnemonics to
62 | SLIP-39.
63 |
64 | Requires licensing.
65 |
66 | ** BIP-39
67 |
68 | Conversion of existing, fragile BIP-39 12- or 24-word Mnemonic phrases into SLIP-39 is supported.
69 |
70 | Enter the BIP-39 recover phrase to recover the original 128- or 256-bit Seed Entropy, and
71 | generate SLIP-39 Mnemonics which will recover the same Seed Entropy as the original 12- or
72 | 24-word BIP-39 Mnemonic.
73 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-LO.txt:
--------------------------------------------------------------------------------
1 | Select an appropriate level of Controls detail.
2 |
3 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4 | Backup Create SLIP-39 Mnemonics from existing BIP-39 Seed Phrase
5 | Create SLIP-39 Mnemonic creation, "Using BIP-39" wallet support
6 | Recover Enhanced SLIP-39 creation and SLIP-39/BIP-39 recovery
7 | Pro Advanced Seeds, conversion of BIP-39 Phrase + passphrase to SLIP-39
8 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
9 |
10 |
11 | 1 Backup
12 | ════════
13 |
14 | The simplest mode, to "back up" a BIP-39 Seed Phrase Mnemonic to
15 | SLIP-39 Mnemonic Card Groups.
16 |
17 | Once you print, test recovery and distribute the SLIP-39 Mnemonic
18 | Cards, you can safely destroy your unreliable and insecure BIP-39 Seed
19 | Phrase Mnemonic backups; you can securely and reliably recover your
20 | BIP-39 Seed Phrase whenever you need it, by collecting a sufficient
21 | number of the SLIP-39 Cards.
22 |
23 |
24 | 2 Create
25 | ════════
26 |
27 | A basic SLIP-39 Mnemonic creation interface. Default support for
28 | [Trezor Safe 3] with native SLIP-39 Mnemonics recovery.
29 |
30 | Select "Using BIP-39" for a traditional BIP-39 Seed Phrase Mnemonic,
31 | to use any other hardware wallets such as the [Ledger Nano] (or even
32 | the Trezor, in BIP-39 Recovery mode).
33 |
34 |
35 | [Trezor Safe 3]
36 |
37 | [Ledger Nano]
38 |
39 |
40 |
41 | 3 Recovery
42 | ══════════
43 |
44 | Greater control over the Mnemonic creation process. Recovery of Seed
45 | Entropy from SLIP-39 Mnemonics.
46 |
47 | Recover Seed Entropy from existing BIP-39 Mnemonic phrases by
48 | selecting "BIP-39 Entropy" in Seed Source.
49 |
50 |
51 | 3.1 Extra Seed Randomness
52 | ─────────────────────────
53 |
54 | Probably most importantly, Extra Seed Entropy can be supplied. Any
55 | data supplied (Dice rolls, for example, add about 2.5 bits of entropy
56 | per roll) is hashed with a standard SHA-512 hash function, which can
57 | be independently confirmed.
58 |
59 | Finally, you can visually confirm that the Entropy is correctly
60 | applied via XOR to the Seed Data Source, to produce the Master Secret
61 | Seed.
62 |
63 | At no point do you need to "Trust" that the SLIP-39 program is
64 | producing a Master Secret Seed from known data!
65 |
66 |
67 | 3.2 SLIP-39
68 | ───────────
69 |
70 | Supports input of existing SLIP-39 mnemonics to recover the original
71 | Seed Entropy.
72 |
73 |
74 | 3.2.1 Recover From Lost SLIP-39 Mnemonic Cards
75 | ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
76 |
77 | If you know that some of your original SLIP-39 Mnemonic cards have
78 | been lost, you can re-issue /another/ set of SLIP-39 cards containing
79 | the same, original Seed Entropy.
80 |
81 |
82 | 4 Pro
83 | ═════
84 |
85 | Advanced SLIP-39 creation and recovery, and recovery (and conversion)
86 | of BIP-39 Mnemonics to SLIP-39.
87 |
88 | Requires licensing.
89 |
90 |
91 | 4.1 BIP-39
92 | ──────────
93 |
94 | Conversion of existing, fragile BIP-39 12- or 24-word Mnemonic phrases
95 | into SLIP-39 is supported.
96 |
97 | Enter the BIP-39 recover phrase to recover the original 128- or
98 | 256-bit Seed Entropy, and generate SLIP-39 Mnemonics which will
99 | recover the same Seed Entropy as the original 12- or 24-word BIP-39
100 | Mnemonic.
101 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-PASSPHRASE.org:
--------------------------------------------------------------------------------
1 | #+title: SLIP-39/BIP-39 Passphrase
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | BIP-39 Seed Phrases are often protected by a Passphrase, to partially offset their insecurity. This
6 | often makes the Seed unrecoverable, because the Passphrase can be so easily lost or forgotten.
7 |
8 | SLIP-39 Mnemonic Card Groups are *much* more reliable (to recover) and secure (against accidental
9 | disclosure); a Passphrase is *not* recommended. Leave it empty!
10 |
11 | #+END_ABSTRACT
12 |
13 | * BIP-39 Passphrase
14 |
15 | Since anyone who sees a BIP-39 phrase can immediately attempt to recover the Seed, it is often
16 | considered necessary to use a Passphrase.
17 |
18 | It is estimated that 20%+ of all Cryptocurrency has been lost, often because the BIP-39 Mnemonic is
19 | available but the Passphrase has been lost.
20 |
21 | ** Safely Using BIP-39 Passphrases
22 |
23 | Once you Backup your BIP-39 Seed Phrase to a set of SLIP-39 Mnemonic Card Groups, you *must* also
24 | arrange to secure and recover any BIP-39 Passphrase(s). Remember; you can have multiple
25 | Passphrases, to produce several sets of Cryptocurrency HD wallet accounts from the same BIP-39
26 | Seed Phrase.
27 |
28 | Make certain that each Passphrase is made available to each intended recipient, and also in at
29 | least one additional location (eg. with someone else who will be at your funeral).
30 |
31 | *** Backup Full 512-bit BIP-39 Seed *including* Passphrase!
32 |
33 | If you've *already* produced a BIP-39 Seed Phrase and a complex Passphrase, and have already
34 | funded or distributed the derived HD Wallet accounts, you can *still* back it up, securely and
35 | reliably with SLIP-39 -- without requiring the Passphrase to be remembered by the recipient!
36 |
37 | Use the Pro controls and select "BIP-39 Seed" + "Passphrase" to fully decrypt your BIP-39 Seed
38 | Phrase. Then, produce 59-word SLIP-39 recovery cards encoding the full, decrypted 512-bit Seed.
39 |
40 | These will *not* be compatible with standard BIP-39 nor SLIP-39 Hardware Wallets! (Don't blame
41 | me -- you elected to create an insecure and unreliable BIP-39 Seed Phrase + Passphrase, instead
42 | of SLIP-39 Mnemonic Cards! ;)
43 |
44 | Your heirs or business partners will need to use a fully standards compliant SLIP-39 recovery
45 | program (like this SLIP-39 App, or [[https://github.com/trezor/python-shamir-mnemonic][python-shamir-mnemonic on Github]] ) to enter the large (but
46 | standards-compliant!) 59 word Mnemonics, and then generate Paper Wallets for each derived HD
47 | Wallet account they want to access. But, they *will* be able to recover your cryptocurrency
48 | accounts, *without* needing to recover the original BIP-39 Seed Phrase or Passphrase!
49 |
50 | * SLIP-39 Passphrase
51 |
52 | If you use SLIP-39 Mnemonic Card Groups, it is usually not necessary to use a Passphrase.
53 |
54 | Since SLIP-39's security is so much greater (chance of accidentally disclosing your Seed is so low
55 | compared to BIP-39), no hardware wallet vendor has implemented SLIP-39 recovery Passphrase.
56 |
57 | ** Hardware Wallet Doesn't Support Passphrase
58 |
59 | The Trezor doesn't presently support using a Passphrase on SLIP-39 recovery. So, if you supply
60 | one here, you will not be able to use it when recovering your SLIP-39 Mnemonics on your Trezor.
61 |
62 | *** Use Trezor's "Hidden Wallets" Instead
63 |
64 | You can provide as many "Hidden Wallets" on your Trezor device as you wish, by entering a
65 | passphrase to switch between them.
66 |
67 | This works regardless of whether you recovered your Hardware Wallet from BIP-39 or SLIP-39.
68 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-PASSPHRASE.txt:
--------------------------------------------------------------------------------
1 | BIP-39 Seed Phrases are often protected by a Passphrase, to partially
2 | offset their insecurity. This often makes the Seed unrecoverable,
3 | because the Passphrase can be so easily lost or forgotten.
4 |
5 | SLIP-39 Mnemonic Card Groups are *much* more reliable (to recover) and
6 | secure (against accidental disclosure); a Passphrase is *not*
7 | recommended. Leave it empty!
8 |
9 |
10 | 1 BIP-39 Passphrase
11 | ═══════════════════
12 |
13 | Since anyone who sees a BIP-39 phrase can immediately attempt to
14 | recover the Seed, it is often considered necessary to use a
15 | Passphrase.
16 |
17 | It is estimated that 20%+ of all Cryptocurrency has been lost, often
18 | because the BIP-39 Mnemonic is available but the Passphrase has been
19 | lost.
20 |
21 |
22 | 1.1 Safely Using BIP-39 Passphrases
23 | ───────────────────────────────────
24 |
25 | Once you Backup your BIP-39 Seed Phrase to a set of SLIP-39 Mnemonic
26 | Card Groups, you *must* also arrange to secure and recover any BIP-39
27 | Passphrase(s). Remember; you can have multiple Passphrases, to
28 | produce several sets of Cryptocurrency HD wallet accounts from the
29 | same BIP-39 Seed Phrase.
30 |
31 | Make certain that each Passphrase is made available to each intended
32 | recipient, and also in at least one additional location (eg. with
33 | someone else who will be at your funeral).
34 |
35 |
36 | 1.1.1 Backup Full 512-bit BIP-39 Seed *including* Passphrase!
37 | ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
38 |
39 | If you've *already* produced a BIP-39 Seed Phrase and a complex
40 | Passphrase, and have already funded or distributed the derived HD
41 | Wallet accounts, you can *still* back it up, securely and reliably
42 | with SLIP-39 – without requiring the Passphrase to be remembered by
43 | the recipient!
44 |
45 | Use the Pro controls and select "BIP-39 Seed" + "Passphrase" to fully
46 | decrypt your BIP-39 Seed Phrase. Then, produce 59-word SLIP-39
47 | recovery cards encoding the full, decrypted 512-bit Seed.
48 |
49 | These will *not* be compatible with standard BIP-39 nor SLIP-39
50 | Hardware Wallets! (Don't blame me – you elected to create an insecure
51 | and unreliable BIP-39 Seed Phrase + Passphrase, instead of SLIP-39
52 | Mnemonic Cards! ;)
53 |
54 | Your heirs or business partners will need to use a fully standards
55 | compliant SLIP-39 recovery program (like this SLIP-39 App, or
56 | [python-shamir-mnemonic on Github] ) to enter the large (but
57 | standards-compliant!) 59 word Mnemonics, and then generate Paper
58 | Wallets for each derived HD Wallet account they want to access. But,
59 | they *will* be able to recover your cryptocurrency accounts, *without*
60 | needing to recover the original BIP-39 Seed Phrase or Passphrase!
61 |
62 |
63 | [python-shamir-mnemonic on Github]
64 |
65 |
66 |
67 | 2 SLIP-39 Passphrase
68 | ════════════════════
69 |
70 | If you use SLIP-39 Mnemonic Card Groups, it is usually not necessary
71 | to use a Passphrase.
72 |
73 | Since SLIP-39's security is so much greater (chance of accidentally
74 | disclosing your Seed is so low compared to BIP-39), no hardware wallet
75 | vendor has implemented SLIP-39 recovery Passphrase.
76 |
77 |
78 | 2.1 Hardware Wallet Doesn't Support Passphrase
79 | ──────────────────────────────────────────────
80 |
81 | The Trezor doesn't presently support using a Passphrase on SLIP-39
82 | recovery. So, if you supply one here, you will not be able to use it
83 | when recovering your SLIP-39 Mnemonics on your Trezor.
84 |
85 |
86 | 2.1.1 Use Trezor's "Hidden Wallets" Instead
87 | ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
88 |
89 | You can provide as many "Hidden Wallets" on your Trezor device as you
90 | wish, by entering a passphrase to switch between them.
91 |
92 | This works regardless of whether you recovered your Hardware Wallet
93 | from BIP-39 or SLIP-39.
94 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-PF.org:
--------------------------------------------------------------------------------
1 | #+title: Paper Sizes
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | Select the desired PDF paper size.
6 |
7 | | Controls | Paper Size | Width | Height |
8 | |-----------+------------+--------+--------|
9 | | (default) | Letter | 8-1/2" | 11" |
10 | | All | Legal | 8-1/2" | 14" |
11 | | Recover | A4 | 210mm | 297mm |
12 | | Pro | Photo | 4" | 6" |
13 | #+END_ABSTRACT
14 |
15 | * Orientation
16 |
17 | SLIP-39 Cards will be laid out on the desired paper size in the most optimal
18 | orientation, to fit the most Cards on the selected paper.
19 |
20 | ** Paper Wallets
21 |
22 | However, if Cryptocurrency "Paper Wallet" are printed, the selected Paper will always
23 | be printed in Portrait orientation.
24 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-PF.txt:
--------------------------------------------------------------------------------
1 | Select the desired PDF paper size.
2 |
3 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4 | Controls Paper Size Width Height
5 | ───────────────────────────────────────
6 | (default) Letter 8-1/2" 11"
7 | All Legal 8-1/2" 14"
8 | Recover A4 210mm 297mm
9 | Pro Photo 4" 6"
10 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
11 |
12 |
13 | 1 Orientation
14 | ═════════════
15 |
16 | SLIP-39 Cards will be laid out on the desired paper size in the most
17 | optimal orientation, to fit the most Cards on the selected paper.
18 |
19 |
20 | 1.1 Paper Wallets
21 | ─────────────────
22 |
23 | However, if Cryptocurrency "Paper Wallet" are printed, the selected
24 | Paper will always be printed in Portrait orientation.
25 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-SD.org:
--------------------------------------------------------------------------------
1 | #+title: Seed Data Source
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | Create (or recover) Seed Data for your SLIP-39 Mnemonic. Or, backup your insecure/unreliable
6 | BIP-39 Mnemonic using SLIP-39.
7 |
8 | | Controls | Source | Description |
9 | |----------+-------------+--------------------------------------------------------|
10 | | Backup | BIP-39 | Create SLIP-39 Mnemonics to recover BIP-39 Seed Phrase |
11 | | Create | Random | Create SLIP-39 Mnemonics from secure randomnes |
12 | | Recover | SLIP-39 | Recover Seed from SLIP-39 Mnemonics |
13 | | Pro | BIP-39 Seed | Backup 512-bit BIP-39 Seed from Mnemonics + passphrase |
14 | #+END_ABSTRACT
15 |
16 | * BIP-39
17 |
18 | Backup an existing 12- or 24-word BIP-39 Seed Phrase Mnemonic. Or, select Create to produce a new
19 | BIP-39 Mnemonic. Save your BIP-39 Seed Phrase as a set of SLIP-39 Mnemonic Card Groups.
20 |
21 | Later, select Recover to input your SLIP-39 Mnemonics, and recover your BIP-39 Seed Phrase. Use
22 | this BIP-39 Seed Phrase (plus your passphrase, if any) to initialize a BIP-39 Hardware Wallet.
23 |
24 | You can then securely destroy your BIP-39 Mnemonic card(s) (or, keep a copy in some *extremely*
25 | secure location), and use the SLIP-39 Mnemonic cards as your distributed backup in case of its
26 | loss.
27 |
28 | ** SLIP-39 vs. BIP-39 Seed
29 |
30 | The Seed is computed *differently* on the hardware wallet (eg. a Ledger or Trezor), when
31 | importing using BIP-39 vs. SLIP-39!
32 |
33 | So, in order for us to compute and show you the correct Cryptocurrency wallet(s), you must
34 | indicate whether you're importing using the SLIP-39 Mnemonics directly (ie. on a Trezor), *or* if
35 | you're recovering the BIP-39 Mnemonic, and using that on the hardware wallet (ie. on a Ledger, or
36 | some other non-SLIP-39 hardware wallet).
37 |
38 | If you recover your Seed Entropy from a BIP-39 Mnemonic, we'll /assume/ you intend to *use* the
39 | BIP-39 Mnemonic on your hardware wallet, and we'll check "Recovering from BIP-39 on my Hardware
40 | Wallet".
41 |
42 | * SLIP-39
43 |
44 | Here's where you can restore a lost Seed using recovered SLIP-39 Mnemonics.
45 |
46 | You don't have to worry about sorting the Mnemonics into Groups or anything; we'll be able to
47 | recover the Seed, if you provide us with a sufficient threshold of SLIP-39 Mnemonic cards from the
48 | required number of separate Mnemonic Card Groups.
49 |
50 | ** Fixing Partially Lost Groups
51 |
52 | If you know you've lost access to some cards, and want to repair your SLIP-39 backup, you can
53 | recover the Seed from the current SLIP-39 Mnemonic cards, here -- and generate a *new* set of
54 | SLIP-39 Mnemonic cards for the *same* Seed.
55 |
56 | Distribute the cards as you wish, again; either the old (partially degraded) SLIP-39 Groups, *or*
57 | the new SLIP-39 Groups can be used to recover your Seed. Obviously, cards from the old and new
58 | SLIP-39 Mnemonics can't be "mixed" together to recover the Seed.
59 |
60 | * Random
61 |
62 | A high-quality 128-bit random seed value is probably adequate, and the 20-word SLIP-39 (and
63 | 12-word BIP-39) Mnemonics are much more practical than those produced for 256-bit seeds.
64 |
65 | 2^128 is aproximately 10^38. There are about 10^57 atoms in our solar system, and about 10^19
66 | atoms in a particle of dust.
67 |
68 | Therefore, the odds of 2 people picking the *same* high-quality random 128-bit Seed (1 in 10^38),
69 | is about the same as 2 people randomly selecting the same particle of *dust* out of the mass of
70 | our entire solar system!
71 |
72 | So, 128-bit seeds are probably fine for most practical levels of account security...
73 |
74 | * BIP-39 Seed
75 |
76 | If you wish, you can backup a /complete/ BIP-39 Seed Phrase *including its passphrase*, as a raw
77 | 512-bit BIP-39 Seed! This ensures that whoever uses the SLIP-39 Mnemonics to recover the wallets
78 | does not need to know the original BIP-39 Mnemonic + passphrase.
79 |
80 | There are a couple of drawbacks with this approach, though:
81 |
82 | - Large 59-word SLIP-39 Mnemonics are produced, to store the 512-bit seed
83 | - The Seed cannot be re-imported into a standard BIP-39 Hardware Wallet
84 | - Produce "Paper Wallets" for whichever derived HD wallets you need to access
85 |
86 | ** The Birthday Paradox
87 |
88 | However, due to the [[https://en.wikipedia.org/wiki/Birthday_attack][Birthday Attack]], the probability of two parties out of /a large number
89 | creating Seeds/ having a Seed *collision* (accidentally selecting the same Seed value) is
90 | somewhat greater.
91 |
92 | If every human and all their devices created a few billion Seeds (about 10^13), the probability
93 | of an /accidental/ collision falls to about 1 in 10^12 -- about 1 in a trillion. Unlikely, but
94 | something like this has happened for IPv4 addresses, so who knows.
95 |
96 | So, if a 1 in a trillion chance of someone eventually stumbling upon your wallet is too great a
97 | risk, choose a 256-bit random Seed where this Birthday Paradox probability falls to 1 in 10^32 --
98 | approximately the chance of 2 people on earth picking the same virus-sized particle in our solar
99 | system.
100 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-SE-SIGS.org:
--------------------------------------------------------------------------------
1 | #+title: Seed Extra Randomness - Ignore Bad Entropy
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | Bad Entropy is a risk to Cryptocurrency HD Wallet Seed Secrets!
6 |
7 | Avoid Harmonic and Shannon Entropy Deficiencies:
8 | - Use strong cryptographically secure randomness for your Seed Data
9 | - Use Extra Randomness from good sources, eg. rolling 20 or so dice
10 | #+END_ABSTRACT
11 |
12 | * Seed Entropy Deficit: {entropy_rating}
13 | #+BEGIN_EXAMPLE
14 | {update_seed_data.analysis}
15 | #+END_EXAMPLE
16 |
17 | #+BEGIN_EXAMPLE
18 | {update_seed_entropy.analysis}
19 | #+END_EXAMPLE
20 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-SE-SIGS.txt:
--------------------------------------------------------------------------------
1 | Bad Entropy is a risk to Cryptocurrency HD Wallet Seed Secrets!
2 |
3 | Avoid Harmonic and Shannon Entropy Deficiencies:
4 | • Use strong cryptographically secure randomness for your Seed Data
5 | • Use Extra Randomness from good sources, eg. rolling 20 or so dice
6 |
7 |
8 | 1 Seed Entropy Deficit: {entropy_rating}
9 | ════════════════════════════════════════
10 |
11 | ┌────
12 | │ {update_seed_data.analysis}
13 | └────
14 |
15 | ┌────
16 | │ {update_seed_entropy.analysis}
17 | └────
18 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-SE.org:
--------------------------------------------------------------------------------
1 | #+title: Seed Extra Randomness
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | Provide extra Entropy, to improve the randomness of your Seed.
6 |
7 | | Controls | Extra Entropy | Description |
8 | |----------+----------------+--------------------------------------------------|
9 | | Create | None | No extra randness; you trust ours completely. :) |
10 | | Recover | Die Rolls, ... | Provide any data; we'll SHA-512 hash it |
11 | | Pro | Hex | Provide raw hex data from an external source |
12 |
13 | It is wise not to trust *anyone* (including this program) to provide randomness for your Seed! Many
14 | wallet tools have been made that produce a "predictable" Seed (mostly pre-defined, with a small
15 | amount of randomness added to make them seem legitimate.) Then, after you derive your addresses and
16 | fund your wallets, the attacker who created the tool can also easily derive your private keys, and
17 | steal your Cryptocurrency.
18 |
19 | All Seed Source and Extra Randomness are combined using XOR, which you can confirm visually (if you
20 | understand hexadecimal representation).
21 | #+END_ABSTRACT
22 | * None
23 |
24 | We are using Python's =secrets.token_bytes=, which is designed to provide cryptographically [[https://docs.python.org/3/library/secrets.html][strong
25 | random]] numbers, to produce entropy for your Seed.
26 |
27 | So, using the default Random Seed source should be fine for most purposes.
28 |
29 | * Die Rolls, ...
30 |
31 | For higher security, provide yourself with a source of high-quality randomness.
32 |
33 | A couple hand-fulls of high-quality dice is a good option. Roll 'em, and enter them here.
34 |
35 | We will SHA-512 hash them; you can confirm our [[https://emn178.github.io/online-tools/sha512.html][SHA-512]] results here, to prove we aren't lying.
36 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-SE.txt:
--------------------------------------------------------------------------------
1 | Provide extra Entropy, to improve the randomness of your Seed.
2 |
3 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4 | Controls Extra Entropy Description
5 | ───────────────────────────────────────────────────────────────────────────
6 | Create None No extra randness; you trust ours completely. :)
7 | Recover Die Rolls, … Provide any data; we'll SHA-512 hash it
8 | Pro Hex Provide raw hex data from an external source
9 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
10 |
11 | It is wise not to trust *anyone* (including this program) to provide
12 | randomness for your Seed! Many wallet tools have been made that produce
13 | a "predictable" Seed (mostly pre-defined, with a small amount of
14 | randomness added to make them seem legitimate.) Then, after you derive
15 | your addresses and fund your wallets, the attacker who created the tool
16 | can also easily derive your private keys, and steal your Cryptocurrency.
17 |
18 | All Seed Source and Extra Randomness are combined using XOR, which you
19 | can confirm visually (if you understand hexadecimal representation).
20 |
21 |
22 | 1 None
23 | ══════
24 |
25 | We are using Python's `secrets.token_bytes', which is designed to
26 | provide cryptographically [strong random] numbers, to produce entropy
27 | for your Seed.
28 |
29 | So, using the default Random Seed source should be fine for most
30 | purposes.
31 |
32 |
33 | [strong random]
34 |
35 |
36 | 2 Die Rolls, …
37 | ══════════════
38 |
39 | For higher security, provide yourself with a source of high-quality
40 | randomness.
41 |
42 | A couple hand-fulls of high-quality dice is a good option. Roll 'em,
43 | and enter them here.
44 |
45 | We will SHA-512 hash them; you can confirm our [SHA-512] results here,
46 | to prove we aren't lying.
47 |
48 |
49 | [SHA-512]
50 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-THRESHOLD.org:
--------------------------------------------------------------------------------
1 | #+title: SLIP-39 Recovery Threshold
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | How many SLIP-39 Mnemonics Groups must be collected to recover the Seed.
6 |
7 | For each Group required, you must collect each group's "Needed" amount of Mnemonics (cards), out of
8 | the total number of cards in that Group.
9 | #+END_ABSTRACT
10 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-THRESHOLD.txt:
--------------------------------------------------------------------------------
1 | How many SLIP-39 Mnemonics Groups must be collected to recover the Seed.
2 |
3 | For each Group required, you must collect each group's "Needed" amount
4 | of Mnemonics (cards), out of the total number of cards in that Group.
5 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-WALLET.org:
--------------------------------------------------------------------------------
1 | #+title: Paper Wallets
2 | #+OPTIONS: toc:nil title:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | Supply a password to produce an encrypted Ethereum JSON wallet or Bitcoin, ... BIP-38 Paper Wallet.
6 |
7 | If you import these SLIP-39 Mnemonics directly into your Trezor hardware wallet -- you do
8 | /not/ need Paper Wallets: you have access to /all/ of the wallets, in every cryptocurrency supported
9 | by the Trezor.
10 |
11 | These are intended to support the importing of /individual/, single wallets into standard software
12 | wallets (eg. Brave browser, Metamask plugins, other software wallets on PCs or mobile devices). If
13 | you need some cryptocurrency "walking around" money, use them to create recoverable "Safe Portable
14 | Crypto Accounts" (below).
15 | #+END_ABSTRACT
16 |
17 | * Password
18 |
19 | If you lose or forget this Paper Wallet password -- you cannot import these wallets into
20 | compatible software Cryptocurrency wallets! Remember; the Seed can still be recovered by
21 | collecting sufficient numbers of Mnemonics (cards), and then new Paper Wallets can be issued.
22 |
23 | ** Hint
24 |
25 | A small (<10 character) hint about what (or where) the Paper Wallet Password is.
26 |
27 | * Safe Portable Crypto Accounts
28 |
29 | If you want to issue temporary Paper Wallets (to carry cryptocurrency with you to give to someone
30 | or buy something), then Paper Wallets derived from your account are a good idea.
31 |
32 | ** Custom Derivation Path
33 |
34 | Use the =SLIP-39= App to recover your Seed, select the desired Cryptocurrency (eg. =BTC=), and
35 | then enter a Paper Wallet Password, and a derivation path "suffix" into the "# to Derive" field,
36 | eg. "/1'/0/0-2".
37 |
38 | For example, if you use the BIP-39 recovery "test" Mnemonic "zoo zoo zoo zoo zoo zoo zoo zoo zoo
39 | zoo zoo wrong", with the above "# to Derive", this would result in 3 paper wallets being
40 | produced, at the following standard BTC Bech32 derivation paths:
41 |
42 | | m/84'/0'/1'/0/0 | bc1q8pqnqs573vx3qdp0xp6qdqzvnvy8px24rxh9lp |
43 | | m/84'/0'/1'/0/0 | bc1qwtc58u4mmnxa29u8j07e6lmqpnrs38vefy3y24 |
44 | | m/84'/0'/1'/0/0 | bc1qg9s8qzm0lcetfv6umhlm3evtca5zsqv7elqd5s |
45 |
46 | You could load these wallets with funds, write the amount on the front, and fold them over twice
47 | (to hide the PRIVATE KEY, while leaving the PUBLIC ADDRESS exposed), and even laminate them to
48 | avoid accidental discovery or exposure to moisture.
49 |
50 | Then, once loaded, they can always be *recovered* by you (if they are lost or accidentally
51 | destroyed). Otherwise, the intended recipient can unfold the Paper Wallet, and move the funds
52 | to their own wallet.
53 |
54 |
55 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39-WALLET.txt:
--------------------------------------------------------------------------------
1 | Supply a password to produce an encrypted Ethereum JSON wallet or
2 | Bitcoin, … BIP-38 Paper Wallet.
3 |
4 | If you import these SLIP-39 Mnemonics directly into your Trezor hardware
5 | wallet – you do /not/ need Paper Wallets: you have access to /all/ of
6 | the wallets, in every cryptocurrency supported by the Trezor.
7 |
8 | These are intended to support the importing of /individual/, single
9 | wallets into standard software wallets (eg. Brave browser, Metamask
10 | plugins, other software wallets on PCs or mobile devices). If you need
11 | some cryptocurrency "walking around" money, use them to create
12 | recoverable "Safe Portable Crypto Accounts" (below).
13 |
14 |
15 | 1 Password
16 | ══════════
17 |
18 | If you lose or forget this Paper Wallet password – you cannot import
19 | these wallets into compatible software Cryptocurrency wallets!
20 | Remember; the Seed can still be recovered by collecting sufficient
21 | numbers of Mnemonics (cards), and then new Paper Wallets can be
22 | issued.
23 |
24 |
25 | 1.1 Hint
26 | ────────
27 |
28 | A small (<10 character) hint about what (or where) the Paper Wallet
29 | Password is.
30 |
31 |
32 | 2 Safe Portable Crypto Accounts
33 | ═══════════════════════════════
34 |
35 | If you want to issue temporary Paper Wallets (to carry cryptocurrency
36 | with you to give to someone or buy something), then Paper Wallets
37 | derived from your account are a good idea.
38 |
39 |
40 | 2.1 Custom Derivation Path
41 | ──────────────────────────
42 |
43 | Use the `SLIP-39' App to recover your Seed, select the desired
44 | Cryptocurrency (eg. `BTC'), and then enter a Paper Wallet Password,
45 | and a derivation path "suffix" into the "# to Derive" field,
46 | eg. "/1'/0/0-2".
47 |
48 | For example, if you use the BIP-39 recovery "test" Mnemonic "zoo zoo
49 | zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", with the above "# to
50 | Derive", this would result in 3 paper wallets being produced, at the
51 | following standard BTC Bech32 derivation paths:
52 |
53 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
54 | m/84'/0'/1'/0/0 bc1q8pqnqs573vx3qdp0xp6qdqzvnvy8px24rxh9lp
55 | m/84'/0'/1'/0/0 bc1qwtc58u4mmnxa29u8j07e6lmqpnrs38vefy3y24
56 | m/84'/0'/1'/0/0 bc1qg9s8qzm0lcetfv6umhlm3evtca5zsqv7elqd5s
57 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
58 |
59 | You could load these wallets with funds, write the amount on the
60 | front, and fold them over twice (to hide the PRIVATE KEY, while
61 | leaving the PUBLIC ADDRESS exposed), and even laminate them to avoid
62 | accidental discovery or exposure to moisture.
63 |
64 | Then, once loaded, they can always be *recovered* by you (if they are
65 | lost or accidentally destroyed). Otherwise, the intended recipient
66 | can unfold the Paper Wallet, and move the funds to their own wallet.
67 |
--------------------------------------------------------------------------------
/slip39/gui/SLIP-39.txt:
--------------------------------------------------------------------------------
1 |
2 | mmmm mm mmmmmm mmmmmm mmmmm mmmm
3 | m#""""# ## ""##"" ##""""#m #""""##m m##""##m
4 | ##m ## ## ## ## m## ## ##
5 | "####m ## ## ######" ##### "##mm###
6 | "## ## ## ## ##### "## """ ##
7 | #mmmmm#" ##mmmmmm mm##mm ## #mmmm##" #mmm##
8 | """"" """""""" """""" "" """"" """"
9 |
10 |
11 | Safe & Effective (tm) Crypto Wallet Backup and Recovery
12 | (explanations and instructions will appear here)
13 |
--------------------------------------------------------------------------------
/slip39/gui/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/gui/__init__.py
--------------------------------------------------------------------------------
/slip39/gui/__main__.py:
--------------------------------------------------------------------------------
1 |
2 | #
3 | # Python-slip39 -- Ethereum SLIP-39 Account Generation and Recovery
4 | #
5 | # Copyright (c) 2022, Dominion Research & Development Corp.
6 | #
7 | # Python-slip39 is free software: you can redistribute it and/or modify it under
8 | # the terms of the GNU General Public License as published by the Free Software
9 | # Foundation, either version 3 of the License, or (at your option) any later
10 | # version. It is also available under alternative (eg. Commercial) licenses, at
11 | # your option. See the LICENSE file at the top of the source tree.
12 | #
13 | # Python-slip39 is distributed in the hope that it will be useful, but WITHOUT
14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 | #
17 |
18 | import sys
19 |
20 | from .main import main
21 |
22 | sys.exit( main() )
23 |
--------------------------------------------------------------------------------
/slip39/invoice/Cryptos/BNB_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Cryptos/BNB_32.png
--------------------------------------------------------------------------------
/slip39/invoice/Cryptos/BTC_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Cryptos/BTC_32.png
--------------------------------------------------------------------------------
/slip39/invoice/Cryptos/CRO_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Cryptos/CRO_32.png
--------------------------------------------------------------------------------
/slip39/invoice/Cryptos/DOGE_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Cryptos/DOGE_32.png
--------------------------------------------------------------------------------
/slip39/invoice/Cryptos/ETH_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Cryptos/ETH_32.png
--------------------------------------------------------------------------------
/slip39/invoice/Cryptos/LTC_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Cryptos/LTC_32.png
--------------------------------------------------------------------------------
/slip39/invoice/Cryptos/XRP_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Cryptos/XRP_32.png
--------------------------------------------------------------------------------
/slip39/invoice/MultiSend-solc-v0-4-11.sol:
--------------------------------------------------------------------------------
1 | contract MultiSend {
2 | function MultiSend(address[] recipients, uint[] amounts, address remainder) {
3 | if(recipients.length != amounts.length)
4 | throw;
5 |
6 | for(uint i = 0; i < recipients.length; i++) {
7 | recipients[i].send(amounts[i]);
8 | }
9 |
10 | selfdestruct(remainder);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/slip39/invoice/MultiSend-solc-v0-5-15.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.15;
2 |
3 | contract MultiSend {
4 | constructor(address payable[] memory recipients, uint256[] memory amounts, address payable remainder) public payable {
5 | // require(recipients.length == amounts.length);
6 |
7 | for(uint256 i = 0; i < recipients.length; i++) {
8 | recipients[i].send(amounts[i]);
9 | }
10 |
11 | selfdestruct(remainder);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/slip39/invoice/MultiTransferEther-solc-v0-5-16.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.15;
2 |
3 | contract MultiSend {
4 | constructor(address payable[] memory recipients, uint256[] memory amounts, address payable remainder) public payable {
5 | // require(recipients.length == amounts.length);
6 |
7 | for(uint256 i = 0; i < recipients.length; i++) {
8 | recipients[i].send(amounts[i]);
9 | }
10 |
11 | selfdestruct(remainder);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/slip39/invoice/Tokens-Goerli.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "contract": "0xaFF4481D10270F50f203E0763e2597776068CBc5",
4 | "name": "Weenus \ud83d\udcaa",
5 | "symbol": "WEENUS",
6 | "decimals": 18,
7 | "icon": null
8 | },
9 | {
10 | "contract": "0x022E292b44B5a146F2e8ee36Ff44D3dd863C915c",
11 | "name": "Xeenus \ud83d\udcaa",
12 | "symbol": "XEENUS",
13 | "decimals": 18,
14 | "icon": null
15 | },
16 | {
17 | "contract": "0xc6fDe3FD2Cc2b173aEC24cc3f267cb3Cd78a26B7",
18 | "name": "Yeenus \ud83d\udcaa",
19 | "symbol": "YEENUS",
20 | "decimals": 8,
21 | "icon": null
22 | },
23 | {
24 | "contract": "0x1f9061B953bBa0E36BF50F21876132DcF276fC6e",
25 | "name": "Zeenus \ud83d\udcaa",
26 | "symbol": "ZEENUS",
27 | "decimals": 0,
28 | "icon": null
29 | }
30 | ]
31 |
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/1INCH_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/1INCH_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/AGIX_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/AGIX_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/AMB_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/AMB_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/AMP_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/AMP_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/ANY_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/ANY_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/AOA_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/AOA_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/APE_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/APE_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/BAL_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/BAL_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/BAND_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/BAND_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/BAT.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/BAT.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/BDG.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/BDG.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/BIT_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/BIT_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/BNB_2.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/BNB_2.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/BNT_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/BNT_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/BTT_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/BTT_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/BUSD_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/BUSD_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/CEL_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/CEL_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/CHSB_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/CHSB_3.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/CHZ_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/CHZ_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/CNN_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/CNN_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/COFI_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/COFI_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/COMP_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/COMP_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/CRO_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/CRO_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/CVX_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/CVX_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/DACC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/DACC.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/DAI_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/DAI_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/DATx_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/DATx_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/DENT.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/DENT.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/DFI_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/DFI_32.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/DYDX_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/DYDX_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/ELEC_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/ELEC_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/ELON_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/ELON_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/ENJ_2.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/ENJ_2.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/ENS_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/ENS_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/EURT_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/EURT_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/FAIR_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/FAIR_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/FEG_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/FEG_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/FET_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/FET_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/FLOKI_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/FLOKI_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/FRAX_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/FRAX_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/FTI_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/FTI_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/FTM_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/FTM_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/FUEL_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/FUEL_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/FUN_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/FUN_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/FXS_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/FXS_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/GALA_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/GALA_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/GLM_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/GLM_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/GMT_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/GMT_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/GNO_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/GNO_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/GRT_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/GRT_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/GSE_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/GSE_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/GTO.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/GTO.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/GUSD_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/GUSD_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/HAND_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/HAND_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/HBTC_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/HBTC_32.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/HEX_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/HEX_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/HOGE_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/HOGE_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/HOT_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/HOT_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/HT_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/HT_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/IHT_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/IHT_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/IIC_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/IIC_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/IMT_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/IMT_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/IND_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/IND_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/IONC_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/IONC_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/IOST_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/IOST_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/IOTX_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/IOTX_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/IOV_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/IOV_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/KAN.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/KAN.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/KCS_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/KCS_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/KNC_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/KNC_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/KUB_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/KUB_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/LDO_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/LDO_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/LEND_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/LEND_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/LEO_2.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/LEO_2.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/LINK_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/LINK_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/LPT_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/LPT_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/LRC_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/LRC_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/LXT_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/LXT_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/LYM_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/LYM_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/MASK_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/MASK_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/MATIC_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/MATIC_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/MCO_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/MCO_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/MITx_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/MITx_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/MKR.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/MKR.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/MWAT_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/MWAT_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/NEAR_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/NEAR_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/NEXO_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/NEXO_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/NXM_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/NXM_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/OCN_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/OCN_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/OHM_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/OHM_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/OKB_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/OKB_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/OMG_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/OMG_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/ONE_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/ONE_32.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/PAI_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/PAI_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/PAXG_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/PAXG_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/PAY_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/PAY_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/POLY_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/POLY_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/POWR_2.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/POWR_2.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/PTT_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/PTT_32.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/QNT_2.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/QNT_2.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/REV_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/REV_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/RFR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/RFR.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/RNDR_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/RNDR_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/RNT_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/RNT_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/RPL_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/RPL_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/RSR_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/RSR_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/SAITAMA_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/SAITAMA_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/SALT_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/SALT_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/SAND_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/SAND_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/SAT_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/SAT_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/SHIB_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/SHIB_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/SLP_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/SLP_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/SNT.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/SNT.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/SNX_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/SNX_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/SRM_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/SRM_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/STORJ_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/STORJ_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/STQ_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/STQ_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/SUSHI_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/SUSHI_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/SYN_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/SYN_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/TEL_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/TEL_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/THETA_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/THETA_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/TOS_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/TOS_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/TUSD_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/TUSD_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/UCASH_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/UCASH_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/UNI_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/UNI_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/USDC_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/USDC_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/USDD_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/USDD_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/USDP_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/USDP_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/USDT_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/USDT_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/VEN_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/VEN_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/VIN_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/VIN_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/WBTC_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/WBTC_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/WETH_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/WETH_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/WOO_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/WOO_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/WQTUM_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/WQTUM_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/XAUt_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/XAUt_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/XCN_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/XCN_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/XDCE_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/XDCE_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/XEN_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/XEN_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/XMX_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/XMX_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/XNN_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/XNN_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/XYO_2.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/XYO_2.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/YEE_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/YEE_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/YFI_2.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/YFI_2.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/ZIL_2.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/ZIL_2.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/ZRX_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/ZRX_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/ZSC_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/ZSC_28.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/aAAVE_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/aAAVE_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/anyLTC_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/anyLTC_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/cDAI_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/cDAI_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/cETH_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/cETH_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/cUSDC_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/cUSDC_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/cUSDT_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/cUSDT_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/nCash_28.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/nCash_28.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/rETH_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/rETH_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/stETH_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/stETH_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/stkAAVE_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/stkAAVE_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/wCELO_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/wCELO_32.png
--------------------------------------------------------------------------------
/slip39/invoice/Tokens/wMANA_32.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/Tokens/wMANA_32.webp
--------------------------------------------------------------------------------
/slip39/invoice/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | #
3 | # Python-slip39 -- Ethereum SLIP-39 Account Generation and Recovery
4 | #
5 | # Copyright (c) 2022, Dominion Research & Development Corp.
6 | #
7 | # Python-slip39 is free software: you can redistribute it and/or modify it under
8 | # the terms of the GNU General Public License as published by the Free Software
9 | # Foundation, either version 3 of the License, or (at your option) any later
10 | # version. It is also available under alternative (eg. Commercial) licenses, at
11 | # your option. See the LICENSE file at the top of the source tree.
12 | #
13 | # Python-slip39 is distributed in the hope that it will be useful, but WITHOUT
14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 | #
17 |
18 | from __future__ import annotations
19 |
20 | from .ethereum import ( # noqa F401
21 | contract_address,
22 | etherscan_urls,
23 | etherscan, gasoracle, ethprice,
24 | etherbalance, ethertx, erc20tx,
25 | Direction, etherio, erc20io,
26 | GasOracle, Chain, Speed, Etherscan,
27 | Contract,
28 | )
29 | from .multipayout import ( # noqa F401
30 | MultiPayoutERC20,
31 | )
32 |
33 | __author__ = "Perry Kundert"
34 | __email__ = "perry@dominionrnd.com"
35 | __copyright__ = "Copyright (c) 2022 Dominion Research & Development Corp."
36 | __license__ = "Dual License: GPLv3 (or later) and Commercial (see LICENSE)"
37 |
--------------------------------------------------------------------------------
/slip39/invoice/artifact_test/dominionrnd-invoice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/artifact_test/dominionrnd-invoice.png
--------------------------------------------------------------------------------
/slip39/invoice/artifact_test/dominionrnd-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/invoice/artifact_test/dominionrnd-logo.png
--------------------------------------------------------------------------------
/slip39/invoice/bitquery_test.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import http.client
3 | import json
4 | import os
5 |
6 |
7 | # We don't want to run this test unless we provide our bitquery API
8 | # key in X-API-KEY
9 | @pytest.mark.skipif( not os.getenv( "BITQUERY_API_KEY" ), reason="Missing BITQUERY_API_KEY environment variable" )
10 | def test_bitquery_smoke():
11 |
12 | queries = [
13 | {
14 | "query": """\
15 | query ($network: EthereumNetwork!, $addresses: [String!]) {
16 | ethereum(network: $network) {
17 | address(address: {in: $addresses}) {
18 | address
19 | annotation
20 | balances {
21 | value
22 | currency {
23 | address
24 | symbol
25 | tokenType
26 | }
27 | }
28 | }
29 | }
30 | }
31 | """,
32 | "variables": {
33 | "network": "ethereum",
34 | "addresses": [
35 | "0x22615C3A31d8f9d47bdB84502780A8D2C136fCF5"
36 | ]
37 | }
38 | },
39 | {
40 | "query": """\
41 | query ($network: BitcoinNetwork!, $addresses: [String!]) {
42 | bitcoin(network: $network) {
43 | inbound: coinpath(receiver: {in: $addresses}) {
44 | receiver {
45 | address
46 | }
47 | amount
48 | }
49 | }
50 | }
51 | """,
52 | "variables": {
53 | "network": "bitcoin",
54 | "addresses": [
55 | "bc1qcj9ujyvrf94wu0902g2lnklzlyn5j5nrr44hwp",
56 | "18cBEMRxXHqzWWCxZNtU91F5sbUNKhL5PX",
57 | "bc1qygm3dlynmjxuflghr0hmq6r7wmff2jd5gtgz0q"
58 | ]
59 | }
60 | }
61 | ]
62 |
63 | headers = {
64 | 'Content-Type': 'application/json',
65 | 'X-API-KEY': os.getenv( "BITQUERY_API_KEY" ),
66 | }
67 |
68 | conn = http.client.HTTPSConnection("graphql.bitquery.io")
69 |
70 | for query in queries:
71 | payload = json.dumps( query )
72 | print( payload )
73 |
74 | conn.request("POST", "/", payload, headers)
75 | rx = conn.getresponse()
76 | rxstr = rx.read().decode("UTF-8")
77 | print(rxstr)
78 | response = json.loads( rxstr )
79 | print( json.dumps( response, indent=4 ))
80 |
--------------------------------------------------------------------------------
/slip39/invoice/contracts/ForwarderERC20.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | // A minimal Forwarder that can be deployed using the EVM CREATE2 opcode at a
5 | // deterministic address. Thus, we do not need to actually deploy the contract
6 | // until funds appear at the address.
7 | //
8 | // This process takes the initiating source address (the address of the Contract initiating the
9 | // CREATE2), a salt and the contract creation code (which includes the constructor arguments). Of
10 | // course, this includes the destination address. But importantly, in order to support a number of
11 | // ERC-20 token Contract addresses, the Forward must know all the possible tokens *in advance* --
12 | // support for additional tokens cannot be made *after* address creation! For example, if you wish to
13 | // allow the client to pay in ETH, or ERC-20 USDC or USDT, only these tokens can *ever* be supported by
14 | // this address!
15 | //
16 | // Some examples of this concept:
17 | //
18 | // https://github.com/gabrieladeniji/forwarder_factory/blob/main/contracts/ForwarderFactory.sol
19 | //
20 | // Our forwarder is a one-shot, where the constructore executes all ERC-20 transfers and finally uses
21 | // selfdestruct to clear out the account's ETH and destroy the contract, reducing its Gas cost.
22 | // Since this is a "push" payment, we must carefully wrap any ERC-20 calls ignoring errors, in
23 | // case one or more of the supported ERC-20 contracts is selfdestructed or is otherwise faulty.
24 | // Since all operations occur during Forwarder construction, no reentrancy is possible.
25 | //
26 | // Coinbase uses/used(?) something like this to manage their merchant payment wallets:
27 | //
28 | // https://web.archive.org/web/20190814233503/https://blog.coinbase.com/usdc-payment-processing-in-coinbase-commerce-b1af1c82fb0?gi=f79ac81c04f1
29 | //
30 | // Note that we can re-deploy the same contract multiple times, if desired (for example, if a client re-uses
31 | // the same payment address multiple times):
32 | //
33 | // https://forum.openzeppelin.com/t/selfdestruct-and-redeploy-in-the-same-transaction-using-create2-fails/8797
34 | //
35 | // This fact makes it possible to deploy 2 functionally *differing* contracts at the same address:
36 | //
37 | // https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2
38 | //
39 | // Deploymenet via the CREATE2 opcode is available in Solidity >=0.8 using:
40 | //
41 | // function deploy( uint256 _salt, uint256 _arg1, address _arg2 ) returns ( address ) {
42 | // return address( new ContractName{ salt: _salt }( _arg1, _arg2 ));
43 | // }
44 | //
45 | // The Contract address can be precomputed: (from https://solidity-by-example.org/app/create2/)
46 | //
47 | // function deploy_address( uint256 _salt, uint256 _arg1, address _arg2 )
48 | // public
49 | // view
50 | // returns ( address )
51 | // {
52 | // bytes memory contract = type(ContractName).creationCode;
53 | // bytes memory creation = abi.encodePacked( contract, abi.encode( _arg1, _arg2 ));
54 | // bytes32 creation_hash = keccak256(
55 | // abi.encodePacked( bytes1( 0xff ), address( this ), _salt, keccak256( creation ))
56 | // );
57 | // return address( uint160( uint256( creation_hash )));
58 | // }
59 | //
60 | // In Python using Web3, we could call this (view) contract function, or we can Contract creation encoded using the ABI:
61 | //
62 | // creation_code = ContractName.constructor( arg1, arg2 ).data_in_transaction;
63 | //
64 | //
65 | import "openzeppelin-contracts/contracts/interfaces/IERC20.sol";
66 |
67 | contract ForwarderERC20 {
68 | constructor( address payable _recipient, IERC20[] memory _tokens ) public payable {
69 | for (uint256 tok = 0; tok < _tokens.length; tok++) {
70 | uint256 tok_balance;
71 | // Get the balance of the contract for the current token
72 | try _tokens[tok].balanceOf( address( this )) returns ( uint256 value ) {
73 | tok_balance = value;
74 | } catch {
75 | continue;
76 | }
77 | if ( tok_balance > 0 ) {
78 | // Forward the balance to the recipient
79 | try _tokens[tok].transfer( _recipient, tok_balance ) returns ( bool ) {
80 | // ignore failing ERC-20 transfer
81 | } catch {
82 | continue; // ignore exception on ERC-20 transfer
83 | }
84 | }
85 | }
86 | selfdestruct( _recipient );
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/slip39/invoice/contracts/MultiPayoutERC20Base.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | import "../openzeppelin-contracts/contracts/security/ReentrancyGuard.sol";
5 | import "../openzeppelin-contracts/contracts/access/Ownable.sol";
6 | import {
7 | IERC20Metadata as IERC20 // w/ decimals()
8 | } from "../openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
9 |
10 | //
11 | // Implements all the ERC-20 handling for MultiPayoutERC20
12 | //
13 | // Allows other contracts that know about MultiPayoutERC20 (such as MultiPayoutERC20Forwarder) to
14 | // access data about the supported ERC-20s.
15 | //
16 | abstract contract MultiPayoutERC20Base is ReentrancyGuard, Ownable {
17 |
18 |
19 | //
20 | // __SELF -- specific at construction, and used to support ...Forwarder collection
21 | //
22 | // NOTE: immutable variables are assigned once at construction, and the construction code is
23 | // modified to contain the value in-place, so "access" to these immutable values in code
24 | // does NOT actually interrogate the contract's data! Thus, in "delegatecall"-ed code,
25 | // we can safely use these values.
26 | //
27 | address internal immutable __SELF = address( this );
28 |
29 | modifier isDelegated() {
30 | require( address( this ) != __SELF );
31 | _;
32 | }
33 | modifier notDelegated() {
34 | require( address( this ) == __SELF );
35 | _;
36 | }
37 |
38 | //
39 | // erc20s (and ..._len(), _add( IERC20 ), _del( IERC20 )
40 | //
41 | IERC20[] public erc20s;
42 |
43 | // Construct w/ 0 or more ERC-20 tokens. Don't duplicate (just a waste, not checked)
44 | constructor(
45 | IERC20[] memory _erc20s
46 | )
47 | payable
48 | {
49 | for ( uint256 t = 0; t < _erc20s.length; t++ ) {
50 | erc20s.push( _erc20s[t] );
51 | }
52 | }
53 |
54 | function erc20s_len()
55 | public
56 | view
57 | returns ( uint256 )
58 | {
59 | return erc20s.length;
60 | }
61 |
62 | function erc20s_add(
63 | IERC20 _token
64 | )
65 | external
66 | onlyOwner
67 | {
68 | for ( uint256 i = 0; i < erc20s.length; ++i ) {
69 | if ( erc20s[i] == _token ) {
70 | return;
71 | }
72 | }
73 | erc20s.push( _token );
74 | }
75 |
76 | function erc20s_del(
77 | IERC20 _token
78 | )
79 | external
80 | onlyOwner
81 | {
82 | for ( uint256 i = 0; i < erc20s.length; i++ ) {
83 | if ( erc20s[i] == _token ) {
84 | unchecked {
85 | erc20s[i] = erc20s[erc20s.length - 1];
86 | }
87 | erc20s.pop();
88 | return;
89 | }
90 | }
91 | }
92 |
93 | //
94 | // Anyone can delegatecall this function, to forward all of their ERC-20 tokens into this contract
95 | //
96 | // Used by MultiPayoutERC20Forwarder to collect its ERC-20 tokens.
97 | //
98 | // Not recommended for general public use, but you can call it if you want! ;)
99 | //
100 | // REENTRANCY ATTACK
101 | //
102 | // It is not necessary to protect this from reentrancy, if only reputable ERC-20 tokens
103 | // are included. A disreputable ERC-20 token's transfer function could re-enter this
104 | // call, resulting in the same token transfers being re-attempted, and subsequent transfers
105 | // delayed. But, only its own failure to implement check-effects-interactions can be exploited,
106 | // since the full .balanceOf each token is being transferred out.
107 | //
108 | // A failing ERC-20 will result in an exception (reverting the ...Forwarder), but this can be solved
109 | // by removing the offending ERC-20 token via MultiPayoutERC20.erc20s_del().
110 | //
111 | function erc20_collect(
112 | IERC20 _token
113 | )
114 | private
115 | {
116 | uint256 balance = _token.balanceOf( address( this ));
117 | if ( balance > 0 ) {
118 | // Forward the caller's balance to the recipient (this contract!)
119 | _token.transfer( __SELF, balance );
120 | }
121 | }
122 |
123 | function erc20s_collector()
124 | external
125 | isDelegated // Only delegatecall allowed! We'll be transferring from the caller's address( this )
126 | {
127 | MultiPayoutERC20Base self = MultiPayoutERC20Base( __SELF );
128 | uint256 t = self.erc20s_len();
129 | while ( t > 0 ) {
130 | erc20_collect( self.erc20s( --t ));
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/slip39/invoice/contracts/MultiPayoutERC20Forwarder.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | // A minimal Forwarder that can be deployed using the EVM CREATE2 opcode at a
5 | // deterministic address. Thus, we do not need to actually deploy the contract
6 | // until funds appear at the address.
7 | //
8 | // This process takes the initiating source address (the address of the Contract initiating the
9 | // CREATE2), a salt and the contract creation code (which includes the constructor arguments). Of
10 | // course, this includes the destination address. But importantly, in order to support a number of
11 | // ERC-20 token Contract addresses, the Forward must know all the possible tokens *in advance* --
12 | // support for additional tokens cannot be made *after* address creation! For example, if you wish to
13 | // allow the client to pay in ETH, or ERC-20 USDC or USDT, only these tokens can *ever* be supported by
14 | // this address!
15 | //
16 | // Some examples of this concept:
17 | //
18 | // https://github.com/gabrieladeniji/forwarder_factory/blob/main/contracts/ForwarderFactory.sol
19 | //
20 | // Our forwarder is a one-shot, where the constructore executes all ERC-20 transfers and finally uses
21 | // selfdestruct to clear out the account's ETH and destroy the contract, reducing its Gas cost.
22 | // Since this is a "push" payment, we must carefully wrap any ERC-20 calls ignoring errors, in
23 | // case one or more of the supported ERC-20 contracts is selfdestructed or is otherwise faulty.
24 | // Since all operations occur during Forwarder construction, no reentrancy is possible.
25 | //
26 | // Coinbase uses/used(?) something like this to manage their merchant payment wallets:
27 | //
28 | // https://web.archive.org/web/20190814233503/https://blog.coinbase.com/usdc-payment-processing-in-coinbase-commerce-b1af1c82fb0?gi=f79ac81c04f1
29 | //
30 | // Note that we can re-deploy the same contract multiple times, if desired (for example, if a client re-uses
31 | // the same payment address multiple times):
32 | //
33 | // https://forum.openzeppelin.com/t/selfdestruct-and-redeploy-in-the-same-transaction-using-create2-fails/8797
34 | //
35 | // This fact makes it possible to deploy 2 functionally *differing* contracts at the same address:
36 | //
37 | // https://docs.soliditylang.org/en/latest/control-structures.html#salted-contract-creations-create2
38 | //
39 | // Deploymenet via the CREATE2 opcode is available in Solidity >=0.8 using:
40 | //
41 | // function deploy( uint256 _salt, uint256 _arg1, address _arg2 ) returns ( address ) {
42 | // return address( new ContractName{ salt: _salt }( _arg1, _arg2 ));
43 | // }
44 | //
45 | // The Contract address can be precomputed: (from https://solidity-by-example.org/app/create2/)
46 | //
47 | // function deploy_address( uint256 _salt, uint256 _arg1, address _arg2 )
48 | // public
49 | // view
50 | // returns ( address )
51 | // {
52 | // bytes memory contract = type(ContractName).creationCode;
53 | // bytes memory creation = abi.encodePacked( contract, abi.encode( _arg1, _arg2 ));
54 | // bytes32 creation_hash = keccak256(
55 | // abi.encodePacked( bytes1( 0xff ), address( this ), _salt, keccak256( creation ))
56 | // );
57 | // return address( uint160( uint256( creation_hash )));
58 | // }
59 | //
60 | // In Python using Web3, we could call this (view) contract function, or we can Contract creation encoded using the ABI:
61 | //
62 | // creation_code = ContractName.constructor( arg1, arg2 ).data_in_transaction;
63 | //
64 | //
65 | import {
66 | MultiPayoutERC20Base
67 | } from "contracts/MultiPayoutERC20Base.sol";
68 |
69 | contract MultiPayoutERC20Forwarder {
70 | constructor(
71 | address payable _multipayout
72 | )
73 | payable
74 | {
75 | _multipayout.delegatecall( abi.encodeWithSignature( "erc20s_collector()" ));
76 | selfdestruct( _multipayout );
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/slip39/invoice/multipayout_test.crypto-keypair-plaintext:
--------------------------------------------------------------------------------
1 | {
2 | "sk":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7aie8zrakLWKjqNAqbw1zZTIVdx3iQ6Y6wEihi1naKQ==",
3 | "vk":"O2onvM62pC1io6jQKm8Nc2UyFXcd4kOmOsBIoYtZ2ik="
4 | }
5 |
--------------------------------------------------------------------------------
/slip39/invoice/multipayout_test.machine-id:
--------------------------------------------------------------------------------
1 | 000102030405060708090A0B0C0D0E0F
2 |
--------------------------------------------------------------------------------
/slip39/invoice/payments_test/payments_test.machine-id:
--------------------------------------------------------------------------------
1 | 000102030405060708090A0B0C0D0E0F
2 |
--------------------------------------------------------------------------------
/slip39/layout/1x1-ffffff3f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/1x1-ffffff3f.png
--------------------------------------------------------------------------------
/slip39/layout/1x1-ffffff54.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/1x1-ffffff54.png
--------------------------------------------------------------------------------
/slip39/layout/1x1-ffffffbf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/1x1-ffffffbf.png
--------------------------------------------------------------------------------
/slip39/layout/BNB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/BNB.png
--------------------------------------------------------------------------------
/slip39/layout/BTC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/BTC.png
--------------------------------------------------------------------------------
/slip39/layout/COVER-BIP-39.org:
--------------------------------------------------------------------------------
1 | #+title: Seed Recovery Using BIP-39
2 | #+OPTIONS: toc:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | SLIP-39 supports Hardware Wallets that require BIP-39 Mnemonics for Seed recovery, such as your
6 | Ledger Nano, etc. Recover your BIP-39 Mnemonic phrase from these cards using the SLIP-39 App
7 | whenever you need it, to restore your Cryptocurrency accounts to your hardware wallet.
8 | #+END_ABSTRACT
9 |
10 | - Open the SLIP-39 App, and set Controls to "Recover"
11 | - In "Seed Source", use "SLIP-39" and input Mnemonics, with sufficient:
12 | - Different Groups to satisfy Recovery Card Groups threshold
13 | - Cards in each Group to meet each groups' recovery minimums
14 | - In "Seed & SLIP-39 Recover Groups", click "Using BIP-39"
15 | - The BIP-39 Mnemonic will be recovered and displayed
16 | - Restore your Cryptocurrency accounts to your hardware wallet by entering the BIP-39 Mnemonic phrase.
17 | - Cut off and *destroy* this BIP-39 Mnemonic backup, once you are confident you can recover it at will!
18 |
19 | #+BEGIN_QUOTE
20 | NOTE: You cannot enter these SLIP-39 Mnemonics directly on a BIP-39 Hardware Wallet to recover the
21 | Seed. Use the SLIP-39 App to recover the BIP-39 Seed Phrase.
22 | #+END_QUOTE
23 |
--------------------------------------------------------------------------------
/slip39/layout/COVER-BIP-39.txt:
--------------------------------------------------------------------------------
1 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2 | SEED RECOVERY USING BIP-39
3 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4 |
5 |
6 | SLIP-39 supports Hardware Wallets that require BIP-39 Mnemonics for Seed
7 | recovery, such as your Ledger Nano, etc. Recover your BIP-39 Mnemonic
8 | phrase from these cards using the SLIP-39 App whenever you need it, to
9 | restore your Cryptocurrency accounts to your hardware wallet.
10 |
11 | • Open the SLIP-39 App, and set Controls to "Recover"
12 | • In "Seed Source", use "SLIP-39" and input Mnemonics, with sufficient:
13 | • Different Groups to satisfy Recovery Card Groups threshold
14 | • Cards in each Group to meet each groups' recovery minimums
15 | • In "Seed & SLIP-39 Recover Groups", click "Using BIP-39"
16 | • The BIP-39 Mnemonic will be recovered and displayed
17 | • Restore your Cryptocurrency accounts to your hardware wallet by
18 | entering the BIP-39 Mnemonic phrase.
19 | • Cut off and *destroy* this BIP-39 Mnemonic backup, once you are
20 | confident you can recover it at will!
21 |
22 | NOTE: You cannot enter these SLIP-39 Mnemonics directly on a
23 | BIP-39 Hardware Wallet to recover the Seed. Use the SLIP-39
24 | App to recover the BIP-39 Seed Phrase.
25 |
--------------------------------------------------------------------------------
/slip39/layout/COVER-SLIP-39.org:
--------------------------------------------------------------------------------
1 | #+title: Seed Recovery Using SLIP-39
2 | #+OPTIONS: toc:nil author:nil
3 |
4 | #+BEGIN_ABSTRACT
5 | SLIP-39 Mnemonic Cards for Hardware Wallets that natively support it, such as your Trezor. Recover
6 | your Cryptocurrency accounts to your hardware wallet directly from these SLIP-39 cards, by entering
7 | them on the screen of the device.
8 | #+END_ABSTRACT
9 |
10 | - Collect these "SLIP-39" Card Mnemonics, with sufficient:
11 | - Different Groups to satisfy Recovery Card Groups threshold
12 | - Cards in each Group to meet each groups' recovery minimums
13 | - Enter SLIP-39 recovery mode on your hardware wallet
14 | - Restore your Cryptocurrency accounts to your hardware wallet by entering the SLIP-39 Mnemonic phrases.
15 |
16 | #+BEGIN_QUOTE
17 | NOTE: There is no BIP-39 Seed Phrase for this cryptocurrency Seed! It must be recovered directly
18 | from the SLIP-39 Mnemonic Card phrases. You cannot use these phrases to recover the Seed to a
19 | BIP-39 compatible Hardware Wallet; only to one supporting native SLIP-39.
20 | #+END_QUOTE
21 |
--------------------------------------------------------------------------------
/slip39/layout/COVER-SLIP-39.txt:
--------------------------------------------------------------------------------
1 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2 | SEED RECOVERY USING SLIP-39
3 | ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4 |
5 |
6 | SLIP-39 Mnemonic Cards for Hardware Wallets that natively support it,
7 | such as your Trezor. Recover your Cryptocurrency accounts to your
8 | hardware wallet directly from these SLIP-39 cards, by entering them on
9 | the screen of the device.
10 |
11 | • Collect these "SLIP-39" Card Mnemonics, with sufficient:
12 | • Different Groups to satisfy Recovery Card Groups threshold
13 | • Cards in each Group to meet each groups' recovery minimums
14 | • Enter SLIP-39 recovery mode on your hardware wallet
15 | • Restore your Cryptocurrency accounts to your hardware wallet by
16 | entering the SLIP-39 Mnemonic phrases.
17 |
18 | NOTE: There is no BIP-39 Seed Phrase for this cryptocurrency
19 | Seed! It must be recovered directly from the SLIP-39
20 | Mnemonic Card phrases. You cannot use these phrases to
21 | recover the Seed to a BIP-39 compatible Hardware Wallet;
22 | only to one supporting native SLIP-39.
23 |
--------------------------------------------------------------------------------
/slip39/layout/COVER.txt:
--------------------------------------------------------------------------------
1 |
2 | # m m m m ""# " mmmm mmmm
3 | # mm mm#mm mm#mm mmmm mmm # # mmm # mmm mmmm " "# #" "m mmm mmm mmmmm
4 | #" # # # #" "# # " # # # # " # # #" "# mmm" #m m# #" " #" "# # # #
5 | # # # # # # """m # # """m # # # # "# """ # # # # # # #
6 | # # "mm "mm ##m#" "mmm" # # # "mmm" "mm mm#mm ##m#" "mmm#" "mmm" # "#mm" "#m#" # # #
7 | # " " #
8 | " "
9 | Safe & Effective (tm) Crypto Wallet Backup and Recovery
10 | (explanations and instructions will appear here)
11 |
--------------------------------------------------------------------------------
/slip39/layout/CRO.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/CRO.png
--------------------------------------------------------------------------------
/slip39/layout/DOGE.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/DOGE.png
--------------------------------------------------------------------------------
/slip39/layout/ETH.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/ETH.png
--------------------------------------------------------------------------------
/slip39/layout/LTC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/LTC.png
--------------------------------------------------------------------------------
/slip39/layout/SLIP-39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/SLIP-39.png
--------------------------------------------------------------------------------
/slip39/layout/XRP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/XRP.png
--------------------------------------------------------------------------------
/slip39/layout/__init__.py:
--------------------------------------------------------------------------------
1 |
2 | #
3 | # Python-slip39 -- Ethereum SLIP-39 Account Generation and Recovery
4 | #
5 | # Copyright (c) 2022, Dominion Research & Development Corp.
6 | #
7 | # Python-slip39 is free software: you can redistribute it and/or modify it under
8 | # the terms of the GNU General Public License as published by the Free Software
9 | # Foundation, either version 3 of the License, or (at your option) any later
10 | # version. It is also available under alternative (eg. Commercial) licenses, at
11 | # your option. See the LICENSE file at the top of the source tree.
12 | #
13 | # Python-slip39 is distributed in the hope that it will be useful, but WITHOUT
14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 | #
17 | from __future__ import annotations
18 |
19 | __author__ = "Perry Kundert"
20 | __email__ = "perry@dominionrnd.com"
21 | __copyright__ = "Copyright (c) 2022 Dominion Research & Development Corp."
22 | __license__ = "Dual License: GPLv3 (or later) and Commercial (see LICENSE)"
23 |
24 | from .components import * # noqa F403
25 | from .printer import * # noqa F403
26 | from .pdf import * # noqa F403
27 |
--------------------------------------------------------------------------------
/slip39/layout/font/DejaVuSansMono-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/DejaVuSansMono-Bold.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/DejaVuSansMono-BoldOblique.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/DejaVuSansMono-BoldOblique.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/DejaVuSansMono-Oblique.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/DejaVuSansMono-Oblique.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/DejaVuSansMono.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/DejaVuSansMono.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/Inconsolata-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/Inconsolata-Bold.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/Inconsolata-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/Inconsolata-Regular.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/NotoSansMono-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/NotoSansMono-Bold.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/NotoSansMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/NotoSansMono-Regular.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/OFL.txt:
--------------------------------------------------------------------------------
1 | Copyright 2006 The Inconsolata Project Authors
2 |
3 | This Font Software is licensed under the SIL Open Font License, Version 1.1.
4 | This license is copied below, and is also available with a FAQ at:
5 | http://scripts.sil.org/OFL
6 |
7 |
8 | -----------------------------------------------------------
9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10 | -----------------------------------------------------------
11 |
12 | PREAMBLE
13 | The goals of the Open Font License (OFL) are to stimulate worldwide
14 | development of collaborative font projects, to support the font creation
15 | efforts of academic and linguistic communities, and to provide a free and
16 | open framework in which fonts may be shared and improved in partnership
17 | with others.
18 |
19 | The OFL allows the licensed fonts to be used, studied, modified and
20 | redistributed freely as long as they are not sold by themselves. The
21 | fonts, including any derivative works, can be bundled, embedded,
22 | redistributed and/or sold with any software provided that any reserved
23 | names are not used by derivative works. The fonts and derivatives,
24 | however, cannot be released under any other type of license. The
25 | requirement for fonts to remain under this license does not apply
26 | to any document created using the fonts or their derivatives.
27 |
28 | DEFINITIONS
29 | "Font Software" refers to the set of files released by the Copyright
30 | Holder(s) under this license and clearly marked as such. This may
31 | include source files, build scripts and documentation.
32 |
33 | "Reserved Font Name" refers to any names specified as such after the
34 | copyright statement(s).
35 |
36 | "Original Version" refers to the collection of Font Software components as
37 | distributed by the Copyright Holder(s).
38 |
39 | "Modified Version" refers to any derivative made by adding to, deleting,
40 | or substituting -- in part or in whole -- any of the components of the
41 | Original Version, by changing formats or by porting the Font Software to a
42 | new environment.
43 |
44 | "Author" refers to any designer, engineer, programmer, technical
45 | writer or other person who contributed to the Font Software.
46 |
47 | PERMISSION & CONDITIONS
48 | Permission is hereby granted, free of charge, to any person obtaining
49 | a copy of the Font Software, to use, study, copy, merge, embed, modify,
50 | redistribute, and sell modified and unmodified copies of the Font
51 | Software, subject to the following conditions:
52 |
53 | 1) Neither the Font Software nor any of its individual components,
54 | in Original or Modified Versions, may be sold by itself.
55 |
56 | 2) Original or Modified Versions of the Font Software may be bundled,
57 | redistributed and/or sold with any software, provided that each copy
58 | contains the above copyright notice and this license. These can be
59 | included either as stand-alone text files, human-readable headers or
60 | in the appropriate machine-readable metadata fields within text or
61 | binary files as long as those fields can be easily viewed by the user.
62 |
63 | 3) No Modified Version of the Font Software may use the Reserved Font
64 | Name(s) unless explicit written permission is granted by the corresponding
65 | Copyright Holder. This restriction only applies to the primary font name as
66 | presented to the users.
67 |
68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69 | Software shall not be used to promote, endorse or advertise any
70 | Modified Version, except to acknowledge the contribution(s) of the
71 | Copyright Holder(s) and the Author(s) or with their explicit written
72 | permission.
73 |
74 | 5) The Font Software, modified or unmodified, in part or in whole,
75 | must be distributed entirely under this license, and must not be
76 | distributed under any other license. The requirement for fonts to
77 | remain under this license does not apply to any document created
78 | using the Font Software.
79 |
80 | TERMINATION
81 | This license becomes null and void if any of the above conditions are
82 | not met.
83 |
84 | DISCLAIMER
85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93 | OTHER DEALINGS IN THE FONT SOFTWARE.
94 |
--------------------------------------------------------------------------------
/slip39/layout/font/OverpassMono-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/OverpassMono-Bold.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/OverpassMono-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/OverpassMono-Regular.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/SourceCodePro-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/SourceCodePro-Bold.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/SourceCodePro-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/SourceCodePro-BoldItalic.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/SourceCodePro-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/SourceCodePro-Italic.ttf
--------------------------------------------------------------------------------
/slip39/layout/font/SourceCodePro-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/font/SourceCodePro-Regular.ttf
--------------------------------------------------------------------------------
/slip39/layout/paper-wallet-background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pjkundert/python-slip39/fa02f5fc03ce123394afe5dd0d9d2132689f671d/slip39/layout/paper-wallet-background.png
--------------------------------------------------------------------------------
/slip39/output_test.py:
--------------------------------------------------------------------------------
1 | import qrcode
2 |
3 | from pytest import approx
4 | from fpdf import FPDF, FlexTemplate
5 |
6 | from .layout import Region, Text, Image, Box, Coordinate
7 | from .defaults import MM_IN
8 |
9 |
10 | def test_Region():
11 | card_size = Coordinate( y=2+1/4, x=3+3/8 )
12 | card_margin = 1/8
13 | card = Box( 'card', 0, 0, card_size.x, card_size.y )
14 | #print( card )
15 | card_interior = card.add_region_relative(
16 | Region( 'card-interior', x1=+card_margin, y1=+card_margin, x2=-card_margin, y2=-card_margin )
17 | )
18 | #print( card_interior )
19 | assert card_interior.x1 == card_margin
20 | assert card_interior.x2 == card_size.x - card_margin
21 | assert card_interior.y2 == card_size.y - card_margin
22 | assert card_interior.x2 - card_interior.x1 == card_size.x - card_margin * 2
23 |
24 | card_qr = card_interior.add_region_proportional(
25 | Image( 'card-qr', x1=1/2, y1=1/4, x2=1, y2=1 )
26 | ).square( maximum=1, justify='BR' )
27 | card_interior.add_region_proportional(
28 | Box( 'card-box-ul', x1=1/2, y1=1/4, x2=1, y2=1 )
29 | ).square( maximum=.5, justify='TL' )
30 | card_interior.add_region_proportional(
31 | Box( 'card-box-cm', x1=1/2, y1=1/4, x2=1, y2=1 )
32 | ).square( maximum=.5 )
33 | card_interior.add_region_proportional(
34 | Box( 'card-box-br', x1=1/2, y1=1/4, x2=1, y2=1 )
35 | ).square( maximum=.5, justify='BR' )
36 |
37 | #card_qr.x1 = card_qr.x2 - 1.0
38 | #card_qr.y1 = card_qr.y2 - 1.0
39 | #print( card_qr )
40 | assert card_qr.x1 == 2.25
41 | assert card_qr.y1 == 1.125
42 |
43 | elements = list( card.elements() )[1:]
44 | #print( json.dumps( elements, indent=4 ))
45 | assert len( elements ) == 4
46 | assert elements[0]['type'] == 'I'
47 |
48 | card_top = card_interior.add_region_proportional(
49 | Region( 'card-top', x1=0, y1=0, x2=1, y2=1/3 )
50 | )
51 | card_top.add_region_proportional(
52 | Text( 'card-title', x1=0, y1=0, x2=1, y2=40/100 )
53 | )
54 |
55 | elements = list( card.elements() )[1:]
56 | #print( json.dumps( elements, indent=4 ))
57 | assert elements[-1]['type'] == 'T'
58 | assert elements[-1]['font'] == 'helvetica'
59 | assert elements[-1]['size'] == approx( 14.4 )
60 |
61 | pdf = FPDF()
62 | pdf.add_page()
63 |
64 | tpl = FlexTemplate( pdf, list( card.elements() ) )
65 | tpl['card-qr'] = qrcode.make( 'abc' ).get_image()
66 | tpl['card-title'] = 'Abc'
67 | # Abc in upper-left
68 | tpl.render()
69 |
70 | tpl['card-qr'] = qrcode.make( 'abc' ).get_image()
71 | tpl['card-title'] = 'Xyz'
72 | # Xyz in lower-right
73 | tpl.render( offsetx = card_size.x * MM_IN, offsety = card_size.y * MM_IN )
74 |
75 | #pdf.output( "test.pdf" ) # To view results in test.pdf, uncomment
76 |
--------------------------------------------------------------------------------
/slip39/recovery/__main__.py:
--------------------------------------------------------------------------------
1 |
2 | #
3 | # Python-slip39 -- Ethereum SLIP-39 Account Generation and Recovery
4 | #
5 | # Copyright (c) 2022, Dominion Research & Development Corp.
6 | #
7 | # Python-slip39 is free software: you can redistribute it and/or modify it under
8 | # the terms of the GNU General Public License as published by the Free Software
9 | # Foundation, either version 3 of the License, or (at your option) any later
10 | # version. It is also available under alternative (eg. Commercial) licenses, at
11 | # your option. See the LICENSE file at the top of the source tree.
12 | #
13 | # Python-slip39 is distributed in the hope that it will be useful, but WITHOUT
14 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 | #
17 |
18 | from __future__ import annotations
19 |
20 | import sys
21 |
22 | from .main import main
23 |
24 | __author__ = "Perry Kundert"
25 | __email__ = "perry@dominionrnd.com"
26 | __copyright__ = "Copyright (c) 2022 Dominion Research & Development Corp."
27 | __license__ = "Dual License: GPLv3 (or later) and Commercial (see LICENSE)"
28 |
29 | sys.exit( main() )
30 |
--------------------------------------------------------------------------------
/slip39/recovery_test.csv:
--------------------------------------------------------------------------------
1 | entropy, passphrase, using_bip39, path, address
2 | zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong,,true,,bc1qk0a9hr7wjfxeenz9nwenw9flhq0tmsf6vsgnn2
3 | zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong,,,,bc1q9yscq3l2yfxlvnlk3cszpqefparrv7tk24u6pl
4 | fruit wave dwarf banana earth journey tattoo true farm silk olive fence,banana,true,,17rxURoF96VhmkcEGCj5LNQkmN9HVhWb7F
5 | 000102030405060708090a0b0c0d0e0f,,,m/0'/1,xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ
6 | fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542,,,m/0,xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH
7 | fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542,,,m/0/2147483647'/1,xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon
8 |
--------------------------------------------------------------------------------
/slip39/version.py:
--------------------------------------------------------------------------------
1 | __version_info__ = ( 13, 1, 0 )
2 | __version__ = '.'.join( map( str, __version_info__ ))
3 |
--------------------------------------------------------------------------------