-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
v1.3.0: (Revision 2) Added Publish command and Swapable.Registry
- Loading branch information
Showing
12 changed files
with
816 additions
and
31 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ import { | |
import { | ||
Reader as ReaderImpl, | ||
} from './adapters/Symbol' | ||
import { PoolService, PoolImpl } from './services/PoolService' | ||
|
||
/** | ||
* @type Swapable.CommandFn | ||
|
@@ -68,26 +69,96 @@ export const AssetCommands: CommandsList = { | |
'AddLiquidity': (c, i): Command => new CommandsImpl.AddLiquidity(c, i), | ||
'RemoveLiquidity': (c, i): Command => new CommandsImpl.RemoveLiquidity(c, i), | ||
'Swap': (c, i): Command => new CommandsImpl.Swap(c, i), | ||
'Publish': (c, i): Command => new CommandsImpl.Publish(c, i), | ||
} | ||
|
||
/** | ||
* @var Swapable.PoolTargetDerivationPath | ||
* @var Swapable.Revision | ||
* @package Swapable | ||
* @subpackage Standard | ||
* @since v1.0.0 | ||
* @description Contains text that describes the derivation path for the | ||
* target account of automated pools. | ||
* @description Object that describes the version of Swapable liquidity pools. | ||
* | ||
* Revision 1: @ubcdigital/[email protected] | ||
* Revision 2: @ubcdigital/[email protected] | ||
*/ | ||
export const PoolTargetDerivationPath: string = 'm/4343\'/0\'/0\'/0\'' | ||
export const Revision: number = 2 | ||
|
||
/** | ||
* @var Swapable.Revision | ||
* @package Swapable | ||
* @subpackage Standard | ||
* @since v1.0.0 | ||
* @description Object that describes the count of revisions for Swapable digital assets. | ||
* @type Swapable.Registry | ||
* @package standards | ||
* @since v1.2.1 | ||
* @description Class that describes a registry for pools. | ||
* | ||
* Registries may list one or more than one liquidity pool(s). | ||
* Each target account hosts one or more than one market pair. | ||
* | ||
* Registries do not own any cryptocurrency. They serve a role | ||
* of public ledger that contains liquidity pools metadata. | ||
*/ | ||
export const Revision: number = 1 | ||
export class Registry { | ||
/** | ||
* The reader execution context | ||
* | ||
* @var {Context} | ||
*/ | ||
public context: Context | ||
|
||
/** | ||
* Constructs a pool registry object. | ||
* | ||
* @param {ReaderImpl} reader | ||
* @param {PublicAccount} publicAccount | ||
*/ | ||
public constructor( | ||
/** | ||
* @readonly | ||
* @access public | ||
* @description The blockchain network reader configuration. | ||
* | ||
* Our first implementation uses a Symbol blockchain network | ||
* adapter as ReaderImpl. It is possible that other networks | ||
* are implemented in the future. | ||
*/ | ||
public readonly reader: ReaderImpl, | ||
|
||
/** | ||
* @readonly | ||
* @access public | ||
* @description The deterministic public account representing | ||
* the registry. This account holds incoming transactions and | ||
* is used for listing capacity. | ||
*/ | ||
public readonly publicAccount: PublicAccount | ||
) { | ||
this.context = new Context( | ||
Revision, | ||
publicAccount, | ||
this.reader, | ||
new TransactionParameters(), | ||
[], | ||
) | ||
} | ||
|
||
/** | ||
* List a registry's liquidity pools. Registries should be used | ||
* for publicly listing liquidity pools. So-called market pairs | ||
* are hosted by the Liquidity Pool target account. | ||
* | ||
* @static | ||
* @param {Registry|PublicAccount} authority | ||
* @return {MosaicId[]} | ||
*/ | ||
public async getPools( | ||
revision?: number, | ||
): Promise<PoolImpl[]> { | ||
// initialize pool service | ||
const service = new PoolService(this.context) | ||
|
||
// use service to read pools (mosaic+metadata) | ||
return await service.getPools(this.publicAccount, !!revision ? revision : Revision) | ||
} | ||
} | ||
|
||
/** | ||
* @class Swapable.AutomatedPool | ||
|
@@ -134,13 +205,6 @@ export const Revision: number = 1 | |
*/ | ||
export class AutomatedPool implements Market { | ||
|
||
/** | ||
* @description The deterministic public account which owns an | ||
* automated liquidity pool. This account is used | ||
* to issue the *automated pool shares* mosaic. | ||
*/ | ||
public target: PublicAccount | ||
|
||
/** | ||
* @description The source blockchain network of assets paired | ||
* in an automated liquidity pool. | ||
|
@@ -207,11 +271,8 @@ export class AutomatedPool implements Market { | |
* owner of the pool shares mosaic which is created for each | ||
* liquidity pool. This account *should* be multi-signature. | ||
*/ | ||
target: PublicAccount, | ||
public readonly target: PublicAccount, | ||
) { | ||
// - Only store the public account in instance | ||
this.target = target | ||
|
||
// - Set asset source network configuration | ||
this.source = new AssetSource(this.reader.generationHash) | ||
} | ||
|
@@ -308,6 +369,43 @@ export class AutomatedPool implements Market { | |
return sharesAssetId | ||
} | ||
|
||
/** | ||
* Publishes an Automated Liquidity Pool to \a registry and | ||
* uses the target public account. Registries serve as list | ||
* of liquidity pools. | ||
* | ||
* @param {PublicAccount} registry | ||
* @returns {Promise<TransactionURI<Transaction>>} | ||
*/ | ||
public async publish( | ||
registry: PublicAccount, | ||
): Promise<TransactionURI<Transaction>> { | ||
// - Reads network information from blockchain "reader" | ||
await this.synchronize() | ||
|
||
try { | ||
// - Prepares command parameters | ||
const argv = [ | ||
new CommandOption('registry', registry) | ||
] | ||
|
||
// - Instanciates a command in a context | ||
const context = this.getContext(this.target, new TransactionParameters(), argv) | ||
const cmdFn = this.getCommand(this.identifier, 'Publish', context) as Executable | ||
|
||
// - Populates the synchronized data | ||
cmdFn.mosaicInfo = this.mosaicInfo | ||
cmdFn.reserveInfo = this.reserveInfo | ||
|
||
// - Executes the automated pool command | ||
return cmdFn.execute(this.target, argv) | ||
} | ||
catch (f) { | ||
// XXX error notifications / events | ||
throw f | ||
} | ||
} | ||
|
||
/** | ||
* Verifies the autorization for \a actor to execute a pool | ||
* command \a command given \a sharesAssetId automated pool | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
/** | ||
* This file is part of Swapable shared under LGPL-3.0-only. | ||
* Copyright (C) 2021 Using Blockchain Ltd, Reg No.: 12658136, United Kingdom | ||
* | ||
* @package Swapable | ||
* @author Grégory Saive for Using Blockchain Ltd <[email protected]> | ||
* @license LGPL-3.0-only | ||
*/ | ||
import { | ||
InnerTransaction, | ||
PublicAccount, | ||
Transaction, | ||
TransferTransaction, | ||
PlainMessage, | ||
} from 'symbol-sdk' | ||
|
||
// internal dependencies | ||
import { | ||
AllowanceResult, | ||
CommandOption, | ||
Symbol, | ||
} from '../../index' | ||
import { Executable } from './Executable' | ||
|
||
/** | ||
* @class Swapable.Publish | ||
* @package Swapable | ||
* @subpackage Commands | ||
* @since v1.0.0 | ||
* @description Class that describes a command for publishing | ||
* automated liquidity pools to a registry. | ||
* @summary | ||
* This automated pool command accepts the following arguments: | ||
* | ||
* | Argument | Description | Example | | ||
* | --- | --- | --- | | ||
* | registry | Liquidity pool registry | `new PublicAccount(...)` | | ||
* | ||
* 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 | Target Account | Creates a registration contract with a signature that contains the token identifier. | | ||
* | ||
*/ | ||
export class Publish extends Executable { | ||
/** | ||
* @access public | ||
* @description The list of **required** arguments to execute | ||
* *this* automated pool command. | ||
*/ | ||
public arguments: string[] = [ | ||
'registry', | ||
] | ||
|
||
/** | ||
* 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). | ||
**/ | ||
public canExecute( | ||
actor: PublicAccount, | ||
argv?: CommandOption[] | ||
): AllowanceResult { | ||
// - Asserts the presence of mandatory inputs | ||
super.assertHasMandatoryArguments(argv, this.arguments) | ||
|
||
// - Allows only the target account of liquidity | ||
// pools to publish a pool to a registry. | ||
return new AllowanceResult( | ||
actor.address.equals(this.target.address) | ||
) | ||
} | ||
|
||
// region abstract methods | ||
/** | ||
* This method returns the automated pool command name, | ||
* e.g. "Publish" or "AddLiquidity", etc. | ||
* | ||
* @access public | ||
* @return {string} | ||
**/ | ||
public get name(): string { | ||
return 'Publish' | ||
} | ||
|
||
/** | ||
* 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} | ||
**/ | ||
public get descriptor(): string { | ||
return 'Swapable(v' + this.context.revision + ')' + ':publish:' + 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. | ||
**/ | ||
protected get transactions(): Transaction[] { | ||
// - Reads the execution context | ||
const reader = this.context.reader as Symbol.Reader | ||
|
||
// - Read external arguments | ||
const registry = this.context.getInput('registry', new PublicAccount()) | ||
|
||
// - Prepares the response | ||
const transactions: InnerTransaction[] = [] | ||
const signers: PublicAccount[] = [] | ||
|
||
// - Transaction 01: Add execution proof transaction | ||
transactions.push(TransferTransaction.create( | ||
this.context.parameters.deadline, | ||
registry.address, | ||
[], // no mosaics | ||
PlainMessage.create(this.descriptor), | ||
reader.networkType, | ||
undefined, // maxFee 0 for inner | ||
)) | ||
|
||
// - Transaction 10 is issued by **provider** account ("the actor") | ||
signers.push(this.target) | ||
|
||
// - Assigns correct signer to each transaction | ||
return transactions.map( | ||
(transaction, i) => transaction.toAggregate(signers[i]) | ||
) | ||
} | ||
// end-region abstract methods | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.