diff --git a/scripts/package-lock.json b/scripts/package-lock.json index 64168032..07eb4db5 100644 --- a/scripts/package-lock.json +++ b/scripts/package-lock.json @@ -18,10 +18,10 @@ }, "../sdk": { "name": "@invariant-labs/a0-sdk", - "version": "0.2.21", + "version": "0.2.24", "license": "ISC", "dependencies": { - "@invariant-labs/a0-sdk-wasm": "0.1.24", + "@invariant-labs/a0-sdk-wasm": "0.1.26", "@polkadot/api": "^10.12.4", "@polkadot/api-contract": "^10.12.4", "@scio-labs/use-inkathon": "^0.6.3", @@ -56,9 +56,9 @@ } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/scripts/package.json b/scripts/package.json index b4049550..f14d7788 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -13,8 +13,9 @@ "create-pool": "npx tsc && node --experimental-wasm-modules target/create-pool.js", "query-tickmap": "npx tsc && node --experimental-wasm-modules target/query-tickmap.js", "swap": "npx tsc && node --experimental-wasm-modules target/swap.js", - "setup": "npx tsc && node --experimental-wasm-modules target/setup.js", "replace-code": "npx tsc && node --experimental-wasm-modules target/replace-code.js", + "setup-localnet": "npx tsc && node --experimental-wasm-modules target/setup-localnet.js", + "setup-testnet": "npx tsc && node --experimental-wasm-modules target/setup-testnet.js", "setup-mainnet": "npx tsc && node --experimental-wasm-modules target/setup-mainnet.js" }, "keywords": [], diff --git a/scripts/src/setup-localnet.ts b/scripts/src/setup-localnet.ts new file mode 100644 index 00000000..dc5faa12 --- /dev/null +++ b/scripts/src/setup-localnet.ts @@ -0,0 +1,176 @@ +import { + FEE_TIERS, + Invariant, + Keyring, + Network, + PSP22, + PoolKey, + WrappedAZERO, + calculateTick, + getLiquidityByX, + initPolkadotApi, + newPoolKey, + priceToSqrtPrice, + toPercentage +} from '@invariant-labs/a0-sdk' +import dotenv from 'dotenv' + +dotenv.config() + +const main = async () => { + const network = Network.Local + const api = await initPolkadotApi(network) + + const keyring = new Keyring({ type: 'sr25519' }) + const account = keyring.addFromUri('//Alice') + console.log(`Deployer: ${account.address}`) + + const invariant = await Invariant.deploy(api, network, account, toPercentage(1n, 2n)) + const WAZERO = await WrappedAZERO.deploy(api, network, account) + console.log(`Invariant: ${invariant.contract.address.toString()}`) + + for (const feeTier of FEE_TIERS) { + await invariant.addFeeTier(account, feeTier) + } + console.log('Successfully added fee tiers') + + const WAZEROAddress = WAZERO.contract.address.toString() + const BTCAddress = await PSP22.deploy(api, account, 0n, 'Bitcoin', 'BTC', 8n) + const ETHAddress = await PSP22.deploy(api, account, 0n, 'Ether', 'ETH', 18n) + const USDCAddress = await PSP22.deploy(api, account, 0n, 'USDC', 'USDC', 6n) + const USDTAddress = await PSP22.deploy(api, account, 0n, 'Tether USD', 'USDT', 6n) + const SOLAddress = await PSP22.deploy(api, account, 0n, 'Solana', 'SOL', 9n) + const decimals = { + [BTCAddress]: 8n, + [ETHAddress]: 12n, + [USDCAddress]: 6n, + [USDTAddress]: 6n, + [SOLAddress]: 9n, + [WAZEROAddress]: 12n + } + console.log( + `BTC: ${BTCAddress}, ETH: ${ETHAddress}, USDC: ${USDCAddress}, USDT: ${USDTAddress}, SOL: ${SOLAddress}` + ) + + const response = await fetch( + 'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&ids=bitcoin,ethereum,aleph-zero,solana' + ) + const data = await response.json() + const prices = { + [BTCAddress]: data.find((coin: any) => coin.id === 'bitcoin').current_price, + [ETHAddress]: data.find((coin: any) => coin.id === 'ethereum').current_price, + [USDCAddress]: 1, + [USDTAddress]: 1, + [SOLAddress]: data.find((coin: any) => coin.id === 'solana').current_price, + [WAZEROAddress]: data.find((coin: any) => coin.id === 'aleph-zero').current_price + } + console.log( + `BTC: ${prices[BTCAddress]}, ETH: ${prices[ETHAddress]}, USDC: ${prices[USDCAddress]}, USDT: ${prices[USDTAddress]}, SOL: ${prices[SOLAddress]}, AZERO: ${prices[WAZEROAddress]}` + ) + + const poolKeys: PoolKey[] = [ + newPoolKey(WAZEROAddress, BTCAddress, FEE_TIERS[1]), + newPoolKey(WAZEROAddress, ETHAddress, FEE_TIERS[1]), + newPoolKey(WAZEROAddress, USDCAddress, FEE_TIERS[1]), + newPoolKey(WAZEROAddress, USDTAddress, FEE_TIERS[1]), + newPoolKey(WAZEROAddress, SOLAddress, FEE_TIERS[1]), + newPoolKey(BTCAddress, ETHAddress, FEE_TIERS[1]), + newPoolKey(BTCAddress, USDCAddress, FEE_TIERS[1]), + newPoolKey(BTCAddress, USDTAddress, FEE_TIERS[1]), + newPoolKey(BTCAddress, SOLAddress, FEE_TIERS[1]), + newPoolKey(ETHAddress, USDCAddress, FEE_TIERS[1]), + newPoolKey(ETHAddress, USDTAddress, FEE_TIERS[1]), + newPoolKey(ETHAddress, SOLAddress, FEE_TIERS[1]), + newPoolKey(USDCAddress, USDTAddress, FEE_TIERS[1]), + newPoolKey(USDCAddress, SOLAddress, FEE_TIERS[1]), + newPoolKey(USDTAddress, SOLAddress, FEE_TIERS[1]) + ] + for (const poolKey of poolKeys) { + const price = + (1 / (prices[poolKey.tokenY] / prices[poolKey.tokenX])) * + 10 ** (Number(decimals[poolKey.tokenY]) - Number(decimals[poolKey.tokenX])) * + 10 ** 24 + try { + const poolSqrtPrice = priceToSqrtPrice(BigInt(Math.round(price))) + await invariant.createPool(account, poolKey, poolSqrtPrice) + } catch (e) { + console.log('Create pool error', poolKey, e) + } + } + console.log('Successfully added pools') + + const psp22 = await PSP22.load(api, network) + await psp22.mint(account, 2n ** 96n - 1n, BTCAddress) + await psp22.mint(account, 2n ** 96n - 1n, ETHAddress) + await psp22.mint(account, 2n ** 96n - 1n, USDCAddress) + await psp22.mint(account, 2n ** 96n - 1n, USDTAddress) + await psp22.mint(account, 2n ** 96n - 1n, SOLAddress) + await psp22.approve(account, invariant.contract.address.toString(), 2n ** 96n - 1n, BTCAddress) + await psp22.approve(account, invariant.contract.address.toString(), 2n ** 96n - 1n, ETHAddress) + await psp22.approve(account, invariant.contract.address.toString(), 2n ** 96n - 1n, USDCAddress) + await psp22.approve(account, invariant.contract.address.toString(), 2n ** 96n - 1n, USDTAddress) + await psp22.approve(account, invariant.contract.address.toString(), 2n ** 96n - 1n, SOLAddress) + const wazero = await WrappedAZERO.load(api, network, WAZEROAddress) + const wazeroBalance = await wazero.balanceOf(account.address) + await wazero.withdraw(account, wazeroBalance) + await wazero.deposit(account, 100000n * 10n ** 12n) + await psp22.approve(account, invariant.contract.address.toString(), 2n ** 96n - 1n, WAZEROAddress) + const BTCBefore = await psp22.balanceOf(account.address, BTCAddress) + const ETHBefore = await psp22.balanceOf(account.address, ETHAddress) + const USDCBefore = await psp22.balanceOf(account.address, USDCAddress) + const USDTBefore = await psp22.balanceOf(account.address, USDTAddress) + const SOLBefore = await psp22.balanceOf(account.address, SOLAddress) + const WAZEROBefore = await psp22.balanceOf(account.address, WAZEROAddress) + for (const poolKey of poolKeys) { + const price = + (1 / (prices[poolKey.tokenY] / prices[poolKey.tokenX])) * + 10 ** (Number(decimals[poolKey.tokenY]) - Number(decimals[poolKey.tokenX])) * + 10 ** 24 + const lowerSqrtPrice = priceToSqrtPrice(BigInt(Math.round(price * 0.95))) + const upperSqrtPrice = priceToSqrtPrice(BigInt(Math.round(price * 1.05))) + const poolSqrtPrice = priceToSqrtPrice(BigInt(Math.round(price))) + try { + const lowerTick = calculateTick(lowerSqrtPrice, FEE_TIERS[1].tickSpacing) + const upperTick = calculateTick(upperSqrtPrice, FEE_TIERS[1].tickSpacing) + const tokenXAmount = BigInt( + Math.round((5000 / prices[poolKey.tokenX]) * 10 ** Number(decimals[poolKey.tokenX])) + ) + const { l: liquidity } = getLiquidityByX( + tokenXAmount, + lowerTick, + upperTick, + poolSqrtPrice, + true + ) + await invariant.createPosition( + account, + poolKey, + lowerTick, + upperTick, + liquidity, + poolSqrtPrice, + 0n + ) + } catch (e) { + console.log('Create position error', poolKey, e) + } + } + const BTCAfter = await psp22.balanceOf(account.address, BTCAddress) + const ETHAfter = await psp22.balanceOf(account.address, ETHAddress) + const USDCAfter = await psp22.balanceOf(account.address, USDCAddress) + const USDTAfter = await psp22.balanceOf(account.address, USDTAddress) + const SOLAfter = await psp22.balanceOf(account.address, SOLAddress) + const WAZEROAfter = await psp22.balanceOf(account.address, WAZEROAddress) + console.log( + `BTC: ${BTCBefore - BTCAfter}, ETH: ${ETHBefore - ETHAfter}, USDC: ${ + USDCBefore - USDCAfter + }, USDT: ${USDTBefore - USDTAfter}, SOL: ${SOLBefore - SOLAfter}, AZERO: ${ + WAZEROBefore - WAZEROAfter + }` + ) + console.log('Successfully created positions') + + process.exit(0) +} + +main() diff --git a/scripts/src/setup-mainnet.ts b/scripts/src/setup-mainnet.ts index 84aaf40a..011f23ef 100644 --- a/scripts/src/setup-mainnet.ts +++ b/scripts/src/setup-mainnet.ts @@ -6,6 +6,7 @@ import { PSP22, PoolKey, calculateTick, + getLiquidityByX, initPolkadotApi, newPoolKey, priceToSqrtPrice, @@ -67,19 +68,19 @@ const main = async () => { `BTC: ${prices[BTCAddress]}, ETH: ${prices[ETHAddress]}, USDC: ${prices[USDCAddress]}, USDT: ${prices[USDTAddress]}, SOL: ${prices[SOLAddress]}` ) - const poolKeys: [PoolKey, bigint][] = [ - [newPoolKey(BTCAddress, ETHAddress, FEE_TIERS[1]), 130559235944405760n], - [newPoolKey(BTCAddress, USDCAddress, FEE_TIERS[1]), 7865049221247086n], - [newPoolKey(BTCAddress, USDTAddress, FEE_TIERS[1]), 7865049221247086n], - [newPoolKey(BTCAddress, SOLAddress, FEE_TIERS[1]), 977937074251981n], - [newPoolKey(ETHAddress, USDCAddress, FEE_TIERS[1]), 3454809855596621497n], - [newPoolKey(ETHAddress, USDTAddress, FEE_TIERS[1]), 3454809855596621497n], - [newPoolKey(ETHAddress, SOLAddress, FEE_TIERS[1]), 423131631710393596n], - [newPoolKey(USDCAddress, USDTAddress, FEE_TIERS[1]), 9999818389598293n], - [newPoolKey(USDCAddress, SOLAddress, FEE_TIERS[1]), 24911294718392400n], - [newPoolKey(USDTAddress, SOLAddress, FEE_TIERS[1]), 24911294718392400n] + const poolKeys: PoolKey[] = [ + newPoolKey(BTCAddress, ETHAddress, FEE_TIERS[1]), + newPoolKey(BTCAddress, USDCAddress, FEE_TIERS[1]), + newPoolKey(BTCAddress, USDTAddress, FEE_TIERS[1]), + newPoolKey(BTCAddress, SOLAddress, FEE_TIERS[1]), + newPoolKey(ETHAddress, USDCAddress, FEE_TIERS[1]), + newPoolKey(ETHAddress, USDTAddress, FEE_TIERS[1]), + newPoolKey(ETHAddress, SOLAddress, FEE_TIERS[1]), + newPoolKey(USDCAddress, USDTAddress, FEE_TIERS[1]), + newPoolKey(USDCAddress, SOLAddress, FEE_TIERS[1]), + newPoolKey(USDTAddress, SOLAddress, FEE_TIERS[1]) ] - for (const [poolKey] of poolKeys) { + for (const poolKey of poolKeys) { const price = (1 / (prices[poolKey.tokenY] / prices[poolKey.tokenX])) * 10 ** (Number(decimals[poolKey.tokenY]) - Number(decimals[poolKey.tokenX])) * @@ -114,7 +115,7 @@ const main = async () => { const USDCBefore = await psp22.balanceOf(account.address, USDCAddress) const USDTBefore = await psp22.balanceOf(account.address, USDTAddress) const SOLBefore = await psp22.balanceOf(account.address, SOLAddress) - for (const [poolKey, amount] of poolKeys) { + for (const poolKey of poolKeys) { const price = (1 / (prices[poolKey.tokenY] / prices[poolKey.tokenX])) * 10 ** (Number(decimals[poolKey.tokenY]) - Number(decimals[poolKey.tokenX])) * @@ -125,12 +126,22 @@ const main = async () => { try { const lowerTick = calculateTick(lowerSqrtPrice, FEE_TIERS[1].tickSpacing) const upperTick = calculateTick(upperSqrtPrice, FEE_TIERS[1].tickSpacing) + const tokenXAmount = BigInt( + Math.round((5000 / prices[poolKey.tokenX]) * 10 ** Number(decimals[poolKey.tokenX])) + ) + const { l: liquidity } = getLiquidityByX( + tokenXAmount, + lowerTick, + upperTick, + poolSqrtPrice, + true + ) await invariant.createPosition( account, poolKey, lowerTick, upperTick, - amount, + liquidity, poolSqrtPrice, 0n ) diff --git a/scripts/src/setup.ts b/scripts/src/setup-testnet.ts similarity index 81% rename from scripts/src/setup.ts rename to scripts/src/setup-testnet.ts index 11226348..1a44da38 100644 --- a/scripts/src/setup.ts +++ b/scripts/src/setup-testnet.ts @@ -8,6 +8,7 @@ import { WAZERO_ADDRESS, WrappedAZERO, calculateTick, + getLiquidityByX, initPolkadotApi, newPoolKey, priceToSqrtPrice, @@ -73,24 +74,24 @@ const main = async () => { }, SOL: ${prices[SOLAddress]}, AZERO: ${prices[WAZERO_ADDRESS[network]]}` ) - const poolKeys: [PoolKey, bigint][] = [ - [newPoolKey(WAZERO_ADDRESS[network], BTCAddress, FEE_TIERS[1]), 10804609546189987720n], - [newPoolKey(WAZERO_ADDRESS[network], ETHAddress, FEE_TIERS[1]), 4711830510277394610468n], - [newPoolKey(WAZERO_ADDRESS[network], USDCAddress, FEE_TIERS[1]), 272063075569508447756n], - [newPoolKey(WAZERO_ADDRESS[network], USDTAddress, FEE_TIERS[1]), 272063075569508447756n], - [newPoolKey(WAZERO_ADDRESS[network], SOLAddress, FEE_TIERS[1]), 37143700245489847211n], - [newPoolKey(BTCAddress, ETHAddress, FEE_TIERS[1]), 130559235944405760n], - [newPoolKey(BTCAddress, USDCAddress, FEE_TIERS[1]), 7865049221247086n], - [newPoolKey(BTCAddress, USDTAddress, FEE_TIERS[1]), 7865049221247086n], - [newPoolKey(BTCAddress, SOLAddress, FEE_TIERS[1]), 977937074251981n], - [newPoolKey(ETHAddress, USDCAddress, FEE_TIERS[1]), 3454809855596621497n], - [newPoolKey(ETHAddress, USDTAddress, FEE_TIERS[1]), 3454809855596621497n], - [newPoolKey(ETHAddress, SOLAddress, FEE_TIERS[1]), 423131631710393596n], - [newPoolKey(USDCAddress, USDTAddress, FEE_TIERS[1]), 9999818389598293n], - [newPoolKey(USDCAddress, SOLAddress, FEE_TIERS[1]), 24911294718392400n], - [newPoolKey(USDTAddress, SOLAddress, FEE_TIERS[1]), 24911294718392400n] + const poolKeys: PoolKey[] = [ + newPoolKey(WAZERO_ADDRESS[network], BTCAddress, FEE_TIERS[1]), + newPoolKey(WAZERO_ADDRESS[network], ETHAddress, FEE_TIERS[1]), + newPoolKey(WAZERO_ADDRESS[network], USDCAddress, FEE_TIERS[1]), + newPoolKey(WAZERO_ADDRESS[network], USDTAddress, FEE_TIERS[1]), + newPoolKey(WAZERO_ADDRESS[network], SOLAddress, FEE_TIERS[1]), + newPoolKey(BTCAddress, ETHAddress, FEE_TIERS[1]), + newPoolKey(BTCAddress, USDCAddress, FEE_TIERS[1]), + newPoolKey(BTCAddress, USDTAddress, FEE_TIERS[1]), + newPoolKey(BTCAddress, SOLAddress, FEE_TIERS[1]), + newPoolKey(ETHAddress, USDCAddress, FEE_TIERS[1]), + newPoolKey(ETHAddress, USDTAddress, FEE_TIERS[1]), + newPoolKey(ETHAddress, SOLAddress, FEE_TIERS[1]), + newPoolKey(USDCAddress, USDTAddress, FEE_TIERS[1]), + newPoolKey(USDCAddress, SOLAddress, FEE_TIERS[1]), + newPoolKey(USDTAddress, SOLAddress, FEE_TIERS[1]) ] - for (const [poolKey] of poolKeys) { + for (const poolKey of poolKeys) { const price = (1 / (prices[poolKey.tokenY] / prices[poolKey.tokenX])) * 10 ** (Number(decimals[poolKey.tokenY]) - Number(decimals[poolKey.tokenX])) * @@ -126,7 +127,7 @@ const main = async () => { }) const wazeroBalance = await wazero.balanceOf(account.address) await wazero.withdraw(account, wazeroBalance) - await wazero.deposit(account, 50000n * 10n ** 12n) + await wazero.deposit(account, 100000n * 10n ** 12n) await psp22.approve( account, invariant.contract.address.toString(), @@ -139,7 +140,7 @@ const main = async () => { const USDTBefore = await psp22.balanceOf(account.address, USDTAddress) const SOLBefore = await psp22.balanceOf(account.address, SOLAddress) const WAZEROBefore = await psp22.balanceOf(account.address, WAZERO_ADDRESS[network]) - for (const [poolKey, amount] of poolKeys) { + for (const poolKey of poolKeys) { const price = (1 / (prices[poolKey.tokenY] / prices[poolKey.tokenX])) * 10 ** (Number(decimals[poolKey.tokenY]) - Number(decimals[poolKey.tokenX])) * @@ -150,12 +151,22 @@ const main = async () => { try { const lowerTick = calculateTick(lowerSqrtPrice, FEE_TIERS[1].tickSpacing) const upperTick = calculateTick(upperSqrtPrice, FEE_TIERS[1].tickSpacing) + const tokenXAmount = BigInt( + Math.round((5000 / prices[poolKey.tokenX]) * 10 ** Number(decimals[poolKey.tokenX])) + ) + const { l: liquidity } = getLiquidityByX( + tokenXAmount, + lowerTick, + upperTick, + poolSqrtPrice, + true + ) await invariant.createPosition( account, poolKey, lowerTick, upperTick, - amount, + liquidity, poolSqrtPrice, 0n ) diff --git a/sdk/contracts/invariant/invariant.json b/sdk/contracts/invariant/invariant.json index b70de937..4a3f9bca 100644 --- a/sdk/contracts/invariant/invariant.json +++ b/sdk/contracts/invariant/invariant.json @@ -1,6 +1,6 @@ { "source": { - "hash": "0x499732ce96a694dfd6f72993c4bb75bafe2dea9d5157bbd0859d3bb8d57941c5", + "hash": "0x6535e78f66cf026b69bf940c0439337244baa2e34a6e9059a4730e00f9783811", "language": "ink! 5.0.0", "compiler": "rustc 1.77.0", "build_info": { diff --git a/sdk/contracts/invariant/invariant.wasm b/sdk/contracts/invariant/invariant.wasm index 52d19ff5..ddd1bf3a 100644 Binary files a/sdk/contracts/invariant/invariant.wasm and b/sdk/contracts/invariant/invariant.wasm differ diff --git a/sdk/contracts/psp22/psp22.json b/sdk/contracts/psp22/psp22.json index 874e2bab..9d94e68b 100644 --- a/sdk/contracts/psp22/psp22.json +++ b/sdk/contracts/psp22/psp22.json @@ -1,6 +1,6 @@ { "source": { - "hash": "0xc286df19a483e4b4fcb2b2342b14e33cdb6dade49ebe0dea80f4fab27ae200ba", + "hash": "0xb4082b7d4aedb8479925aa96a383ea722dc1a7e9b29ad5a4d5f95ad707db4e09", "language": "ink! 5.0.0", "compiler": "rustc 1.77.0", "build_info": { diff --git a/sdk/contracts/psp22/psp22.wasm b/sdk/contracts/psp22/psp22.wasm index 3ec472fd..f4950a15 100644 Binary files a/sdk/contracts/psp22/psp22.wasm and b/sdk/contracts/psp22/psp22.wasm differ diff --git a/sdk/src/abis/invariant.ts b/sdk/src/abis/invariant.ts index a3afe2c3..46f6f30f 100644 --- a/sdk/src/abis/invariant.ts +++ b/sdk/src/abis/invariant.ts @@ -1,7 +1,7 @@ export const abi = ` { "source": { - "hash": "0x499732ce96a694dfd6f72993c4bb75bafe2dea9d5157bbd0859d3bb8d57941c5", + "hash": "0x6535e78f66cf026b69bf940c0439337244baa2e34a6e9059a4730e00f9783811", "language": "ink! 5.0.0", "compiler": "rustc 1.77.0", "build_info": { diff --git a/sdk/src/abis/psp22.ts b/sdk/src/abis/psp22.ts index 2b74032f..5e314bf1 100644 --- a/sdk/src/abis/psp22.ts +++ b/sdk/src/abis/psp22.ts @@ -1,7 +1,7 @@ export const abi = ` { "source": { - "hash": "0xc286df19a483e4b4fcb2b2342b14e33cdb6dade49ebe0dea80f4fab27ae200ba", + "hash": "0xb4082b7d4aedb8479925aa96a383ea722dc1a7e9b29ad5a4d5f95ad707db4e09", "language": "ink! 5.0.0", "compiler": "rustc 1.77.0", "build_info": {