Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/CrocSwap/sdk into scroll-l1gas
Browse files Browse the repository at this point in the history
  • Loading branch information
benwolski committed Feb 26, 2024
2 parents bb335bf + a6739e9 commit 40974c8
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 53 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@crocswap-libs/sdk",
"version": "0.2.82",
"version": "0.2.89",
"description": "🛠🐊🛠 An SDK for building applications on top of CrocSwap",
"author": "Ben Wolski <ben@crocodilelabs.io>",
"repository": "https://github.com/CrocSwap/sdk.git",
Expand Down
28 changes: 20 additions & 8 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ export interface ChainSpec {
addrs: {
dex: ChainAddress;
query: ChainAddress;
impact: ChainAddress
impact: ChainAddress;
router?: ChainAddress
routerBypass?: ChainAddress
}
isTestNet: boolean;
chainId: ChainId;
Expand Down Expand Up @@ -84,12 +86,14 @@ const ARB_GOERLI_CHAIN: ChainSpec = {
};

const MAINNET_CHAIN: ChainSpec = {
nodeUrl: "https://mainnet.infura.io/v3/360ea5fda45b4a22883de8522ebd639e",
wsUrl: "wss://mainnet.infura.io/ws/v3/360ea5fda45b4a22883de8522ebd639e",
nodeUrl: "https://mainnet.infura.io/v3/" + DFLT_SDK_INFURA_KEY,
wsUrl: "wss://mainnet.infura.io/ws/v3/" + DFLT_SDK_INFURA_KEY,
addrs: {
dex: "0xAaAaAAAaA24eEeb8d57D431224f73832bC34f688",
query: "0xc2e1f740E11294C64adE66f69a1271C5B32004c8",
impact: "0x3e3EDd3eD7621891E574E5d7f47b1f30A994c0D0"
impact: "0x3e3EDd3eD7621891E574E5d7f47b1f30A994c0D0",
router: "0x533E164ded63f4c55E83E1f409BDf2BaC5278035",
routerBypass: "0xa3e58B0cB05447398358B6C59E4B2465342EFEd2"
},
poolIndex: 420,
isTestNet: false,
Expand All @@ -106,11 +110,14 @@ const MAINNET_CHAIN: ChainSpec = {
};

const SEPOLIA_CHAIN: ChainSpec = {
nodeUrl: "https://sepolia.infura.io/v3/360ea5fda45b4a22883de8522ebd639e",
nodeUrl: "https://sepolia.infura.io/v3/" + DFLT_SDK_INFURA_KEY,
wsUrl: "wss://sepolia.infura.io/ws/v3/" + DFLT_SDK_INFURA_KEY,
addrs: {
dex: "0xFb8A46E7963E6397DBB4B2E1c0B3f0464fb5BDFF",
query: "0xDB182F4687708D0F5798c77b4d02ad3425f4B672",
impact: "0x80aEB76D091ecbEd3c609c0B794fC1A09B9cB8F4"
impact: "0x80aEB76D091ecbEd3c609c0B794fC1A09B9cB8F4",
router: "0x168dB7Ad649D9f7918028F709C5e2F245af284A4",
routerBypass: "0xBC3d1Bb2d8A59eb25DA1E527bF0cA62B44346EE1"
},
poolIndex: 36000,
isTestNet: true,
Expand All @@ -131,7 +138,9 @@ const SCROLL_SEPOLIA_CHAIN: ChainSpec = {
addrs: {
dex: "0xaaAAAaa6612bd88cD409cb0D70C99556C87A0E8c",
query: "0x43eC1302FE3587862e15B2D52AD9653575FD79e9",
impact: "0x9B28970D51A231741416D8D3e5281d9c51a50892"
impact: "0x9B28970D51A231741416D8D3e5281d9c51a50892",
router: "0x323172539B1B0D9eDDFFBd0318C4d6Ab45292843",
routerBypass: "0xb2aE163293C82DCF36b0cE704591eDC2f9E2608D"
},
poolIndex: 36000,
isTestNet: true,
Expand All @@ -152,7 +161,9 @@ const SCROLL_CHAIN: ChainSpec = {
addrs: {
dex: "0xaaaaAAAACB71BF2C8CaE522EA5fa455571A74106",
query: "0x62223e90605845Cf5CC6DAE6E0de4CDA130d6DDf",
impact: "0xc2c301759B5e0C385a38e678014868A33E2F3ae3"
impact: "0xc2c301759B5e0C385a38e678014868A33E2F3ae3",
router: "0xfB5f26851E03449A0403Ca945eBB4201415fd1fc",
routerBypass: "0xED5535C6237f72BD9b4fDEAa3b6D8d9998b4C4e4",
},
poolIndex: 420,
isTestNet: false,
Expand Down Expand Up @@ -191,4 +202,5 @@ export const CHAIN_SPECS: { [chainId: string]: ChainSpec } = {
"mainnet": MAINNET_CHAIN,
"scrolltest": SCROLL_SEPOLIA_CHAIN,
"scroll": SCROLL_CHAIN,
"scrollsepolia": SCROLL_SEPOLIA_CHAIN,
};
4 changes: 4 additions & 0 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { ERC20_READ_ABI } from "./abis/erc20.read";
export interface CrocContext {
provider: Provider;
dex: Contract;
router?: Contract;
routerBypass?: Contract;
query: Contract;
slipQuery: Contract;
erc20Read: Contract;
Expand Down Expand Up @@ -105,6 +107,8 @@ function inflateContracts(
return {
provider: provider,
dex: new Contract(context.addrs.dex, CROC_ABI, actor),
router: context.addrs.router ? new Contract(context.addrs.router || AddressZero, CROC_ABI, actor) : undefined,
routerBypass: context.addrs.routerBypass ? new Contract(context.addrs.routerBypass || AddressZero, CROC_ABI, actor) : undefined,
query: new Contract(context.addrs.query, QUERY_ABI, provider),
slipQuery: new Contract(context.addrs.impact, IMPACT_ABI, provider),
erc20Write: new Contract(AddressZero, ERC20_ABI, actor),
Expand Down
10 changes: 10 additions & 0 deletions src/croc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { CrocSwapPlan, CrocSwapPlanOpts } from './swap';
import { Signer } from 'ethers';
import { CrocKnockoutHandle } from './knockout';
import { CrocPositionView } from './position';
import { CrocSlotReader } from './slots';
import { TransactionResponse } from "@ethersproject/providers";

/* This is the main entry point for the Croc SDK. It provides a high-level interface
* for interacting with CrocSwap smart contracts in an ergonomic way. */
Expand Down Expand Up @@ -99,6 +101,14 @@ export class CrocEnv {
return this.tokens.materialize(AddressZero)
}

async approveBypassRouter(): Promise<TransactionResponse | undefined> {
return this.tokenEth().approveBypassRouter()
}

slotReader(): CrocSlotReader {
return new CrocSlotReader(this.context)
}

readonly context: Promise<CrocContext>
tokens: TokenRepo
}
Expand Down
41 changes: 35 additions & 6 deletions src/examples/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,44 @@ import { ethers } from 'ethers';

//const ETH = ethers.constants.AddressZero
//const DAI = "0xdc31Ee1784292379Fbb2964b3B9C4124D8F89C60"
//const USDC = "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4"

const USDC = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
// Scroll
const USDC = "0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4"

// Mainnet
//const USDC = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"

// Sepolia
//const USDC = "0x60bBA138A74C5e7326885De5090700626950d509"

// deepcode ignore HardcodedSecret: testnet dummy key
const KEY = "0x7c5e2cfbba7b00ba95e5ed7cd80566021da709442e147ad3e08f23f5044a3d5a"
const KEY = process.env.WALLET_KEY || "0x7c5e2cfbba7b00ba95e5ed7cd80566021da709442e147ad3e08f23f5044a3d5a"

async function demo() {
const wallet = new ethers.Wallet(KEY)

const croc = new CrocEnv("mainnet", wallet)
const croc = new CrocEnv("scroll", wallet)

//console.log(await croc.approveBypassRouter())
//console.log(await croc.token(USDC).approveRouter(100))

console.log((await croc.buy(USDC, 5).withEth().useRouter().swap()))
/*console.log((await croc.sell(USDC, 0.01).forEth().useBypass().swap()))
console.log((await croc.sellEth(0.00001).for(USDC).useBypass().swap()))
console.log((await croc.buyEth(0.00001).with(USDC).useBypass().swap()))*/

//console.log(await croc.sellEth(0.01).for(USDC).swap({ surplus: [true, false]}))
/*const types = ["uint128","uint128","uint128","uint64","uint64","int24","bool","bool","uint8","uint128","uint128",
"uint8","uint16","uint8","uint16","uint8","uint8","uint8","bytes32","address"]
console.log(abi.decode(types, log))*/

//await croc.token(USDC).approve(0.001)
//await croc.token(USDC).approveRouter()
//await croc.token(USDC).approveBypassRouter()

//console.log((await croc.sell(USDC, 7.5).forEth().useBypass().swap()))
//console.log((await croc.sellEth(0).for(USDC).swap()))
//console.log((await croc.buy(USDC, 1).withEth().useBypass().swap()))
//console.log((await croc.buyEth(0).with(USDC).forceProxy().swap()))

/*croc.token(DAI).deposit(1, wallet.address)
croc.token(DAI).withdraw(0.25, wallet.address)
Expand Down Expand Up @@ -193,12 +218,16 @@ async function demo() {
console.log(await posView.queryRangePos(199308, 201312))*/

console.log(await croc.poolEthQuote(USDC).displayPrice())
//console.log(await croc.poolEthQuote(USDC).displayPrice())

//croc.sell(DAI, 200).atLimit(ETH, -64000).burn({surplus: true})

/*console.log((await croc.tokenEth().balance("benwolski.eth")).toString())
console.log(await croc.tokenEth().balanceDisplay("benwolski.eth"))*/

/*croc.slotReader().isHotPathOpen().then(console.log)
console.log(await croc.slotReader().proxyContract(1))
console.log(await croc.slotReader().proxyContract(131))*/
}

demo()
20 changes: 10 additions & 10 deletions src/pool.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable prefer-const */
import { CrocContext } from "./context";
import { decodeCrocPrice, toDisplayPrice, bigNumToFloat, toDisplayQty, fromDisplayPrice, roundForConcLiq, concDepositSkew, pinTickLower, pinTickUpper, neighborTicks, pinTickOutside, tickToPrice } from './utils';
import { decodeCrocPrice, toDisplayPrice, bigNumToFloat, toDisplayQty, fromDisplayPrice, roundForConcLiq, concDepositSkew, pinTickLower, pinTickUpper, neighborTicks, pinTickOutside, tickToPrice, concBaseSlippagePrice, concQuoteSlippagePrice } from './utils';
import { CrocEthView, CrocTokenView, sortBaseQuoteViews, TokenQty } from './tokens';
import { TransactionResponse } from '@ethersproject/providers';
import { WarmPathEncoder } from './encoding/liquidity';
Expand Down Expand Up @@ -208,7 +208,8 @@ export class CrocPoolView {
return this.sendCmd(calldata, {value: await msgVal})
}

private async boundLimits (range: TickRange, limits: PriceRange): Promise<PriceRange> {
private async boundLimits (range: TickRange, limits: PriceRange, isQtyBase: boolean,
floatingSlippage: number = 0.1): Promise<PriceRange> {
let spotPrice = this.spotPrice()
const [lowerPrice, upperPrice] = this.rangeToPrice(range)
const [boundLower, boundUpper] = await this.transformLimits(limits)
Expand All @@ -220,14 +221,12 @@ export class CrocPoolView {
amplifyLower = upperPrice*BOUND_PREC
} else if (lowerPrice > await spotPrice) {
amplifyUpper = lowerPrice/BOUND_PREC

} else {
// Generally assume we don't want to send more than 1% more than the floating side
const MAX_AMPLICATION = 1.02
const slippageCap = 1 - Math.pow(1 - 1/MAX_AMPLICATION, 2)

amplifyLower = ((await spotPrice) - lowerPrice) * slippageCap + lowerPrice
amplifyUpper = upperPrice - (upperPrice - (await spotPrice)) * slippageCap
if (isQtyBase) {
amplifyLower = concBaseSlippagePrice(await spotPrice, upperPrice, floatingSlippage)
} else {
amplifyUpper = concQuoteSlippagePrice(await spotPrice, lowerPrice, floatingSlippage)
}
}

return this.untransformLimits(
Expand Down Expand Up @@ -258,7 +257,7 @@ export class CrocPoolView {

private async mintRange (qty: TokenQty, isQtyBase: boolean,
range: TickRange, limits: PriceRange, opts?: CrocLpOpts): Promise<TransactionResponse> {
const saneLimits = await this.boundLimits(range, limits)
const saneLimits = await this.boundLimits(range, limits, isQtyBase, opts?.floatingSlippage)

let msgVal = this.msgValRange(qty, isQtyBase, range, await saneLimits, opts)
let weiQty = this.normQty(qty, isQtyBase)
Expand Down Expand Up @@ -349,4 +348,5 @@ export class CrocPoolView {

export interface CrocLpOpts {
surplus?: CrocSurplusFlags
floatingSlippage?: number
}
34 changes: 34 additions & 0 deletions src/slots.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { BigNumber, ethers } from 'ethers';
import { CrocContext } from './context';

/* This is the main entry point for the Croc SDK. It provides a high-level interface
* for interacting with CrocSwap smart contracts in an ergonomic way. */
export class CrocSlotReader {
constructor (context: Promise<CrocContext>) {
this.provider = context.then(p => p.provider)
this.dex = context.then(c => c.dex.address)
}

async isHotPathOpen(): Promise<boolean> {
const STATE_SLOT = 0
const HOT_OPEN_OFFSET = 22

const hotShiftBits = 8 * (32 - HOT_OPEN_OFFSET)
const slotVal = this.readSlot(STATE_SLOT).then(BigNumber.from)
return (await slotVal).shl(hotShiftBits).shr(255).gt(0)
}

async readSlot (slot: number): Promise<string> {
return (await this.provider).getStorageAt(await this.dex, slot)
}

async proxyContract (proxyIdx: number): Promise<string> {
const PROXY_SLOT_OFFSET = 1

const slotVal = await this.readSlot(PROXY_SLOT_OFFSET + proxyIdx)
return "0x" + slotVal.slice(26)
}

readonly provider: Promise<ethers.providers.Provider>
readonly dex: Promise<string>
}
Loading

0 comments on commit 40974c8

Please sign in to comment.