Now use solana.tokenlist.json for token lookups.

This commit is contained in:
Geoff Taylor 2021-06-01 18:16:02 +01:00
parent cbd42d24ae
commit f73ee9ca19
10 changed files with 8507 additions and 335 deletions

View File

@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "successful-traveler", "id": "satellite-attachment",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ⚠ Warning\n", "# ⚠ Warning\n",
@ -16,7 +16,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "adequate-accreditation", "id": "antique-studio",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🥭 BaseModel\n", "# 🥭 BaseModel\n",
@ -33,7 +33,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "functional-porcelain", "id": "crucial-norwegian",
"metadata": { "metadata": {
"jupyter": { "jupyter": {
"source_hidden": true "source_hidden": true
@ -45,6 +45,7 @@
"import construct\n", "import construct\n",
"import datetime\n", "import datetime\n",
"import enum\n", "import enum\n",
"import json\n",
"import logging\n", "import logging\n",
"import time\n", "import time\n",
"import typing\n", "import typing\n",
@ -68,7 +69,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "alternate-choir", "id": "mediterranean-cream",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Version enum\n", "## Version enum\n",
@ -79,7 +80,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "blank-salad", "id": "bibliographic-thong",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -94,7 +95,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "arranged-fiber", "id": "previous-standard",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## InstructionType enum\n", "## InstructionType enum\n",
@ -105,7 +106,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "liberal-director", "id": "tight-indication",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -134,7 +135,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "aggregate-philippines", "id": "foreign-performer",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Internal functions\n", "## Internal functions\n",
@ -145,7 +146,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "digital-diabetes", "id": "violent-separate",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -161,7 +162,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "marked-collector", "id": "pacific-stuff",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## AccountInfo class\n" "## AccountInfo class\n"
@ -170,7 +171,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "controlled-bandwidth", "id": "answering-catholic",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -242,7 +243,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "developing-passage", "id": "requested-craps",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## AddressableAccount class\n", "## AddressableAccount class\n",
@ -255,7 +256,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "unexpected-choir", "id": "sublime-broad",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -274,7 +275,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "arbitrary-variable", "id": "infrared-religion",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## SerumAccountFlags class\n", "## SerumAccountFlags class\n",
@ -285,7 +286,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "technical-chosen", "id": "comparable-applicant",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -328,7 +329,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "rental-annual", "id": "fabulous-copper",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## MangoAccountFlags class\n", "## MangoAccountFlags class\n",
@ -339,7 +340,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "alternative-november", "id": "adolescent-provincial",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -372,7 +373,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "thermal-behavior", "id": "excellent-edmonton",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Index class" "## Index class"
@ -381,7 +382,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "effective-kentucky", "id": "knowing-discipline",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -408,7 +409,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "speaking-introduction", "id": "regular-repeat",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## AggregatorConfig class" "## AggregatorConfig class"
@ -417,7 +418,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "current-stone", "id": "convinced-african",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -450,7 +451,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "agreed-louisville", "id": "afraid-addiction",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Round class" "## Round class"
@ -459,7 +460,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "uniform-hollywood", "id": "manual-malaysia",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -484,7 +485,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "purple-deficit", "id": "chemical-functionality",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Answer class" "## Answer class"
@ -493,7 +494,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "possible-position", "id": "flying-blame",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -519,7 +520,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "focal-minute", "id": "collective-float",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Aggregator class" "## Aggregator class"
@ -528,7 +529,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "unlikely-surprise", "id": "chinese-green",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -594,7 +595,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "caroline-hospital", "id": "acting-protection",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Token class\n", "## Token class\n",
@ -605,31 +606,32 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "critical-hamburg", "id": "raised-sender",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"class Token:\n", "class Token:\n",
" def __init__(self, name: str, mint: PublicKey, decimals: Decimal):\n", " def __init__(self, symbol: str, name: str, mint: PublicKey, decimals: Decimal):\n",
" self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)\n", " self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)\n",
" self.name: str = name.upper()\n", " self.symbol: str = symbol.upper()\n",
" self.name: str = name\n",
" self.mint: PublicKey = mint\n", " self.mint: PublicKey = mint\n",
" self.decimals: Decimal = decimals\n", " self.decimals: Decimal = decimals\n",
"\n", "\n",
" def round(self, value: Decimal) -> Decimal:\n", " def round(self, value: Decimal) -> Decimal:\n",
" return round(value, int(self.decimals))\n", " return round(value, int(self.decimals))\n",
"\n", "\n",
" def name_matches(self, name: str) -> bool:\n", " def symbol_matches(self, symbol: str) -> bool:\n",
" return self.name.upper() == name.upper()\n", " return self.symbol.upper() == symbol.upper()\n",
"\n", "\n",
" @staticmethod\n", " @staticmethod\n",
" def find_by_name(values: typing.List[\"Token\"], name: str) -> \"Token\":\n", " def find_by_symbol(values: typing.List[\"Token\"], symbol: str) -> \"Token\":\n",
" found = [value for value in values if value.name_matches(name)]\n", " found = [value for value in values if value.symbol_matches(symbol)]\n",
" if len(found) == 0:\n", " if len(found) == 0:\n",
" raise Exception(f\"Token '{name}' not found in token values: {values}\")\n", " raise Exception(f\"Token '{symbol}' not found in token values: {values}\")\n",
"\n", "\n",
" if len(found) > 1:\n", " if len(found) > 1:\n",
" raise Exception(f\"Token '{name}' matched multiple tokens in values: {values}\")\n", " raise Exception(f\"Token '{symbol}' matched multiple tokens in values: {values}\")\n",
"\n", "\n",
" return found[0]\n", " return found[0]\n",
"\n", "\n",
@ -659,71 +661,229 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "surface-astrology", "id": "mental-advertising",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## SolToken object\n", "## SolToken object\n",
"\n", "\n",
"It's sometimes handy to have a `Token` for SOL, but SOL isn't actually a token and can't appear in baskets. This object defines a special case for SOL." "It's sometimes handy to have a `Token` for SOL, but SOL isn't actually a token and can't appear in baskets. This object defines a special case for SOL.\n"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "centered-respect", "id": "signed-emphasis",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"SolToken = Token(\"SOL\", SOL_MINT_ADDRESS, SOL_DECIMALS)" "SolToken = Token(\"SOL\", \"Pure SOL\", SOL_MINT_ADDRESS, SOL_DECIMALS)"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "ready-projection", "id": "capital-input",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## TokenLookup class\n", "## TokenLookup class\n",
"\n", "\n",
"The sole reason for this class is for us to be able to look up a token by name or mint address, and return a `Token` instances.\n", "This class allows us to look up token symbols, names, mint addresses and decimals, all from our Solana static data.\n",
"\n", "\n",
"It's complicated because:\n", "The `_find_data_by_symbol()` is used here and later in the `SpotMarketLookup` class.\n",
"* Our static token data is in `MangoConstants`\n", "\n",
"* Our `Token` class is defined in `BaseModel`\n", "The static data is the [Solana token list](https://raw.githubusercontent.com/solana-labs/token-list/main/src/tokens/solana.tokenlist.json) provided by Serum.\n",
"* Our `context` is the only part that knows which cluster we're in\n", "\n",
"* `Context` can't use anything from `BaseModel` (it would cause a dependency cycle)\n", "You can load a `TokenLookup` class by something like:\n",
"* SOL isn't mentioned in our `MangoConstants` data\n" "```\n",
"with open(\"solana.tokenlist.json\") as json_file:\n",
" token_data = json.load(json_file)\n",
" token_lookup = TokenLookup(token_data)\n",
"```"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "frequent-worth", "id": "formed-table",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"def _find_data_by_symbol(symbol: str, token_data: typing.Dict) -> typing.Optional[typing.Dict]:\n",
" for token in token_data[\"tokens\"]:\n",
" if token[\"symbol\"] == symbol:\n",
" return token\n",
" return None\n",
"\n",
"\n",
"class TokenLookup:\n", "class TokenLookup:\n",
" @staticmethod\n", " def __init__(self, token_data: typing.Dict) -> None:\n",
" def find_by_name(context: Context, name: str) -> Token:\n", " self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)\n",
" if SolToken.name_matches(name):\n", " self.token_data = token_data\n",
" return SolToken\n", "\n",
" mint = context.lookup_token_address(name)\n", " def find_by_symbol(self, symbol: str):\n",
" if mint is None:\n", " found = _find_data_by_symbol(symbol, self.token_data)\n",
" raise Exception(f\"Could not find token with name '{name}'.\")\n", " if found is not None:\n",
" return Token(name, mint, Decimal(6))\n", " return Token(found[\"symbol\"], found[\"name\"], PublicKey(found[\"address\"]), Decimal(found[\"decimals\"]))\n",
"\n",
" return None\n",
"\n",
" def find_by_mint(self, mint: PublicKey):\n",
" mint_string: str = str(mint)\n",
" for token in self.token_data[\"tokens\"]:\n",
" if token[\"address\"] == mint_string:\n",
" return Token(token[\"symbol\"], token[\"name\"], PublicKey(token[\"address\"]), Decimal(token[\"decimals\"]))\n",
"\n",
" return None\n",
"\n", "\n",
" @staticmethod\n", " @staticmethod\n",
" def find_by_mint(context: Context, mint: PublicKey) -> Token:\n", " def default_lookups() -> \"TokenLookup\":\n",
" if SolToken.mint == mint:\n", " with open(\"solana.tokenlist.json\") as json_file:\n",
" return SolToken\n", " token_data = json.load(json_file)\n",
" name = context.lookup_token_name(mint)\n", " return TokenLookup(token_data)"
" if name is None:\n",
" raise Exception(f\"Could not find token with mint '{mint}'.\")\n",
" return Token(name, mint, Decimal(6))\n"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "plastic-cambridge", "id": "southern-gather",
"metadata": {},
"source": [
"## SpotMarket class"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "automatic-vegetation",
"metadata": {},
"outputs": [],
"source": [
"class SpotMarket:\n",
" def __init__(self, address: PublicKey, base: Token, quote: Token):\n",
" self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)\n",
" self.address: PublicKey = address\n",
" self.base: Token = base\n",
" self.quote: Token = quote\n",
"\n",
" @property\n",
" def name(self) -> str:\n",
" return f\"{self.base.symbol}/{self.quote.symbol}\"\n",
"\n",
" def __str__(self) -> str:\n",
" return f\"« Market {self.name}: {self.address} »\"\n",
"\n",
" def __repr__(self) -> str:\n",
" return f\"{self}\"\n"
]
},
{
"cell_type": "markdown",
"id": "handy-batch",
"metadata": {},
"source": [
"## SpotMarketLookup class\n",
"\n",
"This class allows us to look up Serum market addresses and tokens, all from our Solana static data.\n",
"\n",
"The static data is the [Solana token list](https://raw.githubusercontent.com/solana-labs/token-list/main/src/tokens/solana.tokenlist.json) provided by Serum.\n",
"\n",
"You can load a `SpotMarketLookup` class by something like:\n",
"```\n",
"with open(\"solana.tokenlist.json\") as json_file:\n",
" token_data = json.load(json_file)\n",
" token_lookup = SpotMarketLookup(token_data)\n",
"```\n",
"This uses the same data file as `TokenLookup` but it looks a lot more complicated. The main reason for this is that tokens are described in a list, whereas markets are optional child attributes of tokens.\n",
"\n",
"To find a token, we can just go through the list.\n",
"\n",
"To find a market, we need to split the market symbol into the two token symbols, go through the list, check if the item has the optional `extensions` attribute, and in there see if there is a name-value pair for the particular market we're interested in. Also, the current file only lists USDC and USDT markets, so that's all we can support this way."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "arctic-portsmouth",
"metadata": {},
"outputs": [],
"source": [
"class SpotMarketLookup:\n",
" def __init__(self, token_data: typing.Dict) -> None:\n",
" self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)\n",
" self.token_data: typing.Dict = token_data\n",
"\n",
" def find_by_symbol(self, symbol: str) -> typing.Optional[SpotMarket]:\n",
" base_symbol, quote_symbol = symbol.split(\"/\")\n",
" base_data = _find_data_by_symbol(base_symbol, self.token_data)\n",
" if base_data is None:\n",
" self.logger.warning(f\"Could not find data for base token '{base_symbol}'\")\n",
" return None\n",
" base = Token(base_data[\"symbol\"], base_data[\"name\"], PublicKey(base_data[\"address\"]), Decimal(base_data[\"decimals\"]))\n",
"\n",
" quote_data = _find_data_by_symbol(quote_symbol, self.token_data)\n",
" if quote_data is None:\n",
" self.logger.warning(f\"Could not find data for quote token '{quote_symbol}'\")\n",
" return None\n",
" quote = Token(quote_data[\"symbol\"], quote_data[\"name\"], PublicKey(quote_data[\"address\"]), Decimal(quote_data[\"decimals\"]))\n",
"\n",
" if \"extensions\" not in base_data:\n",
" self.logger.warning(f\"No markets found for base token '{base.symbol}'.\")\n",
" return None\n",
"\n",
" if quote.symbol == \"USDC\":\n",
" if \"serumV3Usdc\" not in base_data[\"extensions\"]:\n",
" self.logger.warning(f\"No USDC market found for base token '{base.symbol}'.\")\n",
" return None\n",
"\n",
" market_address_string = base_data[\"extensions\"][\"serumV3Usdc\"]\n",
" market_address = PublicKey(market_address_string)\n",
" elif quote.symbol == \"USDT\":\n",
" if \"serumV3Usdt\" not in base_data[\"extensions\"]:\n",
" self.logger.warning(f\"No USDT market found for base token '{base.symbol}'.\")\n",
" return None\n",
"\n",
" market_address_string = base_data[\"extensions\"][\"serumV3Usdt\"]\n",
" market_address = PublicKey(market_address_string)\n",
" else:\n",
" self.logger.warning(f\"Could not find market with quote token '{quote.symbol}'. Only markets based on USDC or USDT are supported.\")\n",
" return None\n",
"\n",
" return SpotMarket(market_address, base, quote)\n",
"\n",
" def find_by_address(self, address: PublicKey) -> typing.Optional[SpotMarket]:\n",
" address_string: str = str(address)\n",
" for token_data in self.token_data[\"tokens\"]:\n",
" if \"extensions\" in token_data:\n",
" if \"serumV3Usdc\" in token_data[\"extensions\"]:\n",
" if token_data[\"extensions\"][\"serumV3Usdc\"] == address_string:\n",
" market_address_string = token_data[\"extensions\"][\"serumV3Usdc\"]\n",
" market_address = PublicKey(market_address_string)\n",
" base = Token(token_data[\"symbol\"], token_data[\"name\"], PublicKey(token_data[\"address\"]), Decimal(token_data[\"decimals\"]))\n",
" quote_data = _find_data_by_symbol(\"USDC\", self.token_data)\n",
" if quote_data is None:\n",
" raise Exception(\"Could not load token data for USDC (which should always be present).\")\n",
" quote = Token(quote_data[\"symbol\"], quote_data[\"name\"], PublicKey(quote_data[\"address\"]), Decimal(quote_data[\"decimals\"]))\n",
" return SpotMarket(market_address, base, quote)\n",
" if \"serumV3Usdt\" in token_data[\"extensions\"]:\n",
" if token_data[\"extensions\"][\"serumV3Usdt\"] == address_string:\n",
" market_address_string = token_data[\"extensions\"][\"serumV3Usdt\"]\n",
" market_address = PublicKey(market_address_string)\n",
" base = Token(token_data[\"symbol\"], token_data[\"name\"], PublicKey(token_data[\"address\"]), Decimal(token_data[\"decimals\"]))\n",
" quote_data = _find_data_by_symbol(\"USDT\", self.token_data)\n",
" if quote_data is None:\n",
" raise Exception(\"Could not load token data for USDT (which should always be present).\")\n",
" quote = Token(quote_data[\"symbol\"], quote_data[\"name\"], PublicKey(quote_data[\"address\"]), Decimal(quote_data[\"decimals\"]))\n",
" return SpotMarket(market_address, base, quote)\n",
" return None\n",
"\n",
" @staticmethod\n",
" def default_lookups() -> \"SpotMarketLookup\":\n",
" with open(\"solana.tokenlist.json\") as json_file:\n",
" token_data = json.load(json_file)\n",
" return SpotMarketLookup(token_data)"
]
},
{
"cell_type": "markdown",
"id": "moderate-taxation",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## BasketToken class\n", "## BasketToken class\n",
@ -734,7 +894,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "pretty-baghdad", "id": "protective-travel",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -746,13 +906,13 @@
" self.index: Index = index\n", " self.index: Index = index\n",
"\n", "\n",
" @staticmethod\n", " @staticmethod\n",
" def find_by_name(values: typing.List[\"BasketToken\"], name: str) -> \"BasketToken\":\n", " def find_by_symbol(values: typing.List[\"BasketToken\"], symbol: str) -> \"BasketToken\":\n",
" found = [value for value in values if value.token.name_matches(name)]\n", " found = [value for value in values if value.token.symbol_matches(symbol)]\n",
" if len(found) == 0:\n", " if len(found) == 0:\n",
" raise Exception(f\"Token '{name}' not found in token values: {values}\")\n", " raise Exception(f\"Token '{symbol}' not found in token values: {values}\")\n",
"\n", "\n",
" if len(found) > 1:\n", " if len(found) > 1:\n",
" raise Exception(f\"Token '{name}' matched multiple tokens in values: {values}\")\n", " raise Exception(f\"Token '{symbol}' matched multiple tokens in values: {values}\")\n",
"\n", "\n",
" return found[0]\n", " return found[0]\n",
"\n", "\n",
@ -790,7 +950,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "suburban-teaching", "id": "enclosed-morocco",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## TokenValue class\n", "## TokenValue class\n",
@ -801,7 +961,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "indirect-image", "id": "provincial-submission",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -842,13 +1002,13 @@
" reporter(f\"{value.value:>18,.8f} {value.token.name}\")\n", " reporter(f\"{value.value:>18,.8f} {value.token.name}\")\n",
"\n", "\n",
" @staticmethod\n", " @staticmethod\n",
" def find_by_name(values: typing.List[\"TokenValue\"], name: str) -> \"TokenValue\":\n", " def find_by_symbol(values: typing.List[\"TokenValue\"], symbol: str) -> \"TokenValue\":\n",
" found = [value for value in values if value.token.name_matches(name)]\n", " found = [value for value in values if value.token.symbol_matches(symbol)]\n",
" if len(found) == 0:\n", " if len(found) == 0:\n",
" raise Exception(f\"Token '{name}' not found in token values: {values}\")\n", " raise Exception(f\"Token '{symbol}' not found in token values: {values}\")\n",
"\n", "\n",
" if len(found) > 1:\n", " if len(found) > 1:\n",
" raise Exception(f\"Token '{name}' matched multiple tokens in values: {values}\")\n", " raise Exception(f\"Token '{symbol}' matched multiple tokens in values: {values}\")\n",
"\n", "\n",
" return found[0]\n", " return found[0]\n",
"\n", "\n",
@ -886,7 +1046,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "specialized-dominican", "id": "exterior-petersburg",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## OwnedTokenValue class\n", "## OwnedTokenValue class\n",
@ -897,7 +1057,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "charged-steering", "id": "earned-patio",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -937,7 +1097,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "responsible-missile", "id": "spanish-wagner",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## MarketMetadata class" "## MarketMetadata class"
@ -946,33 +1106,33 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "humanitarian-emperor", "id": "through-bruce",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"class MarketMetadata:\n", "class MarketMetadata:\n",
" def __init__(self, name: str, address: PublicKey, base: BasketToken, quote: BasketToken,\n", " def __init__(self, name: str, address: PublicKey, base: BasketToken, quote: BasketToken,\n",
" spot: PublicKey, oracle: PublicKey, decimals: Decimal):\n", " spot: SpotMarket, oracle: PublicKey, decimals: Decimal):\n",
" self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)\n", " self.logger: logging.Logger = logging.getLogger(self.__class__.__name__)\n",
" self.name: str = name\n", " self.name: str = name\n",
" self.address: PublicKey = address\n", " self.address: PublicKey = address\n",
" self.base: BasketToken = base\n", " self.base: BasketToken = base\n",
" self.quote: BasketToken = quote\n", " self.quote: BasketToken = quote\n",
" self.spot: PublicKey = spot\n", " self.spot: SpotMarket = spot\n",
" self.oracle: PublicKey = oracle\n", " self.oracle: PublicKey = oracle\n",
" self.decimals: Decimal = decimals\n", " self.decimals: Decimal = decimals\n",
" self._market = None\n", " self._market = None\n",
"\n", "\n",
" def fetch_market(self, context: Context) -> Market:\n", " def fetch_market(self, context: Context) -> Market:\n",
" if self._market is None:\n", " if self._market is None:\n",
" self._market = Market.load(context.client, self.spot)\n", " self._market = Market.load(context.client, self.spot.address)\n",
"\n", "\n",
" return self._market\n", " return self._market\n",
"\n", "\n",
" def __str__(self) -> str:\n", " def __str__(self) -> str:\n",
" base = f\"{self.base}\".replace(\"\\n\", \"\\n \")\n", " base = f\"{self.base}\".replace(\"\\n\", \"\\n \")\n",
" quote = f\"{self.quote}\".replace(\"\\n\", \"\\n \")\n", " quote = f\"{self.quote}\".replace(\"\\n\", \"\\n \")\n",
" return f\"\"\"« Market '{self.name}' [{self.spot}]:\n", " return f\"\"\"« Market '{self.name}' [{self.address}/{self.spot.address}]:\n",
" Base: {base}\n", " Base: {base}\n",
" Quote: {quote}\n", " Quote: {quote}\n",
" Oracle: {self.oracle} ({self.decimals} decimals)\n", " Oracle: {self.oracle} ({self.decimals} decimals)\n",
@ -984,7 +1144,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "floppy-glasgow", "id": "collected-capitol",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Group class\n", "## Group class\n",
@ -995,7 +1155,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "threaded-lebanon", "id": "domestic-discovery",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1033,29 +1193,32 @@
" return self.basket_tokens[:-1]\n", " return self.basket_tokens[:-1]\n",
"\n", "\n",
" @staticmethod\n", " @staticmethod\n",
" def from_layout(layout: construct.Struct, context: Context, account_info: AccountInfo, version: Version) -> \"Group\":\n", " def from_layout(layout: construct.Struct, context: Context, account_info: AccountInfo, version: Version, token_lookup: TokenLookup = TokenLookup.default_lookups(), spot_market_lookup: SpotMarketLookup = SpotMarketLookup.default_lookups()) -> \"Group\":\n",
" account_flags: MangoAccountFlags = MangoAccountFlags.from_layout(layout.account_flags)\n", " account_flags: MangoAccountFlags = MangoAccountFlags.from_layout(layout.account_flags)\n",
" indexes = list(map(lambda pair: Index.from_layout(pair[0], pair[1]), zip(layout.indexes, layout.mint_decimals)))\n", " indexes = list(map(lambda pair: Index.from_layout(pair[0], pair[1]), zip(layout.indexes, layout.mint_decimals)))\n",
"\n", "\n",
" basket_tokens: typing.List[BasketToken] = []\n", " basket_tokens: typing.List[BasketToken] = []\n",
" for index, token_address in enumerate(layout.tokens):\n", " for index, token_address in enumerate(layout.tokens):\n",
" token_name = context.lookup_token_name(token_address)\n", " static_token_data = token_lookup.find_by_mint(token_address)\n",
" if token_name is None:\n", " if static_token_data is None:\n",
" raise Exception(f\"Could not find token with mint '{token_address}' in Group ['{account_info.address}'].\")\n", " raise Exception(f\"Could not find token with mint '{token_address}'.\")\n",
" token = Token(token_name, token_address, layout.mint_decimals[index])\n", "\n",
" # We create a new Token object here specifically to force the use of our own decimals\n",
" token = Token(static_token_data.symbol, static_token_data.name, token_address, layout.mint_decimals[index])\n",
" basket_token = BasketToken(token, layout.vaults[index], indexes[index])\n", " basket_token = BasketToken(token, layout.vaults[index], indexes[index])\n",
" basket_tokens += [basket_token]\n", " basket_tokens += [basket_token]\n",
"\n", "\n",
" markets: typing.List[MarketMetadata] = []\n", " markets: typing.List[MarketMetadata] = []\n",
" for index, market_address in enumerate(layout.spot_markets):\n", " for index, market_address in enumerate(layout.spot_markets):\n",
" market_name = context.lookup_market_name(market_address)\n", " spot_market = spot_market_lookup.find_by_address(market_address)\n",
" base_name, quote_name = market_name.split(\"/\")\n", " if spot_market is None:\n",
" base_token = BasketToken.find_by_name(basket_tokens, base_name)\n", " raise Exception(f\"Could not find spot market with address '{market_address}'.\")\n",
" quote_token = BasketToken.find_by_name(basket_tokens, quote_name)\n", "\n",
" market = MarketMetadata(market_name, market_address, base_token, quote_token,\n", " base_token = BasketToken.find_by_mint(basket_tokens, spot_market.base.mint)\n",
" layout.spot_markets[index],\n", " quote_token = BasketToken.find_by_mint(basket_tokens, spot_market.quote.mint)\n",
" layout.oracles[index],\n", "\n",
" layout.oracle_decimals[index])\n", " market = MarketMetadata(spot_market.name, market_address, base_token, quote_token,\n",
" spot_market, layout.oracles[index], layout.oracle_decimals[index])\n",
" markets += [market]\n", " markets += [market]\n",
"\n", "\n",
" maint_coll_ratio = layout.maint_coll_ratio.quantize(Decimal('.01'))\n", " maint_coll_ratio = layout.maint_coll_ratio.quantize(Decimal('.01'))\n",
@ -1126,7 +1289,6 @@
" balances += [TokenValue(SolToken, sol_balance)]\n", " balances += [TokenValue(SolToken, sol_balance)]\n",
"\n", "\n",
" for basket_token in self.basket_tokens:\n", " for basket_token in self.basket_tokens:\n",
" if basket_token.token != SolToken:\n",
" balance = TokenValue.fetch_total_value(self.context, root_address, basket_token.token)\n", " balance = TokenValue.fetch_total_value(self.context, root_address, basket_token.token)\n",
" balances += [balance]\n", " balances += [balance]\n",
" return balances\n", " return balances\n",
@ -1252,7 +1414,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "statistical-dominant", "id": "motivated-chorus",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## TokenAccount class" "## TokenAccount class"
@ -1261,7 +1423,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "blessed-usage", "id": "fewer-pilot",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1345,7 +1507,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "romance-funds", "id": "hispanic-difficulty",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## OpenOrders class\n" "## OpenOrders class\n"
@ -1354,7 +1516,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "homeless-palmer", "id": "annual-brain",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1474,7 +1636,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "downtown-facing", "id": "dependent-proposition",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## BalanceSheet class" "## BalanceSheet class"
@ -1483,7 +1645,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "renewable-redhead", "id": "compound-commitment",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1530,7 +1692,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "atmospheric-arbitration", "id": "located-linux",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## MarginAccount class\n" "## MarginAccount class\n"
@ -1539,7 +1701,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "aquatic-republican", "id": "aerial-weight",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1755,7 +1917,7 @@
" # If this becomes more painful than typing.Optional[Token], we can go with making\n", " # If this becomes more painful than typing.Optional[Token], we can go with making\n",
" # Token optional.\n", " # Token optional.\n",
" summary_name = \"-\".join([bal.token.name for bal in balance_sheets])\n", " summary_name = \"-\".join([bal.token.name for bal in balance_sheets])\n",
" summary_token = Token(summary_name, SYSTEM_PROGRAM_ADDRESS, Decimal(0))\n", " summary_token = Token(summary_name, f\"{summary_name} Summary\", SYSTEM_PROGRAM_ADDRESS, Decimal(0))\n",
" return BalanceSheet(summary_token, liabilities, settled_assets, unsettled_assets)\n", " return BalanceSheet(summary_token, liabilities, settled_assets, unsettled_assets)\n",
"\n", "\n",
" def get_intrinsic_balances(self, group: Group) -> typing.List[TokenValue]:\n", " def get_intrinsic_balances(self, group: Group) -> typing.List[TokenValue]:\n",
@ -1789,7 +1951,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "common-albania", "id": "geological-winner",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## MarginAccountMetadata class" "## MarginAccountMetadata class"
@ -1798,7 +1960,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "assumed-giant", "id": "natural-semester",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1824,7 +1986,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "impressed-tender", "id": "introductory-premises",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# Events" "# Events"
@ -1832,7 +1994,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "quick-finland", "id": "varied-spokesman",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## LiquidationEvent" "## LiquidationEvent"
@ -1841,7 +2003,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "narrative-reason", "id": "faced-death",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1860,7 +2022,7 @@
"\n", "\n",
" def __str__(self) -> str:\n", " def __str__(self) -> str:\n",
" result = \"✅\" if self.succeeded else \"❌\"\n", " result = \"✅\" if self.succeeded else \"❌\"\n",
" changes_text = \"\\n \".join([f\"{change.value:>15,.8f} {change.token.name}\" for change in self.changes])\n", " changes_text = \"\\n \".join([f\"{change.value:>15,.8f} {change.token.symbol}\" for change in self.changes])\n",
" return f\"\"\"« 🥭 Liqudation Event {result} at {self.timestamp}\n", " return f\"\"\"« 🥭 Liqudation Event {result} at {self.timestamp}\n",
" 💧 Liquidator: {self.liquidator_name}\n", " 💧 Liquidator: {self.liquidator_name}\n",
" 🗃️ Group: {self.group_name}\n", " 🗃️ Group: {self.group_name}\n",
@ -1877,7 +2039,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "positive-twist", "id": "appreciated-citation",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ✅ Testing" "# ✅ Testing"
@ -1886,7 +2048,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "breeding-nirvana", "id": "average-rapid",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -1895,8 +2057,6 @@
" try:\n", " try:\n",
" logging.getLogger().setLevel(logging.CRITICAL)\n", " logging.getLogger().setLevel(logging.CRITICAL)\n",
"\n", "\n",
" from Context import default_context\n",
"\n",
" list_to_split = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"]\n", " list_to_split = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"]\n",
" split_3 = _split_list_into_chunks(list_to_split, 3)\n", " split_3 = _split_list_into_chunks(list_to_split, 3)\n",
" assert(len(split_3) == 4)\n", " assert(len(split_3) == 4)\n",
@ -1915,15 +2075,32 @@
" assert(len(split_20) == 1)\n", " assert(len(split_20) == 1)\n",
" assert(split_20[0] == [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"])\n", " assert(split_20[0] == [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"])\n",
"\n", "\n",
" token_lookup = TokenLookup.default_lookups()\n",
"\n",
" assert(token_lookup.find_by_symbol(\"ETH\").mint == PublicKey(\"2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk\"))\n",
" assert(token_lookup.find_by_mint(\"AKJHspCwDhABucCxNLXUSfEzb7Ny62RqFtC9uNjJi4fq\").symbol == \"SRM-SOL\")\n",
"\n",
" market_lookup = SpotMarketLookup.default_lookups()\n",
" assert(market_lookup.find_by_symbol(\"ETH/USDT\").base.symbol == \"ETH\")\n",
" assert(market_lookup.find_by_symbol(\"ETH/USDT\").quote.symbol == \"USDT\")\n",
" assert(market_lookup.find_by_symbol(\"ETH/USDT\").address == PublicKey(\"7dLVkUfBVfCGkFhSXDCq1ukM9usathSgS716t643iFGF\"))\n",
" assert(market_lookup.find_by_symbol(\"BTC/USDC\").base.symbol == \"BTC\")\n",
" assert(market_lookup.find_by_symbol(\"BTC/USDC\").quote.symbol == \"USDC\")\n",
" assert(market_lookup.find_by_symbol(\"BTC/USDC\").address == PublicKey(\"A8YFbxQYFVqKZaoYJLLUVcQiWP7G2MeEgW5wsAQgMvFw\"))\n",
" assert(market_lookup.find_by_symbol(\"ETH/BTC\") is None) # No such market\n",
" assert(market_lookup.find_by_address(\"ByRys5tuUWDgL73G8JBAEfkdFf8JWBzPBDHsBVQ5vbQA\").base.symbol == \"SRM\")\n",
" assert(market_lookup.find_by_address(\"ByRys5tuUWDgL73G8JBAEfkdFf8JWBzPBDHsBVQ5vbQA\").quote.symbol == \"USDC\")\n",
" assert(market_lookup.find_by_address(\"ByRys5tuUWDgL73G8JBAEfkdFf8JWBzPBDHsBVQ5vbQA\").address == PublicKey(\"ByRys5tuUWDgL73G8JBAEfkdFf8JWBzPBDHsBVQ5vbQA\"))\n",
"\n",
" balances_before = [\n", " balances_before = [\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"ETH\"), Decimal(1)),\n", " TokenValue(token_lookup.find_by_symbol(\"ETH\"), Decimal(1)),\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"BTC\"), Decimal(\"0.1\")),\n", " TokenValue(token_lookup.find_by_symbol(\"BTC\"), Decimal(\"0.1\")),\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"USDT\"), Decimal(1000))\n", " TokenValue(token_lookup.find_by_symbol(\"USDT\"), Decimal(1000))\n",
" ]\n", " ]\n",
" balances_after = [\n", " balances_after = [\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"ETH\"), Decimal(1)),\n", " TokenValue(token_lookup.find_by_symbol(\"ETH\"), Decimal(1)),\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"BTC\"), Decimal(\"0.05\")),\n", " TokenValue(token_lookup.find_by_symbol(\"BTC\"), Decimal(\"0.05\")),\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"USDT\"), Decimal(2000))\n", " TokenValue(token_lookup.find_by_symbol(\"USDT\"), Decimal(2000))\n",
" ]\n", " ]\n",
" timestamp = datetime.datetime(2021, 5, 17, 12, 20, 56)\n", " timestamp = datetime.datetime(2021, 5, 17, 12, 20, 56)\n",
" event = LiquidationEvent(timestamp, \"Liquidator\", \"Group\", True, \"signature\",\n", " event = LiquidationEvent(timestamp, \"Liquidator\", \"Group\", True, \"signature\",\n",
@ -1950,7 +2127,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "african-clinic", "id": "variable-employee",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🏃 Running" "# 🏃 Running"
@ -1959,12 +2136,15 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "applicable-silence", "id": "accurate-tsunami",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"if __name__ == \"__main__\":\n", "if __name__ == \"__main__\":\n",
" logging.getLogger().setLevel(logging.INFO)\n", " def _notebook_main():\n",
" log_level = logging.getLogger().level\n",
" try:\n",
" logging.getLogger().setLevel(logging.CRITICAL)\n",
"\n", "\n",
" import base64\n", " import base64\n",
" from Context import default_context\n", " from Context import default_context\n",
@ -1990,11 +2170,12 @@
" print(\"\\n\\nThis is hard-coded, not live information!\")\n", " print(\"\\n\\nThis is hard-coded, not live information!\")\n",
" print(\"5-token group\", group_5)\n", " print(\"5-token group\", group_5)\n",
"\n", "\n",
" print(TokenLookup.find_by_name(default_context, \"ETH\"))\n", " token_lookup = TokenLookup.default_lookups()\n",
" print(TokenLookup.find_by_name(default_context, \"BTC\"))\n", " print(token_lookup.find_by_symbol(\"ETH\"))\n",
" print(token_lookup.find_by_symbol(\"BTC\"))\n",
"\n", "\n",
" # USDT\n", " # USDT\n",
" print(TokenLookup.find_by_mint(default_context, PublicKey(\"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB\")))\n", " print(token_lookup.find_by_mint(PublicKey(\"Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB\")))\n",
"\n", "\n",
" single_account_info = AccountInfo.load(default_context, default_context.dex_program_id)\n", " single_account_info = AccountInfo.load(default_context, default_context.dex_program_id)\n",
" print(\"DEX account info\", single_account_info)\n", " print(\"DEX account info\", single_account_info)\n",
@ -2003,20 +2184,25 @@
" print(\"Mango program and DEX account info\", multiple_account_info)\n", " print(\"Mango program and DEX account info\", multiple_account_info)\n",
"\n", "\n",
" balances_before = [\n", " balances_before = [\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"ETH\"), Decimal(1)),\n", " TokenValue(token_lookup.find_by_symbol(\"ETH\"), Decimal(1)),\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"BTC\"), Decimal(\"0.1\")),\n", " TokenValue(token_lookup.find_by_symbol(\"BTC\"), Decimal(\"0.1\")),\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"USDT\"), Decimal(1000))\n", " TokenValue(token_lookup.find_by_symbol(\"USDT\"), Decimal(1000))\n",
" ]\n", " ]\n",
" balances_after = [\n", " balances_after = [\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"ETH\"), Decimal(1)),\n", " TokenValue(token_lookup.find_by_symbol(\"ETH\"), Decimal(1)),\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"BTC\"), Decimal(\"0.05\")),\n", " TokenValue(token_lookup.find_by_symbol(\"BTC\"), Decimal(\"0.05\")),\n",
" TokenValue(TokenLookup.find_by_name(default_context, \"USDT\"), Decimal(2000))\n", " TokenValue(token_lookup.find_by_symbol(\"USDT\"), Decimal(2000))\n",
" ]\n", " ]\n",
" timestamp = datetime.datetime(2021, 5, 17, 12, 20, 56)\n", " timestamp = datetime.datetime(2021, 5, 17, 12, 20, 56)\n",
" event = LiquidationEvent(timestamp, \"Liquidator\", \"Group\", True, \"signature\",\n", " event = LiquidationEvent(timestamp, \"Liquidator\", \"Group\", True, \"signature\",\n",
" SYSTEM_PROGRAM_ADDRESS, SYSTEM_PROGRAM_ADDRESS,\n", " SYSTEM_PROGRAM_ADDRESS, SYSTEM_PROGRAM_ADDRESS,\n",
" balances_before, balances_after)\n", " balances_before, balances_after)\n",
" print(event)\n" " print(event)\n",
" finally:\n",
" logging.getLogger().setLevel(log_level)\n",
"\n",
" _notebook_main()\n",
" del _notebook_main\n"
] ]
} }
], ],

View File

@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "fitting-ticket", "id": "successful-ordinary",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ⚠ Warning\n", "# ⚠ Warning\n",
@ -16,7 +16,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "historical-grace", "id": "living-league",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🥭 Constants\n", "# 🥭 Constants\n",
@ -27,7 +27,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "subtle-idaho", "id": "spatial-korean",
"metadata": { "metadata": {
"jupyter": { "jupyter": {
"source_hidden": true "source_hidden": true
@ -44,7 +44,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "institutional-earthquake", "id": "constitutional-former",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## SYSTEM_PROGRAM_ADDRESS\n", "## SYSTEM_PROGRAM_ADDRESS\n",
@ -55,7 +55,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "everyday-donna", "id": "undefined-majority",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -64,27 +64,27 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "motivated-northwest", "id": "liberal-hamilton",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## SOL_MINT_ADDRESS\n", "## SOL_MINT_ADDRESS\n",
"\n", "\n",
"The mint address of the SOL token." "The fake mint address of the SOL token. **Note:** Wrapped SOL has a different mint address - it is So11111111111111111111111111111111111111112."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "speaking-homework", "id": "accepting-circumstances",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"SOL_MINT_ADDRESS = PublicKey(\"So11111111111111111111111111111111111111112\")" "SOL_MINT_ADDRESS = PublicKey(\"So11111111111111111111111111111111111111111\")"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "dated-appeal", "id": "sacred-valve",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## SOL_DECIMALS\n", "## SOL_DECIMALS\n",
@ -95,7 +95,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "ready-tension", "id": "female-customs",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -104,7 +104,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "artistic-batch", "id": "excess-tyler",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## SOL_DECIMAL_DIVISOR decimal\n", "## SOL_DECIMAL_DIVISOR decimal\n",
@ -115,7 +115,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "powerful-warrior", "id": "divine-concord",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -124,7 +124,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "mathematical-gender", "id": "western-removal",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## NUM_TOKENS\n", "## NUM_TOKENS\n",
@ -135,7 +135,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "isolated-sandwich", "id": "hungry-disco",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -144,7 +144,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "marine-florist", "id": "abroad-woman",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## NUM_MARKETS\n", "## NUM_MARKETS\n",
@ -155,7 +155,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "defensive-jewel", "id": "flush-wages",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -164,7 +164,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "optimum-wagner", "id": "pleasant-convergence",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# WARNING_DISCLAIMER_TEXT\n", "# WARNING_DISCLAIMER_TEXT\n",
@ -175,7 +175,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "arranged-hypothesis", "id": "residential-roots",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -195,7 +195,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "focused-electricity", "id": "surrounded-magnet",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## MangoConstants\n", "## MangoConstants\n",
@ -206,7 +206,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "otherwise-pencil", "id": "radical-submission",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -216,7 +216,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "dependent-pursuit", "id": "dutch-tension",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🏃 Running\n", "# 🏃 Running\n",
@ -227,7 +227,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "primary-graphic", "id": "settled-clock",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [

View File

@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "proud-accommodation", "id": "artistic-cheese",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ⚠ Warning\n", "# ⚠ Warning\n",
@ -16,7 +16,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "manufactured-subcommittee", "id": "endless-table",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🥭 Context\n", "# 🥭 Context\n",
@ -26,7 +26,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "academic-liberia", "id": "willing-companion",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Environment Variables\n", "## Environment Variables\n",
@ -41,7 +41,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "equivalent-conspiracy", "id": "infinite-ambassador",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Provided Configured Objects\n", "## Provided Configured Objects\n",
@ -61,7 +61,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "automotive-diamond", "id": "suffering-soccer",
"metadata": { "metadata": {
"jupyter": { "jupyter": {
"source_hidden": true "source_hidden": true
@ -86,7 +86,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "private-vessel", "id": "unlimited-plymouth",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Context class" "## Context class"
@ -95,7 +95,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "blessed-azerbaijan", "id": "through-factory",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -172,18 +172,9 @@
" return name\n", " return name\n",
" return \"« Unknown Group »\"\n", " return \"« Unknown Group »\"\n",
"\n", "\n",
" def lookup_market_name(self, market_address: PublicKey) -> str:\n",
" return Context._lookup_name_by_address(market_address, MangoConstants[self.cluster][\"mango_groups\"][self.group_name][\"spot_market_symbols\"]) or \"« Unknown Market »\"\n",
"\n",
" def lookup_oracle_name(self, token_address: PublicKey) -> str:\n", " def lookup_oracle_name(self, token_address: PublicKey) -> str:\n",
" return Context._lookup_name_by_address(token_address, MangoConstants[self.cluster][\"oracles\"]) or \"« Unknown Oracle »\"\n", " return Context._lookup_name_by_address(token_address, MangoConstants[self.cluster][\"oracles\"]) or \"« Unknown Oracle »\"\n",
"\n", "\n",
" def lookup_token_name(self, token_address: PublicKey) -> typing.Optional[str]:\n",
" return Context._lookup_name_by_address(token_address, MangoConstants[self.cluster][\"mango_groups\"][self.group_name][\"symbols\"])\n",
"\n",
" def lookup_token_address(self, token_name: str) -> typing.Optional[PublicKey]:\n",
" return Context._lookup_address_by_name(token_name, MangoConstants[self.cluster][\"mango_groups\"][self.group_name][\"symbols\"])\n",
"\n",
" def wait_for_confirmation(self, transaction_id: str, max_wait_in_seconds: int = 60) -> typing.Optional[typing.Dict]:\n", " def wait_for_confirmation(self, transaction_id: str, max_wait_in_seconds: int = 60) -> typing.Optional[typing.Dict]:\n",
" self.logger.info(f\"Waiting up to {max_wait_in_seconds} seconds for {transaction_id}.\")\n", " self.logger.info(f\"Waiting up to {max_wait_in_seconds} seconds for {transaction_id}.\")\n",
" for wait in range(0, max_wait_in_seconds):\n", " for wait in range(0, max_wait_in_seconds):\n",
@ -253,7 +244,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "guilty-conservation", "id": "brazilian-ethnic",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## default_context object\n", "## default_context object\n",
@ -264,7 +255,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "classified-underground", "id": "scenic-morgan",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -283,7 +274,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "ceramic-nightlife", "id": "educational-equilibrium",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## solana_context object\n", "## solana_context object\n",
@ -294,7 +285,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "animated-louisiana", "id": "published-jordan",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -306,7 +297,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "thick-crash", "id": "beautiful-coffee",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## serum_context object\n", "## serum_context object\n",
@ -317,7 +308,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "behavioral-laser", "id": "velvet-bride",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -329,7 +320,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "neural-malpractice", "id": "fiscal-contribution",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🏃 Running\n", "# 🏃 Running\n",
@ -340,7 +331,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "previous-capacity", "id": "recovered-proceeding",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -349,10 +340,6 @@
"\n", "\n",
" print(default_context)\n", " print(default_context)\n",
"\n", "\n",
" print(\"Lookup ETH token name result:\", default_context.lookup_token_name(PublicKey(\"2FPyTwcZLUg1MDrwsyoP4D6s1tM7hAkHYRjkNb5w6Pxk\")))\n",
" print(\"Lookup ETH token address result:\", default_context.lookup_token_address(\"ETH\"))\n",
" print(\"Lookup BTC/USDC market name result:\", default_context.lookup_market_name(PublicKey(\"CVfYa8RGXnuDBeGmniCcdkBwoLqVxh92xB1JqgRQx3F\")))\n",
"\n",
" # Fill out your account address between the quotes below\n", " # Fill out your account address between the quotes below\n",
" MY_ACCOUNT_ADDRESS = \"\"\n", " MY_ACCOUNT_ADDRESS = \"\"\n",
" # Don't edit anything beyond here.\n", " # Don't edit anything beyond here.\n",

View File

@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "corresponding-metabolism", "id": "numeric-sheep",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ⚠ Warning\n", "# ⚠ Warning\n",
@ -16,7 +16,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "hollywood-victory", "id": "lesser-small",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🥭 Instructions\n", "# 🥭 Instructions\n",
@ -27,7 +27,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "disturbed-washer", "id": "african-picking",
"metadata": { "metadata": {
"jupyter": { "jupyter": {
"source_hidden": true "source_hidden": true
@ -55,7 +55,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "different-philosophy", "id": "trained-cartridge",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# InstructionBuilder class\n", "# InstructionBuilder class\n",
@ -66,7 +66,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "secret-eugene", "id": "apparent-plane",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -85,7 +85,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "accessory-drunk", "id": "daily-dependence",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ForceCancelOrdersInstructionBuilder class" "# ForceCancelOrdersInstructionBuilder class"
@ -93,7 +93,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "touched-consideration", "id": "ceramic-football",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Rust Interface\n", "## Rust Interface\n",
@ -125,7 +125,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "blank-biodiversity", "id": "empirical-ultimate",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Client API call\n", "## Client API call\n",
@ -169,7 +169,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "physical-gentleman", "id": "eligible-madison",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -200,7 +200,7 @@
" AccountMeta(is_signer=False, is_writable=True, pubkey=self.margin_account.address),\n", " AccountMeta(is_signer=False, is_writable=True, pubkey=self.margin_account.address),\n",
" AccountMeta(is_signer=False, is_writable=True, pubkey=self.market_metadata.base.vault),\n", " AccountMeta(is_signer=False, is_writable=True, pubkey=self.market_metadata.base.vault),\n",
" AccountMeta(is_signer=False, is_writable=True, pubkey=self.market_metadata.quote.vault),\n", " AccountMeta(is_signer=False, is_writable=True, pubkey=self.market_metadata.quote.vault),\n",
" AccountMeta(is_signer=False, is_writable=True, pubkey=self.market_metadata.spot),\n", " AccountMeta(is_signer=False, is_writable=True, pubkey=self.market_metadata.spot.address),\n",
" AccountMeta(is_signer=False, is_writable=True, pubkey=self.market.state.bids()),\n", " AccountMeta(is_signer=False, is_writable=True, pubkey=self.market.state.bids()),\n",
" AccountMeta(is_signer=False, is_writable=True, pubkey=self.market.state.asks()),\n", " AccountMeta(is_signer=False, is_writable=True, pubkey=self.market.state.asks()),\n",
" AccountMeta(is_signer=False, is_writable=False, pubkey=self.group.signer_key),\n", " AccountMeta(is_signer=False, is_writable=False, pubkey=self.group.signer_key),\n",
@ -224,7 +224,7 @@
" def from_margin_account_and_market(context: Context, group: Group, wallet: Wallet, margin_account: MarginAccount, market_metadata: MarketMetadata) -> \"ForceCancelOrdersInstructionBuilder\":\n", " def from_margin_account_and_market(context: Context, group: Group, wallet: Wallet, margin_account: MarginAccount, market_metadata: MarketMetadata) -> \"ForceCancelOrdersInstructionBuilder\":\n",
" market = market_metadata.fetch_market(context)\n", " market = market_metadata.fetch_market(context)\n",
" nonce = struct.pack(\"<Q\", market.state.vault_signer_nonce())\n", " nonce = struct.pack(\"<Q\", market.state.vault_signer_nonce())\n",
" dex_signer = PublicKey.create_program_address([bytes(market_metadata.spot), nonce], context.dex_program_id)\n", " dex_signer = PublicKey.create_program_address([bytes(market_metadata.spot.address), nonce], context.dex_program_id)\n",
" oracles = list([mkt.oracle for mkt in group.markets])\n", " oracles = list([mkt.oracle for mkt in group.markets])\n",
"\n", "\n",
" return ForceCancelOrdersInstructionBuilder(context, group, wallet, margin_account, market_metadata, market, oracles, dex_signer)\n", " return ForceCancelOrdersInstructionBuilder(context, group, wallet, margin_account, market_metadata, market, oracles, dex_signer)\n",
@ -258,7 +258,7 @@
" liqee_margin_account_acc: &Pubkey: {self.margin_account.address},\n", " liqee_margin_account_acc: &Pubkey: {self.margin_account.address},\n",
" base_vault_pk: &Pubkey: {self.market_metadata.base.vault},\n", " base_vault_pk: &Pubkey: {self.market_metadata.base.vault},\n",
" quote_vault_pk: &Pubkey: {self.market_metadata.quote.vault},\n", " quote_vault_pk: &Pubkey: {self.market_metadata.quote.vault},\n",
" spot_market_pk: &Pubkey: {self.market_metadata.spot},\n", " spot_market_pk: &Pubkey: {self.market_metadata.spot.address},\n",
" bids_pk: &Pubkey: {self.market.state.bids()},\n", " bids_pk: &Pubkey: {self.market.state.bids()},\n",
" asks_pk: &Pubkey: {self.market.state.asks()},\n", " asks_pk: &Pubkey: {self.market.state.asks()},\n",
" signer_pk: &Pubkey: {self.group.signer_key},\n", " signer_pk: &Pubkey: {self.group.signer_key},\n",
@ -275,7 +275,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "changing-humanity", "id": "expanded-separate",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# LiquidateInstructionBuilder class\n", "# LiquidateInstructionBuilder class\n",
@ -287,7 +287,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "occupational-steam", "id": "stupid-arrest",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Rust Interface\n", "## Rust Interface\n",
@ -333,7 +333,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "heard-farming", "id": "identical-november",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Client API call\n", "## Client API call\n",
@ -370,7 +370,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "changed-literacy", "id": "logical-burning",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## from_margin_account_and_market() function\n", "## from_margin_account_and_market() function\n",
@ -391,7 +391,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "former-cemetery", "id": "pending-services",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -503,7 +503,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "traditional-assembly", "id": "retired-bundle",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🏃 Running" "# 🏃 Running"
@ -512,7 +512,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "victorian-character", "id": "wrong-rebel",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [

View File

@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "enclosed-algebra", "id": "ordinary-duplicate",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ⚠ Warning\n", "# ⚠ Warning\n",
@ -16,7 +16,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "aggressive-physiology", "id": "sound-earthquake",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🥭 Notification\n", "# 🥭 Notification\n",
@ -27,7 +27,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "patient-blame", "id": "tamil-carpet",
"metadata": { "metadata": {
"jupyter": { "jupyter": {
"source_hidden": true "source_hidden": true
@ -49,7 +49,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "global-feature", "id": "brave-coordinate",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# NotificationTarget class\n", "# NotificationTarget class\n",
@ -64,7 +64,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "noted-marking", "id": "weekly-financing",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -88,7 +88,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "forward-compact", "id": "negative-madagascar",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# TelegramNotificationTarget class\n", "# TelegramNotificationTarget class\n",
@ -113,7 +113,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "quarterly-nothing", "id": "binary-export",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -136,7 +136,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "published-ideal", "id": "whole-design",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# DiscordNotificationTarget class\n", "# DiscordNotificationTarget class\n",
@ -147,7 +147,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "junior-conditions", "id": "naughty-disney",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -170,7 +170,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "actual-bronze", "id": "finite-caribbean",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# MailjetNotificationTarget class\n", "# MailjetNotificationTarget class\n",
@ -224,7 +224,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "reduced-rabbit", "id": "daily-accreditation",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -271,7 +271,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "gross-stereo", "id": "physical-norfolk",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# CsvFileNotificationTarget class\n", "# CsvFileNotificationTarget class\n",
@ -288,7 +288,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "given-african", "id": "awful-airport",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -318,7 +318,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "adult-chicago", "id": "instrumental-adams",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# FilteringNotificationTarget class\n", "# FilteringNotificationTarget class\n",
@ -329,7 +329,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "acceptable-christopher", "id": "iraqi-dryer",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -349,7 +349,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "falling-cattle", "id": "monthly-translator",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# parse_subscription_target() function\n", "# parse_subscription_target() function\n",
@ -362,7 +362,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "speaking-vocabulary", "id": "overall-camera",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -383,7 +383,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "bacterial-coffee", "id": "original-heating",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## NotificationHandler class\n", "## NotificationHandler class\n",
@ -394,7 +394,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "norman-bruce", "id": "different-breach",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -410,7 +410,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "cloudy-czech", "id": "entertaining-mobility",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ✅ Testing" "# ✅ Testing"
@ -419,7 +419,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "rough-structure", "id": "animal-player",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -466,7 +466,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "solved-switzerland", "id": "after-definition",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🏃 Running\n", "# 🏃 Running\n",
@ -477,7 +477,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "signed-guyana", "id": "anticipated-destruction",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -503,18 +503,21 @@
" # from Context import default_context\n", " # from Context import default_context\n",
" # from decimal import Decimal\n", " # from decimal import Decimal\n",
" # from Wallet import default_wallet\n", " # from Wallet import default_wallet\n",
" # token_lookup = TokenLookup.default_lookups()\n",
" # balances_before = [\n", " # balances_before = [\n",
" # TokenValue(TokenLookup.find_by_name(default_context, \"ETH\"), Decimal(1)),\n", " # TokenValue(token_lookup.find_by_symbol(\"ETH\"), Decimal(1)),\n",
" # TokenValue(TokenLookup.find_by_name(default_context, \"BTC\"), Decimal(\"0.1\")),\n", " # TokenValue(token_lookup.find_by_symbol(\"BTC\"), Decimal(\"0.1\")),\n",
" # TokenValue(TokenLookup.find_by_name(default_context, \"USDT\"), Decimal(1000))\n", " # TokenValue(token_lookup.find_by_symbol(\"USDT\"), Decimal(1000))\n",
" # ]\n", " # ]\n",
" # balances_after = [\n", " # balances_after = [\n",
" # TokenValue(TokenLookup.find_by_name(default_context, \"ETH\"), Decimal(1)),\n", " # TokenValue(token_lookup.find_by_symbol(\"ETH\"), Decimal(1)),\n",
" # TokenValue(TokenLookup.find_by_name(default_context, \"BTC\"), Decimal(\"0.05\")),\n", " # TokenValue(token_lookup.find_by_symbol(\"BTC\"), Decimal(\"0.05\")),\n",
" # TokenValue(TokenLookup.find_by_name(default_context, \"USDT\"), Decimal(2000))\n", " # TokenValue(token_lookup.find_by_symbol(\"USDT\"), Decimal(2000))\n",
" # ]\n", " # ]\n",
" #\n",
" # event = LiquidationEvent(datetime.datetime.now(),\n", " # event = LiquidationEvent(datetime.datetime.now(),\n",
" # \"Liquidator Name\",\n",
" # \"GROUP_NAME\",\n",
" # True,\n",
" # \"SIGNATURE\",\n", " # \"SIGNATURE\",\n",
" # default_wallet.address,\n", " # default_wallet.address,\n",
" # default_wallet.address,\n", " # default_wallet.address,\n",

View File

@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "juvenile-netherlands", "id": "french-mexico",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ⚠ Warning\n", "# ⚠ Warning\n",
@ -16,7 +16,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "changed-correspondence", "id": "eastern-relevance",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🥭 TradeExecutor\n", "# 🥭 TradeExecutor\n",
@ -31,7 +31,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "pacific-organic", "id": "descending-attendance",
"metadata": { "metadata": {
"jupyter": { "jupyter": {
"source_hidden": true "source_hidden": true
@ -59,7 +59,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "champion-wheel", "id": "impressed-hazard",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# TradeExecutor class\n", "# TradeExecutor class\n",
@ -77,7 +77,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "competent-former", "id": "thirty-habitat",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -104,7 +104,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "latin-electronics", "id": "possible-blank",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## NullTradeExecutor class\n", "## NullTradeExecutor class\n",
@ -115,7 +115,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "accessible-decline", "id": "subjective-violation",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -144,7 +144,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "noted-immunology", "id": "paperback-america",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# SerumImmediateTradeExecutor class\n", "# SerumImmediateTradeExecutor class\n",
@ -174,7 +174,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "enabling-convenience", "id": "greatest-impression",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -327,7 +327,7 @@
" self.reporter(\"All settlement transaction IDs confirmed.\")\n", " self.reporter(\"All settlement transaction IDs confirmed.\")\n",
"\n", "\n",
" def _tokens_and_market(self, symbol: str) -> typing.Tuple[MarketMetadata, Token, Token]:\n", " def _tokens_and_market(self, symbol: str) -> typing.Tuple[MarketMetadata, Token, Token]:\n",
" base_token = BasketToken.find_by_name(self.group.basket_tokens, symbol).token\n", " base_token = BasketToken.find_by_symbol(self.group.basket_tokens, symbol).token\n",
" quote_token = self.group.shared_quote_token.token\n", " quote_token = self.group.shared_quote_token.token\n",
" self.logger.info(f\"Base token: {base_token}\")\n", " self.logger.info(f\"Base token: {base_token}\")\n",
" self.logger.info(f\"Quote token: {quote_token}\")\n", " self.logger.info(f\"Quote token: {quote_token}\")\n",
@ -356,7 +356,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "front-queens", "id": "living-mitchell",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🏃 Running\n", "# 🏃 Running\n",
@ -369,7 +369,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "optimum-judgment", "id": "collected-simon",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [

View File

@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "corrected-sunrise", "id": "described-pencil",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ⚠ Warning\n", "# ⚠ Warning\n",
@ -16,7 +16,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "aware-hollywood", "id": "nervous-bikini",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🥭 TransactionScount\n", "# 🥭 TransactionScount\n",
@ -29,7 +29,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "coastal-wilson", "id": "fitting-andrews",
"metadata": { "metadata": {
"jupyter": { "jupyter": {
"source_hidden": true "source_hidden": true
@ -54,7 +54,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "indirect-mount", "id": "weighted-annotation",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Transaction Indices\n", "## Transaction Indices\n",
@ -79,7 +79,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "gothic-grace", "id": "spiritual-buffer",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -149,7 +149,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "oriented-defense", "id": "suspected-broadcasting",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## TransactionInstruction class\n", "## TransactionInstruction class\n",
@ -160,7 +160,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "entire-russian", "id": "compact-extreme",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -273,7 +273,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "auburn-liability", "id": "portuguese-implement",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# TransactionScout class" "# TransactionScout class"
@ -282,7 +282,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "strong-olive", "id": "focused-poultry",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -358,7 +358,7 @@
" decimals = Decimal(balance[\"uiTokenAmount\"][\"decimals\"])\n", " decimals = Decimal(balance[\"uiTokenAmount\"][\"decimals\"])\n",
" divisor = Decimal(10) ** decimals\n", " divisor = Decimal(10) ** decimals\n",
" value = amount / divisor\n", " value = amount / divisor\n",
" token = TokenLookup.find_by_mint(context, mint)\n", " token = TokenLookup.default_lookups().find_by_mint(mint)\n",
" return OwnedTokenValue(account, TokenValue(token, value))\n", " return OwnedTokenValue(account, TokenValue(token, value))\n",
"\n", "\n",
" try:\n", " try:\n",
@ -436,7 +436,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "enormous-boxing", "id": "electronic-cassette",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -462,7 +462,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "lonely-proceeding", "id": "false-merchant",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🏃 Running\n", "# 🏃 Running\n",
@ -479,7 +479,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "static-affiliation", "id": "recovered-times",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -489,7 +489,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "quantitative-wellington", "id": "descending-norwegian",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [

View File

@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "important-firmware", "id": "intense-illinois",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ⚠ Warning\n", "# ⚠ Warning\n",
@ -16,7 +16,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "limited-ordering", "id": "ceramic-smoke",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🥭 WalletBalancer\n", "# 🥭 WalletBalancer\n",
@ -31,7 +31,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "immediate-berlin", "id": "adequate-costume",
"metadata": { "metadata": {
"jupyter": { "jupyter": {
"source_hidden": true "source_hidden": true
@ -54,7 +54,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "atomic-studio", "id": "special-nomination",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# Target Balances\n", "# Target Balances\n",
@ -75,7 +75,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "muslim-whale", "id": "unknown-relationship",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## TargetBalance class\n", "## TargetBalance class\n",
@ -86,7 +86,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "fallen-plumbing", "id": "mighty-stock",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -105,7 +105,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "acting-december", "id": "earlier-internship",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## FixedTargetBalance class\n", "## FixedTargetBalance class\n",
@ -116,7 +116,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "fuzzy-laptop", "id": "electronic-cycle",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -134,7 +134,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "ready-costume", "id": "muslim-priority",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## PercentageTargetBalance\n", "## PercentageTargetBalance\n",
@ -150,7 +150,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "premium-basin", "id": "potential-mustang",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -170,7 +170,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "behavioral-convertible", "id": "assigned-mississippi",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## TargetBalanceParser class\n", "## TargetBalanceParser class\n",
@ -183,7 +183,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "democratic-crowd", "id": "hired-laundry",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -197,7 +197,7 @@
" except Exception as exception:\n", " except Exception as exception:\n",
" raise Exception(f\"Could not parse target balance '{to_parse}'\") from exception\n", " raise Exception(f\"Could not parse target balance '{to_parse}'\") from exception\n",
"\n", "\n",
" token = Token.find_by_name(self.tokens, token_name)\n", " token = Token.find_by_symbol(self.tokens, token_name)\n",
"\n", "\n",
" # The value we have may be an int (like 27), a fraction (like 0.1) or a percentage\n", " # The value we have may be an int (like 27), a fraction (like 0.1) or a percentage\n",
" # (like 25%). In all cases we want the number as a number, but we also want to know if\n", " # (like 25%). In all cases we want the number as a number, but we also want to know if\n",
@ -221,7 +221,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "supreme-kentucky", "id": "private-colorado",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# sort_changes_for_trades function\n", "# sort_changes_for_trades function\n",
@ -234,7 +234,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "small-period", "id": "signal-reputation",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -244,7 +244,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "significant-bearing", "id": "regular-array",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# calculate_required_balance_changes function\n", "# calculate_required_balance_changes function\n",
@ -255,7 +255,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "regulation-essay", "id": "minimal-kinase",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -271,7 +271,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "taken-salvation", "id": "round-appendix",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# FilterSmallChanges class\n", "# FilterSmallChanges class\n",
@ -286,7 +286,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "clean-horizon", "id": "european-ratio",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -315,7 +315,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "animated-switzerland", "id": "three-shareware",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# WalletBalancers\n", "# WalletBalancers\n",
@ -331,7 +331,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "essential-heating", "id": "destroyed-validation",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## WalletBalancer class\n", "## WalletBalancer class\n",
@ -342,7 +342,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "behind-product", "id": "engaged-thunder",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -354,7 +354,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "mighty-minimum", "id": "democratic-series",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## NullWalletBalancer class\n", "## NullWalletBalancer class\n",
@ -365,7 +365,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "serious-ghost", "id": "wound-flour",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -376,7 +376,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "metric-veteran", "id": "painful-stake",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## LiveWalletBalancer class\n", "## LiveWalletBalancer class\n",
@ -387,7 +387,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "shared-craft", "id": "south-ministry",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -454,7 +454,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "living-fitness", "id": "compatible-mustang",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# ✅ Testing" "# ✅ Testing"
@ -463,7 +463,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "superb-proportion", "id": "little-exposure",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -548,7 +548,7 @@
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"id": "built-evidence", "id": "emotional-instruction",
"metadata": {}, "metadata": {},
"source": [ "source": [
"# 🏃 Running\n", "# 🏃 Running\n",
@ -559,7 +559,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"id": "welcome-secretariat", "id": "adjusted-myrtle",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
@ -569,9 +569,9 @@
" from Context import default_context\n", " from Context import default_context\n",
"\n", "\n",
" group = Group.load(default_context)\n", " group = Group.load(default_context)\n",
" eth = BasketToken.find_by_name(group.basket_tokens, \"eth\").token\n", " eth = BasketToken.find_by_symbol(group.basket_tokens, \"eth\").token\n",
" btc = BasketToken.find_by_name(group.basket_tokens, \"btc\").token\n", " btc = BasketToken.find_by_symbol(group.basket_tokens, \"btc\").token\n",
" usdt = BasketToken.find_by_name(group.basket_tokens, \"usdt\").token\n", " usdt = BasketToken.find_by_symbol(group.basket_tokens, \"usdt\").token\n",
"\n", "\n",
" parser = TargetBalanceParser([eth, btc])\n", " parser = TargetBalanceParser([eth, btc])\n",
" eth_target = parser.parse(\"ETH:20%\")\n", " eth_target = parser.parse(\"ETH:20%\")\n",

View File

@ -80,7 +80,7 @@ try:
logging.info(f"Wallet address: {wallet.address}") logging.info(f"Wallet address: {wallet.address}")
group = Group.load(context) group = Group.load(context)
group_basket_token = BasketToken.find_by_name(group.basket_tokens, args.token_symbol) group_basket_token = BasketToken.find_by_symbol(group.basket_tokens, args.token_symbol)
group_token = group_basket_token.token group_token = group_basket_token.token
spl_token = Token(context.client, group_token.mint, TOKEN_PROGRAM_ID, wallet.account) spl_token = Token(context.client, group_token.mint, TOKEN_PROGRAM_ID, wallet.account)

7996
solana.tokenlist.json Normal file

File diff suppressed because it is too large Load Diff