diff --git a/examples/typescript/facoin/Move.toml b/examples/typescript/facoin/Move.toml new file mode 100644 index 000000000..e400d79c6 --- /dev/null +++ b/examples/typescript/facoin/Move.toml @@ -0,0 +1,12 @@ +[package] +name = "facoin" +version = "1.0.0" +authors = [] + +[addresses] +FACoin = "_" + +[dependencies.AptosFramework] +git = "https://github.com/aptos-labs/aptos-core.git" +rev = "mainnet" +subdir = "aptos-move/framework/aptos-framework" diff --git a/examples/typescript/facoin/sources/fa_coin_cat.move b/examples/typescript/facoin/sources/fa_coin_cat.move new file mode 100644 index 000000000..6c9278241 --- /dev/null +++ b/examples/typescript/facoin/sources/fa_coin_cat.move @@ -0,0 +1,158 @@ +/// A 2-in-1 module that combines managed_fungible_asset and coin_example into one module that when deployed, the +/// deployer will be creating a new managed fungible asset with the hardcoded supply config, name, symbol, and decimals. +/// The address of the asset can be obtained via get_metadata(). As a simple version, it only deals with primary stores. +module FACoin::cat { + use aptos_framework::fungible_asset::{Self, MintRef, TransferRef, BurnRef, Metadata, FungibleAsset}; + use aptos_framework::object::{Self, Object}; + use aptos_framework::primary_fungible_store; + use std::error; + use std::signer; + use std::string::utf8; + use std::option; + + /// Only fungible asset metadata owner can make changes. + const ENOT_OWNER: u64 = 1; + + const ASSET_SYMBOL: vector = b"CAT"; + + #[resource_group_member(group = aptos_framework::object::ObjectGroup)] + /// Hold refs to control the minting, transfer and burning of fungible assets. + struct ManagedFungibleAsset has key { + mint_ref: MintRef, + transfer_ref: TransferRef, + burn_ref: BurnRef, + } + + /// Initialize metadata object and store the refs. + // :!:>initialize + fun init_module(admin: &signer) { + let constructor_ref = &object::create_named_object(admin, ASSET_SYMBOL); + primary_fungible_store::create_primary_store_enabled_fungible_asset( + constructor_ref, + option::none(), + utf8(b"CAT Coin"), /* name */ + utf8(ASSET_SYMBOL), /* symbol */ + 8, /* decimals */ + utf8(b"http://example.com/favicon.ico"), /* icon */ + utf8(b"http://example.com"), /* project */ + ); + + // Create mint/burn/transfer refs to allow creator to manage the fungible asset. + let mint_ref = fungible_asset::generate_mint_ref(constructor_ref); + let burn_ref = fungible_asset::generate_burn_ref(constructor_ref); + let transfer_ref = fungible_asset::generate_transfer_ref(constructor_ref); + let metadata_object_signer = object::generate_signer(constructor_ref); + move_to( + &metadata_object_signer, + ManagedFungibleAsset { mint_ref, transfer_ref, burn_ref } + )// <:!:initialize + } + + #[view] + /// Return the address of the managed fungible asset that's created when this module is deployed. + public fun get_metadata(): Object { + let asset_address = object::create_object_address(&@FACoin, ASSET_SYMBOL); + object::address_to_object(asset_address) + } + + // :!:>mint + /// Mint as the owner of metadata object and deposit to a specific account. + public entry fun mint(admin: &signer, to: address, amount: u64) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let managed_fungible_asset = authorized_borrow_refs(admin, asset); + let to_wallet = primary_fungible_store::ensure_primary_store_exists(to, asset); + let fa = fungible_asset::mint(&managed_fungible_asset.mint_ref, amount); + fungible_asset::deposit_with_ref(&managed_fungible_asset.transfer_ref, to_wallet, fa); + }// <:!:mint_to + + /// Transfer as the owner of metadata object ignoring `frozen` field. + public entry fun transfer(admin: &signer, from: address, to: address, amount: u64) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let transfer_ref = &authorized_borrow_refs(admin, asset).transfer_ref; + let from_wallet = primary_fungible_store::primary_store(from, asset); + let to_wallet = primary_fungible_store::ensure_primary_store_exists(to, asset); + fungible_asset::transfer_with_ref(transfer_ref, from_wallet, to_wallet, amount); + } + + /// Burn fungible assets as the owner of metadata object. + public entry fun burn(admin: &signer, from: address, amount: u64) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let burn_ref = &authorized_borrow_refs(admin, asset).burn_ref; + let from_wallet = primary_fungible_store::primary_store(from, asset); + fungible_asset::burn_from(burn_ref, from_wallet, amount); + } + + /// Freeze an account so it cannot transfer or receive fungible assets. + public entry fun freeze_account(admin: &signer, account: address) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let transfer_ref = &authorized_borrow_refs(admin, asset).transfer_ref; + let wallet = primary_fungible_store::ensure_primary_store_exists(account, asset); + fungible_asset::set_frozen_flag(transfer_ref, wallet, true); + } + + /// Unfreeze an account so it can transfer or receive fungible assets. + public entry fun unfreeze_account(admin: &signer, account: address) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let transfer_ref = &authorized_borrow_refs(admin, asset).transfer_ref; + let wallet = primary_fungible_store::ensure_primary_store_exists(account, asset); + fungible_asset::set_frozen_flag(transfer_ref, wallet, false); + } + + /// Withdraw as the owner of metadata object ignoring `frozen` field. + public fun withdraw(admin: &signer, amount: u64, from: address): FungibleAsset acquires ManagedFungibleAsset { + let asset = get_metadata(); + let transfer_ref = &authorized_borrow_refs(admin, asset).transfer_ref; + let from_wallet = primary_fungible_store::primary_store(from, asset); + fungible_asset::withdraw_with_ref(transfer_ref, from_wallet, amount) + } + + /// Deposit as the owner of metadata object ignoring `frozen` field. + public fun deposit(admin: &signer, to: address, fa: FungibleAsset) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let transfer_ref = &authorized_borrow_refs(admin, asset).transfer_ref; + let to_wallet = primary_fungible_store::ensure_primary_store_exists(to, asset); + fungible_asset::deposit_with_ref(transfer_ref, to_wallet, fa); + } + + /// Borrow the immutable reference of the refs of `metadata`. + /// This validates that the signer is the metadata object's owner. + inline fun authorized_borrow_refs( + owner: &signer, + asset: Object, + ): &ManagedFungibleAsset acquires ManagedFungibleAsset { + assert!(object::is_owner(asset, signer::address_of(owner)), error::permission_denied(ENOT_OWNER)); + borrow_global(object::object_address(&asset)) + } + + #[test(creator = @FACoin)] + fun test_basic_flow( + creator: &signer, + ) acquires ManagedFungibleAsset { + init_module(creator); + let creator_address = signer::address_of(creator); + let aaron_address = @0xface; + + mint(creator, creator_address, 100); + let asset = get_metadata(); + assert!(primary_fungible_store::balance(creator_address, asset) == 100, 4); + freeze_account(creator, creator_address); + assert!(primary_fungible_store::is_frozen(creator_address, asset), 5); + transfer(creator, creator_address, aaron_address, 10); + assert!(primary_fungible_store::balance(aaron_address, asset) == 10, 6); + + unfreeze_account(creator, creator_address); + assert!(!primary_fungible_store::is_frozen(creator_address, asset), 7); + burn(creator, creator_address, 90); + } + + #[test(creator = @FACoin, aaron = @0xface)] + #[expected_failure(abort_code = 0x50001, location = Self)] + fun test_permission_denied( + creator: &signer, + aaron: &signer + ) acquires ManagedFungibleAsset { + init_module(creator); + let creator_address = signer::address_of(creator); + mint(aaron, creator_address, 100); + } +} diff --git a/examples/typescript/facoin/sources/fa_coin_dog.move b/examples/typescript/facoin/sources/fa_coin_dog.move new file mode 100644 index 000000000..ba5cce3fe --- /dev/null +++ b/examples/typescript/facoin/sources/fa_coin_dog.move @@ -0,0 +1,158 @@ +/// A 2-in-1 module that combines managed_fungible_asset and coin_example into one module that when deployed, the +/// deployer will be creating a new managed fungible asset with the hardcoded supply config, name, symbol, and decimals. +/// The address of the asset can be obtained via get_metadata(). As a simple version, it only deals with primary stores. +module FACoin::dog { + use aptos_framework::fungible_asset::{Self, MintRef, TransferRef, BurnRef, Metadata, FungibleAsset}; + use aptos_framework::object::{Self, Object}; + use aptos_framework::primary_fungible_store; + use std::error; + use std::signer; + use std::string::utf8; + use std::option; + + /// Only fungible asset metadata owner can make changes. + const ENOT_OWNER: u64 = 1; + + const ASSET_SYMBOL: vector = b"DOG"; + + #[resource_group_member(group = aptos_framework::object::ObjectGroup)] + /// Hold refs to control the minting, transfer and burning of fungible assets. + struct ManagedFungibleAsset has key { + mint_ref: MintRef, + transfer_ref: TransferRef, + burn_ref: BurnRef, + } + + /// Initialize metadata object and store the refs. + // :!:>initialize + fun init_module(admin: &signer) { + let constructor_ref = &object::create_named_object(admin, ASSET_SYMBOL); + primary_fungible_store::create_primary_store_enabled_fungible_asset( + constructor_ref, + option::none(), + utf8(b"DOG Coin"), /* name */ + utf8(ASSET_SYMBOL), /* symbol */ + 8, /* decimals */ + utf8(b"http://example.com/favicon.ico"), /* icon */ + utf8(b"http://example.com"), /* project */ + ); + + // Create mint/burn/transfer refs to allow creator to manage the fungible asset. + let mint_ref = fungible_asset::generate_mint_ref(constructor_ref); + let burn_ref = fungible_asset::generate_burn_ref(constructor_ref); + let transfer_ref = fungible_asset::generate_transfer_ref(constructor_ref); + let metadata_object_signer = object::generate_signer(constructor_ref); + move_to( + &metadata_object_signer, + ManagedFungibleAsset { mint_ref, transfer_ref, burn_ref } + )// <:!:initialize + } + + #[view] + /// Return the address of the managed fungible asset that's created when this module is deployed. + public fun get_metadata(): Object { + let asset_address = object::create_object_address(&@FACoin, ASSET_SYMBOL); + object::address_to_object(asset_address) + } + + // :!:>mint + /// Mint as the owner of metadata object and deposit to a specific account. + public entry fun mint(admin: &signer, to: address, amount: u64) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let managed_fungible_asset = authorized_borrow_refs(admin, asset); + let to_wallet = primary_fungible_store::ensure_primary_store_exists(to, asset); + let fa = fungible_asset::mint(&managed_fungible_asset.mint_ref, amount); + fungible_asset::deposit_with_ref(&managed_fungible_asset.transfer_ref, to_wallet, fa); + }// <:!:mint_to + + /// Transfer as the owner of metadata object ignoring `frozen` field. + public entry fun transfer(admin: &signer, from: address, to: address, amount: u64) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let transfer_ref = &authorized_borrow_refs(admin, asset).transfer_ref; + let from_wallet = primary_fungible_store::primary_store(from, asset); + let to_wallet = primary_fungible_store::ensure_primary_store_exists(to, asset); + fungible_asset::transfer_with_ref(transfer_ref, from_wallet, to_wallet, amount); + } + + /// Burn fungible assets as the owner of metadata object. + public entry fun burn(admin: &signer, from: address, amount: u64) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let burn_ref = &authorized_borrow_refs(admin, asset).burn_ref; + let from_wallet = primary_fungible_store::primary_store(from, asset); + fungible_asset::burn_from(burn_ref, from_wallet, amount); + } + + /// Freeze an account so it cannot transfer or receive fungible assets. + public entry fun freeze_account(admin: &signer, account: address) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let transfer_ref = &authorized_borrow_refs(admin, asset).transfer_ref; + let wallet = primary_fungible_store::ensure_primary_store_exists(account, asset); + fungible_asset::set_frozen_flag(transfer_ref, wallet, true); + } + + /// Unfreeze an account so it can transfer or receive fungible assets. + public entry fun unfreeze_account(admin: &signer, account: address) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let transfer_ref = &authorized_borrow_refs(admin, asset).transfer_ref; + let wallet = primary_fungible_store::ensure_primary_store_exists(account, asset); + fungible_asset::set_frozen_flag(transfer_ref, wallet, false); + } + + /// Withdraw as the owner of metadata object ignoring `frozen` field. + public fun withdraw(admin: &signer, amount: u64, from: address): FungibleAsset acquires ManagedFungibleAsset { + let asset = get_metadata(); + let transfer_ref = &authorized_borrow_refs(admin, asset).transfer_ref; + let from_wallet = primary_fungible_store::primary_store(from, asset); + fungible_asset::withdraw_with_ref(transfer_ref, from_wallet, amount) + } + + /// Deposit as the owner of metadata object ignoring `frozen` field. + public fun deposit(admin: &signer, to: address, fa: FungibleAsset) acquires ManagedFungibleAsset { + let asset = get_metadata(); + let transfer_ref = &authorized_borrow_refs(admin, asset).transfer_ref; + let to_wallet = primary_fungible_store::ensure_primary_store_exists(to, asset); + fungible_asset::deposit_with_ref(transfer_ref, to_wallet, fa); + } + + /// Borrow the immutable reference of the refs of `metadata`. + /// This validates that the signer is the metadata object's owner. + inline fun authorized_borrow_refs( + owner: &signer, + asset: Object, + ): &ManagedFungibleAsset acquires ManagedFungibleAsset { + assert!(object::is_owner(asset, signer::address_of(owner)), error::permission_denied(ENOT_OWNER)); + borrow_global(object::object_address(&asset)) + } + + #[test(creator = @FACoin)] + fun test_basic_flow( + creator: &signer, + ) acquires ManagedFungibleAsset { + init_module(creator); + let creator_address = signer::address_of(creator); + let aaron_address = @0xface; + + mint(creator, creator_address, 100); + let asset = get_metadata(); + assert!(primary_fungible_store::balance(creator_address, asset) == 100, 4); + freeze_account(creator, creator_address); + assert!(primary_fungible_store::is_frozen(creator_address, asset), 5); + transfer(creator, creator_address, aaron_address, 10); + assert!(primary_fungible_store::balance(aaron_address, asset) == 10, 6); + + unfreeze_account(creator, creator_address); + assert!(!primary_fungible_store::is_frozen(creator_address, asset), 7); + burn(creator, creator_address, 90); + } + + #[test(creator = @FACoin, aaron = @0xface)] + #[expected_failure(abort_code = 0x50001, location = Self)] + fun test_permission_denied( + creator: &signer, + aaron: &signer + ) acquires ManagedFungibleAsset { + init_module(creator); + let creator_address = signer::address_of(creator); + mint(aaron, creator_address, 100); + } +} diff --git a/examples/typescript/package.json b/examples/typescript/package.json index 442878702..b2f781c5c 100644 --- a/examples/typescript/package.json +++ b/examples/typescript/package.json @@ -9,7 +9,8 @@ "mint_nft": "ts-node mint_nft.ts", "simple_sponsored_transaction": "ts-node simple_sponsored_transaction.ts", "transfer_coin": "ts-node transfer_coin.ts", - "custom_client": "ts-node custom_client.ts" + "custom_client": "ts-node custom_client.ts", + "swap": "ts-node swap.ts" }, "keywords": [], "author": "", diff --git a/examples/typescript/swap.ts b/examples/typescript/swap.ts new file mode 100644 index 000000000..b0593d795 --- /dev/null +++ b/examples/typescript/swap.ts @@ -0,0 +1,247 @@ +/** + * Example to demonstrate creating and adding to liquidity pools, swapping between two fungible asset. + * + * Steps: + * 1. Create two accounts (Alice and Bob) + * 2. Fund Alice and Bob + * 3. Create a FA with Alice as the owner + * 4. Create another FA with Bob as the owner + * 5. Create a liquidity pool with Alice's FA and Bob's FA + * 6. Swap between Alice's FA and Bob's FA + */ + +import { Account, AccountAddress, Aptos, Bool, Ed25519PrivateKey, U64, ViewRequestData } from "aptos"; + +const readline = require("readline").createInterface({ + input: process.stdin, + output: process.stdout, +}); + +const getOptimalLpAmount = async ( + aptos: Aptos, + swap: AccountAddress, + token1Addr: AccountAddress, + token2Addr: AccountAddress, +): Promise => { + const payload: ViewRequestData = { + function: `0x${swap.toStringWithoutPrefix()}::router::optimal_liquidity_amounts`, + functionArguments: [token1Addr.toString(), token2Addr.toString(), false, "200000", "300000", "200", "300"], + }; + const result = await aptos.view({ payload }); + console.log("Optimal LP amount: ", result); +}; + +const addLiquidity = async ( + aptos: Aptos, + swap: AccountAddress, + deployer: Account, + token1Addr: AccountAddress, + token2Addr: AccountAddress, +): Promise => { + const rawTxn = await aptos.generateTransaction({ + sender: deployer.accountAddress.toString(), + data: { + function: `0x${swap.toStringLongWithoutPrefix()}::router::add_liquidity_entry`, + functionArguments: [ + token1Addr, + token2Addr, + new Bool(false), + new U64(200000), + new U64(300000), + new U64(200), + new U64(300), + ], + }, + }); + const pendingTxn = await aptos.signAndSubmitTransaction({ signer: deployer, transaction: rawTxn }); + const response = await aptos.waitForTransaction({ transactionHash: pendingTxn.hash }); + console.log("Add liquidity succeed. - ", response.hash); + return response.hash; +}; + +const swap = async ( + aptos: Aptos, + swap: AccountAddress, + deployer: Account, + fromToken: AccountAddress, + toToken: AccountAddress, + amountIn: number, + amountOutMin: number, + recipient: AccountAddress, +): Promise => { + const rawTxn = await aptos.generateTransaction({ + sender: deployer.accountAddress.toString(), + data: { + function: `0x${swap.toStringLongWithoutPrefix()}::router::swap_entry`, + functionArguments: [new U64(amountIn), new U64(amountOutMin), fromToken, toToken, new Bool(false), recipient], + }, + }); + const pendingTxn = await aptos.signAndSubmitTransaction({ signer: deployer, transaction: rawTxn }); + const response = await aptos.waitForTransaction({ transactionHash: pendingTxn.hash }); + console.log("Swap succeed. - ", response.hash); + return response.hash; +}; + +const getAssetType = async (aptos: Aptos, owner: Account): Promise => { + const data = await aptos.getFungibleAssetMetadata({ + options: { + where: { + creator_address: { _eq: owner.accountAddress.toString() }, + }, + }, + }); + + if (data.length !== 2) throw new Error("Expected two Fungible Assets."); + + console.log("Fungible Asset: ", data); + return { + cat: data[0].asset_type, + dog: data[1].asset_type, + }; +}; + +const getFaBalance = async (aptos: Aptos, owner: Account, assetType: string): Promise => { + const data = await aptos.getCurrentFungibleAssetBalances({ + options: { + where: { + owner_address: { _eq: owner.accountAddress.toString() }, + asset_type: { _eq: assetType }, + }, + }, + }); + + return data[0].amount; +}; + +const createLiquidityPool = async ( + aptos: Aptos, + swap: AccountAddress, + deployer: Account, + dogCoinAddr: AccountAddress, + catCoinAddr: AccountAddress, +): Promise => { + const rawTxn = await aptos.generateTransaction({ + sender: deployer.accountAddress.toString(), + data: { + function: `0x${swap.toStringLongWithoutPrefix()}::router::create_pool`, + functionArguments: [dogCoinAddr, catCoinAddr, new Bool(false)], + }, + }); + const pendingTxn = await aptos.signAndSubmitTransaction({ signer: deployer, transaction: rawTxn }); + const response = await aptos.waitForTransaction({ transactionHash: pendingTxn.hash }); + console.log("Creating liquidity pool successful. - ", response.hash); + return response.hash; +}; + +const initLiquidityPool = async (aptos: Aptos, swap: AccountAddress, deployer: Account): Promise => { + const rawTxn = await aptos.generateTransaction({ + sender: deployer.accountAddress.toString(), + data: { + function: `0x${swap.toStringLongWithoutPrefix()}::liquidity_pool::initialize`, + functionArguments: [], + }, + }); + const pendingTxn = await aptos.signAndSubmitTransaction({ signer: deployer, transaction: rawTxn }); + const response = await aptos.waitForTransaction({ transactionHash: pendingTxn.hash }); + console.log("Init LP Pool success. - ", response.hash); + return response.hash; +}; + +const createFungibleAsset = async (aptos: Aptos, admin: Account): Promise => { + await new Promise((resolve) => { + readline.question( + `Follow the steps to publish the Dog and Cat Coin module with Admin's address, and press enter. \n` + + "1. cd to /aptos-ts-sdk/examples/typescript/facoin folder \n" + + "2. run 'aptos move publish --named-address FACoin=[admin] --profile=[admin] \n" + + " Note: [admin] is the same profile you used to publish your 'swap' package", + () => { + resolve(); + }, + ); + }); +}; + +/** Admin mint the coin*/ +const mintCoin = async (aptos: Aptos, admin: Account, amount: number | bigint, coinName: string): Promise => { + const rawTxn = await aptos.generateTransaction({ + sender: admin.accountAddress.toString(), + data: { + function: `0x${admin.accountAddress.toStringLongWithoutPrefix()}::${coinName}::mint`, + functionArguments: [admin.accountAddress, new U64(amount)], + }, + }); + const pendingTxn = await aptos.signAndSubmitTransaction({ signer: admin, transaction: rawTxn }); + const response = await aptos.waitForTransaction({ transactionHash: pendingTxn.hash }); + console.log(`Minting ${coinName} coin successful. - `, response.hash); + return response.hash; +}; + +const example = async () => { + console.log( + "This example will create a main user account called 'Admin', it will be used to deploy Liquidity pool and two new fungible assets. \n" + + "After creating the Dog and Cat coin, and the liquidity pool, it will swap one token for another. \n" + + "Note: This example requires you to have the 'swap' module published before running. \n" + + "If you haven't published the 'swap' module, please publish the package using \n" + + "'aptos move create-resource-account-and-publish-package --seed 0 --address-name=swap --named-addresses deployer=[admin] --profile [admin]' first. \n" + + "[admin] is the account profile you will be using for this example. \n", + ); + + // Prerequisite check + if (process.argv.length !== 4) { + console.log("Required usage: pnpm swap [swap_address] [user_private_key]"); + process.exit(1); + } + + const aptos = new Aptos(); + // Create three accounts + const admin = Account.fromPrivateKey(new Ed25519PrivateKey(process.argv[3])); + const swapAddress = AccountAddress.fromHexInput(process.argv[2]); + + console.log("====== Account info ======\n"); + console.log(`Admin's address is: ${admin.accountAddress.toString()}`); + console.log(`Swap address is: ${swapAddress.toString()}`); + // Fund Admin account + await aptos.fundAccount({ accountAddress: admin.accountAddress.toString(), amount: 100_000_000 }); + + console.log("\n====== Create Fungible Asset -> (Dog and Cat coin) ======\n"); + await createFungibleAsset(aptos, admin); + const assetTypes = await getAssetType(aptos, admin); + const dogCoinAddr = AccountAddress.fromHexInput(assetTypes.dog.toString()); + const catCoinAddr = AccountAddress.fromHexInput(assetTypes.cat.toString()); + console.log(`Cat FACoin asset type: ${catCoinAddr}`); + console.log(`Dog FACoin asset type: ${dogCoinAddr}`); + + console.log("\n====== Mint Dog and Cat Coin ======\n"); + console.log("minting 20_000_000 Dog coin..."); + await mintCoin(aptos, admin, 20_000_000, "dog"); + console.log("minting 30_000_000 Cat coin..."); + await mintCoin(aptos, admin, 30_000_000, "cat"); + + console.log("\n====== Current Balance ======\n"); + console.log(`Admin's Dog coin balance: ${await getFaBalance(aptos, admin, dogCoinAddr.toString())}.`); + console.log(`Admin's Cat coin balance: ${await getFaBalance(aptos, admin, catCoinAddr.toString())}.`); + + console.log("\n====== Create Liquidity Pool ======\n"); + console.log("initializing Lquidity Pool......"); + await initLiquidityPool(aptos, swapAddress, admin); + console.log("Creating liquidity pool......"); + await createLiquidityPool(aptos, swapAddress, admin, dogCoinAddr, catCoinAddr); + console.log("Getting optimal LP amount......"); + await getOptimalLpAmount(aptos, swapAddress, dogCoinAddr, catCoinAddr); + console.log("Adding liquidity......"); + await addLiquidity(aptos, swapAddress, admin, dogCoinAddr, catCoinAddr); + console.log("Done."); + + console.log("\n====== Swap 100 Dog coins for Cat coins ======\n"); + console.log("Swaping 100 Dog coin to Cat coin......"); + await swap(aptos, swapAddress, admin, dogCoinAddr, catCoinAddr, 100, 1, admin.accountAddress); + console.log("Swap finished."); + + console.log("\n====== Current Balance ======\n"); + console.log(`Admin's Dog coin balance: ${await getFaBalance(aptos, admin, dogCoinAddr.toString())}.`); + console.log(`Admin's Cat coin balance: ${await getFaBalance(aptos, admin, catCoinAddr.toString())}.`); + + readline.close(); +}; + +example();