Created
April 7, 2024 14:10
-
-
Save satanworker/7be5914dcd8276197c1cef7297a2f574 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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