Skip to content

Commit

Permalink
Update use-dex examples with withChainContext
Browse files Browse the repository at this point in the history
  • Loading branch information
ken-futureverse committed Jun 7, 2024
1 parent f35adae commit ff8209a
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 40 deletions.
110 changes: 98 additions & 12 deletions examples/substrate/use-dex/src/addLiquidity.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents";
import { formatEventData } from "@trne/utils/formatEventData";
import {
createDispatcher,
filterExtrinsicEvents,
nativeWalletSigner,
} from "@therootnetwork/extrinsic";
import { createKeyring } from "@trne/utils/createKeyring";
import { ASTO_ASSET_ID, XRP_ASSET_ID } from "@trne/utils/porcini-assets";
import { sendExtrinsic } from "@trne/utils/sendExtrinsic";
import { withChainApi } from "@trne/utils/withChainApi";
import { withChainContext } from "@trne/utils/withChainContext";
import { cleanEnv, str } from "envalid";
import assert from "node:assert";

interface Liquidity {
0: number;
1: number;
}

const { CHAIN_ENDPOINT, CALLER_PRIVATE_KEY } = cleanEnv(process.env, {
CHAIN_ENDPOINT: str({ default: "porcini" }),
CALLER_PRIVATE_KEY: str(), // private key of extrinsic caller
});

/**
* Use `dex.addLiquidity` to add more liquidity for existing pair [XRP, ASTO], following the
* existing ratio between the 2 tokens
*
* Assumes caller has ASTO for liquidity and XRP for both gas and liquidity.
*/
withChainApi("porcini", async (api, caller, logger) => {
withChainContext(CHAIN_ENDPOINT, async (api, logger) => {
const caller = createKeyring(CALLER_PRIVATE_KEY);
const { estimate, signAndSend } = createDispatcher(
api,
caller.address,
[],
nativeWalletSigner(caller)
);

const tokenA = XRP_ASSET_ID;
const tokenB = ASTO_ASSET_ID;

Expand Down Expand Up @@ -56,18 +74,86 @@ withChainApi("porcini", async (api, caller, logger) => {
null // deadline
);

logger.info(`dispatch extrinsic from caller="${caller.address}"`);
const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
const [addEvent] = filterExtrinsicEvents(result.events, ["Dex.AddLiquidity"]);
const feeResult = await estimate(extrinsic);
assert(feeResult.ok, (feeResult.value as Error).message);
logger.info(
{ parameters: { caller: caller.address, fee: feeResult.ok ? feeResult.value : undefined } },
`dispatch extrinsic`
);

const result = await signAndSend(extrinsic, (status) => {
logger.debug(status);
});
assert(result.ok, (result.value as Error).message);

const { id, events } = result.value;
const [transferEvent] = filterExtrinsicEvents(events, ["dex.AddLiquidity"]);
assert(transferEvent);

logger.info(
{
result: {
extrinsicId,
blockNumber: result.blockNumber,
addEvent: formatEventData(addEvent.event),
extrinsicId: id,
transferEvent,
},
},
"receive result"
"dispatch result"
);
});

// withChainApi("porcini", async (api, caller, logger) => {
// const tokenA = XRP_ASSET_ID;
// const tokenB = ASTO_ASSET_ID;

// // 💡 use `api.rpc.dex.getLiquidity` to get current ratio
// const liquidity = (await api.rpc.dex.getLiquidity(tokenA, tokenB)) as unknown as Liquidity;

// const tokenALiquidity = BigInt(liquidity["0"]);
// const tokenBLiquidity = BigInt(liquidity["1"]);

// const amountADesired = BigInt(1_000_000); // 1 XRP
// const amountBDesired = (amountADesired * tokenBLiquidity) / tokenALiquidity;

// const amountAMin = (amountADesired * BigInt(95)) / BigInt(100); // 5% slippage
// const amountBMin = (amountBDesired * BigInt(95)) / BigInt(100); // 5% slippage

// logger.info(
// {
// parameters: {
// tokenA,
// tokenB,
// amountADesired,
// amountBDesired,
// amountAMin,
// amountBMin,
// },
// },
// `create a "dex.addLiquidity" extrinsic`
// );

// const extrinsic = api.tx.dex.addLiquidity(
// tokenA,
// tokenB,
// amountADesired.toString(),
// amountBDesired.toString(),
// amountAMin.toString(),
// amountBMin.toString(),
// null, // to
// null // deadline
// );

// logger.info(`dispatch extrinsic from caller="${caller.address}"`);
// const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
// const [addEvent] = filterExtrinsicEvents(result.events, ["Dex.AddLiquidity"]);

// logger.info(
// {
// result: {
// extrinsicId,
// blockNumber: result.blockNumber,
// addEvent: formatEventData(addEvent.event),
// },
// },
// "receive result"
// );
// });
57 changes: 41 additions & 16 deletions examples/substrate/use-dex/src/removeLiquidity.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,42 @@
import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents";
import { formatEventData } from "@trne/utils/formatEventData";
import {
createDispatcher,
filterExtrinsicEvents,
nativeWalletSigner,
} from "@therootnetwork/extrinsic";
import { createKeyring } from "@trne/utils/createKeyring";
import { ASTO_ASSET_ID, XRP_ASSET_ID } from "@trne/utils/porcini-assets";
import { sendExtrinsic } from "@trne/utils/sendExtrinsic";
import { withChainApi } from "@trne/utils/withChainApi";
import { withChainContext } from "@trne/utils/withChainContext";
import { cleanEnv, str } from "envalid";
import assert from "node:assert";

interface LiquidityToken {
Ok: number;
}

const { CHAIN_ENDPOINT, CALLER_PRIVATE_KEY } = cleanEnv(process.env, {
CHAIN_ENDPOINT: str({ default: "porcini" }),
CALLER_PRIVATE_KEY: str(), // private key of extrinsic caller
});

/**
* Use `dex.removeLiquidity` to remove your own liqidity from the pair [XRP, ASTO]
*
* Assumes caller liquidity of the pair and XRP to pay gas.
*/
withChainApi("porcini", async (api, caller, logger) => {
withChainContext(CHAIN_ENDPOINT, async (api, logger) => {
const caller = createKeyring(CALLER_PRIVATE_KEY);
const { estimate, signAndSend } = createDispatcher(
api,
caller.address,
[],
nativeWalletSigner(caller)
);

const tokenA = XRP_ASSET_ID;
const tokenB = ASTO_ASSET_ID;

const lpAssetId = (await api.rpc.dex.getLPTokenID(tokenA, tokenB)) as unknown as LiquidityToken;
const liquidity = await api.query.assets.account(lpAssetId.Ok, caller.address);
assert(liquidity.isSome);

logger.info(
{
liquidityBalance: {
Expand All @@ -31,10 +46,8 @@ withChainApi("porcini", async (api, caller, logger) => {
},
`${caller.address} liquidity balance`
);

const amountAMin = 0;
const amountBMin = 0;

logger.info(
{
parameters: {
Expand All @@ -45,7 +58,7 @@ withChainApi("porcini", async (api, caller, logger) => {
amountBMin,
},
},
`create a "futurepass.proxyExtrinsic" extrinsic`
`create a "dex.removeLiquidity" extrinsic`
);
const extrinsic = api.tx.dex.removeLiquidity(
tokenA,
Expand All @@ -57,17 +70,29 @@ withChainApi("porcini", async (api, caller, logger) => {
null // deadline
);

const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
const [removeEvent] = filterExtrinsicEvents(result.events, ["Dex.RemoveLiquidity"]);
const feeResult = await estimate(extrinsic);
assert(feeResult.ok, (feeResult.value as Error).message);
logger.info(
{ parameters: { caller: caller.address, fee: feeResult.ok ? feeResult.value : undefined } },
`dispatch extrinsic`
);

const result = await signAndSend(extrinsic, (status) => {
logger.debug(status);
});
assert(result.ok, (result.value as Error).message);

const { id, events } = result.value;
const [transferEvent] = filterExtrinsicEvents(events, ["dex.RemoveLiquidity"]);
assert(transferEvent);

logger.info(
{
result: {
extrinsicId,
blockNumber: result.blockNumber,
removeEvent: formatEventData(removeEvent.event),
extrinsicId: id,
transferEvent,
},
},
"receive result"
"dispatch result"
);
});
53 changes: 41 additions & 12 deletions examples/substrate/use-dex/src/swap.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents";
import { formatEventData } from "@trne/utils/formatEventData";
import {
createDispatcher,
filterExtrinsicEvents,
nativeWalletSigner,
} from "@therootnetwork/extrinsic";
import { createKeyring } from "@trne/utils/createKeyring";
import { ASTO_ASSET_ID, XRP_ASSET_ID } from "@trne/utils/porcini-assets";
import { sendExtrinsic } from "@trne/utils/sendExtrinsic";
import { withChainApi } from "@trne/utils/withChainApi";
import { withChainContext } from "@trne/utils/withChainContext";
import { cleanEnv, str } from "envalid";
import assert from "node:assert";

interface AmountsOut {
Ok: [number, number];
}

const { CHAIN_ENDPOINT, CALLER_PRIVATE_KEY } = cleanEnv(process.env, {
CHAIN_ENDPOINT: str({ default: "porcini" }),
CALLER_PRIVATE_KEY: str(), // private key of extrinsic caller
});

/**
* Use `dex.swapWithExactSupply` to swap XRP for ASTO, with exact amount in.
*
* Similar swap called can be used is `dex.swapWithExactTarget` to swap token with exact amount out.
*
* Assumes caller has XRP to pay for gas and to swap for ASTO.
*/
withChainApi("porcini", async (api, caller, logger) => {
withChainContext(CHAIN_ENDPOINT, async (api, logger) => {
const caller = createKeyring(CALLER_PRIVATE_KEY);
const { estimate, signAndSend } = createDispatcher(
api,
caller.address,
[],
nativeWalletSigner(caller)
);

const tokenA = XRP_ASSET_ID;
const tokenB = ASTO_ASSET_ID;
const oneXrp = 1_000_000;
Expand Down Expand Up @@ -44,18 +62,29 @@ withChainApi("porcini", async (api, caller, logger) => {
null // deadline
);

logger.info(`dispatch extrinsic from caller="${caller.address}"`);
const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
const [swapEvent] = filterExtrinsicEvents(result.events, ["Dex.Swap"]);
const feeResult = await estimate(extrinsic);
assert(feeResult.ok, (feeResult.value as Error).message);
logger.info(
{ parameters: { caller: caller.address, fee: feeResult.ok ? feeResult.value : undefined } },
`dispatch extrinsic`
);

const result = await signAndSend(extrinsic, (status) => {
logger.debug(status);
});
assert(result.ok, (result.value as Error).message);

const { id, events } = result.value;
const [transferEvent] = filterExtrinsicEvents(events, ["dex.Swap"]);
assert(transferEvent);

logger.info(
{
result: {
extrinsicId,
blockNumber: result.blockNumber,
swapEvent: formatEventData(swapEvent.event),
extrinsicId: id,
transferEvent,
},
},
"receive result"
"dispatch result"
);
});

0 comments on commit ff8209a

Please sign in to comment.