-
Notifications
You must be signed in to change notification settings - Fork 0
feat: build transaction to update pool Fee #1
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import { Blockfrost, Lucid } from '@lucid-evolution/lucid'; | ||
| import { updatePoolFeeTx } from './tx'; | ||
|
|
||
| async function main() { | ||
| const blockfrostProjectId = '<>YOUR_BLOCKFROST_PROJECT_ID<>'; | ||
| const blockfrostUrl = 'https://cardano-preprod.blockfrost.io/api/v0'; | ||
|
|
||
| // Example wallet: It has been granted permissions to manage the pool | ||
| const seed = | ||
| 'mouse carpet zebra giant just pizza very song simple state rebel lunar above naive bundle accuse buffalo hurry mango scorpion country silly layer average'; | ||
| const walletAddr = | ||
| 'addr_test1qz280luwccrquk3lk4ykjjsexl840ppsy2u6vtq4wflwa2c279l7xk8kwpt4zc27c4dsngvpyuqn700m3s8e0k6fw9nsdudnqx'; | ||
|
Comment on lines
+11
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be derived from the seed. I.e. after lucid initialisation from the seed, get the address from the lucid instance. |
||
| // The LP asset for the pool we want to update fees for | ||
| const poolLPAsset = { | ||
| policyId: 'd6aae2059baee188f74917493cf7637e679cd219bdfbbf4dcbeb1d0b', | ||
| tokenName: | ||
| '0c9dfded2857d530ce2cc536d4517a6e4c54e280f5e89b4f315fe0d81cabbcf5', | ||
| }; | ||
|
Comment on lines
+14
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's pass only the token name to the tx building, and let the tx building pick the right LP policy from the constant there. |
||
|
|
||
| const lucid = await Lucid( | ||
| new Blockfrost(blockfrostUrl, blockfrostProjectId), | ||
| 'Preprod', | ||
| ); | ||
|
|
||
| lucid.selectWallet.fromSeed(seed); | ||
|
|
||
| const tx = updatePoolFeeTx(lucid, { | ||
| managerAddress: walletAddr, | ||
| poolLPAsset: poolLPAsset, | ||
| newFeeA: 0.9, | ||
| newFeeB: 0.3, | ||
|
Comment on lines
+30
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's maybe rename these parameters to |
||
| }); | ||
|
|
||
| const txComplete = await tx.complete(); | ||
| const signedTx = await txComplete.sign.withWallet().complete(); | ||
| const txHash = await signedTx.submit(); | ||
| console.log('Transaction submitted successfully: ', txHash); | ||
| } | ||
|
|
||
| void main(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| import { getAddressDetails, LucidEvolution, TxBuilder } from "@lucid-evolution/lucid"; | ||
| import JSONBig from "json-bigint" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aaa, this is nice, didn't know about this package, thanks. |
||
|
|
||
| const MIN_TRADING_FEE: bigint = 5n; // 0.05% | ||
| const MAX_TRADING_FEE: bigint = 2000n; // 20% | ||
|
|
||
| const LP_POLICY_ID_CFG = { | ||
| ["Mainnet"]: "f5808c2c990d86da54bfc97d89cee6efa20cd8461616359478d96b4c", | ||
| ["Preprod"]: "d6aae2059baee188f74917493cf7637e679cd219bdfbbf4dcbeb1d0b", | ||
| } | ||
|
|
||
| function assetToDottedString(asset: { policyId: string; tokenName: string }): string { | ||
| if (asset.policyId === "" && asset.tokenName === "") { | ||
| return "lovelace" | ||
| } | ||
| if (asset.tokenName === "") { | ||
| return asset.policyId; | ||
| } | ||
| return `${asset.policyId}.${asset.tokenName}`; | ||
| } | ||
|
Comment on lines
+12
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should utilise the |
||
|
|
||
| /** | ||
| * Request to update the trading fees for a liquidity pool. | ||
| * @property managerAddress - The address of the pool manager authorized to update fees | ||
| * @property poolLPAsset - The LP token asset identifying the pool | ||
| * @property newFeeA - The new fee for trading direction A as a percentage (0.05% - 20%) | ||
| * @property newFeeB - The new fee for trading direction B as a percentage (0.05% - 20%) | ||
| * @property version - Protocol version for the fee request format | ||
| */ | ||
| export type PoolFeeRequest = { | ||
| managerAddress: string; | ||
| poolLPAsset: { | ||
| policyId: string, | ||
| tokenName: string | ||
| }; | ||
|
Comment on lines
+32
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above, this should be only a token name. |
||
| newFeeA: number; | ||
| newFeeB: number; | ||
| version: "1"; | ||
| }; | ||
|
|
||
| export type RequestPoolFeeOptions = { | ||
| request: Omit<PoolFeeRequest, "version">; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm curious what the reason is for omitting the version field? |
||
| }; | ||
|
|
||
| /** | ||
| * Creates a transaction to update the trading fees for a liquidity pool. | ||
| * This method builds a transaction with metadata that requests fee changes for a pool. | ||
| * The transaction must be signed by the pool manager address. | ||
| */ | ||
| export function updatePoolFeeTx( | ||
| lucid: LucidEvolution, | ||
| options: Omit<PoolFeeRequest, "version"> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the |
||
| ): TxBuilder { | ||
| const { managerAddress, poolLPAsset, newFeeA, newFeeB } = options; | ||
| const newFeeABps = BigInt(Math.floor(newFeeA * 100)); | ||
| const newFeeBBps = BigInt(Math.floor(newFeeB * 100)); | ||
|
|
||
| if (newFeeABps < MIN_TRADING_FEE || newFeeABps > MAX_TRADING_FEE) { | ||
| throw new Error( | ||
| `Liquidity Pool Fee A must be in 0.05% - 20%, actual: ${newFeeA}%` | ||
| ); | ||
| } | ||
| if (newFeeBBps < MIN_TRADING_FEE || newFeeBBps > MAX_TRADING_FEE) { | ||
| throw new Error( | ||
| `Liquidity Pool Fee B must be in 0.05% - 20%, actual: ${newFeeB}%` | ||
|
Comment on lines
+60
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally, use the |
||
| ); | ||
| } | ||
|
|
||
| const network = lucid.config().network; | ||
| if (network !== "Mainnet" && network !== "Preprod") { | ||
| throw new Error(`Unsupported network: ${network}`); | ||
| } | ||
|
|
||
| if (poolLPAsset.policyId != LP_POLICY_ID_CFG[network]) { | ||
| throw new Error( | ||
| `Invalid LP Policy ID for network ${network}: ${poolLPAsset.policyId}` | ||
| ); | ||
| } | ||
|
|
||
| const feeRequestJSON = JSONBig.stringify({ | ||
| managerAddress: managerAddress, | ||
| poolLPAsset: assetToDottedString(poolLPAsset), | ||
| newFeeA: newFeeABps.toString(), | ||
| newFeeB: newFeeBBps.toString(), | ||
| version: "1", | ||
| }).match(/.{1,64}/g); | ||
|
|
||
| if (!feeRequestJSON) { | ||
| throw new Error("Failed to create fee request JSON metadata"); | ||
| } | ||
| const addressDetails = getAddressDetails(managerAddress); | ||
| if (addressDetails.type != "Base" && addressDetails.type != "Enterprise") { | ||
| throw new Error("Manager address must be a Base or Enterprise address"); | ||
| } | ||
| const paymentCred = addressDetails.paymentCredential; | ||
| if (!paymentCred) { | ||
| throw new Error("Manager address must have a payment credential"); | ||
| } | ||
| if (paymentCred.type !== "Key") { | ||
| throw new Error("Manager address must be a key address"); | ||
| } | ||
|
|
||
| return lucid | ||
| .newTx() | ||
| .addSigner(managerAddress) | ||
| .attachMetadata(674, { | ||
| ["msg"]: ["Minswap: Request of Pool Fee Manager"], | ||
| ["extraData"]: feeRequestJSON, | ||
| }); | ||
|
Comment on lines
+103
to
+109
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tx building still missing here. |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move this out of source control into a gitignored
.env