Skip to content

Commit

Permalink
feat: swapAndStakeForFee (#175)
Browse files Browse the repository at this point in the history
  • Loading branch information
00xSam authored Nov 11, 2024
1 parent ae65ff0 commit e37ba22
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 2 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Security

## @mercurial-finance/dynamic-amm-sdk [1.1.12] - PR[#173](https://github.com/mercurial-finance/mercurial-dynamic-amm-sdk/pull/173)

### Added

- New function `swapAndStakeForFee`

## @mercurial-finance/dynamic-amm-sdk [1.1.11] - PR[#170](https://github.com/mercurial-finance/mercurial-dynamic-amm-sdk/pull/170)

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion ts-client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mercurial-finance/dynamic-amm-sdk",
"version": "1.1.11",
"version": "1.1.12",
"description": "Mercurial Vaults SDK is a typescript library that allows you to interact with Mercurial v2's AMM.",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
Expand Down
93 changes: 92 additions & 1 deletion ts-client/src/amm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,7 @@ export default class AmmImpl implements AmmImplementation {
const preInstructions: TransactionInstruction[] = [];

const initFeeVaultParams = opt?.feeVault ? { ...opt.feeVault, padding: new Array(64).fill(0) } : undefined;

const createFeeVaultIxs = await StakeForFee.createFeeVaultInstructions(
connection,
poolPubkey,
Expand Down Expand Up @@ -1987,6 +1987,97 @@ export default class AmmImpl implements AmmImplementation {
}).add(swapTx);
}

/**
* `swap` is a function that takes in a `PublicKey` of the owner, a `PublicKey` of the input token
* mint, an `BN` of the input amount of lamports, and an `BN` of the output amount of lamports. It
* returns a `Promise<Transaction>` of the swap transaction
* @param {PublicKey} owner - The public key of the user who is swapping
* @param {PublicKey} inTokenMint - The mint of the token you're swapping from.
* @param {BN} inAmountLamport - The amount of the input token you want to swap.
* @param {BN} outAmountLamport - The minimum amount of the output token you want to receive.
* @param {PublicKey} [referralOwner] - The referrer wallet will receive the host fee, fee will be transferred to ATA of referrer wallet.
* @returns A transaction object
*/
public async swapAndStakeForFee(
owner: PublicKey,
inTokenMint: PublicKey,
inAmountLamport: BN,
outAmountLamport: BN,
stakeForFee: StakeForFee,
): Promise<Transaction[]> {
const resultTxs: Transaction[] = [];
const [sourceToken, destinationToken] = this.tokenAMint.address.equals(inTokenMint)
? [this.poolState.tokenAMint, this.poolState.tokenBMint]
: [this.poolState.tokenBMint, this.poolState.tokenAMint];

const protocolTokenFee = this.tokenAMint.address.equals(inTokenMint)
? this.poolState.protocolTokenAFee
: this.poolState.protocolTokenBFee;

let preInstructions: Array<TransactionInstruction> = [];
const [[userSourceToken, createUserSourceIx], [userDestinationToken, createUserDestinationIx]] =
await this.createATAPreInstructions(owner, [sourceToken, destinationToken]);

createUserSourceIx && preInstructions.push(createUserSourceIx);
createUserDestinationIx && preInstructions.push(createUserDestinationIx);

if (sourceToken.equals(NATIVE_MINT)) {
preInstructions = preInstructions.concat(
wrapSOLInstruction(owner, userSourceToken, BigInt(inAmountLamport.toString())),
);
}

const postInstructions: Array<TransactionInstruction> = [];
if (NATIVE_MINT.equals(destinationToken)) {
const unwrapSOLIx = await unwrapSOLInstruction(owner);
unwrapSOLIx && postInstructions.push(unwrapSOLIx);
}

const remainingAccounts = this.swapCurve.getRemainingAccounts();

const swapTx = await this.program.methods
.swap(inAmountLamport, outAmountLamport)
.accounts({
aTokenVault: this.vaultA.vaultState.tokenVault,
bTokenVault: this.vaultB.vaultState.tokenVault,
aVault: this.poolState.aVault,
bVault: this.poolState.bVault,
aVaultLp: this.poolState.aVaultLp,
bVaultLp: this.poolState.bVaultLp,
aVaultLpMint: this.vaultA.vaultState.lpMint,
bVaultLpMint: this.vaultB.vaultState.lpMint,
userSourceToken,
userDestinationToken,
user: owner,
protocolTokenFee,
pool: this.address,
tokenProgram: TOKEN_PROGRAM_ID,
vaultProgram: this.vaultProgram.programId,
})
.remainingAccounts(remainingAccounts)
.preInstructions(preInstructions)
.postInstructions(postInstructions)
.transaction();

resultTxs.push(
new Transaction({
feePayer: owner,
...(await this.program.provider.connection.getLatestBlockhash(this.program.provider.connection.commitment)),
}).add(swapTx),
);

const stakeTx = await stakeForFee.stake(outAmountLamport, owner);

resultTxs.push(
new Transaction({
feePayer: owner,
...(await this.program.provider.connection.getLatestBlockhash(this.program.provider.connection.commitment)),
}).add(stakeTx),
);

return resultTxs;
}

/**
* `getDepositQuote` is a function that takes in a tokenAInAmount, tokenBInAmount, balance, and
* slippage, and returns a poolTokenAmountOut, tokenAInAmount, and tokenBInAmount. `tokenAInAmount` or `tokenBAmount`
Expand Down

0 comments on commit e37ba22

Please sign in to comment.