Skip to content

Commit

Permalink
refactor(ui): Update for new PoolState
Browse files Browse the repository at this point in the history
  • Loading branch information
wormat committed Oct 25, 2022
1 parent 3ba7019 commit 8c58bc9
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 235 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
} from "../solana";

export const useSolanaPoolOperationsMutation = () => {
const { env } = useEnvironment();
const config = useEnvironment(selectConfig, shallow);
const { pools } = config;
const { data: splTokenAccounts = [] } = useUserSolanaTokenAccountsQuery();
Expand Down Expand Up @@ -65,7 +64,6 @@ export const useSolanaPoolOperationsMutation = () => {
let inputTxId = inputState.txId;
if (inputTxId === null) {
inputTxId = await doSingleSolanaPoolOperation(
env,
solanaClient,
wallet,
splTokenAccounts,
Expand Down Expand Up @@ -97,7 +95,6 @@ export const useSolanaPoolOperationsMutation = () => {
inputTx,
);
const outputTxId = await doSingleSolanaPoolOperation(
env,
solanaClient,
wallet,
splTokenAccounts,
Expand Down
4 changes: 2 additions & 2 deletions apps/ui/src/hooks/swim/usePoolMaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ const getPoolMath = ({

// lpFee
const humanLpFee = atomicToHuman(
new Decimal(poolState.lpFee),
new Decimal(poolState.lpFee.value),
poolSpec.feeDecimals,
);

// governanceFee
const humanGovernanceFee = atomicToHuman(
new Decimal(poolState.governanceFee),
new Decimal(poolState.governanceFee.value),
poolSpec.feeDecimals,
);

Expand Down
21 changes: 8 additions & 13 deletions apps/ui/src/hooks/swim/usePoolStateQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,19 @@ import { EVM_ECOSYSTEMS } from "@swim-io/evm";
import { SOLANA_ECOSYSTEM_ID } from "@swim-io/solana";
import type { UseQueryResult } from "react-query";
import { useQueries } from "react-query";
import shallow from "zustand/shallow.js";

import type { PoolSpec } from "../../config";
import { selectConfig } from "../../core/selectors";
import { useEnvironment } from "../../core/store";
import type { PoolState } from "../../models";
import { getEvmPoolState, getSolanaPoolState } from "../../models";
import { getLegacySolanaPoolState } from "../../models";
import { useGetEvmClient } from "../evm";
import { useSolanaClient } from "../solana";

export const usePoolStateQueries = (
poolSpecs: readonly PoolSpec[],
): readonly UseQueryResult<PoolState | null, Error>[] => {
const { env } = useEnvironment();
const { tokens } = useEnvironment(selectConfig, shallow);
const getEvmConnection = useGetEvmClient();
const getEvmClient = useGetEvmClient();
const solanaClient = useSolanaClient();

return useQueries(
Expand All @@ -27,23 +24,21 @@ export const usePoolStateQueries = (
queryFn: async () => {
const { ecosystem } = poolSpec;
if (ecosystem === SOLANA_ECOSYSTEM_ID) {
return await getSolanaPoolState(solanaClient, poolSpec);
if (poolSpec.isLegacyPool) {
return await getLegacySolanaPoolState(solanaClient, poolSpec);
}
return await solanaClient.getPoolState(poolSpec.id);
}
if (ecosystem === APTOS_ECOSYSTEM_ID) {
return null; // TODO aptos
}
const evmConnection = getEvmConnection(ecosystem);
const evmClient = getEvmClient(ecosystem);
const routingContractAddress =
EVM_ECOSYSTEMS[ecosystem].chains[env]?.routingContractAddress ?? null;
if (routingContractAddress === null) {
return null;
}
return await getEvmPoolState(
evmConnection,
poolSpec,
tokens,
routingContractAddress,
);
return await evmClient.getPoolState(poolSpec.id);
},
})),
) as readonly UseQueryResult<PoolState | null, Error>[];
Expand Down
117 changes: 117 additions & 0 deletions apps/ui/src/models/solana/deserializeLegacySolanaPoolState.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { Buffer } from "buffer";

import { PublicKey } from "@solana/web3.js";
import BN from "bn.js";

import type { LegacySolanaPoolState } from "./deserializeLegacySolanaPoolState";
import { deserializeLegacySolanaPoolState } from "./deserializeLegacySolanaPoolState";

describe("deserializeLegacySolanaPoolState", () => {
it("deserializes a SolanaPoolState", () => {
const serialized = Buffer.from(
"00000100000000000000000000000000000000e8030000000000000000000000000000002c01000064000000990e9632b0b9f2e636feb3f0a4220f8aadf9677b451c982a4151af42e0362e8800c6fa7af3bedbad3a3d65f36aabc97431b1bbe4c2d2f6e0e47ca60203452f5d61ce010e60afedb22717bd63192f54145a3f965a33bb82d2c7029eb2ce1e20826487f81d7f931ba1c5db9f5a8b2ac5e149ef9c76d9cf196615bd21163316e8c410bdd7aa20228a7bc21e67ddfe78d5d89b986d4bf5c8d5dc9d4574d81ab11e5a02012262c2067049b5c6d6a6869e7a37bbee162637f78192c3b15e8427676a422574616a65b31ff1d8f707eb279bf8a729a6644151b16d72f9694af6ae499881ed02020202000048ccc8aa094ba7b3495776e123587f2454a935671548ccdc3f4311a9febbdd18fb56a83f5d24d5e7513f96b8c24bff58e7259e92f2fd6f01162f9b0b5188d23e32bf5157ba942716dbab775cde82f881ededa5a96b325714e2bef602679dc3cd1205cdb06ade7ab0c78b50a6e7cc2dd83edfa10423348951b7ce231b6c920334bfcf845603efc68ddea00872ad53de92ed69227e373bdca1a21f78782ec87fec7b90e07d2a4fd0d055d08430d9524a755cacd7a7a531ed91705e8b823e59d820cf609300f5b15b7009876930926f1b5c4a6ecdbc035219127e8ff47ef369abbc7ef4d44674e963fe6e94097d729f1c29c382a3ca684cfd454347f97ee142959e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d8fcd9e56d407000000000000000000",
"hex",
);

const expected: LegacySolanaPoolState = {
ecosystem: "solana",
bump: 0,
isPaused: false,
ampFactor: {
initialValue: {
value: new BN(1),
decimals: 0,
},
initialTs: new BN(0),
targetValue: {
value: new BN(1000),
decimals: 0,
},
targetTs: new BN(0),
},
lpFee: 300,
governanceFee: 100,
lpMintKey: new PublicKey("BJUH9GJLaMSLV1E7B3SQLCy9eCfyr6zsrwGcpS2MkqR1"),
lpDecimalEqualizer: 0,
tokenMintKeys: [
new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"),
new PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB"),
new PublicKey("A9mUU4qviSctJVPJdBJWkb28deg915LYJKrzQ19ji3FM"),
new PublicKey("Dn4noZ5jgGfkntzcQSUZ8czkreiZ1ForXYoV2H8Dm7S1"),
new PublicKey("5RpUwQ8wtdPCZHhu6MERp2RGrpobsbZ6MH5dDHkUjs2"),
new PublicKey("8qJSyQprMC57TWKaYEmetUR3UUiTP2M3hXdcvFhkZdmv"),
],
tokenDecimalEqualizers: [2, 2, 2, 2, 0, 0],
tokenKeys: [
new PublicKey("5uBU2zUG8xTLA6XwwcTFWib1p7EjCBzWbiy44eVASTfV"),
new PublicKey("Hv7yPYnGs6fpN3o1NZvkima9mKDrRDJtNxf23oKLCjau"),
new PublicKey("4R6b4aibi46JzAnuA8ZWXrHAsR1oZBTZ8dqkuer3LsbS"),
new PublicKey("2DMUL42YEb4g1HAKXhUxL3Yjfgoj4VvRqKwheorfFcPV"),
new PublicKey("DukQAFyxR41nbbq2FBUDMyrtF2CRmWBREjZaTVj4u9As"),
new PublicKey("9KMH3p8cUocvQRbJfKRAStKG52xCCWNmEPsJm5gc8fzw"),
],
governanceKey: new PublicKey(
"ExWoeFoyYwCFx2cp9PZzj4eYL5fsDEFQEpC8REsksNpb",
),
governanceFeeKey: new PublicKey(
"9Yau6DnqYasBUKcyxQJQZqThvUnqZ32ZQuUCcC2AdT9P",
),
preparedGovernanceKey: PublicKey.default,
governanceTransitionTs: new BN(0),
preparedLpFee: { value: 0 },
preparedGovernanceFee: { value: 0 },
feeTransitionTs: new BN(0),
previousDepth: new BN(2203793333522317),
};
const decoded = deserializeLegacySolanaPoolState(6, serialized);
expect(decoded.bump).toBe(expected.bump);
expect(decoded.isPaused).toBe(expected.isPaused);
expect(
decoded.ampFactor.initialValue.value.eq(
expected.ampFactor.initialValue.value,
),
).toBe(true);
expect(decoded.ampFactor.initialValue.decimals).toBe(
expected.ampFactor.initialValue.decimals,
);
expect(decoded.ampFactor.initialTs.eq(expected.ampFactor.initialTs)).toBe(
true,
);
expect(
decoded.ampFactor.targetValue.value.eq(
expected.ampFactor.targetValue.value,
),
).toBe(true);
expect(decoded.ampFactor.targetValue.decimals).toBe(
expected.ampFactor.targetValue.decimals,
);
expect(decoded.ampFactor.targetTs.eq(expected.ampFactor.targetTs)).toBe(
true,
);
expect(decoded.lpFee).toBe(expected.lpFee);
expect(decoded.governanceFee).toBe(expected.governanceFee);
expect(decoded.lpMintKey).toStrictEqual(expected.lpMintKey);
expect(decoded.lpDecimalEqualizer).toBe(expected.lpDecimalEqualizer);
decoded.tokenMintKeys.forEach((tokenMintKey, i) => {
expect(tokenMintKey).toStrictEqual(expected.tokenMintKeys[i]);
});
decoded.tokenDecimalEqualizers.forEach((tokenDecimalEqualizer, i) => {
expect(tokenDecimalEqualizer).toBe(expected.tokenDecimalEqualizers[i]);
});
decoded.tokenKeys.forEach((tokenKey, i) => {
expect(tokenKey).toStrictEqual(expected.tokenKeys[i]);
});
expect(decoded.governanceKey).toStrictEqual(expected.governanceKey);
expect(decoded.governanceFeeKey).toStrictEqual(expected.governanceFeeKey);
expect(decoded.preparedGovernanceKey).toStrictEqual(
expected.preparedGovernanceKey,
);
expect(
decoded.governanceTransitionTs.eq(expected.governanceTransitionTs),
).toBe(true);
expect(decoded.preparedLpFee).toBe(expected.preparedLpFee);
expect(decoded.preparedGovernanceFee).toBe(expected.preparedGovernanceFee);
expect(decoded.feeTransitionTs.eq(expected.feeTransitionTs)).toBe(true);
expect(decoded.previousDepth.eq(expected.previousDepth)).toBe(true);
});
});
65 changes: 65 additions & 0 deletions apps/ui/src/models/solana/deserializeLegacySolanaPoolState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
array,
bool,
i64,
publicKey,
struct,
u128,
u32,
u8,
} from "@project-serum/borsh";
import type { Layout } from "@project-serum/borsh";
import type { SolanaEcosystemId, SolanaPoolState } from "@swim-io/solana";
import { SOLANA_ECOSYSTEM_ID, ampFactor } from "@swim-io/solana";

type U8 = (property?: string) => Layout<number>;

export interface LegacySolanaPoolState
extends Omit<SolanaPoolState, "governanceFee" | "lpFee" | "pauseKey"> {
readonly governanceFee: number;
readonly lpFee: number;
readonly ecosystem: SolanaEcosystemId;
}

export const solanaPool = (
numberOfTokens: number,
property = "solanaPool",
): Layout<Omit<LegacySolanaPoolState, "ecosystem">> =>
struct(
[
u8("bump"),
bool("isPaused"),
ampFactor(),
u32("lpFee"),
u32("governanceFee"),
publicKey("lpMintKey"),
u8("lpDecimalEqualizer"),
array(publicKey(), numberOfTokens, "tokenMintKeys"),
array((u8 as U8)(), numberOfTokens, "tokenDecimalEqualizers"),
array(publicKey(), numberOfTokens, "tokenKeys"),
publicKey("governanceKey"),
publicKey("governanceFeeKey"),
publicKey("preparedGovernanceKey"),
i64("governanceTransitionTs"),
u32("preparedLpFee"),
u32("preparedGovernanceFee"),
i64("feeTransitionTs"),
u128("previousDepth"),
],
property,
);

export const deserializeLegacySolanaPoolState = (
numberOfTokens: number,
accountData: Buffer,
): LegacySolanaPoolState => {
const layout = solanaPool(numberOfTokens);
if (accountData.length !== layout.span) {
throw new Error("Incorrect account data length");
}
const decoded = layout.decode(accountData);
return {
...decoded,
ecosystem: SOLANA_ECOSYSTEM_ID,
};
};
1 change: 1 addition & 0 deletions apps/ui/src/models/solana/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./deserializeLegacySolanaPoolState";
export * from "./findOrCreateSplTokenAccount";
export * from "./getSwimUsdBalanceChange";
4 changes: 0 additions & 4 deletions apps/ui/src/models/swim/SwimDefiInstructor.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { TOKEN_PROGRAM_ID, createApproveInstruction } from "@solana/spl-token";
import type { AccountMeta, Transaction } from "@solana/web3.js";
import { Keypair, PublicKey, TransactionInstruction } from "@solana/web3.js";
import type { Env } from "@swim-io/core";
import {
SOLANA_ECOSYSTEM_ID,
createMemoIx,
Expand Down Expand Up @@ -35,7 +34,6 @@ import type {
} from "./operation";

export class SwimDefiInstructor {
private readonly env: Env;
private readonly solanaClient: SolanaClient;
private readonly signer: SolanaWalletAdapter;
private readonly programId: PublicKey;
Expand All @@ -49,7 +47,6 @@ export class SwimDefiInstructor {
private userTokenAccounts: readonly PublicKey[];

public constructor(
env: Env,
solanaClient: SolanaClient,
signer: SolanaWalletAdapter,
swimProgramAddress: string,
Expand All @@ -72,7 +69,6 @@ export class SwimDefiInstructor {
"Number of user token accounts does not match number of token mints",
);
}
this.env = env;
this.solanaClient = solanaClient;
this.signer = signer;
this.programId = new PublicKey(swimProgramAddress);
Expand Down
6 changes: 4 additions & 2 deletions apps/ui/src/models/swim/SwimInitializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@ import {
SystemProgram,
TransactionInstruction,
} from "@solana/web3.js";
import { createTx, swimPool } from "@swim-io/solana";
import { createTx } from "@swim-io/solana";
import type {
DecimalBN,
SolanaClient,
SolanaWalletAdapter,
} from "@swim-io/solana";
import { chunks } from "@swim-io/utils";

import { solanaPool } from "../solana";

import { SwimInstruction, initInstruction } from "./instructions";

export class SwimInitializer {
Expand Down Expand Up @@ -148,7 +150,7 @@ export class SwimInitializer {
if (!this.stateAccount) {
throw new Error("No state account");
}
const layout = swimPool(this.numberOfTokens);
const layout = solanaPool(this.numberOfTokens);
const lamports =
await this.solanaClient.connection.getMinimumBalanceForRentExemption(
layout.span,
Expand Down
44 changes: 0 additions & 44 deletions apps/ui/src/models/swim/deserializeSwimPoolV2.ts

This file was deleted.

Loading

0 comments on commit 8c58bc9

Please sign in to comment.