@@ -1764,3 +1764,211 @@ def update_voting_ticket(self, ticket_id, new_target_type, amount_to_update,
17641764 }
17651765 )
17661766 return self .finalizeOp (op , account , "active" , ** kwargs )
1767+
1768+
1769+ def create_liquidity_pool (self , asset_a , asset_b , share_asset ,
1770+ taker_fee_percent , withdrawal_fee_percent ,
1771+ account = None , ** kwargs ):
1772+ """Create a liquidity pool
1773+
1774+ :param str asset_a: First asset in the pool pair.
1775+ :param str asset_b: Second asset in the pool pair.
1776+ :param str share_asset: The asset which represents shares in the pool.
1777+
1778+ For asset parameters, these can be either symbols or asset_id
1779+ strings. Note that network expects asset_a to have a lower-numbered
1780+ asset_id than asset_b.
1781+
1782+ :param float taker_fee_percent: The pool's taker fee percentage.
1783+ :param float withdrawal_fee_percent: The pool's withdrawal fee percent.
1784+
1785+ For percentages, meaningful range is [0.00, 100.00], where 1% is
1786+ represented as 1.0. Smallest non-zero value recognized by BitShares
1787+ chain is 0.01 for 0.01%.
1788+
1789+ """
1790+ if not account :
1791+ if "default_account" in self .config :
1792+ account = self .config ["default_account" ]
1793+ if not account :
1794+ raise ValueError ("You need to provide an account" )
1795+ account = Account (account , blockchain_instance = self )
1796+
1797+ asset_a = Asset (asset_a )["id" ]
1798+ asset_b = Asset (asset_b )["id" ]
1799+ share_asset = Asset (share_asset )["id" ]
1800+
1801+ if not (taker_fee_percent >= 0 and taker_fee_percent <= 100 ):
1802+ raise ValueError ("Percentages must be in range [0.00, 100.00]." )
1803+ if not (withdrawal_fee_percent >= 0 and withdrawal_fee_percent <= 100 ):
1804+ raise ValueError ("Percentages must be in range [0.00, 100.00]." )
1805+ graphene_1_percent = 100
1806+ taker_fee_percent = int (taker_fee_percent * graphene_1_percent )
1807+ withdrawal_fee_percent = int (withdrawal_fee_percent * graphene_1_percent )
1808+
1809+ op = operations .Liquidity_pool_create (
1810+ ** {
1811+ "fee" : {"amount" : 0 , "asset_id" : "1.3.0" },
1812+ "account" : account ["id" ],
1813+ "asset_a" : asset_a ,
1814+ "asset_b" : asset_b ,
1815+ "share_asset" : share_asset ,
1816+ "taker_fee_percent" : taker_fee_percent ,
1817+ "withdrawal_fee_percent" : withdrawal_fee_percent ,
1818+ "extensions" : [],
1819+ }
1820+ )
1821+ return self .finalizeOp (op , account , "active" , ** kwargs )
1822+
1823+
1824+ def _find_liquidity_pool (self , pool ):
1825+ # Ad-hoc helper for the liquidity pool verbs. It locates a pool id
1826+ # irrespective of whether 'pool' is already a pool id, or perhaps an
1827+ # asset or asset_id of a share asset for a pool. The approach is
1828+ # ad-hoc. Would be better if there was a Pool class to represent pool
1829+ # objects like there is an Asset class to represent asset objects.
1830+ # Then locating a pool could happen in the initialization of the Pool
1831+ # object given either an id or asset/symbol. TBD someday.
1832+ if isinstance (pool , str ) and pool .startswith ("1.19." ):
1833+ pool_id = pool
1834+ else :
1835+ try :
1836+ pool_asset = Asset (pool , blockchain_instance = self )
1837+ except :
1838+ raise ValueError ("'pool' is neither a pool id nor share asset." )
1839+ if "for_liquidity_pool" in pool_asset :
1840+ pool_id = pool_asset ["for_liquidity_pool" ]
1841+ else :
1842+ raise ValueError ("Asset is not a share asset for a pool." )
1843+ return pool_id
1844+
1845+
1846+ def delete_liquidity_pool (self , pool , account = None , ** kwargs ):
1847+ """Delete a liquidity pool
1848+
1849+ :param str,Asset pool: The liquidity pool to delete. Can be the pool id
1850+ as a string, or can be an Asset, asset_id, or symbol of the
1851+ share asset for the pool.
1852+
1853+ """
1854+ if not account :
1855+ if "default_account" in self .config :
1856+ account = self .config ["default_account" ]
1857+ if not account :
1858+ raise ValueError ("You need to provide an account" )
1859+ account = Account (account , blockchain_instance = self )
1860+
1861+ pool_id = self ._find_liquidity_pool (pool )
1862+
1863+ op = operations .Liquidity_pool_delete (
1864+ ** {
1865+ "fee" : {"amount" : 0 , "asset_id" : "1.3.0" },
1866+ "account" : account ["id" ],
1867+ "pool" : pool_id ,
1868+ "extensions" : [],
1869+ }
1870+ )
1871+ return self .finalizeOp (op , account , "active" , ** kwargs )
1872+
1873+
1874+ def deposit_into_liquidity_pool (self , pool , amount_a , amount_b , account = None , ** kwargs ):
1875+ """Deposit assets into a liquidity pool
1876+
1877+ :param str,Asset pool: The liquidity pool to use. Can be the pool id
1878+ as a string, or can be an Asset, asset_id, or symbol of the
1879+ share asset for the pool.
1880+
1881+ :param Amount amount_a:
1882+ :param Amount amount_b:
1883+
1884+ """
1885+ if not account :
1886+ if "default_account" in self .config :
1887+ account = self .config ["default_account" ]
1888+ if not account :
1889+ raise ValueError ("You need to provide an account" )
1890+ account = Account (account , blockchain_instance = self )
1891+
1892+ pool_id = self ._find_liquidity_pool (pool )
1893+
1894+ num_id_a = int (amount_a .asset ["id" ].split ("." )[- 1 ])
1895+ num_id_b = int (amount_b .asset ["id" ].split ("." )[- 1 ])
1896+ if (num_id_b < num_id_a ):
1897+ amount_a , amount_b = amount_b , amount_a
1898+
1899+ op = operations .Liquidity_pool_deposit (
1900+ ** {
1901+ "fee" : {"amount" : 0 , "asset_id" : "1.3.0" },
1902+ "account" : account ["id" ],
1903+ "pool" : pool_id ,
1904+ "amount_a" : amount_a .json (),
1905+ "amount_b" : amount_b .json (),
1906+ "extensions" : [],
1907+ }
1908+ )
1909+ return self .finalizeOp (op , account , "active" , ** kwargs )
1910+
1911+
1912+ def withdraw_from_liquidity_pool (self , pool , share_amount , account = None , ** kwargs ):
1913+ """Withdraw stake from a liquidity pool
1914+
1915+ :param str,Asset pool: The liquidity pool to use. Can be the pool id
1916+ as a string, or can be an Asset, asset_id, or symbol of the
1917+ share asset for the pool.
1918+
1919+ :param Amount share_amount: Amount of share asset to redeem. Must be a
1920+ quantity of the pool's share_asset.
1921+
1922+ """
1923+ if not account :
1924+ if "default_account" in self .config :
1925+ account = self .config ["default_account" ]
1926+ if not account :
1927+ raise ValueError ("You need to provide an account" )
1928+ account = Account (account , blockchain_instance = self )
1929+
1930+ pool_id = self ._find_liquidity_pool (pool )
1931+
1932+ op = operations .Liquidity_pool_withdraw (
1933+ ** {
1934+ "fee" : {"amount" : 0 , "asset_id" : "1.3.0" },
1935+ "account" : account ["id" ],
1936+ "pool" : pool_id ,
1937+ "share_amount" : share_amount .json (),
1938+ "extensions" : [],
1939+ }
1940+ )
1941+ return self .finalizeOp (op , account , "active" , ** kwargs )
1942+
1943+
1944+ def exchange_with_liquidity_pool (self , pool , amount_to_sell , min_to_receive , account = None , ** kwargs ):
1945+ """Exchange assets against a liquidity pool
1946+
1947+ :param str,Asset pool: The liquidity pool to use. Can be the pool id
1948+ as a string, or can be an Asset, asset_id, or symbol of the
1949+ share asset for the pool.
1950+
1951+ :param Amount amount_to_sell:
1952+ :param Amount min_to_receive:
1953+
1954+ """
1955+ if not account :
1956+ if "default_account" in self .config :
1957+ account = self .config ["default_account" ]
1958+ if not account :
1959+ raise ValueError ("You need to provide an account" )
1960+ account = Account (account , blockchain_instance = self )
1961+
1962+ pool_id = self ._find_liquidity_pool (pool )
1963+
1964+ op = operations .Liquidity_pool_exchange (
1965+ ** {
1966+ "fee" : {"amount" : 0 , "asset_id" : "1.3.0" },
1967+ "account" : account ["id" ],
1968+ "pool" : pool_id ,
1969+ "amount_to_sell" : amount_to_sell .json (),
1970+ "min_to_receive" : min_to_receive .json (),
1971+ "extensions" : [],
1972+ }
1973+ )
1974+ return self .finalizeOp (op , account , "active" , ** kwargs )
0 commit comments