Skip to content

Commit

Permalink
Merge with stage
Browse files Browse the repository at this point in the history
  • Loading branch information
mattupham committed Aug 9, 2024
2 parents b2348e5 + 82456a9 commit e0a4935
Show file tree
Hide file tree
Showing 140 changed files with 11,524 additions and 969 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/frontend-e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ jobs:
preview-pools-and-select-pair-tests:
timeout-minutes: 10
needs: wait-for-deployment
runs-on: buildjet-4vcpu-ubuntu-2204
runs-on: macos-14
steps:
- name: Check out repository
uses: actions/checkout@v4
Expand All @@ -131,6 +131,7 @@ jobs:
- name: Run Pools tests
env:
BASE_URL: "https://${{ needs.wait-for-deployment.outputs.environment_url }}"
USE_TRADE: "use"
run: |
cd packages/web
npx playwright test pools select
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/monitoring-e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ jobs:
BASE_URL: ${{ matrix.base-url }}
run: |
cd packages/web
npx playwright test -g "Test Select Swap Pair feature"
npx playwright test pools
- name: upload test results
if: failure()
id: e2e-test-results
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/prod-frontend-e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ jobs:
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
ref: master
- name: Setup Node.js
uses: actions/setup-node@v4
with:
Expand Down
3 changes: 2 additions & 1 deletion packages/bridge/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"long": "^5.2.3",
"lru-cache": "^10.0.1",
"viem": "2.16.4",
"zod": "^3.22.4"
"zod": "^3.22.4",
"base-x": "^5.0.0"
},
"devDependencies": {
"@types/jest-in-case": "^1.0.6",
Expand Down
3 changes: 3 additions & 0 deletions packages/bridge/src/bridge-providers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AxelarBridgeProvider } from "./axelar";
import { IbcBridgeProvider } from "./ibc";
import { BridgeProviderContext } from "./interface";
import { NitroBridgeProvider } from "./nitro";
import { NomicBridgeProvider } from "./nomic";
import { SkipBridgeProvider } from "./skip";
import { SquidBridgeProvider } from "./squid";
Expand All @@ -17,6 +18,7 @@ export class BridgeProviders {
[IbcBridgeProvider.ID]: IbcBridgeProvider;
[NomicBridgeProvider.ID]: NomicBridgeProvider;
[WormholeBridgeProvider.ID]: WormholeBridgeProvider;
[NitroBridgeProvider.ID]: NitroBridgeProvider;
};

constructor(integratorId: string, commonContext: BridgeProviderContext) {
Expand All @@ -34,6 +36,7 @@ export class BridgeProviders {
[IbcBridgeProvider.ID]: new IbcBridgeProvider(commonContext),
[NomicBridgeProvider.ID]: new NomicBridgeProvider(commonContext),
[WormholeBridgeProvider.ID]: new WormholeBridgeProvider(commonContext),
[NitroBridgeProvider.ID]: new NitroBridgeProvider(commonContext),
};
}
}
19 changes: 16 additions & 3 deletions packages/bridge/src/ibc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,27 @@ export class IbcBridgeProvider implements BridgeProvider {
}

/**
* Gets gas asset from asset list, attempting to match the coinMinimalDenom or counterparty denom.
* Gets gas asset from asset list or chain list, attempting to match the coinMinimalDenom or chainSuggestionDenom.
* @returns gas bridge asset, or undefined if not found.
*/
async getGasAsset(
fromChainId: string,
denom: string
): Promise<BridgeAsset | undefined> {
// check the asset list
// try to get asset list fee asset first, or otherwise the chain fee currency
const assetListAsset = this.ctx.assetLists
.flatMap(({ assets }) => assets)
.find((asset) => asset.coinMinimalDenom);

if (assetListAsset) {
return {
address: assetListAsset.coinMinimalDenom,
denom: assetListAsset.symbol,
decimals: assetListAsset.decimals,
coinGeckoId: assetListAsset.coingeckoId,
};
}

const chains = await this.getChains();
const chain = chains.find((c) => c.chain_id === fromChainId);
const feeCurrency = chain?.feeCurrencies.find(
Expand Down Expand Up @@ -366,7 +379,7 @@ export class IbcBridgeProvider implements BridgeProvider {
fromAsset,
toAsset,
}: GetBridgeExternalUrlParams): Promise<BridgeExternalUrl | undefined> {
if (fromChain?.chainType === "evm" || toChain?.chainType === "evm") {
if (fromChain?.chainType !== "cosmos" || toChain?.chainType !== "cosmos") {
return undefined;
}

Expand Down
14 changes: 14 additions & 0 deletions packages/bridge/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,25 @@ const bitcoinChainSchema = z.object({
chainType: z.literal("bitcoin"),
});

const tronChainSchema = z.object({
/**
* 728126428
*/
chainId: z.number(),
/**
* Optional: The human-readable name of the chain.
*/
chainName: z.string().optional(),

chainType: z.literal("tron"),
});

export const bridgeChainSchema = z.discriminatedUnion("chainType", [
cosmosChainSchema,
evmChainSchema,
solanaChainSchema,
bitcoinChainSchema,
tronChainSchema,
]);

export type BridgeChain = z.infer<typeof bridgeChainSchema>;
Expand Down
142 changes: 142 additions & 0 deletions packages/bridge/src/nitro/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import {
NativeEVMTokenConstantAddress,
TronChainInfo,
} from "@osmosis-labs/utils";
import basex from "base-x";

import {
BridgeAsset,
BridgeChain,
BridgeExternalUrl,
BridgeProvider,
BridgeProviderContext,
BridgeQuote,
BridgeTransactionRequest,
GetBridgeExternalUrlParams,
GetBridgeSupportedAssetsParams,
} from "../interface";

const BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const bs58 = basex(BASE58);

export class NitroBridgeProvider implements BridgeProvider {
static readonly ID = "Nitro";
readonly providerName = NitroBridgeProvider.ID;

constructor(protected readonly ctx: BridgeProviderContext) {}

async getQuote(): Promise<BridgeQuote> {
throw new Error("Nitro quotes are currently not supported.");
}

async getSupportedAssets({
asset,
}: GetBridgeSupportedAssetsParams): Promise<(BridgeChain & BridgeAsset)[]> {
try {
// just supports TRX, TRX.rt from Tron

const assets = this.ctx.assetLists.flatMap(({ assets }) => assets);
const assetListAsset = assets.find(
(a) => a.coinMinimalDenom.toLowerCase() === asset.address.toLowerCase()
);

if (assetListAsset) {
const variants = assets
.filter((a) => a?.variantGroupKey === assetListAsset.variantGroupKey)
.sort((a) =>
a.coinMinimalDenom === assetListAsset.variantGroupKey ? -1 : 1
);

const tronAsset = variants.length > 1 ? variants[1] : variants[0];

const tronCounterparty = tronAsset.counterparty.find(
(c) => c.chainName === "tron"
);

if (tronCounterparty) {
const isTRC20Token = tronCounterparty.sourceDenom.startsWith("T");
const address = isTRC20Token
? Buffer.from(bs58.decode(tronCounterparty.sourceDenom))
.toString("hex")
// Tron addresses in hexadecimal format always start with '41'.
// This prefix should be replaced with '0x' to convert it to a valid address.
.replace("41", "0x")
.substring(0, 42) // Tron addresses are 21 bytes long, so we need to truncate the last byte.
: undefined;

const resolvedAddress =
tronCounterparty.sourceDenom === "sun"
? NativeEVMTokenConstantAddress // Nitro uses the constant address to reference the native token
: address ?? tronCounterparty.sourceDenom;

return [
{
chainType: "tron",
chainId: TronChainInfo.chainId,
chainName: TronChainInfo.chainName,
denom: tronCounterparty.symbol,
address: resolvedAddress,
decimals: tronCounterparty.decimals,
},
];
}
}

return [];
} catch (e) {
// Avoid returning options if there's an unexpected error, such as the provider being down
if (process.env.NODE_ENV !== "production") {
console.error(
NitroBridgeProvider.ID,
"failed to get supported assets:",
e
);
}
return [];
}
}

async getTransactionData(): Promise<BridgeTransactionRequest> {
throw new Error("Nitro transactions are currently not supported.");
}

async getExternalUrl({
fromChain,
toChain,
fromAsset,
toAsset,
}: GetBridgeExternalUrlParams): Promise<BridgeExternalUrl | undefined> {
const url = new URL("https://beta-mainnet.routernitro.com/swap");

if (fromChain) {
url.searchParams.set("fromChain", String(fromChain.chainId));
}

if (toChain) {
url.searchParams.set("toChain", String(toChain.chainId));
}

const setTokenParam = (asset: BridgeAsset, param: string) => {
if (asset.address.includes("alloyed")) {
const assets = this.ctx.assetLists.flatMap(({ assets }) => assets);
const alloy = assets.find((a) => a.coinMinimalDenom === asset.address);
const variant = assets.find(
(a) =>
a.variantGroupKey === alloy?.variantGroupKey &&
a.coinMinimalDenom !== alloy?.coinMinimalDenom
);
if (variant) url.searchParams.set(param, variant.coinMinimalDenom);
} else {
url.searchParams.set(param, asset.address);
}
};

if (fromAsset) setTokenParam(fromAsset, "fromToken");
if (toAsset) setTokenParam(toAsset, "toToken");

return {
urlProviderName: "Nitro",
url,
};
}
}
3 changes: 3 additions & 0 deletions packages/math/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,8 @@
"@keplr-wallet/types": "0.10.24-ibc.go.v7.hot.fix",
"@keplr-wallet/unit": "0.10.24-ibc.go.v7.hot.fix",
"big-integer": "^1.6.48"
},
"devDependencies": {
"jest-in-case": "^1.0.2"
}
}
39 changes: 38 additions & 1 deletion packages/math/src/pool/concentrated/__tests__/tick.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Dec, Int } from "@keplr-wallet/unit";
// eslint-disable-next-line import/no-extraneous-dependencies
import cases from "jest-in-case";

import { approxSqrt } from "../../../utils";
import { maxSpotPrice, maxTick, minSpotPrice } from "../const";
import { priceToTick, tickToSqrtPrice } from "../tick";
import { priceToTick, tickToPrice, tickToSqrtPrice } from "../tick";

// https://github.com/osmosis-labs/osmosis/blob/0f9eb3c1259078035445b3e3269659469b95fd9f/x/concentrated-liquidity/math/tick_test.go#L30
describe("tickToSqrtPrice", () => {
Expand Down Expand Up @@ -217,6 +219,41 @@ describe("priceToTick", () => {
});
});

cases(
"tickToPrice",
({ tick, priceExpected }) => {
const price = tickToPrice(tick);
expect(price.toString()).toEqual(priceExpected.toString());
},
[
{
name: "Tick Zero",
tick: new Int("0"),
priceExpected: new Dec("1"),
},
{
name: "Large Positive Tick",
tick: new Int("1000000"),
priceExpected: new Dec("2"),
},
{
name: "Large Negative Tick",
tick: new Int("-5000000"),
priceExpected: new Dec("0.5"),
},
{
name: "Max Tick",
tick: new Int("182402823"),
priceExpected: new Dec("340282300000000000000"),
},
{
name: "Min Tick",
tick: new Int("-108000000"),
priceExpected: new Dec("0.000000000001"),
},
]
);

// TEMORARY: commenting out until we confirm adding a buffer around current tick avoids invalid queries
// describe("estimateInitialTickBound", () => {
// // src: https://github.com/osmosis-labs/osmosis/blob/0b199ee187fbff02f68c2dc503d60efe617a67b2/x/concentrated-liquidity/tick_test.go#L1865
Expand Down
47 changes: 47 additions & 0 deletions packages/math/src/pool/concentrated/tick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,53 @@ export function tickToSqrtPrice(tickIndex: Int): Dec {
return approxSqrt(price);
}

export function tickToPrice(tickIndex: Int): Dec {
if (tickIndex.isZero()) {
return new Dec(1);
}

const geometricExponentIncrementDistanceInTicks = nine.mul(
powTenBigDec(new Int(exponentAtPriceOne).neg()).toDec()
);

if (tickIndex.lt(minTick) || tickIndex.gt(maxTick)) {
throw new Error(
`tickIndex is out of range: ${tickIndex.toString()}, min: ${minTick.toString()}, max: ${maxTick.toString()}`
);
}

const geometricExponentDelta = new Dec(tickIndex)
.quoTruncate(new Dec(geometricExponentIncrementDistanceInTicks.truncate()))
.truncate();

let exponentAtCurTick = new Int(exponentAtPriceOne).add(
geometricExponentDelta
);
if (tickIndex.lt(new Int(0))) {
exponentAtCurTick = exponentAtCurTick.sub(new Int(1));
}

const currentAdditiveIncrementInTicks = powTenBigDec(exponentAtCurTick);

const numAdditiveTicks = tickIndex.sub(
geometricExponentDelta.mul(
geometricExponentIncrementDistanceInTicks.truncate()
)
);

const price = powTenBigDec(geometricExponentDelta)
.add(new BigDec(numAdditiveTicks).mul(currentAdditiveIncrementInTicks))
.toDec();

if (price.gt(maxSpotPrice) || price.lt(minSpotPrice)) {
throw new Error(
`price is out of range: ${price.toString()}, min: ${minSpotPrice.toString()}, max: ${maxSpotPrice.toString()}`
);
}

return price;
}

/** PriceToTick takes a price and returns the corresponding tick index
* This function does not take into consideration tick spacing.
*/
Expand Down
Loading

0 comments on commit e0a4935

Please sign in to comment.