UNPKG

swapable

Version:
188 lines (187 loc) 9.72 kB
"use strict"; /** * This file is part of Swapable shared under AGPL-3.0 * Copyright (C) 2021 Using Blockchain Ltd, Reg No.: 12658136, United Kingdom * * @package Swapable * @author Grégory Saive for Using Blockchain Ltd <greg@ubc.digital> * @license AGPL-3.0 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.RemoveLiquidity = void 0; const symbol_sdk_1 = require("symbol-sdk"); // internal dependencies const index_1 = require("../../index"); const Executable_1 = require("./Executable"); //XXX remove this, used only for type-discovery in command options below. const Symbol_Testnet_SWP = new index_1.AssetIdentifier('00000001', new symbol_sdk_1.PublicAccount()); const Symbol_Testnet_XYM = new index_1.AssetIdentifier('00000002', new symbol_sdk_1.PublicAccount()); /** * @class Swapable.RemoveLiquidity * @package Swapable * @subpackage Commands * @since v1.0.0 * @description Class that describes a command for removing assets * in automated liquidity pools (i.e. "withdrawal"). * @summary * This automated pool command accepts the following arguments: * * | Argument | Description | Example | * | --- | --- | --- | * | provider | Liquidity provider | `new PublicAccount(...)` | * | input_x | Amount and asset identifier of `x` (first in pair) | `new AssetAmount(...)` | * | input_y | Amount and asset identifier of `y` (second in pair) | `new AssetAmount(...)` | * * The execution of this command results in the creation of * the following list of transactions with their respective * *signer* and a description: * * | Sequence | Type | Signer | Description | * | --- | --- | --- | --- | * | 01 | TransferTransaction | Provider Account | Transfers a proportional amount of automated pool shares to the **target** account, where they will be burned. | * | 02 | MosaicSupplyChangeTransaction | Target Account | Removes the amount of automated pool shares that is proportional to the amount of liquidity removed from the pool. | * | 03 | TransferTransaction | Target Account | Transfers the **removed liquidity** of `x` and `y` to the provider account. | * | 04 | TransferTransaction | Provider Account | Adds an execution proof message sent to the **target** account. | * */ class RemoveLiquidity extends Executable_1.Executable { constructor() { super(...arguments); /** * @access public * @description The list of **required** arguments to execute * *this* automated pool command. */ this.arguments = [ 'provider', 'input_x', 'input_y', ]; // end-region abstract methods } /** * Verifies **allowance** of \a actor to execute a command * with arguments \a argv. This method returns true if all * required arguments are present. * * This method asserts the presence of mandatory arguments. * * @access public * @param {PublicAccount} actor The actor is whom executes the command. * @param {Array<CommandOption>} argv The command options (arguments). * @return {AllowanceResult} Returns whether an actor is authorized to execute this command. * @throws {FailureMissingArgument} On missing mandatory argument(s). **/ canExecute(actor, argv) { // - Asserts the presence of mandatory inputs super.assertHasMandatoryArguments(argv, this.arguments); // - Allows anyone to add liquidity to automated pools // given a connected command execution (read-only). return new index_1.AllowanceResult(!!this.reserveInfo && !!this.mosaicInfo); } // region abstract methods /** * This method returns the automated pool command name, * e.g. "CreatePool" or "AddLiquidity", etc. * * @access public * @return {string} **/ get name() { return 'RemoveLiquidity'; } /** * This method MUST return a unique automated pool command * descriptor which includes: * * - the open standard descriptor (e.g.: "Swapable") ; * - the open standard *revision* (e.g.: 1) ; * - the kebab-case command name (e.g.: "create-pool") ; * - and the automated pool shares asset identifier. * * Items are joined with the `:` operator and attached to a * so-called execution proof transaction. * * @access public * @return {string} **/ get descriptor() { return 'Swapable(v' + this.context.revision + ')' + ':remove-liquidity:' + this.identifier.id; } /** * This method returns a list of unsigned transactions in a * sequencial order of execution. The resulting transaction * array is later wrapped inside a digital contract that is * executed atomically such that either all transactions do * succeed or all transactions are cancelled. * * :warning: This method creates at least one- or more than * one - network-wide **account restriction**. Restrictions * can potentially lock you out of your account, please use * this only with caution and if you understand the risks. * * @see {execute()} * @access public * @return {Transaction[]} Given the execution of a command, returns a list of unsigned transactions. **/ get transactions() { var _a, _b, _c, _d, _e; // - Reads the execution context const reader = this.context.reader; // - Reads external arguments const provider = this.context.getInput('provider', new symbol_sdk_1.PublicAccount()); const input_x = this.context.getInput('input_x', new index_1.AssetAmount(Symbol_Testnet_SWP, 10)); const input_y = this.context.getInput('input_y', new index_1.AssetAmount(Symbol_Testnet_XYM, 10)); // - Reads shares and reserves information const supply_lp = (_c = (_b = (_a = this.mosaicInfo) === null || _a === void 0 ? void 0 : _a.supply) === null || _b === void 0 ? void 0 : _b.compact()) !== null && _c !== void 0 ? _c : 0; const reserve_x = this.reserveOf(input_x.identifier); const reserve_y = this.reserveOf(input_y.identifier); // MINT FEE principle (0.05 % of shares issued), // https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2Pair.sol#L117 // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k) //XXX if (pool_exists) //XXX rootK = Math.sqrt(reserve0 * reserve1) //XXX rootKLast = Math.sqrt(kLast) //XXX if (rootK > rootKLast) //XXX numerator = totalSupply.mul(rootK.sub(rootKLast)); //XXX denominator = rootK.mul(5).add(rootKLast); //XXX liquidity = numerator / denominator; //XXX if (liquidity > 0) _mint(feeTo, liquidity); //XXX else kLast = 0 // - Calculate liquidity proportions ("contribution of provider") const liquidity = Math.min((input_x.amount * supply_lp) / reserve_x, (input_y.amount * supply_lp) / reserve_y); // - Prepares the response const transactions = []; const signers = []; // - Transaction 01: Transfers proportional automated pool shares to liquidity provider transactions.push(symbol_sdk_1.TransferTransaction.create(this.context.parameters.deadline, this.target.address, [ new symbol_sdk_1.Mosaic(this.identifier.toMosaicId(), symbol_sdk_1.UInt64.fromUint(liquidity)) ], symbol_sdk_1.EmptyMessage, reader.networkType, undefined)); // - Transaction 01 is issued by **provider** account signers.push(provider); // - Transaction 02: MosaicSupplyChangeTransaction // :note: The canExecute() method verifies that `mosaicInfo` is set. // :warning: This transaction effectively **burns** mosaics. transactions.push(symbol_sdk_1.MosaicSupplyChangeTransaction.create(this.context.parameters.deadline, (_d = this.mosaicInfo) === null || _d === void 0 ? void 0 : _d.id, symbol_sdk_1.MosaicSupplyChangeAction.Decrease, symbol_sdk_1.UInt64.fromUint(liquidity), reader.networkType, undefined)); // - Transaction 02 is issued by **target** account signers.push(this.target); // - Transaction 03: Transfers the removed liquidity of `x` and `y` to the provider account. transactions.push(symbol_sdk_1.TransferTransaction.create(this.context.parameters.deadline, provider.address, [ new symbol_sdk_1.Mosaic(input_x.identifier.toMosaicId(), symbol_sdk_1.UInt64.fromUint(input_x.amount)), new symbol_sdk_1.Mosaic(input_y.identifier.toMosaicId(), symbol_sdk_1.UInt64.fromUint(input_y.amount)) ], symbol_sdk_1.EmptyMessage, reader.networkType, undefined)); // - Transaction 03 is issued by **target** account signers.push(this.target); // - Transaction 04: Add execution proof transaction transactions.push(symbol_sdk_1.TransferTransaction.create(this.context.parameters.deadline, this.target.address, [], // no mosaics symbol_sdk_1.PlainMessage.create(this.descriptor + ':' + ((_e = this.mosaicInfo) === null || _e === void 0 ? void 0 : _e.id.toHex()) + ':' + input_x.identifier.toMosaicId().toHex() + ':' + input_y.identifier.toMosaicId().toHex()), reader.networkType, undefined)); // - Transaction 04 is issued by **provider** account ("the actor") signers.push(provider); // - Assigns correct signer to each transaction return transactions.map((transaction, i) => transaction.toAggregate(signers[i])); } } exports.RemoveLiquidity = RemoveLiquidity;