|
|
@@ -4,6 +4,7 @@ import { Wallet, Provider, utils } from 'zksync-web3'
|
|
|
import { ConfigType } from '@nestjs/config'
|
|
|
import { AccountsService } from '../accounts/accounts.service'
|
|
|
import erc20 from './erc20.json'
|
|
|
+import { web3Config } from './web3config'
|
|
|
import {
|
|
|
ChainId,
|
|
|
initialChainTable,
|
|
|
@@ -32,58 +33,26 @@ import {
|
|
|
getWithdrawLiquidityValue
|
|
|
} from 'iziswap-sdk/lib/liquidityManager'
|
|
|
import { getPoolContract, getPoolState, getPointDelta } from 'iziswap-sdk/lib/pool'
|
|
|
-import { getQuoterContract, quoterSwapChainWithExactOutput } from 'iziswap-sdk/lib/quoter'
|
|
|
-import { getSwapContract, getSwapChainWithExactOutputCall } from 'iziswap-sdk/lib/swap'
|
|
|
+import {
|
|
|
+ getQuoterContract,
|
|
|
+ quoterSwapChainWithExactOutput,
|
|
|
+ quoterSwapChainWithExactInput
|
|
|
+} from 'iziswap-sdk/lib/quoter'
|
|
|
+import { getSwapContract, getSwapChainWithExactOutputCall, getSwapChainWithExactInputCall } from 'iziswap-sdk/lib/swap'
|
|
|
import mintSquareAbi from './mintSquareAbi.json'
|
|
|
import { Network } from './network.enum'
|
|
|
+import { Cron } from '@nestjs/schedule'
|
|
|
|
|
|
@Injectable()
|
|
|
export class Web3Service {
|
|
|
- config: { [key: string]: Web3Config } = {
|
|
|
- testnet: {
|
|
|
- ethereumNetwork: 'goerli',
|
|
|
- ethereumExplorer: 'https://goerli.etherscan.io',
|
|
|
- infuraApiKey: '6e36ce031e304b79af723a0a28789083',
|
|
|
- zksyncRpcUrl: 'https://testnet.era.zksync.dev',
|
|
|
- zksyncChainId: 280,
|
|
|
- zksyncExplorer: 'https://goerli.explorer.zksync.io',
|
|
|
- liquidityManagerAddress: '0x25727b360604E1e6B440c3B25aF368F54fc580B6',
|
|
|
- tokenAddress: '0x0faF6df7054946141266420b43783387A78d82A9',
|
|
|
- quoterAddress: '0xE93D1d35a63f7C6b51ef46a27434375761a7Db28',
|
|
|
- swapAddress: '0x3040EE148D09e5B92956a64CDC78b49f48C0cDdc',
|
|
|
- mintAddress: '0x74E6d686F70fD5829f00dB0F95EC0f153970baD3',
|
|
|
- orbiterEthAddress: '0x0043d60e87c5dd08C86C3123340705a1556C4719',
|
|
|
- orbiterEthId: 9514,
|
|
|
- orbiterZkAddress: '0x0043d60e87c5dd08C86C3123340705a1556C4719',
|
|
|
- orbiterZkId: 9005
|
|
|
- },
|
|
|
- mainnet: {
|
|
|
- ethereumNetwork: 'mainnet',
|
|
|
- ethereumExplorer: 'https://etherscan.io',
|
|
|
- infuraApiKey: '6e36ce031e304b79af723a0a28789083',
|
|
|
- zksyncRpcUrl: 'https://mainnet.era.zksync.io',
|
|
|
- zksyncChainId: 324,
|
|
|
- zksyncExplorer: 'https://explorer.zksync.io/',
|
|
|
- liquidityManagerAddress: '0x936c9A1B8f88BFDbd5066ad08e5d773BC82EB15F',
|
|
|
- tokenAddress: '0x3355df6D4c9C3035724Fd0e3914dE96A5a83aaf4',
|
|
|
- quoterAddress: '0x377EC7c9ae5a0787F384668788a1654249059dD6',
|
|
|
- swapAddress: '0x9606eC131EeC0F84c95D82c9a63959F2331cF2aC',
|
|
|
- mintAddress: '0x53eC17BD635F7A54B3551E76Fd53Db8881028fC3',
|
|
|
- orbiterEthAddress: '0xE4eDb277e41dc89aB076a1F049f4a3EfA700bCE8',
|
|
|
- orbiterEthId: 9014,
|
|
|
- orbiterZkAddress: '0xE4eDb277e41dc89aB076a1F049f4a3EfA700bCE8',
|
|
|
- orbiterZkId: 9005
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
constructor(private readonly accountService: AccountsService) {}
|
|
|
|
|
|
async zkDeposit(accountId, amount, network: Network) {
|
|
|
const account = await this.accountService.findById(accountId)
|
|
|
- const provider = new Provider(this.config[network].zksyncRpcUrl)
|
|
|
+ const provider = new Provider(web3Config[network].zksyncRpcUrl)
|
|
|
const ethProvider = new ethers.providers.InfuraProvider(
|
|
|
- this.config[network].ethereumNetwork,
|
|
|
- this.config[network].infuraApiKey
|
|
|
+ web3Config[network].ethereumNetwork,
|
|
|
+ web3Config[network].infuraApiKey
|
|
|
)
|
|
|
const wallet = new Wallet(account.privateKey, provider, ethProvider)
|
|
|
const deposit = await wallet.deposit({
|
|
|
@@ -111,17 +80,17 @@ export class Web3Service {
|
|
|
|
|
|
async zkWithdraw(accountId, amount, network: Network) {
|
|
|
const account = await this.accountService.findById(accountId)
|
|
|
- const provider = new Provider(this.config[network].zksyncRpcUrl)
|
|
|
+ const provider = new Provider(web3Config[network].zksyncRpcUrl)
|
|
|
const ethProvider = new ethers.providers.InfuraProvider(
|
|
|
- this.config[network].ethereumNetwork,
|
|
|
- this.config[network].infuraApiKey
|
|
|
+ web3Config[network].ethereumNetwork,
|
|
|
+ web3Config[network].infuraApiKey
|
|
|
)
|
|
|
const wallet = new Wallet(account.privateKey, provider, ethProvider)
|
|
|
const withdrawL2 = await wallet.withdraw({
|
|
|
token: utils.ETH_ADDRESS,
|
|
|
amount: ethers.utils.parseEther(amount)
|
|
|
})
|
|
|
- Logger.log(`Widthdraw sent. ${this.config[network].zksyncExplorer}/tx/${withdrawL2.hash}`)
|
|
|
+ Logger.log(`Widthdraw sent. ${web3Config[network].zksyncExplorer}/tx/${withdrawL2.hash}`)
|
|
|
// // Await processing of the deposit on L1
|
|
|
// const ethereumTxReceipt = await deposit.waitL1Commit()
|
|
|
|
|
|
@@ -143,14 +112,14 @@ export class Web3Service {
|
|
|
async orbiterDeposit(accountId, amount, network: Network) {
|
|
|
const account = await this.accountService.findById(accountId)
|
|
|
const provider = new ethers.providers.InfuraProvider(
|
|
|
- this.config[network].ethereumNetwork,
|
|
|
- this.config[network].infuraApiKey
|
|
|
+ web3Config[network].ethereumNetwork,
|
|
|
+ web3Config[network].infuraApiKey
|
|
|
)
|
|
|
const wallet = new ethers.Wallet(account.privateKey, provider)
|
|
|
const tx = await wallet.sendTransaction({
|
|
|
from: wallet.address,
|
|
|
- to: this.config[network].orbiterEthAddress,
|
|
|
- value: ethers.utils.parseEther(amount).add(this.config[network].orbiterEthId)
|
|
|
+ to: web3Config[network].orbiterEthAddress,
|
|
|
+ value: ethers.utils.parseEther(amount).add(web3Config[network].orbiterIdCodeZk)
|
|
|
})
|
|
|
console.log('Mining transaction...')
|
|
|
// Waiting for the transaction to be mined
|
|
|
@@ -163,26 +132,26 @@ export class Web3Service {
|
|
|
}
|
|
|
|
|
|
async addLiquidity(accountId, amount, network: Network) {
|
|
|
- const chainId = this.config[network].ethereumNetwork == 'goerli' ? ChainId.ZkSyncAlphaTest : ChainId.ZkSyncEra
|
|
|
+ const chainId = web3Config[network].ethereumNetwork == 'goerli' ? ChainId.ZkSyncAlphaTest : ChainId.ZkSyncEra
|
|
|
const account = await this.accountService.findById(accountId)
|
|
|
- const provider = new Provider(this.config[network].zksyncRpcUrl)
|
|
|
+ const provider = new Provider(web3Config[network].zksyncRpcUrl)
|
|
|
const zkWallet = new Wallet(account.privateKey).connect(provider)
|
|
|
const chain = initialChainTable[chainId]
|
|
|
- const web3 = new Web3(new Web3.providers.HttpProvider(this.config[network].zksyncRpcUrl))
|
|
|
+ const web3 = new Web3(new Web3.providers.HttpProvider(web3Config[network].zksyncRpcUrl))
|
|
|
console.log('address: ', zkWallet.address)
|
|
|
|
|
|
const liquidityManagerContract = getLiquidityManagerContract(
|
|
|
- this.config[network].liquidityManagerAddress,
|
|
|
+ web3Config[network].liquidityManagerAddress,
|
|
|
web3 as any
|
|
|
)
|
|
|
- console.log('liquidity manager address: ', this.config[network].liquidityManagerAddress)
|
|
|
+ console.log('liquidity manager address: ', web3Config[network].liquidityManagerAddress)
|
|
|
|
|
|
const tokenA = getGasToken(chainId)
|
|
|
console.log('tokenA: ', tokenA)
|
|
|
- const tokenB = await fetchToken(this.config[network].tokenAddress, chain, web3 as any)
|
|
|
+ const tokenB = await fetchToken(web3Config[network].zkUsdcAddress, chain, web3 as any)
|
|
|
console.log('tokenB: ', tokenB)
|
|
|
|
|
|
- await this.approve(tokenB.address, this.config[network].liquidityManagerAddress, zkWallet, network)
|
|
|
+ await this.approve(tokenB.address, web3Config[network].liquidityManagerAddress, zkWallet, network)
|
|
|
|
|
|
const fee = 2000 // 2000 means 0.2%
|
|
|
const poolAddress = await getPoolAddress(liquidityManagerContract, tokenA, tokenB, fee)
|
|
|
@@ -247,7 +216,7 @@ export class Web3Service {
|
|
|
const tx = await zkWallet.sendTransaction({
|
|
|
from: options.from,
|
|
|
value: Web3.utils.numberToHex(options.value),
|
|
|
- to: this.config[network].liquidityManagerAddress,
|
|
|
+ to: web3Config[network].liquidityManagerAddress,
|
|
|
data: calling.encodeABI(),
|
|
|
gasLimit
|
|
|
})
|
|
|
@@ -255,21 +224,21 @@ export class Web3Service {
|
|
|
}
|
|
|
|
|
|
async removeLiquidity(accountId, network: Network) {
|
|
|
- const chainId = this.config[network].ethereumNetwork == 'goerli' ? ChainId.ZkSyncAlphaTest : ChainId.ZkSyncEra
|
|
|
+ const chainId = web3Config[network].ethereumNetwork == 'goerli' ? ChainId.ZkSyncAlphaTest : ChainId.ZkSyncEra
|
|
|
const account = await this.accountService.findById(accountId)
|
|
|
- const provider = new Provider(this.config[network].zksyncRpcUrl)
|
|
|
+ const provider = new Provider(web3Config[network].zksyncRpcUrl)
|
|
|
const wallet = new Wallet(account.privateKey).connect(provider)
|
|
|
const chain = initialChainTable[chainId]
|
|
|
- const web3 = new Web3(new Web3.providers.HttpProvider(this.config[network].zksyncRpcUrl))
|
|
|
+ const web3 = new Web3(new Web3.providers.HttpProvider(web3Config[network].zksyncRpcUrl))
|
|
|
|
|
|
const liquidityManagerContract = getLiquidityManagerContract(
|
|
|
- this.config[network].liquidityManagerAddress,
|
|
|
+ web3Config[network].liquidityManagerAddress,
|
|
|
web3 as any
|
|
|
)
|
|
|
- Logger.log('liquidity manager address: ', this.config[network].liquidityManagerAddress)
|
|
|
+ Logger.log('liquidity manager address: ', web3Config[network].liquidityManagerAddress)
|
|
|
|
|
|
const tokenA = getGasToken(chainId)
|
|
|
- const tokenB = await fetchToken(this.config[network].tokenAddress, chain, web3 as any)
|
|
|
+ const tokenB = await fetchToken(web3Config[network].zkUsdcAddress, chain, web3 as any)
|
|
|
|
|
|
Logger.log(`tokenA: ${tokenA.symbol} tokenB: ${tokenB.symbol}`, 'FetchLiquidities')
|
|
|
const liquidities = await fetchLiquiditiesOfAccount(
|
|
|
@@ -314,7 +283,7 @@ export class Web3Service {
|
|
|
console.log('gas limit: ', gasLimit)
|
|
|
const tx0 = await wallet.sendTransaction({
|
|
|
from: wallet.address,
|
|
|
- to: this.config[network].liquidityManagerAddress,
|
|
|
+ to: web3Config[network].liquidityManagerAddress,
|
|
|
data: decLiquidityCalling.encodeABI(),
|
|
|
gasLimit
|
|
|
})
|
|
|
@@ -322,7 +291,7 @@ export class Web3Service {
|
|
|
}
|
|
|
|
|
|
async allowance(tokenAddress, spender, wallet: Wallet, network: Network): Promise<number> {
|
|
|
- const web3 = new Web3(new Web3.providers.HttpProvider(this.config[network].zksyncRpcUrl))
|
|
|
+ const web3 = new Web3(new Web3.providers.HttpProvider(web3Config[network].zksyncRpcUrl))
|
|
|
const tokenAContract = new web3.eth.Contract(erc20, tokenAddress)
|
|
|
// @ts-ignore
|
|
|
const allowanceCalling = tokenAContract.methods.allowance(wallet.address, spender)
|
|
|
@@ -336,7 +305,7 @@ export class Web3Service {
|
|
|
if (allowance > 0) {
|
|
|
return
|
|
|
}
|
|
|
- const web3 = new Web3(new Web3.providers.HttpProvider(this.config[network].zksyncRpcUrl))
|
|
|
+ const web3 = new Web3(new Web3.providers.HttpProvider(web3Config[network].zksyncRpcUrl))
|
|
|
const tokenAContract = new web3.eth.Contract(erc20, tokenAddress)
|
|
|
// @ts-ignore
|
|
|
const approveCalling = tokenAContract.methods.approve(spender, '0xffffffffffffffffffffffffffffffff')
|
|
|
@@ -354,11 +323,11 @@ export class Web3Service {
|
|
|
|
|
|
async swapWithExactOutput(accountId, amount, network: Network) {
|
|
|
const account = await this.accountService.findById(accountId)
|
|
|
- const chainId = this.config[network].ethereumNetwork == 'goerli' ? ChainId.ZkSyncAlphaTest : ChainId.ZkSyncEra
|
|
|
+ const chainId = web3Config[network].ethereumNetwork == 'goerli' ? ChainId.ZkSyncAlphaTest : ChainId.ZkSyncEra
|
|
|
const chain = initialChainTable[chainId]
|
|
|
- const provider = new Provider(this.config[network].zksyncRpcUrl)
|
|
|
+ const provider = new Provider(web3Config[network].zksyncRpcUrl)
|
|
|
const wallet = new Wallet(account.privateKey).connect(provider)
|
|
|
- const web3 = new Web3(new Web3.providers.HttpProvider(this.config[network].zksyncRpcUrl))
|
|
|
+ const web3 = new Web3(new Web3.providers.HttpProvider(web3Config[network].zksyncRpcUrl))
|
|
|
console.log('address: ', wallet.address)
|
|
|
|
|
|
const balance = await web3.eth.getBalance(wallet.address)
|
|
|
@@ -366,7 +335,7 @@ export class Web3Service {
|
|
|
|
|
|
const fromToken = getGasToken(chainId)
|
|
|
console.log('fromToken: ', fromToken)
|
|
|
- const toToken = await fetchToken(this.config[network].tokenAddress, chain, web3 as any)
|
|
|
+ const toToken = await fetchToken(web3Config[network].zkUsdcAddress, chain, web3 as any)
|
|
|
console.log('toToken: ', toToken)
|
|
|
const fee = 2000 // 2000 means 0.2%
|
|
|
|
|
|
@@ -375,7 +344,7 @@ export class Web3Service {
|
|
|
const toTokenBalance = await toTokenContract.methods.balanceOf(wallet.address).call()
|
|
|
console.log(toToken.symbol + ' balance: ' + amount2Decimal(new BigNumber(toTokenBalance), toToken))
|
|
|
|
|
|
- const quoterContract = getQuoterContract(this.config[network].quoterAddress, web3 as any)
|
|
|
+ const quoterContract = getQuoterContract(web3Config[network].quoterAddress, web3 as any)
|
|
|
|
|
|
const receiveAmount = new BigNumber(amount).times(10 ** toToken.decimal)
|
|
|
|
|
|
@@ -394,7 +363,7 @@ export class Web3Service {
|
|
|
console.log(toToken.symbol + ' to desired: ', amount)
|
|
|
console.log(fromToken.symbol + ' to pay: ', payAmountDecimal)
|
|
|
|
|
|
- const swapContract = getSwapContract(this.config[network].swapAddress, web3 as any)
|
|
|
+ const swapContract = getSwapContract(web3Config[network].swapAddress, web3 as any)
|
|
|
|
|
|
const swapParams = {
|
|
|
...params,
|
|
|
@@ -417,30 +386,93 @@ export class Web3Service {
|
|
|
|
|
|
const tx = await wallet.sendTransaction({
|
|
|
value: Web3.utils.numberToHex(options.value),
|
|
|
- data: swapCalling.arguments[0][0],
|
|
|
- to: this.config[network].swapAddress,
|
|
|
+ data: swapCalling.encodeABI(),
|
|
|
+ to: web3Config[network].swapAddress,
|
|
|
gasLimit
|
|
|
})
|
|
|
console.log(tx)
|
|
|
}
|
|
|
|
|
|
+ async swapWithExactInput(accountId, amount, network: Network) {
|
|
|
+ const account = await this.accountService.findById(accountId)
|
|
|
+ const chainId = web3Config[network].ethereumNetwork == 'goerli' ? ChainId.ZkSyncAlphaTest : ChainId.ZkSyncEra
|
|
|
+ const chain = initialChainTable[chainId]
|
|
|
+ const provider = new Provider(web3Config[network].zksyncRpcUrl)
|
|
|
+ const wallet = new Wallet(account.privateKey).connect(provider)
|
|
|
+ const web3 = new Web3(new Web3.providers.HttpProvider(web3Config[network].zksyncRpcUrl))
|
|
|
+ console.log('address: ', wallet.address)
|
|
|
+
|
|
|
+ const fromToken = await fetchToken(web3Config[network].zkUsdcAddress, chain, web3 as any)
|
|
|
+ console.log('fromToken: ', fromToken)
|
|
|
+ const toToken = getGasToken(chainId)
|
|
|
+ console.log('toToken: ', toToken)
|
|
|
+
|
|
|
+ await this.approve(fromToken.address, web3Config[network].swapAddress, wallet, network)
|
|
|
+
|
|
|
+ const quoterContract = getQuoterContract(web3Config[network].quoterAddress, web3 as any)
|
|
|
+
|
|
|
+ const payAmount = new BigNumber(amount).times(10 ** fromToken.decimal)
|
|
|
+ const fee = 2000 // 2000 means 0.2%
|
|
|
+ const params = {
|
|
|
+ // pay testA to buy testB
|
|
|
+ tokenChain: [fromToken, toToken],
|
|
|
+ feeChain: [fee],
|
|
|
+ inputAmount: payAmount.toFixed(0)
|
|
|
+ }
|
|
|
+
|
|
|
+ const { outputAmount } = await quoterSwapChainWithExactInput(quoterContract, params)
|
|
|
+
|
|
|
+ const receiveAmount = outputAmount
|
|
|
+ const receiveAmountDecimal = amount2Decimal(new BigNumber(receiveAmount), toToken)
|
|
|
+
|
|
|
+ console.log(fromToken.symbol + ' to pay: ', amount)
|
|
|
+ console.log(toToken.symbol + ' to acquire: ', receiveAmountDecimal)
|
|
|
+
|
|
|
+ const swapContract = getSwapContract(web3Config[network].swapAddress, web3 as any)
|
|
|
+
|
|
|
+ const swapParams = {
|
|
|
+ ...params,
|
|
|
+ // slippery is 1.5%
|
|
|
+ minOutputAmount: new BigNumber(receiveAmount).times(0.985).toFixed(0),
|
|
|
+ strictERC20Token: false
|
|
|
+ }
|
|
|
+
|
|
|
+ const gasPrice = await web3.eth.getGasPrice()
|
|
|
+ const { swapCalling, options } = getSwapChainWithExactInputCall(
|
|
|
+ swapContract,
|
|
|
+ account.address,
|
|
|
+ chain,
|
|
|
+ swapParams,
|
|
|
+ gasPrice.toString()
|
|
|
+ )
|
|
|
+ const gasLimit = await swapCalling.estimateGas(options)
|
|
|
+ console.log('gas limit: ', gasLimit)
|
|
|
+ const tx = await wallet.sendTransaction({
|
|
|
+ value: Web3.utils.numberToHex(options.value),
|
|
|
+ data: swapCalling.encodeABI(),
|
|
|
+ to: web3Config[network].swapAddress,
|
|
|
+ gasLimit
|
|
|
+ })
|
|
|
+ console.log(JSON.stringify(tx, null, 4))
|
|
|
+ }
|
|
|
+
|
|
|
async mint(accountId, network: Network) {
|
|
|
const account = await this.accountService.findById(accountId)
|
|
|
- const chainId = this.config[network].ethereumNetwork == 'goerli' ? ChainId.ZkSyncAlphaTest : ChainId.ZkSyncEra
|
|
|
+ const chainId = web3Config[network].ethereumNetwork == 'goerli' ? ChainId.ZkSyncAlphaTest : ChainId.ZkSyncEra
|
|
|
const chain = initialChainTable[chainId]
|
|
|
- const provider = new Provider(this.config[network].zksyncRpcUrl)
|
|
|
+ const provider = new Provider(web3Config[network].zksyncRpcUrl)
|
|
|
const wallet = new Wallet(account.privateKey).connect(provider)
|
|
|
- const web3 = new Web3(new Web3.providers.HttpProvider(this.config[network].zksyncRpcUrl))
|
|
|
+ const web3 = new Web3(new Web3.providers.HttpProvider(web3Config[network].zksyncRpcUrl))
|
|
|
console.log('address: ', wallet.address)
|
|
|
|
|
|
- const contract = new web3.eth.Contract(mintSquareAbi, this.config[network].mintAddress, web3 as any)
|
|
|
+ const contract = new web3.eth.Contract(mintSquareAbi, web3Config[network].mintAddress, web3 as any)
|
|
|
// @ts-ignore
|
|
|
const mintCall = await contract.methods.mint('ipfs://QmPxcRPvjMDrv7d4WjQK5KNXkuXudGhKjPTDnzuFkRQ6Fs')
|
|
|
const gasLimit = await mintCall.estimateGas({ from: wallet.address })
|
|
|
console.log('gas limit: ', gasLimit)
|
|
|
const tx = await wallet.sendTransaction({
|
|
|
from: wallet.address,
|
|
|
- to: this.config[network].mintAddress,
|
|
|
+ to: web3Config[network].mintAddress,
|
|
|
data: mintCall.encodeABI(),
|
|
|
gasLimit
|
|
|
})
|