Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MIN-1266: Off-chain Integration with StableSwap Smart Contract #39

Merged
merged 17 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
219 changes: 219 additions & 0 deletions examples/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ import {
NetworkId,
OrderV2,
PoolV1,
StableOrder,
StableswapCalculation,
StableswapConstant,
} from "../src";
import { Slippage } from "../src/utils/slippage.internal";
import { Stableswap } from "../src/stableswap";

const MIN: Asset = {
policyId: "e16c2dc8ae937e8d3790c7fd7168d7b994621ba14ca11415f39fed72",
Expand Down Expand Up @@ -845,6 +849,221 @@ async function _cancelV2TxExample(
});
}

async function _swapStableExample(
lucid: Lucid,
blockfrostAdapter: BlockfrostAdapter,
address: Address,
availableUtxos: UTxO[]
): Promise<TxComplete> {
const lpAsset = Asset.fromString(
"d16339238c9e1fb4d034b6a48facb2f97794a9cdb7bc049dd7c49f54646a65642d697573642d76312e342d6c70"
);
const config = StableswapConstant.getConfigByLpAsset(
lpAsset,
NetworkId.TESTNET
);

const pool = await blockfrostAdapter.getStablePoolByLpAsset(lpAsset);

const swapAmount = 1_000n;

const amountOut = StableswapCalculation.calculateSwapAmount({
inIndex: 0,
outIndex: 1,
amountIn: swapAmount,
amp: pool.amp,
multiples: config.multiples,
datumBalances: pool.datum.balances,
fee: config.fee,
adminFee: config.adminFee,
feeDenominator: config.feeDenominator,
});

return new Stableswap(lucid).buildCreateTx({
sender: address,
availableUtxos: availableUtxos,
lpAsset: lpAsset,
type: StableOrder.StepType.SWAP,
assetIn: Asset.fromString(config.assets[0]),
assetInAmount: swapAmount,
assetInIndex: 0n,
assetOutIndex: 1n,
minimumAssetOut: amountOut,
});
}

async function _depositStableExample(
lucid: Lucid,
blockfrostAdapter: BlockfrostAdapter,
address: Address,
availableUtxos: UTxO[]
): Promise<TxComplete> {
const lpAsset = Asset.fromString(
"d16339238c9e1fb4d034b6a48facb2f97794a9cdb7bc049dd7c49f54646a65642d697573642d76312e342d6c70"
);
const config = StableswapConstant.getConfigByLpAsset(
lpAsset,
NetworkId.TESTNET
);

const pool = await blockfrostAdapter.getStablePoolByLpAsset(lpAsset);

const amountIns = [100_000n, 1_000n];

const lpAmount = StableswapCalculation.calculateDeposit({
amountIns: amountIns,
totalLiquidity: pool.totalLiquidity,
amp: pool.amp,
multiples: config.multiples,
datumBalances: pool.datum.balances,
fee: config.fee,
adminFee: config.adminFee,
feeDenominator: config.feeDenominator,
});

return new Stableswap(lucid).buildCreateTx({
sender: address,
availableUtxos: availableUtxos,
lpAsset: lpAsset,
type: StableOrder.StepType.DEPOSIT,
assetsAmount: [
[Asset.fromString(pool.assets[0]), 100_000n],
[Asset.fromString(pool.assets[1]), 1_000n],
],
minimumLPReceived: lpAmount,
totalLiquidity: pool.totalLiquidity,
});
}

async function _withdrawStableExample(
lucid: Lucid,
blockfrostAdapter: BlockfrostAdapter,
address: Address,
availableUtxos: UTxO[]
): Promise<TxComplete> {
const lpAsset = Asset.fromString(
"d16339238c9e1fb4d034b6a48facb2f97794a9cdb7bc049dd7c49f54646a65642d697573642d76312e342d6c70"
);
const config = StableswapConstant.getConfigByLpAsset(
lpAsset,
NetworkId.TESTNET
);

const pool = await blockfrostAdapter.getStablePoolByLpAsset(lpAsset);

const lpAmount = 10_000n;

const amountOuts = StableswapCalculation.calculateWithdraw({
withdrawalLPAmount: lpAmount,
multiples: config.multiples,
datumBalances: pool.datum.balances,
totalLiquidity: pool.totalLiquidity,
});

return new Stableswap(lucid).buildCreateTx({
sender: address,
availableUtxos: availableUtxos,
lpAsset: lpAsset,
type: StableOrder.StepType.WITHDRAW,
lpAmount: lpAmount,
minimumAmounts: amountOuts,
});
}

async function _withdrawImbalanceStableExample(
lucid: Lucid,
blockfrostAdapter: BlockfrostAdapter,
address: Address,
availableUtxos: UTxO[]
): Promise<TxComplete> {
const lpAsset = Asset.fromString(
"d16339238c9e1fb4d034b6a48facb2f97794a9cdb7bc049dd7c49f54646a65642d697573642d76312e342d6c70"
);
const config = StableswapConstant.getConfigByLpAsset(
lpAsset,
NetworkId.TESTNET
);

const pool = await blockfrostAdapter.getStablePoolByLpAsset(lpAsset);

const withdrawAmounts = [1234n, 5678n];

const lpAmount = StableswapCalculation.calculateWithdrawImbalance({
withdrawAmounts: withdrawAmounts,
totalLiquidity: pool.totalLiquidity,
amp: pool.amp,
multiples: config.multiples,
datumBalances: pool.datum.balances,
fee: config.fee,
adminFee: config.adminFee,
feeDenominator: config.feeDenominator,
});

return new Stableswap(lucid).buildCreateTx({
sender: address,
availableUtxos: availableUtxos,
lpAsset: lpAsset,
type: StableOrder.StepType.WITHDRAW_IMBALANCE,
lpAmount: lpAmount,
withdrawAmounts: withdrawAmounts,
});
}

async function _zapOutStableExample(
lucid: Lucid,
blockfrostAdapter: BlockfrostAdapter,
address: Address,
availableUtxos: UTxO[]
): Promise<TxComplete> {
const lpAsset = Asset.fromString(
"d16339238c9e1fb4d034b6a48facb2f97794a9cdb7bc049dd7c49f54646a65642d697573642d76312e342d6c70"
);
const config = StableswapConstant.getConfigByLpAsset(
lpAsset,
NetworkId.TESTNET
);

const pool = await blockfrostAdapter.getStablePoolByLpAsset(lpAsset);

const lpAmount = 12345n;
const outIndex = 0;
const amountOut = StableswapCalculation.calculateZapOut({
amountLpIn: lpAmount,
outIndex: outIndex,
totalLiquidity: pool.totalLiquidity,
amp: pool.amp,
multiples: config.multiples,
datumBalances: pool.datum.balances,
fee: config.fee,
adminFee: config.adminFee,
feeDenominator: config.feeDenominator,
});

return new Stableswap(lucid).buildCreateTx({
sender: address,
availableUtxos: availableUtxos,
lpAsset: lpAsset,
type: StableOrder.StepType.ZAP_OUT,
lpAmount: lpAmount,
assetOutIndex: BigInt(outIndex),
minimumAssetOut: amountOut,
});
}

async function _cancelStableExample(lucid: Lucid): Promise<TxComplete> {
const orderUtxos = await lucid.utxosByOutRef([
{
txHash:
"f1c873201c3638860dc7d831a2266a7b0f46e48674da27fd0bcd1dc0c3835889",
outputIndex: 0,
},
]);
invariant(orderUtxos.length === 1, "Can not find order to cancel");
return new Stableswap(lucid).buildCancelOrdersTx({
orderUtxos: orderUtxos,
});
}

/**
* Initialize Lucid Instance for Browser Environment
* @param network Network you're working on
Expand Down
42 changes: 31 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"big.js": "^6.2.1",
"bignumber.js": "^9.1.2",
"lucid-cardano": "0.10.10",
"remeda": "^2.12.1",
"sha3": "^2.1.4"
},
"devDependencies": {
Expand Down
15 changes: 15 additions & 0 deletions src/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,21 @@ export class BlockfrostAdapter {
};
}

public async getStablePoolByLpAsset(
lpAsset: Asset
): Promise<StablePool.State> {
const pool = (await this.getAllStablePools()).pools.find(
(pool) => pool.lpAsset === Asset.toString(lpAsset)
);
invariant(
pool,
`getStablePoolByLpAsset: Can not find pool by LP Asset ${Asset.toString(
lpAsset
)}`
);
return pool;
}
m1n999999 marked this conversation as resolved.
Show resolved Hide resolved

public async getStablePoolByNFT(
nft: Asset
): Promise<StablePool.State | null> {
Expand Down
Loading