Skip to content

Instantly share code, notes, and snippets.

@satanworker
Created April 7, 2024 14:10
Show Gist options
  • Save satanworker/7be5914dcd8276197c1cef7297a2f574 to your computer and use it in GitHub Desktop.
Save satanworker/7be5914dcd8276197c1cef7297a2f574 to your computer and use it in GitHub Desktop.
// import { Address } from "@ton/core";
import { JettonsService } from "../../jettons/jettonsService";
import { WalletService } from "../../wallet/walletService";
import { PROXY_TON, Web3TransportService } from "../../web3infra/web3TransportService";
import { zeroTONtopTON } from "../../web3infra/zeroTONtopTON";
import { Asset, Factory, MAINNET_FACTORY_ADDR, PoolType, VaultNative, ReadinessStatus, JettonRoot, VaultJetton, Pool } from '@dedust/sdk';
import { Address, OpenedContract, Sender, toNano, TonClient, TonClient4, WalletContractV3R1, WalletContractV4 } from "@ton/ton";
import { SimulateSwap, Swap } from "../swapService";
export class Dedust {
private jettonService: JettonsService;
private walletService: WalletService
private web3TransportService: Web3TransportService
constructor(
jettonService: JettonsService,
walletService: WalletService,
web3TransportService: Web3TransportService,
) {
this.jettonService = jettonService;
this.walletService = walletService
this.web3TransportService = web3TransportService
}
async simulate({ offerJettonAddress, askJettonAddress, amount }: Omit<SimulateSwap, 'deFi'>): Promise<Omit<SimulateSwap, 'deFi'> & {
amountOutInNano: bigint
}> {
const client = this.web3TransportService.TonClient4;
const factory = client.open(Factory.createFromAddress(MAINNET_FACTORY_ADDR));
const getEstimatedSwap = async (offerAddress: string, askAddress: string, isOfferNative: boolean, amountIn: bigint) => {
const jettonRoot = client.open(JettonRoot.createFromAddress(Address.parse(isOfferNative ? askAddress : offerAddress)));
const poolAddress = await factory.getPoolAddress({
poolType: PoolType.VOLATILE,
assets: [Asset.native(), Asset.jetton(jettonRoot.address)],
});
const pool = client.open(Pool.createFromAddress(poolAddress));
const estimatedSwap = await pool.getEstimatedSwapOut({
assetIn: isOfferNative ? Asset.native() : Asset.jetton(jettonRoot.address),
amountIn,
});
return {
offerJettonAddress,
askJettonAddress,
amount,
amountOutInNano: estimatedSwap.amountOut,
}
};
const isOfferNative = zeroTONtopTON(offerJettonAddress) === PROXY_TON;
const isAskNative = zeroTONtopTON(askJettonAddress) === PROXY_TON;
const amountIn = BigInt(amount);
if (isOfferNative || isAskNative) {
return await getEstimatedSwap(offerJettonAddress, askJettonAddress, isOfferNative, amountIn)
} else {
const estimatedOffer = await getEstimatedSwap(offerJettonAddress, askJettonAddress, false, amountIn);
return await getEstimatedSwap(offerJettonAddress, askJettonAddress, true, estimatedOffer.amountOutInNano)
}
}
async swap({ userId, accountIndex, offerJettonAddress, askJettonAddress, queryId, offerAmount }: Omit<Swap, 'deFi'>) {
const secretKey = await this.walletService.getTonWalletSecretKey({
userId,
accountIndex
})
const client = this.web3TransportService.TonClient4
const wallet = await this.walletService.getTONWallet4({ userId, accountIndex })
let contractMyWallet = client.open(wallet);
const sender = contractMyWallet.sender(secretKey);
const TON = Asset.native();
const factory = client.open(Factory.createFromAddress(MAINNET_FACTORY_ADDR));
const tonVault = client.open(await factory.getNativeVault());
if ((await tonVault.getReadinessStatus()) !== ReadinessStatus.READY) {
throw new Error('Vault (TON) does not exist.');
}
if (zeroTONtopTON(offerJettonAddress) === PROXY_TON) {
await this.handleTonToJettonSwap({ client, factory, sender, askJettonAddress, offerAmount, TON, tonVault, queryId });
} else if (zeroTONtopTON(askJettonAddress) === PROXY_TON) {
await this.handleJettonToTonSwap({ client, factory, contractMyWallet, sender, offerJettonAddress, offerAmount, TON, queryId });
} else {
await this.handleJettonToJettonSwap({ client, factory, contractMyWallet, sender, offerJettonAddress, askJettonAddress, offerAmount, TON, queryId });
}
}
async handleTonToJettonSwap({ client, factory, sender, askJettonAddress, offerAmount, TON, tonVault, queryId }: {
client: TonClient4,
factory: OpenedContract<Factory>,
sender: Sender,
askJettonAddress: string,
offerAmount: string
TON: Asset
tonVault: OpenedContract<VaultNative>,
queryId: number
}) {
console.log('TON > Jetton');
const JETTON = Asset.jetton(Address.parse(askJettonAddress));
const TON_JETTON = client.open(await factory.getPool(PoolType.VOLATILE, [TON, JETTON]));
if ((await TON_JETTON.getReadinessStatus()) !== ReadinessStatus.READY) {
throw new Error('Pool does not exist.');
}
await tonVault.sendSwap(sender, {
poolAddress: TON_JETTON.address,
amount: BigInt(offerAmount),
gasAmount: toNano(JettonsService.defaultTONAmount),
queryId,
});
}
async handleJettonToTonSwap({ client, factory, contractMyWallet, sender, offerJettonAddress, offerAmount, TON, queryId }: {
client: TonClient4,
factory: OpenedContract<Factory>,
contractMyWallet: OpenedContract<WalletContractV3R1>,
sender: Sender,
TON: Asset,
offerJettonAddress: string,
offerAmount: string,
queryId: number
}) {
console.log('Jetton > TON');
const jettonRoot = client.open(JettonRoot.createFromAddress(Address.parse(offerJettonAddress)));
const jettonWallet = client.open(await jettonRoot.getWallet(contractMyWallet.address));
const jettonVault = client.open(await factory.getJettonVault(Address.parse(offerJettonAddress)));
const JETTON = Asset.jetton(Address.parse(offerJettonAddress));
const JETTON_TON = client.open(await factory.getPool(PoolType.VOLATILE, [JETTON, TON]));
if ((await JETTON_TON.getReadinessStatus()) !== ReadinessStatus.READY) {
throw new Error('Pool does not exist.');
}
await jettonWallet.sendTransfer(sender, toNano("0.3"), {
amount: BigInt(offerAmount),
destination: jettonVault.address,
responseAddress: contractMyWallet.address,
forwardAmount: toNano("0.01"),
queryId,
forwardPayload: VaultJetton.createSwapPayload({ poolAddress: JETTON_TON.address }),
});
}
async handleJettonToJettonSwap({ client, factory, contractMyWallet, sender, askJettonAddress, offerJettonAddress, offerAmount, TON, queryId }: {
client: TonClient4,
factory: OpenedContract<Factory>,
contractMyWallet: OpenedContract<WalletContractV3R1>,
sender: Sender,
askJettonAddress: string,
offerJettonAddress: string,
offerAmount: string,
TON: Asset,
queryId: number
}) {
console.log('Jetton -> Jetton');
const offerRoot = client.open(JettonRoot.createFromAddress(Address.parse(offerJettonAddress)));
const offerWallet = client.open(await offerRoot.getWallet(contractMyWallet.address));
const offerVault = client.open(await factory.getJettonVault(Address.parse(offerJettonAddress)));
const OFFER_JETTON = Asset.jetton(Address.parse(offerJettonAddress));
const ASK_JETTON = Asset.jetton(Address.parse(askJettonAddress));
const TON_JETTON = client.open(await factory.getPool(PoolType.VOLATILE, [TON, OFFER_JETTON]));
if ((await TON_JETTON.getReadinessStatus()) !== ReadinessStatus.READY) {
throw new Error('First pool does not exist.');
}
const JETTON_TON = client.open(await factory.getPool(PoolType.VOLATILE, [TON, ASK_JETTON]));
if ((await JETTON_TON.getReadinessStatus()) !== ReadinessStatus.READY) {
throw new Error('Second pool does not exist.');
}
await offerWallet.sendTransfer(sender, toNano("0.3"), {
amount: BigInt(offerAmount),
destination: offerVault.address,
responseAddress: contractMyWallet.address,
forwardAmount: toNano("0.01"),
queryId,
forwardPayload: VaultJetton.createSwapPayload({
poolAddress: TON_JETTON.address,
// limit: minimalAmountOut,
next: {
poolAddress: JETTON_TON.address,
},
}),
},)
}
// async swap(userId: number, accountIndex: number, offerJettonAddress: string, askJettonAddress: string, queryId: string, offerAmount: string) {
// const client = new TonClient4({
// endpoint: 'https://mainnet-v4.tonhubapi.com',
// });
// let workchain = 0;
// let keys = await this.walletService.TONKeyPair({ userId, accountIndex })
// let wallet = WalletContractV3R1.create({ workchain, publicKey: keys.publicKey });
// let contractMyWallet = client.open(wallet);
// const sender = contractMyWallet.sender(keys.secretKey);
// const TON = Asset.native();
// // ======================================================================
// const factory = client.open(Factory.createFromAddress(MAINNET_FACTORY_ADDR));
// const tonVault = client.open(await factory.getNativeVault());
// // =====================================================================
// if ((await tonVault.getReadinessStatus()) !== ReadinessStatus.READY) {
// throw new Error('Vault (TON) does not exist.');
// }
// // =====================================================================
// if (zeroTONtopTON(offerJettonAddress) === PROXY_TON) {
// console.log('TON > Jettton')
// const JETTON = Asset.jetton(Address.parse(askJettonAddress));
// const TON_JETTON = client.open(await factory.getPool(PoolType.VOLATILE, [TON, JETTON]));
// if ((await TON_JETTON.getReadinessStatus()) !== ReadinessStatus.READY) {
// throw new Error('Pool (TON, SCALE) does not exist.');
// }
// try {
// await tonVault.sendSwap(sender, {
// poolAddress: TON_JETTON.address,
// amount: toNano(offerAmount),
// gasAmount: toNano("0.25"),
// });
// } catch (error) {
// console.log(error)
// }
// } else if (zeroTONtopTON(askJettonAddress) === PROXY_TON) {
// console.log('Jettton > TON')
// const jettonRoot = client.open(JettonRoot.createFromAddress(Address.parse(offerJettonAddress)));
// const jettonWallet = client.open(await jettonRoot.getWallet(contractMyWallet.address));
// const jettonVault = client.open(await factory.getJettonVault(Address.parse(offerJettonAddress)));
// const JETTON = Asset.jetton(Address.parse(offerJettonAddress));
// const JETTON_TON = client.open(await factory.getPool(PoolType.VOLATILE, [JETTON, TON]));
// if ((await JETTON_TON.getReadinessStatus()) !== ReadinessStatus.READY) {
// throw new Error('Pool (TON, SCALE) does not exist.');
// }
// try {
// await jettonWallet.sendTransfer(sender, toNano("0.3"), {
// amount: toNano(offerAmount),
// destination: jettonVault.address,
// responseAddress: contractMyWallet.address,
// forwardAmount: toNano("0.2"),
// forwardPayload: VaultJetton.createSwapPayload({ poolAddress: JETTON_TON.address }),
// });
// } catch (error) {
// console.log(error)
// }
// } else {
// console.log('Jettton -> Jettton')
// const offerRoot = client.open(JettonRoot.createFromAddress(Address.parse(offerJettonAddress)));
// const offerWallet = client.open(await offerRoot.getWallet(contractMyWallet.address));
// const offerVault = client.open(await factory.getJettonVault(Address.parse(offerJettonAddress)));
// const OFFER_JETTON = Asset.jetton(Address.parse(offerJettonAddress));
// const ASK_JETTON = Asset.jetton(Address.parse(askJettonAddress));
// const TON_JETTON = client.open(await factory.getPool(PoolType.VOLATILE, [TON, OFFER_JETTON]));
// if ((await TON_JETTON.getReadinessStatus()) !== ReadinessStatus.READY) {
// throw new Error('Pool (TON, SCALE) does not exist.');
// }
// const JETTON_TON = client.open(await factory.getPool(PoolType.VOLATILE, [TON, ASK_JETTON]));
// if ((await JETTON_TON.getReadinessStatus()) !== ReadinessStatus.READY) {
// throw new Error('Pool (TON, SCALE) does not exist.');
// }
// try {
// await offerWallet.sendTransfer(sender, toNano("0.3"), {
// amount: toNano(offerAmount),
// destination: offerVault.address,
// responseAddress: contractMyWallet.address,
// forwardAmount: toNano("0.25"),
// forwardPayload: VaultJetton.createSwapPayload({
// poolAddress: TON_JETTON.address,
// // limit: minimalAmountOut,
// next: {
// poolAddress: JETTON_TON.address,
// },
// }),
// },)
// } catch (error) {
// console.log(error)
// }
// }
// }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment