Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sdk 331 account management should be moved to instruments #246

Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 2 additions & 67 deletions packages/js/src/plugins/instrumentModule/methods.ts
Original file line number Diff line number Diff line change
@@ -1,86 +1,21 @@
import { Leg, QuoteAsset, legBeet } from '@convergence-rfq/rfq';
import { QuoteAsset, legBeet } from '@convergence-rfq/rfq';

import { AccountMeta } from '@solana/web3.js';
import { createSerializerFromFixableBeetArgsStruct } from '../../types';
import { addDecimals } from '../../utils/conversions';
import { toSolitaLegSide } from '../rfqModule/models/LegSide';
import { PsyoptionsEuropeanInstrument } from '../psyoptionsEuropeanInstrumentModule';
import { PsyoptionsAmericanInstrument } from '../psyoptionsAmericanInstrumentModule';
import { SpotLegInstrument } from '../spotInstrumentModule';
import { LegInstrument, QuoteInstrument } from './types';
import { Convergence } from '@/Convergence';

export function toLeg(legInstrument: LegInstrument): Leg {
return {
instrumentProgram: legInstrument.getProgramId(),
baseAssetIndex: legInstrument.getBaseAssetIndex(),
instrumentData: legInstrument.serializeInstrumentData(),
instrumentAmount: addDecimals(
legInstrument.getAmount(),
legInstrument.getDecimals()
),
instrumentDecimals: legInstrument.getDecimals(),
side: toSolitaLegSide(legInstrument.getSide()),
};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why to move this logic to the instrument interface? The logic in each instrument is the same and is a clone of this logic


export function serializeAsLeg(legInstrument: LegInstrument) {
const legSerializer = createSerializerFromFixableBeetArgsStruct(legBeet);
return legSerializer.serialize(toLeg(legInstrument));
return legSerializer.serialize(legInstrument.toLeg());
}

export function getSerializedLegLength(legInstrument: LegInstrument) {
return serializeAsLeg(legInstrument).length;
}

export function getProgramAccount(legInstrument: LegInstrument): AccountMeta {
return {
pubkey: legInstrument.getProgramId(),
isSigner: false,
isWritable: false,
};
}

export function getValidationAccounts(
legInstrument: LegInstrument
): AccountMeta[] {
return [getProgramAccount(legInstrument)].concat(
legInstrument.getValidationAccounts()
);
}

export function toQuote(legInstrument: QuoteInstrument): QuoteAsset {
return {
instrumentProgram: legInstrument.getProgramId(),
instrumentData: legInstrument.serializeInstrumentData(),
instrumentDecimals: legInstrument.getDecimals(),
};
}

//TODO: refactor this method to use instrument interface in the future
export const legToBaseAssetMint = async (
convergence: Convergence,
leg: LegInstrument
) => {
if (leg instanceof PsyoptionsEuropeanInstrument) {
const euroMetaOptionMint = await convergence.tokens().findMintByAddress({
address: leg.optionMint,
});

return euroMetaOptionMint;
} else if (leg instanceof PsyoptionsAmericanInstrument) {
const americanOptionMint = await convergence.tokens().findMintByAddress({
address: leg.optionMint,
});

return americanOptionMint;
} else if (leg instanceof SpotLegInstrument) {
const mint = await convergence.tokens().findMintByAddress({
address: leg.mintAddress,
});

return mint;
}

throw Error('Unsupported instrument!');
};
4 changes: 2 additions & 2 deletions packages/js/src/plugins/instrumentModule/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const instrumentModule = (): ConvergencePlugin => ({
legInstrumentParsers.push([programAddress, factory]);
};

convergence.parseLegInstrument = function (leg: SolitaLeg) {
convergence.parseLegInstrument = async function (leg: SolitaLeg) {
const factory = legInstrumentParsers.find(([key]) =>
leg.instrumentProgram.equals(key)
)?.[1];
Expand All @@ -48,7 +48,7 @@ declare module '../../Convergence' {
programAddress: PublicKey,
factory: LegInstrumentParser
): void;
parseLegInstrument(leg: SolitaLeg): LegInstrument;
parseLegInstrument(leg: SolitaLeg): Promise<LegInstrument>;
}
}

Expand Down
7 changes: 6 additions & 1 deletion packages/js/src/plugins/instrumentModule/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Convergence } from '../../Convergence';
import { LegSide } from '../rfqModule/models/LegSide';

export interface LegInstrumentParser {
parseFromLeg(convergence: Convergence, leg: Leg): LegInstrument;
parseFromLeg(convergence: Convergence, leg: Leg): Promise<LegInstrument>;
}

export type CreateOptionInstrumentsResult = TransactionInstruction[];
Expand All @@ -18,8 +18,13 @@ export interface LegInstrument {
getDecimals: () => number;
getSide: () => LegSide;
serializeInstrumentData: () => Buffer;
getBaseAssetMint(): PublicKey;
getBaseAssetAccount(): AccountMeta;
getOracleAccount(): Promise<AccountMeta>;
getValidationAccounts(): AccountMeta[];
getPreparationsBeforeRfqCreation(): Promise<CreateOptionInstrumentsResult>;
getUnderlyingBaseAssetMint(): PublicKey;
toLeg(): Leg;
Copy link
Contributor

@EquilateralDelta EquilateralDelta Sep 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of those method are option-specific, but not generic. For example, they can be confusing when applied to spot instrument, rename getUnderlyingBaseAssetMint

}

// TODO add registration of quote instruments
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Keypair, PublicKey, TransactionInstruction } from '@solana/web3.js';
import {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File instrument.ts has 473 lines of code (exceeds 250 allowed). Consider refactoring.

AccountMeta,
Keypair,
PublicKey,
TransactionInstruction,
} from '@solana/web3.js';
import { Leg, BaseAssetIndex } from '@convergence-rfq/rfq';
import { OptionMarketWithKey } from '@mithraic-labs/psy-american';
import { OptionType } from '@mithraic-labs/tokenized-euros';
Expand All @@ -15,7 +20,11 @@ import {
import { addDecimals, removeDecimals } from '../../utils/conversions';
import { Convergence } from '../../Convergence';
import { createSerializerFromFixableBeetArgsStruct } from '../../types';
import { LegSide, fromSolitaLegSide } from '../rfqModule/models/LegSide';
import {
LegSide,
fromSolitaLegSide,
toSolitaLegSide,
} from '../rfqModule/models/LegSide';
import { CvgWallet, NoopWallet } from '../../utils/Wallets';
import {
GetOrCreateATAtxBuilderReturnType,
Expand Down Expand Up @@ -66,14 +75,25 @@ export class PsyoptionsAmericanInstrument implements LegInstrument {
readonly baseAssetIndex: BaseAssetIndex,
readonly amount: number,
readonly side: LegSide,
readonly underlyingAssetMint?: PublicKey,
readonly stableAssetMint?: PublicKey
readonly underlyingAssetMint: PublicKey,
readonly stableAssetMint: PublicKey
) {}

getBaseAssetIndex = () => this.baseAssetIndex;
getAmount = () => this.amount;
getBaseAssetIndex = () => this.baseAssetIndex;
getDecimals = () => PsyoptionsAmericanInstrument.decimals;
getSide = () => this.side;
toLeg(): Leg {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar blocks of code found in 3 locations. Consider refactoring.

return {
instrumentProgram: this.getProgramId(),
baseAssetIndex: this.getBaseAssetIndex(),
instrumentData: this.serializeInstrumentData(),
instrumentAmount: addDecimals(this.getAmount(), this.getDecimals()),
instrumentDecimals: this.getDecimals(),
side: toSolitaLegSide(this.getSide()),
};
}

async getPreparationsBeforeRfqCreation(): Promise<CreateOptionInstrumentsResult> {
if (!this.underlyingAssetMint) {
throw new Error('Missing underlying asset mint');
Expand All @@ -94,6 +114,48 @@ export class PsyoptionsAmericanInstrument implements LegInstrument {
);
return optionMarketIxs;
}
getBaseAssetAccount(): AccountMeta {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar blocks of code found in 3 locations. Consider refactoring.

const baseAsset = this.convergence
.protocol()
.pdas()
.baseAsset({ index: this.baseAssetIndex.value });

const baseAssetAccount: AccountMeta = {
pubkey: baseAsset,
isSigner: false,
isWritable: false,
};

return baseAssetAccount;
}
getBaseAssetMint(): PublicKey {
return this.optionMint;
}

getUnderlyingBaseAssetMint(): PublicKey {
return this.underlyingAssetMint;
}

async getOracleAccount(): Promise<AccountMeta> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar blocks of code found in 3 locations. Consider refactoring.

const baseAsset = this.convergence
.protocol()
.pdas()
.baseAsset({ index: this.baseAssetIndex.value });

const baseAssetModel = await this.convergence
.protocol()
.findBaseAssetByAddress({ address: baseAsset });

if (!baseAssetModel.priceOracle.address) {
throw Error('Base asset does not have a price oracle!');
}
const oracleAccount = {
pubkey: baseAssetModel.priceOracle.address,
isSigner: false,
isWritable: false,
};
return oracleAccount;
}

static async create(
convergence: Convergence,
Expand Down Expand Up @@ -186,6 +248,11 @@ export class PsyoptionsAmericanInstrument implements LegInstrument {
.pdas()
.mintInfo({ mint: this.stableAssetMint });
return [
{
pubkey: this.getProgramId(),
isSigner: false,
isWritable: false,
},
{ pubkey: this.optionMetaPubKey, isSigner: false, isWritable: false },
{
pubkey: mintInfoPda,
Expand Down Expand Up @@ -237,10 +304,10 @@ export class PsyoptionsAmericanInstrument implements LegInstrument {
}

export const psyoptionsAmericanInstrumentParser = {
parseFromLeg(
async parseFromLeg(
convergence: Convergence,
leg: Leg
): PsyoptionsAmericanInstrument {
): Promise<PsyoptionsAmericanInstrument> {
const { side, instrumentAmount, instrumentData, baseAssetIndex } = leg;
const [
{
Expand All @@ -257,6 +324,11 @@ export const psyoptionsAmericanInstrumentParser = {
Buffer.from(instrumentData)
);

const optionMeta = await PsyoptionsAmericanInstrument.fetchMeta(
convergence,
metaKey
);

return new PsyoptionsAmericanInstrument(
convergence,
optionType,
Expand All @@ -272,7 +344,9 @@ export const psyoptionsAmericanInstrumentParser = {
metaKey,
baseAssetIndex,
removeDecimals(instrumentAmount, PsyoptionsAmericanInstrument.decimals),
fromSolitaLegSide(side)
fromSolitaLegSide(side),
optionMeta.underlyingAssetMint,
optionMeta.quoteAssetMint
);
},
};
Expand Down
Loading