mango-explorer/Wallet.ipynb

232 lines
7.2 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"id": "tested-retreat",
"metadata": {},
"source": [
"# ⚠ Warning\n",
"\n",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
"\n",
"[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gl/OpinionatedGeek%2Fmango-explorer/HEAD?filepath=Wallet.ipynb) _🏃 To run this notebook press the ⏩ icon in the toolbar above._\n",
"\n",
"[🥭 Mango Markets](https://mango.markets/) support is available at: [Docs](https://docs.mango.markets/) | [Discord](https://discord.gg/67jySBhxrg) | [Twitter](https://twitter.com/mangomarkets) | [Github](https://github.com/blockworks-foundation) | [Email](mailto:hello@blockworks.foundation)"
]
},
{
"cell_type": "markdown",
"id": "incomplete-fundamentals",
"metadata": {},
"source": [
"# 🥭 Wallet\n",
"\n",
"This notebook holds all the code around handling a wallet of private and public keys.\n",
"\n",
"**Please be careful with your private keys, and don't provide them to any code if you are not 100% confident you know what it will do.**"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "special-membrane",
"metadata": {
"jupyter": {
"source_hidden": true
}
},
"outputs": [],
"source": [
"import json\n",
"import logging\n",
"import os.path\n",
"\n",
"from solana.account import Account\n",
"from solana.publickey import PublicKey\n"
]
},
{
"cell_type": "markdown",
"id": "significant-sound",
"metadata": {},
"source": [
"## Wallet class\n",
"\n",
"The `Wallet` class wraps our understanding of saving and loading keys, and creating the appropriate Solana `Account` object.\n",
"\n",
"To load a private key from a file, the file must be a JSON-formatted text file with a root array of the 64 bytes making up the secret key.\n",
"\n",
"For example:\n",
"```\n",
"[200,48,184,13... for another 60 bytes...]\n",
"```\n",
"**TODO:** It would be good to be able to load a `Wallet` from a mnemonic string. I haven't yet found a Python library that can generate a BIP44 derived seed for Solana that matches the derived seeds created by Sollet and Ledger."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ranking-special",
"metadata": {},
"outputs": [],
"source": [
"_DEFAULT_WALLET_FILENAME: str = \"id.json\"\n",
"\n",
"\n",
"class Wallet:\n",
" def __init__(self, secret_key):\n",
" self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)\n",
" self.secret_key = secret_key[0:32]\n",
" self.account = Account(self.secret_key)\n",
"\n",
" @property\n",
" def address(self) -> PublicKey:\n",
" return self.account.public_key()\n",
"\n",
" def save(self, filename: str, overwrite: bool = False) -> None:\n",
" if os.path.isfile(filename) and not overwrite:\n",
" raise Exception(f\"Wallet file '{filename}' already exists.\")\n",
"\n",
" with open(filename, \"w\") as json_file:\n",
" json.dump(list(self.secret_key), json_file)\n",
"\n",
" @staticmethod\n",
" def load(filename: str = _DEFAULT_WALLET_FILENAME) -> \"Wallet\":\n",
" if not os.path.isfile(filename):\n",
" logging.error(f\"Wallet file '{filename}' is not present.\")\n",
" raise Exception(f\"Wallet file '{filename}' is not present.\")\n",
" else:\n",
" with open(filename) as json_file:\n",
" data = json.load(json_file)\n",
" return Wallet(data)\n",
"\n",
" @staticmethod\n",
" def create() -> \"Wallet\":\n",
" new_account = Account()\n",
" new_secret_key = new_account.secret_key()\n",
" return Wallet(new_secret_key)\n"
]
},
{
"cell_type": "markdown",
"id": "romance-manchester",
"metadata": {},
"source": [
"# default_wallet object\n",
"\n",
"A default Wallet object that loads the private key from the id.json file, if it exists."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "professional-graduation",
"metadata": {},
"outputs": [],
"source": [
"default_wallet = None\n",
"if os.path.isfile(_DEFAULT_WALLET_FILENAME):\n",
" try:\n",
" default_wallet = Wallet.load(_DEFAULT_WALLET_FILENAME)\n",
" except Exception as exception:\n",
" logging.warning(f\"Failed to load default wallet from file '{_DEFAULT_WALLET_FILENAME}' - exception: {exception}\")\n"
]
},
{
"cell_type": "markdown",
"id": "actual-swift",
"metadata": {},
"source": [
"# 🏃 Running\n",
"\n",
"A simple harness to load a `Wallet` if the `wallet.json` file exists, and print out its `PublicKey`.\n",
"\n",
"**Please be careful with your private keys!**"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "yellow-illness",
"metadata": {},
"outputs": [],
"source": [
"if __name__ == \"__main__\":\n",
" logging.getLogger().setLevel(logging.INFO)\n",
"\n",
" import os.path\n",
"\n",
" filename = _DEFAULT_WALLET_FILENAME\n",
" if not os.path.isfile(filename):\n",
" print(f\"Wallet file '{filename}' is not present.\")\n",
" else:\n",
" wallet = Wallet.load(filename)\n",
" print(\"Wallet address:\", wallet.address)\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
},
"varInspector": {
"cols": {
"lenName": 16,
"lenType": 16,
"lenVar": 40
},
"kernels_config": {
"python": {
"delete_cmd_postfix": "",
"delete_cmd_prefix": "del ",
"library": "var_list.py",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"delete_cmd_postfix": ") ",
"delete_cmd_prefix": "rm(",
"library": "var_list.r",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 5
}