Query Minswap data and build transactions
npm install @minswap/sdkThe Minswap open-source project provides a comprehensive suite of off-chain tools, including price feeds, historical data storage, and integration methods for Stableswap, AMM V1, AMM V2, and LBE V2.
- See the Minswap Example for a demonstration of how to use the SDK.
- For additional transaction-building examples, refer to the examples/ directory in this repository.
- [x] Pool price feed
- [x] Historical data of pool
- [x] Calculate trade price
- [x] Calculate price impact
- [x] Create orders and submit with Lucid
- [x] Syncer to sync minswap's liquidity pool data
We provide multiple adapters to get the price and liquidity pool information.
- BlockfrostAdapter: use Blockfrost to query the data.
- MinswapAdapter: use Syncer to query the data. If you want to use MinswapAdapter you need to run syncer by yourself.
- MaestroAdapter: use Maestro to query the data.
- NPM: npm install @minswap/sdk
- Yarn: yarn add @minswap/sdk
This package depends on @spacebudz/lucid, which is an ESM package, so it's also an ESM package. To import from ESM package, you need to specify "type": "module" in package.json and configure other build flags accordingly.
Also, --experimental-wasm-modules flag needs to be set in Node.js and @jsr:registry=https://npm.jsr.io needs to be added to .npmrc file.
Create an adapter using either BlockfrostAdapter or MinswapAdapter:
``ts
import { BlockFrostAPI } from "@blockfrost/blockfrost-js";
import { BlockfrostAdapter, NetworkId } from "@minswap/sdk";
const blockFrostApi = new BlockFrostAPI({
projectId: "
network: "mainnet",
});
const blockfrostAdapter = new BlockfrostAdapter(
NetworkId.MAINNET,
blockFrostApi
);
`
- Install docker compose.
- Update the .env file to specify the exact network you want to sync.docker compose -f docker-compose.yaml up --build -d
- Run the command: to build.docker compose -f docker-compose.yaml logs -f
- Run the command: to view log.
`ts
import { BlockFrostAPI } from "@blockfrost/blockfrost-js";
import {
BlockfrostAdapter,
MinswapAdapter,
NetworkEnvironment,
NetworkId,
newPrismaClient,
PostgresRepositoryReader,
} from "@minswap/sdk";
const blockFrostApi = new BlockFrostAPI({
projectId: "
network: "mainnet",
});
const prismaClient = await newPrismaClient(
"postgresql://postgres:minswap@postgres:5432/syncer?schema=public&connection_limit=5"
);
const repositoryReader = new PostgresRepositoryReader(
NetworkEnvironment.MAINNET,
prismaClient
);
const minswapAdapter = new MinswapAdapter({
networkId: NetworkId.MAINNET,
networkEnv: NetworkEnvironment.MAINNET,
blockFrostApi: blockFrostApi,
repository: repositoryReader,
});
`
`ts
import { MaestroAdapter } from "@minswap/sdk";
import { MaestroClient, Configuration } from "@maestro-org/typescript-sdk";
const maestroClient = new MaestroClient(
new Configuration({
apiKey: maestroApiKey,
network: cardanoNetwork,
})
);
const maestroAdapter = new MaestroAdapter(NetworkId.TESTNET, maestroClient);
`
#### MIN/ADA pool v1:
`tsADA/MIN price: ${price0.toString()}; MIN/ADA price: ${price1.toString()}
for (let i = 1; ; i++) {
const pools = await adapter.getV1Pools({
page: i,
});
if (pools.length === 0) {
// last page
break;
}
const minAdaPool = pools.find(
(p) =>
p.assetA === "lovelace" &&
p.assetB ===
"29d222ce763455e3d7a09a665ce554f00ac89d2e99a1a83d267170c64d494e"
);
if (minAdaPool) {
const [price0, price1] = await adapter.getV1PoolPrice({ pool: minAdaPool });
console.log(
ADA/MIN pool ID: ${minAdaPool.id}
);
// we can later use this ID to call getPoolById
console.log();`
break;
}
}
#### MIN/ADA pool v2:
`ts
const minAdaPool = await adapter.getV2PoolByPair(
Asset.fromString("lovelace"),
Asset.fromString(
"29d222ce763455e3d7a09a665ce554f00ac89d2e99a1a83d267170c64d494e"
)
);
if (minAdaPool) {
const [a, b] = await adapter.getV2PoolPrice({ pool: minAdaPool });
console.log(ADA/MIN price: ${a.toString()}; MIN/ADA price: ${b.toString()});`
}
#### MIN/ADA pool v1:
`ts
const MIN_ADA_POOL_ID =
"6aa2153e1ae896a95539c9d62f76cedcdabdcdf144e564b8955f609d660cf6a2";
const history = await adapter.getV1PoolHistory({ id: MIN_ADA_POOL_ID });
for (const historyPoint of history) {
const pool = await adapter.getV1PoolInTx({ txHash: historyPoint.txHash });
if (!pool) {
throw new Error("pool not found");
}
const [price0, price1] = await adapter.getV1PoolPrice({ pool: pool });
console.log(${historyPoint.time}: ${price0} ADA/MIN, ${price1} MIN/ADA);`
}
#### MIN/ADA pool v2:
`ts
for (let i = 1; ; i++) {
const pools = await adapter.getV2PoolHistory({
assetA: Asset.fromString("lovelace"),
assetB: Asset.fromString(
"29d222ce763455e3d7a09a665ce554f00ac89d2e99a1a83d267170c64d494e"
),
page: i,
});
if (pools.length === 0) {
// last page
break;
}
for (const pool of pools) {
const [price0, price1] = await adapter.getV2PoolPrice({ pool: pool });
console.log(
ADA/MIN price: ${a.toString()}; MIN/ADA price: ${price1.toString()}`
);
}
}
- Swap MIN-ADA in V2 pool on testnet:
#### With Blockfrost adapter:
`ts
import {
ADA, Asset,
BlockfrostAdapter,
calculateAmountWithSlippageTolerance,
DexV2,
DexV2Calculation,
getBackendBlockfrostLucidInstance,
NetworkId,
OrderV2
} from "@minswap/sdk";
import {BlockFrostAPI} from "@blockfrost/blockfrost-js";
export async function swapExactInV2TxExample() {
const networkId: NetworkId = NetworkId.TESTNET;
const blockfrostProjectId = "
const blockfrostUrl = "https://cardano-preprod.blockfrost.io/api/v0";
const address = " const lucid = await getBackendBlockfrostLucidInstance( const adapter = new BlockfrostAdapter( const MIN: Asset = { const utxos = await lucid.utxosAt(address); const assetA = ADA; const pool = await adapter.getV2PoolByPair(assetA, assetB); const swapAmount = 1_000n; // 20% slippage tolerance const txComplete = await new DexV2(lucid, adapter).createBulkOrdersTx({ const signedTx = await txComplete console.log(Transaction submitted successfully: ${txId} void swapExactInV2TxExample(); #### With Meastro adapter: ` export async function swapExactInV2TxExample() { const address = " const lucid = await getBackendMaestroLucidInstance( const maestroClient = new MaestroClient( const MIN: Asset = { const adapter = new MaestroAdapter(NetworkId.TESTNET, maestroClient); const utxos = await lucid.utxosAt(address); const assetA = ADA; const pool = await adapter.getV2PoolByPair(assetA, assetB); const swapAmount = 1_000n; // 20% slippage tolerance const txComplete = await new DexV2(lucid, adapter).createBulkOrdersTx({ const signedTx = await txComplete console.log(Transaction submitted successfully: ${txId} void swapExactInV2TxExample(); See examples/
networkId,
blockfrostProjectId,
blockfrostUrl,
address
);
NetworkId.TESTNET,
new BlockFrostAPI({
projectId: blockfrostProjectId,
network: "preprod",
})
);
policyId: "e16c2dc8ae937e8d3790c7fd7168d7b994621ba14ca11415f39fed72",
tokenName: "4d494e",
};
const assetB = MIN;
if (!pool) {
throw new Error("Pool not found");
}
const amountOut = DexV2Calculation.calculateAmountOut({
reserveIn: pool.reserveA,
reserveOut: pool.reserveB,
amountIn: swapAmount,
tradingFeeNumerator: pool.feeA[0],
});
const acceptedAmountOut = calculateAmountWithSlippageTolerance({
slippageTolerancePercent: 20,
amount: amountOut,
type: "down",
});
sender: address,
availableUtxos: utxos,
orderOptions: [
{
type: OrderV2.StepType.SWAP_EXACT_IN,
amountIn: swapAmount,
assetIn: assetA,
direction: OrderV2.Direction.A_TO_B,
minimumAmountOut: acceptedAmountOut,
lpAsset: pool.lpAsset,
isLimitOrder: false,
killOnFailed: false,
},
],
});
.signWithPrivateKey("
.commit();
const txId = await signedTx.submit(););
}
`ts
import {
ADA,
Asset,
calculateAmountWithSlippageTolerance,
DexV2,
DexV2Calculation,
getBackendMaestroLucidInstance,
MaestroAdapter,
NetworkId,
OrderV2
} from "@minswap/sdk";
import {Configuration, MaestroClient} from "@maestro-org/typescript-sdk";
const networkId: NetworkId = NetworkId.TESTNET;
const maestroApiKey = "
"Preprod",
maestroApiKey,
address
);
new Configuration({
apiKey: maestroApiKey,
network: "Preprod",
})
);
policyId: "e16c2dc8ae937e8d3790c7fd7168d7b994621ba14ca11415f39fed72",
tokenName: "4d494e",
};
const assetB = MIN;
if (!pool) {
throw new Error("Pool not found");
}
const amountOut = DexV2Calculation.calculateAmountOut({
reserveIn: pool.reserveA,
reserveOut: pool.reserveB,
amountIn: swapAmount,
tradingFeeNumerator: pool.feeA[0],
});
const acceptedAmountOut = calculateAmountWithSlippageTolerance({
slippageTolerancePercent: 20,
amount: amountOut,
type: "down",
});
sender: address,
availableUtxos: utxos,
orderOptions: [
{
type: OrderV2.StepType.SWAP_EXACT_IN,
amountIn: swapAmount,
assetIn: assetA,
direction: OrderV2.Direction.A_TO_B,
minimumAmountOut: acceptedAmountOut,
lpAsset: pool.lpAsset,
isLimitOrder: false,
killOnFailed: false,
},
],
});
.signWithPrivateKey("
.commit();
const txId = await signedTx.submit(););
}
` or docs for more details. You can run a single file like npm run exec examples/example.ts`.