diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index a1095a022..8792880e8 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,16 @@ # @convergence-rfq/cli +## 6.5.0 + +### Minor Changes + +- Replace risk engine program with a simplified one, add squads integration + +### Patch Changes + +- Updated dependencies + - @convergence-rfq/sdk@6.5.0 + ## 6.4.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index de53d2f6a..31d79d482 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@convergence-rfq/cli", "description": "Official Convergence CLI", - "version": "6.4.2", + "version": "6.5.0", "license": "MIT", "publishConfig": { "access": "public" @@ -47,7 +47,7 @@ "cli": "ts-node src/index.ts" }, "dependencies": { - "@convergence-rfq/sdk": "6.4.2", + "@convergence-rfq/sdk": "6.5.0", "@solana/web3.js": "^1.87.6", "@types/cookie": "^0.5.1", "commander": "^10.0.0" diff --git a/packages/cli/src/actions.ts b/packages/cli/src/actions.ts index b5729e5c3..f738a4c7d 100644 --- a/packages/cli/src/actions.ts +++ b/packages/cli/src/actions.ts @@ -1,8 +1,6 @@ import { PublicKey, LAMPORTS_PER_SOL } from '@solana/web3.js'; import { token, - toRiskCategoryInfo, - toScenario, devnetAirdrops, PriceOracle, SpotLegInstrument, @@ -33,7 +31,6 @@ import { logTx, logError, logTokenAccount, - logRiskEngineConfig, logRegisteredMint, logCollateral, logToken, @@ -497,121 +494,6 @@ export const getCollateral = async (opts: Opts) => { } }; -// Risk engine - -export const initializeRiskEngine = async (opts: Opts) => { - const cvg = await createCvg(opts); - try { - const { response } = await expirationRetry( - () => - cvg.riskEngine().initializeConfig({ - collateralMintDecimals: opts.collateralMintDecimals, - minCollateralRequirement: opts.minCollateralRequirement, - collateralForFixedQuoteAmountRfqCreation: - opts.collateralForFixedQuoteAmountRfqCreation, - safetyPriceShiftFactor: opts.safetyPriceShiftFactor, - overallSafetyFactor: opts.overallSafetyFace, - acceptedOracleStaleness: opts.acceptedOracleStaleness, - acceptedOracleConfidenceIntervalPortion: - opts.acceptedOracleConfidenceIntervalPortion, - }), - opts - ); - logResponse(response); - } catch (e) { - logError(e); - } -}; - -export const updateRiskEngine = async (opts: Opts) => { - const cvg = await createCvg(opts); - try { - const { response } = await expirationRetry( - () => - cvg.riskEngine().updateConfig({ - collateralMintDecimals: opts.collateralMintDecimals, - minCollateralRequirement: opts.minCollateralRequirement, - collateralForFixedQuoteAmountRfqCreation: - opts.collateralForFixedQuoteAmountRfqCreation, - safetyPriceShiftFactor: opts.safetyPriceShiftFactor, - overallSafetyFactor: opts.overallSafetyFace, - acceptedOracleStaleness: opts.acceptedOracleStaleness, - acceptedOracleConfidenceIntervalPortion: - opts.acceptedOracleConfidenceIntervalPortion, - }), - opts - ); - logResponse(response); - } catch (e) { - logError(e); - } -}; -export const closeRiskEngine = async (opts: Opts) => { - const cvg = await createCvg(opts); - try { - const { response } = await cvg.riskEngine().closeConfig(); - logResponse(response); - } catch (e) { - logError(e); - } -}; - -export const getRiskEngineConfig = async (opts: Opts) => { - const cvg = await createCvg(opts); - try { - const config = await cvg.riskEngine().fetchConfig(); - logRiskEngineConfig(config); - } catch (e) { - logError(e); - } -}; - -export const setRiskEngineInstrumentType = async (opts: Opts) => { - const cvg = await createCvg(opts); - try { - const { response } = await expirationRetry( - () => - cvg.riskEngine().setInstrumentType({ - instrumentProgram: new PublicKey(opts.program), - instrumentType: opts.type, - }), - opts - ); - logResponse(response); - } catch (e) { - logError(e); - } -}; - -export const setRiskEngineCategoriesInfo = async (opts: Opts) => { - const newValue = opts.newValue.split(',').map((x: string) => parseFloat(x)); - const cvg = await createCvg(opts); - try { - const { response } = await expirationRetry( - () => - cvg.riskEngine().setRiskCategoriesInfo({ - changes: [ - { - value: toRiskCategoryInfo(newValue[0], newValue[1], [ - toScenario(newValue[2], newValue[3]), - toScenario(newValue[4], newValue[5]), - toScenario(newValue[6], newValue[7]), - toScenario(newValue[8], newValue[9]), - toScenario(newValue[10], newValue[11]), - toScenario(newValue[12], newValue[13]), - ]), - category: opts.category, - }, - ], - }), - opts - ); - logResponse(response); - } catch (e) { - logError(e); - } -}; - // Devnet and localnet helpers export const airdrop = async (opts: Opts) => { diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 860f86830..32f3abd85 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -1,7 +1,6 @@ import { Command } from 'commander'; import { - riskEngineGroup, protocolGroup, collateralGroup, airdropGroup, @@ -16,7 +15,6 @@ export const makeCli = (): Command => { airdropGroup, tokenGroup, protocolGroup, - riskEngineGroup, collateralGroup, rfqGroup, hxroGroup, diff --git a/packages/cli/src/groups/index.ts b/packages/cli/src/groups/index.ts index ca0333b87..59d765cc6 100644 --- a/packages/cli/src/groups/index.ts +++ b/packages/cli/src/groups/index.ts @@ -2,7 +2,6 @@ export * from './airdrop'; export * from './collateral'; export * from './protocol'; export * from './rfq'; -export * from './riskEngine'; export * from './token'; export * from './hxro'; export * from './spotInstrument'; diff --git a/packages/cli/src/groups/riskEngine.ts b/packages/cli/src/groups/riskEngine.ts deleted file mode 100644 index ea48d065a..000000000 --- a/packages/cli/src/groups/riskEngine.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { Command } from 'commander'; - -import { - initializeRiskEngine, - getRiskEngineConfig, - updateRiskEngine, - setRiskEngineInstrumentType, - setRiskEngineCategoriesInfo, - closeRiskEngine, -} from '../actions'; -import { addCmd } from '../helpers'; - -const riskEngineOptions = [ - { - flags: '--collateral-mint-decimals ', - description: 'collateral decimals', - defaultValue: '6', - }, - { - flags: '--min-collateral-requirement ', - description: 'collateral for fixed quote amount RFQ creation', - defaultValue: '10000000', - }, - { - flags: '--collateral-for-variable-size-rfq-creation ', - description: 'collateral for variable size RFQ creation', - defaultValue: '10000000', - }, - { - flags: '--collateral-for-fixed-quote-amount-rfq-creation ', - description: 'collateral for fixed quote amount RFQ creation', - defaultValue: '10000000', - }, - { - flags: '--safety-price-shift-factor ', - description: 'safety price shift factor', - defaultValue: '0.01', - }, - { - flags: '--overall-safety-factor ', - description: 'overall safety factor', - defaultValue: '0.1', - }, - { - flags: '--accepted-oracle-staleness ', - description: 'accepted oracle staleness', - defaultValue: '300', - }, - { - flags: '--accepted-oracle-confidence-interval-portion ', - description: 'accepted oracle confidence interval portion', - defaultValue: '0.1', - }, -]; - -const initializeCmd = (c: Command) => - addCmd( - c, - 'initialize', - 'initializes risk engine', - initializeRiskEngine, - riskEngineOptions - ); - -const closeCmd = (c: Command) => - addCmd(c, 'close', 'closes risk engine', closeRiskEngine); - -const updateCmd = (c: Command) => - addCmd( - c, - 'update', - 'updates risk engine', - updateRiskEngine, - riskEngineOptions - ); - -const setInstrumentTypeCmd = (c: Command) => - addCmd( - c, - 'set-instrument-type', - 'sets risk engine instrument type', - setRiskEngineInstrumentType, - [ - { - flags: '--type ', - description: 'instrument type', - }, - { - flags: '--program ', - description: 'instrument program', - }, - ] - ); - -const setCategoriesInfoCmd = (c: Command) => - addCmd( - c, - 'set-risk-categories-info', - 'sets risk engine risk categories info', - setRiskEngineCategoriesInfo, - [ - { - flags: '--category ', - description: 'category', - }, - { - flags: '--new-value ', - description: 'new value', - }, - ] - ); - -const getCmd = (c: Command) => - addCmd(c, 'get', 'gets risk engine config', getRiskEngineConfig); - -export const riskEngineGroup = (c: Command) => { - const group = c.command('risk-engine'); - initializeCmd(group); - closeCmd(group); - updateCmd(group); - setInstrumentTypeCmd(group); - setCategoriesInfoCmd(group); - getCmd(group); -}; diff --git a/packages/cli/src/logger.ts b/packages/cli/src/logger.ts index daa85a652..505cea445 100644 --- a/packages/cli/src/logger.ts +++ b/packages/cli/src/logger.ts @@ -120,22 +120,6 @@ export const logProtocol = (p: Protocol): void => { }); }; -export const logRiskEngineConfig = (r: any): void => { - l('Address:', r.address.toString()); - l( - 'Minimal collateral requirement:', - N(r.minCollateralRequirement.toString()) - ); - l( - 'Collateral for fixed quote amount RFQ creation:', - N(r.collateralForFixedQuoteAmountRfqCreation.toString()) - ); - l('Collateral mint decimals:', N(r.collateralMintDecimals.toString())); - l('Safety price shift factor:', N(r.safetyPriceShiftFactor.toString())); - l('Overall safety factor:', r.overallSafetyFactor); - r.riskCategoriesInfo.map(logRiskCategoryInfo); -}; - export const logRiskCategoryInfo = (c: any): void => { const formatRatio = (x: any) => { return [x.baseAssetPriceChange, x.volatilityChange].join('/'); diff --git a/packages/cli/tests/unit/riskEngine.spec.ts b/packages/cli/tests/unit/riskEngine.spec.ts deleted file mode 100644 index 71b1c8188..000000000 --- a/packages/cli/tests/unit/riskEngine.spec.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { expect } from 'expect'; -import sinon, { SinonStub } from 'sinon'; -import { PROGRAM_ADDRESS as SPOT_INSTRUMENT } from '@convergence-rfq/spot-instrument'; -import { PROGRAM_ADDRESS as PSYOPTIONS_AMERICAN_INSTRUMENT } from '@convergence-rfq/psyoptions-american-instrument'; -import { PROGRAM_ADDRESS as PSYOPTIONS_EUROPEAN_INSTRUMENT } from '@convergence-rfq/psyoptions-european-instrument'; - -import { ADDRESS_LABEL, TX_LABEL, runCli } from '../helpers'; - -describe('unit.riskEngine', () => { - let stub: SinonStub; - - beforeEach(() => { - stub = sinon.stub(console, 'log'); - }); - - afterEach(() => { - stub.restore(); - }); - - it('get', async () => { - await runCli(['risk-engine', 'get']); - expect(stub.args[0][0]).toEqual(ADDRESS_LABEL); - }); - - it('update', async () => { - await runCli(['risk-engine', 'update']); - expect(stub.args[0][0]).toEqual(TX_LABEL); - }); - - it('close', async () => { - await runCli(['risk-engine', 'close']); - expect(stub.args[0][0]).toEqual(TX_LABEL); - }); - - it('initialize', async () => { - await runCli(['risk-engine', 'initialize']); - expect(stub.args[0][0]).toEqual(TX_LABEL); - }); - - it('set-instrument-type [spot]', async () => { - await runCli([ - 'risk-engine', - 'set-instrument-type', - '--program', - SPOT_INSTRUMENT, - '--type', - 'spot', - ]); - expect(stub.args[0][0]).toEqual(TX_LABEL); - }); - - it('set-instrument-type [psyoptions european]', async () => { - await runCli([ - 'risk-engine', - 'set-instrument-type', - '--program', - PSYOPTIONS_EUROPEAN_INSTRUMENT, - '--type', - 'option', - ]); - expect(stub.args[0][0]).toEqual(TX_LABEL); - }); - - it('set-instrument-type [psyoptions american]', async () => { - await runCli([ - 'risk-engine', - 'set-instrument-type', - '--program', - PSYOPTIONS_AMERICAN_INSTRUMENT, - '--type', - 'option', - ]); - expect(stub.args[0][0]).toEqual(TX_LABEL); - }); - - it('set-risk-categories-info [very low]', async () => { - await runCli([ - 'risk-engine', - 'set-risk-categories-info', - '--category', - 'very-low', - '--new-value', - '0,0,0,0,0,0,0,0,0,0,0,0,0,0', - ]); - expect(stub.args[0][0]).toEqual(TX_LABEL); - }); - - it('set-risk-categories-info [low]', async () => { - await runCli([ - 'risk-engine', - 'set-risk-categories-info', - '--category', - 'low', - '--new-value', - '0,0,0,0,0,0,0,0,0,0,0,0,0,0', - ]); - expect(stub.args[0][0]).toEqual(TX_LABEL); - }); - - it('set-risk-categories-info [medium]', async () => { - await runCli([ - 'risk-engine', - 'set-risk-categories-info', - '--category', - 'medium', - '--new-value', - '0,0,0,0,0,0,0,0,0,0,0,0,0,0', - ]); - expect(stub.args[0][0]).toEqual(TX_LABEL); - }); - - it('set-risk-categories-info [high]', async () => { - await runCli([ - 'risk-engine', - 'set-risk-categories-info', - '--category', - 'high', - '--new-value', - '0,0,0,0,0,0,0,0,0,0,0,0,0,0', - ]); - expect(stub.args[0][0]).toEqual(TX_LABEL); - }); - - it('set-risk-categories-info [very high]', async () => { - await runCli([ - 'risk-engine', - 'set-risk-categories-info', - '--category', - 'very-high', - '--new-value', - '0,0,0,0,0,0,0,0,0,0,0,0,0,0', - ]); - expect(stub.args[0][0]).toEqual(TX_LABEL); - }); -}); diff --git a/packages/js/CHANGELOG.md b/packages/js/CHANGELOG.md index fa30d044e..66be5b240 100644 --- a/packages/js/CHANGELOG.md +++ b/packages/js/CHANGELOG.md @@ -1,5 +1,11 @@ # @convergence-rfq/sdk +## 6.5.0 + +### Minor Changes + +- Replace risk engine program with a simplified one, add squads integration + ## 6.4.2 ### Patch Changes diff --git a/packages/js/package.json b/packages/js/package.json index 6edede2df..d18914ab6 100644 --- a/packages/js/package.json +++ b/packages/js/package.json @@ -1,7 +1,7 @@ { "name": "@convergence-rfq/sdk", "description": "Official Convergence RFQ SDK", - "version": "6.4.2", + "version": "6.5.0", "license": "MIT", "publishConfig": { "access": "public" @@ -52,13 +52,13 @@ "@bundlr-network/client": "^0.8.8", "@convergence-rfq/beet": "0.7.10", "@convergence-rfq/beet-solana": "0.4.11", - "@convergence-rfq/hxro-print-trade-provider": "3.9.0", - "@convergence-rfq/psyoptions-american-instrument": "3.9.0", - "@convergence-rfq/psyoptions-european-instrument": "3.9.0", - "@convergence-rfq/rfq": "3.9.0", - "@convergence-rfq/risk-engine": "3.9.0", - "@convergence-rfq/spot-instrument": "3.9.0", - "@convergence-rfq/vault-operator": "^3.9.0", + "@convergence-rfq/hxro-print-trade-provider": "3.10.0", + "@convergence-rfq/psyoptions-american-instrument": "3.10.0", + "@convergence-rfq/psyoptions-european-instrument": "3.10.0", + "@convergence-rfq/rfq": "3.10.0", + "@convergence-rfq/risk-engine": "3.10.0", + "@convergence-rfq/spot-instrument": "3.10.0", + "@convergence-rfq/vault-operator": "^3.10.0", "@coral-xyz/anchor": "^0.28.0", "@coral-xyz/borsh": "^0.28.0", "@hxronetwork/dexterity-ts": "1.6.16", @@ -69,6 +69,7 @@ "@project-serum/anchor": "^0.26.0", "@solana/spl-token": "^0.3.8", "@solana/web3.js": "^1.87.6", + "@sqds/multisig": "^2.1.1", "@types/uuid": "^9.0.1", "big.js": "^6.2.1", "bignumber.js": "^9.0.2", diff --git a/packages/js/src/plugins/rfqModule/operations/confirmResponse.ts b/packages/js/src/plugins/rfqModule/operations/confirmResponse.ts index 3aae5831b..c5f8b2f28 100644 --- a/packages/js/src/plugins/rfqModule/operations/confirmResponse.ts +++ b/packages/js/src/plugins/rfqModule/operations/confirmResponse.ts @@ -17,7 +17,6 @@ import { import { Response } from '../models'; import { ResponseSide, toSolitaQuoteSide } from '../models/ResponseSide'; import { toSolitaOverrideLegMultiplierBps } from '../models/Confirmation'; -import { getRiskEngineAccounts } from '@/plugins/riskEngineModule/helpers'; const Key = 'ConfirmResponseOperation' as const; @@ -201,12 +200,6 @@ export const confirmResponseBuilder = async ( programs, }); - const rfqModel = await convergence.rfqs().findRfqByAddress({ address: rfq }); - const riskEngineAccounts = await getRiskEngineAccounts( - convergence, - rfqModel.legs - ); - return TransactionBuilder.make() .setFeePayer(payer) .add( @@ -227,7 +220,6 @@ export const confirmResponseBuilder = async ( taker: taker.publicKey, protocol: convergence.protocol().pdas().protocol(), riskEngine: convergence.programs().getRiskEngine(programs).address, - anchorRemainingAccounts: riskEngineAccounts, }, { side: toSolitaQuoteSide(side), diff --git a/packages/js/src/plugins/rfqModule/operations/finalizeRfqConstruction.ts b/packages/js/src/plugins/rfqModule/operations/finalizeRfqConstruction.ts index 23ed3a7b3..d287c82ad 100644 --- a/packages/js/src/plugins/rfqModule/operations/finalizeRfqConstruction.ts +++ b/packages/js/src/plugins/rfqModule/operations/finalizeRfqConstruction.ts @@ -17,7 +17,6 @@ import { } from '../../../types'; import { Convergence } from '../../../Convergence'; import { LegInstrument } from '@/plugins/instrumentModule'; -import { getRiskEngineAccounts } from '@/plugins/riskEngineModule/helpers'; import { PrintTradeLeg } from '@/plugins/printTradeModule'; const Key = 'FinalizeRfqConstructionOperation' as const; @@ -198,8 +197,6 @@ export const finalizeRfqConstructionBuilder = async ( collateralInfo = collateralInfo ?? collateralInfoPda; collateralToken = collateralToken ?? collateralTokenPda; - const riskEngineAccounts = await getRiskEngineAccounts(convergence, legs); - const protocol = convergence.protocol().pdas().protocol(); return TransactionBuilder.make() @@ -223,7 +220,6 @@ export const finalizeRfqConstructionBuilder = async ( collateralInfo, collateralToken, riskEngine, - anchorRemainingAccounts: riskEngineAccounts, }, rfqProgram.address ), diff --git a/packages/js/src/plugins/rfqModule/operations/respondToRfq.ts b/packages/js/src/plugins/rfqModule/operations/respondToRfq.ts index 4761f477d..3dd4d8b30 100644 --- a/packages/js/src/plugins/rfqModule/operations/respondToRfq.ts +++ b/packages/js/src/plugins/rfqModule/operations/respondToRfq.ts @@ -18,7 +18,6 @@ import { import { Quote, Rfq } from '../models'; import { toSolitaQuote } from '../models/Quote'; import { rfqProgram } from '../program'; -import { getRiskEngineAccounts } from '@/plugins/riskEngineModule/helpers'; import { convertTimestampToSeconds } from '@/utils'; import { AdditionalResponseData, @@ -275,11 +274,6 @@ export const respondToRfqBuilder = async ( rfqModel ); - const riskEngineAccounts = await getRiskEngineAccounts( - convergence, - rfqModel.legs - ); - const defaultPubkey = PublicKey.default; const whitelist = rfqModel.whitelist.toBase58() !== defaultPubkey.toBase58() @@ -322,10 +316,7 @@ export const respondToRfqBuilder = async ( riskEngine, whitelist, maker: maker.publicKey, - anchorRemainingAccounts: [ - ...validateResponseAccounts, - ...riskEngineAccounts, - ], + anchorRemainingAccounts: validateResponseAccounts, }, { bid: bid && toSolitaQuote(bid, rfqModel.quoteAsset.getDecimals()), diff --git a/packages/js/src/plugins/riskEngineModule/RiskEngineClient.ts b/packages/js/src/plugins/riskEngineModule/RiskEngineClient.ts index a5b877fac..55648560b 100644 --- a/packages/js/src/plugins/riskEngineModule/RiskEngineClient.ts +++ b/packages/js/src/plugins/riskEngineModule/RiskEngineClient.ts @@ -1,23 +1,11 @@ import { - initializeConfigOperation, - InitializeConfigInput, - updateConfigOperation, - UpdateConfigInput, - SetInstrumentTypeInput, - setInstrumentTypeOperation, calculateCollateralForConfirmationOperation, calculateCollateralForResponseOperation, calculateCollateralForRfqOperation, CalculateCollateralForConfirmationInput, CalculateCollateralForRfqInput, CalculateCollateralForResponseInput, - setRiskCategoriesInfoOperation, - SetRiskCategoriesInfoInput, - fetchConfigOperation, - CloseConfigInput, - closeConfigOperation, } from './operations'; -import { RiskEnginePdasClient } from './RiskEnginePdasClient'; import type { Convergence } from '@/Convergence'; import { OperationOptions } from '@/types'; @@ -36,55 +24,6 @@ import { OperationOptions } from '@/types'; export class RiskEngineClient { constructor(protected readonly convergence: Convergence) {} - /** - * You may use the `pdas()` client to build PDAs related to this module. - * - * ```ts - * const pdasClient = convergence.riskEngine().pdas(); - * ``` - */ - pdas() { - return new RiskEnginePdasClient(this.convergence); - } - - /** {@inheritDoc initializeConfig} */ - initializeConfig(input?: InitializeConfigInput, options?: OperationOptions) { - return this.convergence - .operations() - .execute(initializeConfigOperation(input), options); - } - - /** {@inheritDoc updateConfig} */ - updateConfig(input?: UpdateConfigInput, options?: OperationOptions) { - return this.convergence - .operations() - .execute(updateConfigOperation(input), options); - } - - /** {@inheritDoc closeConfig} */ - closeConfig(input?: CloseConfigInput, options?: OperationOptions) { - return this.convergence - .operations() - .execute(closeConfigOperation(input), options); - } - - /** {@inheritDoc setInstrumentTypeOperation} */ - setInstrumentType(input: SetInstrumentTypeInput, options?: OperationOptions) { - return this.convergence - .operations() - .execute(setInstrumentTypeOperation(input), options); - } - - /** {@inheritDoc setRiskCategoriesInfoOperation} */ - setRiskCategoriesInfo( - input: SetRiskCategoriesInfoInput, - options?: OperationOptions - ) { - return this.convergence - .operations() - .execute(setRiskCategoriesInfoOperation(input), options); - } - /** {@inheritDoc calculateCollateralForRfq} */ calculateCollateralForRfq( input: CalculateCollateralForRfqInput, @@ -114,11 +53,4 @@ export class RiskEngineClient { .operations() .execute(calculateCollateralForConfirmationOperation(input), options); } - - /** {@inheritDoc fetchConfig} */ - fetchConfig(options?: OperationOptions) { - return this.convergence - .operations() - .execute(fetchConfigOperation({}), options); - } } diff --git a/packages/js/src/plugins/riskEngineModule/RiskEnginePdasClient.ts b/packages/js/src/plugins/riskEngineModule/RiskEnginePdasClient.ts deleted file mode 100644 index e6c30ff06..000000000 --- a/packages/js/src/plugins/riskEngineModule/RiskEnginePdasClient.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Buffer } from 'buffer'; - -import type { Convergence } from '../../Convergence'; -import { Pda, Program } from '../../types'; - -/** - * This client allows you to build PDAs related to the protocol module. - * - * @see {@link RiskEnginePdasClient} - * @group Module Pdas - */ -export class RiskEnginePdasClient { - constructor(protected readonly convergence: Convergence) {} - - /** Finds the Config PDA. */ - config(): Pda { - const programId = this.programId(); - return Pda.find(programId, [Buffer.from('config', 'utf8')]); - } - - private programId(programs?: Program[]) { - return this.convergence.programs().getRiskEngine(programs).address; - } -} diff --git a/packages/js/src/plugins/riskEngineModule/accounts.ts b/packages/js/src/plugins/riskEngineModule/accounts.ts deleted file mode 100644 index e34e14898..000000000 --- a/packages/js/src/plugins/riskEngineModule/accounts.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Config } from '@convergence-rfq/risk-engine'; - -import { - Account, - getAccountParsingAndAssertingFunction, - getAccountParsingFunction, -} from '../../types'; - -/** @group Accounts */ -export type ConfigAccount = Account; - -/** @group Account Helpers */ -export const parseConfigAccount = getAccountParsingFunction(Config); - -/** @group Account Helpers */ -export const toConfigAccount = getAccountParsingAndAssertingFunction(Config); diff --git a/packages/js/src/plugins/riskEngineModule/cache.ts b/packages/js/src/plugins/riskEngineModule/cache.ts deleted file mode 100644 index 82b496118..000000000 --- a/packages/js/src/plugins/riskEngineModule/cache.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Convergence } from '../../Convergence'; -import { useCache } from '../../utils'; -import { toConfigAccount } from './accounts'; -import { assertConfig, toConfig } from './models'; - -export const riskEngineConfigCache = useCache( - async (cvg: Convergence, commitment = 'confirmed') => { - const account = await cvg - .rpc() - .getAccount(cvg.riskEngine().pdas().config(), commitment); - - const config = toConfig(toConfigAccount(account)); - assertConfig(config); - - return config; - } -); diff --git a/packages/js/src/plugins/riskEngineModule/clientCollateralCalculator.ts b/packages/js/src/plugins/riskEngineModule/clientCollateralCalculator.ts deleted file mode 100644 index b35d56865..000000000 --- a/packages/js/src/plugins/riskEngineModule/clientCollateralCalculator.ts +++ /dev/null @@ -1,496 +0,0 @@ -import { RiskCategory } from '@convergence-rfq/rfq'; -import { - futureCommonDataBeet, - optionCommonDataBeet, - OptionType, - RiskCategoryInfo, - Scenario, -} from '@convergence-rfq/risk-engine'; -import { Commitment, PublicKey } from '@solana/web3.js'; -// @ts-ignore this package is missing type declarations -import { blackScholes } from 'black-scholes'; - -import { Convergence } from '../../Convergence'; -import { toPriceOracle, toSolitaRiskCategory } from '../protocolModule'; -import { LegInstrument } from '../instrumentModule'; -import { AuthoritySide } from '../rfqModule/models/AuthoritySide'; -import { PrintTradeLeg } from '../printTradeModule'; -import { ResponseSide } from '../rfqModule'; -import { AggregatorAccount } from './switchboard/aggregatorAccount'; -import { AggregatorAccountData } from './switchboard/types/aggregatorAccountData'; -import { Config, InstrumentType } from './models'; -import { - FUTURE_UNDERLYING_AMOUNT_PER_CONTRACT_DECIMALS, - SETTLEMENT_WINDOW_BREAKPOINS, - SETTLEMENT_WINDOW_PEDIODS, -} from './constants'; -import { removeDecimals } from '@/utils/conversions'; - -export type CalculationCase = { - legsMultiplier: number; - authoritySide: AuthoritySide; - quoteSide: ResponseSide; -}; - -type PortfolioStatistics = { - maxLoss: number; - maxProfit: number; -}; - -type BaseAssetStatistics = { - biggestLoss: number; - biggestProfit: number; - absoluteValueOfLegs: number; -}; - -type BaseAssetInfo = { - index: number; - riskCategory: RiskCategory; - price: number; -}; - -type LegInfo = { - baseAssetIndex: number; - amount: number; - instrumentType: InstrumentType; - data: Buffer; -}; - -export async function calculateRisk( - convergence: Convergence, - config: Config, - legs: LegInstrument[] | PrintTradeLeg[], - cases: CalculationCase[], - settlementPeriod: number, - commitment?: Commitment -) { - const baseAssetIds = new Set( - legs.map((leg) => leg.getBaseAssetIndex().value) - ); // select unique base asset ids - const baseAssetInfos = await Promise.all( - Array.from(baseAssetIds).map((id) => - fetchBaseAssetInfo(convergence, id, commitment) - ) - ); - - const legInfos: LegInfo[] = legs.map((leg) => { - let amount = leg.getAmount(); - if (leg.getSide() == 'long') { - amount = -amount; - } - - let assetType: InstrumentType; - if (leg.legType === 'printTrade') { - assetType = leg.getInstrumentType(); - } else { - const escrowAssetType = config.instrumentTypes[leg.getInstrumentIndex()]; - if (escrowAssetType === null) { - throw new Error( - `Instrument index ${leg.getInstrumentIndex()} is not registered in the risk engine` - ); - } - - if (escrowAssetType === undefined) { - throw Error( - `Instrument ${leg - .getProgramId() - .toString()} is missing from risk engine config!` - ); - } - - assetType = escrowAssetType; - } - - return { - baseAssetIndex: leg.getBaseAssetIndex().value, - amount, - instrumentType: assetType, - data: Buffer.from(leg.serializeInstrumentData()), - }; - }); - - const statistics = calculatePortfolioStatistics( - legInfos, - config, - baseAssetInfos, - settlementPeriod - ); - - const results: number[] = []; - for (const calculationCase of cases) { - results.push(calculateRiskInner(statistics, calculationCase, config)); - } - - return results; -} - -function calculateRiskInner( - statistics: PortfolioStatistics, - calculationCase: CalculationCase, - config: Config -): number { - let portfolioInverted = false; - - if (calculationCase.quoteSide.hasOwnProperty('bid')) { - portfolioInverted = !portfolioInverted; - } - - if (calculationCase.authoritySide.hasOwnProperty('taker')) { - portfolioInverted = !portfolioInverted; - } - - let portfolioRisk = portfolioInverted - ? statistics.maxProfit - : statistics.maxLoss; - portfolioRisk = Math.max(portfolioRisk, 0); // risk can't be lower that 0 - - return Math.max( - portfolioRisk * calculationCase.legsMultiplier, - removeDecimals( - config.minCollateralRequirement, - Number(config.collateralMintDecimals) - ) - ); -} - -async function fetchBaseAssetInfo( - convergence: Convergence, - baseAssetIndex: number, - commitment?: Commitment -): Promise { - const address = convergence - .protocol() - .pdas() - .baseAsset({ index: baseAssetIndex }); - const baseAsset = await convergence - .protocol() - .findBaseAssetByAddress({ address }); - const priceOracle = toPriceOracle(baseAsset); - - let price: number; - - if (priceOracle.price !== undefined) { - price = priceOracle.price; - } else { - if (priceOracle.address === undefined) { - throw Error('Price oracle address is missing'); - } - price = await fetchLatestOraclePrice( - convergence, - priceOracle.address, - commitment - ); - } - - return { - index: baseAssetIndex, - riskCategory: toSolitaRiskCategory(baseAsset.riskCategory), - price, - }; -} - -async function fetchLatestOraclePrice( - convergence: Convergence, - aggregatorPubkey: PublicKey, - commitment?: Commitment -) { - // TODO: Use retry method - const aggregatorAccount = await convergence.connection.getAccountInfo( - aggregatorPubkey, - commitment - ); - - if (aggregatorAccount === null) { - throw Error( - `Expected price aggregator at address ${aggregatorPubkey}, but the account is missing` - ); - } - - const aggregatorData = AggregatorAccountData.decode(aggregatorAccount.data); - const decodedPrice = AggregatorAccount.decodeLatestValue(aggregatorData); - - if (decodedPrice === null) { - throw Error( - `Price from the aggregator at address ${aggregatorPubkey} can't be parsed!` - ); - } - - return decodedPrice.toNumber(); -} - -function calculatePortfolioStatistics( - legs: LegInfo[], - config: Config, - baseAssetInfos: BaseAssetInfo[], - settlementPeriod: number -): PortfolioStatistics { - let allProfits = 0.0; - let allLosses = 0.0; - let totalLegValues = 0.0; - - for (const baseAsset of baseAssetInfos) { - const { biggestLoss, biggestProfit, absoluteValueOfLegs } = - calculateStatisticsForBaseAsset( - legs, - config, - baseAsset, - settlementPeriod - ); - - allProfits += biggestProfit; - allLosses -= biggestLoss; - totalLegValues += absoluteValueOfLegs; - } - - const priceShift = totalLegValues * config.safetyPriceShiftFactor; - - allProfits += priceShift; - allLosses += priceShift; - allProfits = applyOverallRiskFactor(allProfits, config); - allLosses = applyOverallRiskFactor(allLosses, config); - - return { - maxLoss: allLosses, - maxProfit: allProfits, - }; -} - -function applyOverallRiskFactor(value: number, config: Config): number { - return value * (config.overallSafetyFactor + 1.0); -} - -function calculateStatisticsForBaseAsset( - allLegs: LegInfo[], - config: Config, - baseAssetInfo: BaseAssetInfo, - settlementPeriod: number -): BaseAssetStatistics { - const legs = allLegs.filter( - (leg) => leg.baseAssetIndex == baseAssetInfo.index - ); - const riskCategoryInfo = - config.riskCategoriesInfo[baseAssetInfo.riskCategory]; - - const legValues = legs.map((leg) => - calculateCurrentValue(leg, baseAssetInfo.price, riskCategoryInfo) - ); - const scenarios = selectScenarios(legs, riskCategoryInfo, settlementPeriod); - - let biggestProfit = Number.MIN_VALUE; - let biggestLoss = Number.MAX_VALUE; - for (const scenario of scenarios) { - const pnl = calculateScenario( - legs, - legValues, - scenario, - baseAssetInfo.price, - riskCategoryInfo - ); - - biggestProfit = Math.max(biggestProfit, pnl); - biggestLoss = Math.min(biggestLoss, pnl); - } - - const absoluteValueOfLegs = legValues - .map((value) => Math.abs(value)) - .reduce((x, y) => x + y, 0); - - return { - biggestProfit, - biggestLoss, - absoluteValueOfLegs, - }; -} - -function calculateCurrentValue( - leg: LegInfo, - price: number, - riskCategoryInfo: RiskCategoryInfo -) { - return calculateAssetValue( - leg, - price, - riskCategoryInfo.annualized30DayVolatility, - riskCategoryInfo.interestRate - ); -} - -function calculateAssetValue( - leg: LegInfo, - price: number, - annualized30DayVolatility: number, - interestRate: number -): number { - const unitValue = calculateAssetUnitValue( - leg, - price, - annualized30DayVolatility, - interestRate - ); - - return unitValue * leg.amount; -} - -function calculateAssetUnitValue( - leg: LegInfo, - price: number, - annualized30DayVolatility: number, - interestRate: number -): number { - switch (leg.instrumentType) { - case 'spot': - return price; - case 'term-future': - case 'perp-future': - const [futureCommonData] = futureCommonDataBeet.deserialize(leg.data); - const amountPerContract = - Number(futureCommonData.underlyingAmountPerContract) / - 10 ** FUTURE_UNDERLYING_AMOUNT_PER_CONTRACT_DECIMALS; - return price * amountPerContract; - case 'option': - const [optionCommonData] = optionCommonDataBeet.deserialize(leg.data); - const optionType = - optionCommonData.optionType == OptionType.Call ? 'call' : 'put'; - - const underlyingAmountPerContract = - Number(optionCommonData.underlyingAmountPerContract) / - 10 ** optionCommonData.underlyingAmountPerContractDecimals; - - const strikePrice = - Number(optionCommonData.strikePrice) / - 10 ** optionCommonData.strikePriceDecimals; - - const expirationTimestamp = Number(optionCommonData.expirationTimestamp); - - const currentTimestamp = Math.floor(Date.now() / 1000); - const secondsTillExpiration = Math.max( - 0, - expirationTimestamp - currentTimestamp - ); - const secondsInYear = 365 * 24 * 60 * 60; - const yearsTillExpiration = secondsTillExpiration / secondsInYear; - - const optionPrice = blackScholes( - price, - strikePrice, - yearsTillExpiration, - annualized30DayVolatility, - interestRate, - optionType - ); - - return optionPrice * underlyingAmountPerContract; - } -} - -function selectScenarios( - legs: LegInfo[], - riskCategoryInfo: RiskCategoryInfo, - settlementPeriod: number -): Scenario[] { - const haveOptionLegs = - legs.filter((leg) => leg.instrumentType === 'option').length > 0; - - const getScenarioIndex = (settlementPeriod: number) => { - for (let i = 0; i < SETTLEMENT_WINDOW_BREAKPOINS.length; i++) { - const breakpoint = SETTLEMENT_WINDOW_BREAKPOINS[i]; - if (settlementPeriod < breakpoint) { - return i; - } - } - - return SETTLEMENT_WINDOW_PEDIODS - 1; - }; - - const scenarioIndex = getScenarioIndex(settlementPeriod); - const baseScenario = - riskCategoryInfo.scenarioPerSettlementPeriod[scenarioIndex]; - - const scenarioConstructor = ( - baseAssetPriceChange: number, - volatilityChange: number - ) => { - return { baseAssetPriceChange, volatilityChange }; - }; - - if (haveOptionLegs) { - return [ - baseScenario, - scenarioConstructor( - baseScenario.baseAssetPriceChange, - -baseScenario.volatilityChange - ), - scenarioConstructor( - -baseScenario.baseAssetPriceChange, - baseScenario.volatilityChange - ), - scenarioConstructor( - -baseScenario.baseAssetPriceChange, - -baseScenario.volatilityChange - ), - ]; - } - - return [ - scenarioConstructor(baseScenario.baseAssetPriceChange, 0.0), - scenarioConstructor(-baseScenario.baseAssetPriceChange, 0.0), - ]; -} - -function calculateScenario( - legs: LegInfo[], - legValues: number[], - scenario: Scenario, - price: number, - riskCategoryInfo: RiskCategoryInfo -): number { - let totalPnl = 0.0; - - for (const [index, leg] of legs.entries()) { - const pnl = calculateLegPnl( - leg, - legValues[index], - scenario, - price, - riskCategoryInfo - ); - totalPnl += pnl; - } - - return totalPnl; -} - -function calculateLegPnl( - leg: LegInfo, - legValue: number, - scenario: Scenario, - price: number, - riskCategoryInfo: RiskCategoryInfo -): number { - const shockedValue = calculateShockedValue( - leg, - scenario, - price, - riskCategoryInfo - ); - return shockedValue - legValue; -} - -function calculateShockedValue( - leg: LegInfo, - scenario: Scenario, - price: number, - riskCategoryInfo: RiskCategoryInfo -): number { - const shockedPrice = price * (scenario.baseAssetPriceChange + 1.0); - const shockedVolatility = - riskCategoryInfo.annualized30DayVolatility * - (scenario.volatilityChange + 1.0); - - return calculateAssetValue( - leg, - shockedPrice, - shockedVolatility, - riskCategoryInfo.interestRate - ); -} diff --git a/packages/js/src/plugins/riskEngineModule/constants.ts b/packages/js/src/plugins/riskEngineModule/constants.ts deleted file mode 100644 index 3ca19f761..000000000 --- a/packages/js/src/plugins/riskEngineModule/constants.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { RiskCategoryInfo, Scenario } from '@convergence-rfq/risk-engine'; - -import { toBigNumber as tbn } from '../../types'; - -export const DEFAULT_MIN_COLLATERAL_REQUIREMENT = tbn(0); - -export const DEFAULT_COLLATERAL_FOR_FIXED_QUOTE_AMOUNT_RFQ = tbn(0); - -export const DEFAULT_MINT_DECIMALS = 9; - -export const DEFAULT_SAFETY_PRICE_SHIFT_FACTOR = 0; - -export const DEFAULT_OVERALL_SAFETY_FACTOR = 0; - -export const DEFAULT_ORACLE_STALENESS = 60 * 60 * 24 * 365 * 10; - -export const DEFAULT_ACCEPTED_ORACLE_CONFIDENCE_INTERVAL_POSITION = 0.1; - -export const DEFAULT_ACCEPTED_ORACLE_STALENESS = 60 * 60 * 24 * 365 * 10; -export const DEFAULT_ACCEPTED_ORACLE_CONFIDENCE_INTERVAL_PORTION = 0.01; - -export const SETTLEMENT_WINDOW_PEDIODS = 6; -export const SETTLEMENT_WINDOW_BREAKPOINS = [ - 60 * 60, - 4 * 60 * 60, - 12 * 60 * 60, - 24 * 60 * 60, - 48 * 60 * 60, -]; - -export const FUTURE_UNDERLYING_AMOUNT_PER_CONTRACT_DECIMALS = 9; -export const OPTION_UNDERLYING_AMOUNT_PER_CONTRACT_DECIMALS = 9; -export const OPTION_STRIKE_PRICE_DECIMALS = 9; - -export const DEFAULT_RISK_CATEGORIES_INFO = { - veryLow: toRiskCategoryInfo(0, 0, [ - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - ]), - low: toRiskCategoryInfo(0, 0, [ - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - ]), - medium: toRiskCategoryInfo(0, 0, [ - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - ]), - high: toRiskCategoryInfo(0, 0, [ - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - ]), - veryHigh: toRiskCategoryInfo(0, 0, [ - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - toScenario(0, 0), - ]), -}; - -export function toScenario( - baseAssetPriceChange: number, - volatilityChange: number -): Scenario { - return { - baseAssetPriceChange, - volatilityChange, - }; -} - -export function toRiskCategoryInfo( - interestRate: number, - annualized30DayVolatility: number, - scenarioPerSettlementPeriod: [ - Scenario, - Scenario, - Scenario, - Scenario, - Scenario, - Scenario - ] -): RiskCategoryInfo { - return { - interestRate, - annualized30DayVolatility, - scenarioPerSettlementPeriod, - }; -} diff --git a/packages/js/src/plugins/riskEngineModule/helpers.ts b/packages/js/src/plugins/riskEngineModule/helpers.ts deleted file mode 100644 index bbe644d27..000000000 --- a/packages/js/src/plugins/riskEngineModule/helpers.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { AccountMeta, PublicKey } from '@solana/web3.js'; -import { LegInstrument } from '../instrumentModule'; -import { PrintTradeLeg } from '../printTradeModule'; -import { toPriceOracle } from '../protocolModule'; -import { Convergence } from '@/Convergence'; - -export async function getRiskEngineAccounts( - cvg: Convergence, - legs: LegInstrument[] | PrintTradeLeg[] -): Promise { - const configAddress = cvg.riskEngine().pdas().config(); - - const baseAssetIndexSet: Set = new Set( - legs.map((leg) => leg.getBaseAssetIndex().value) - ); - const uniqueBaseAssetIndexes = Array.from(baseAssetIndexSet); - - const baseAssetAddresses = uniqueBaseAssetIndexes.map((value) => - cvg.protocol().pdas().baseAsset({ index: value }) - ); - - const oracleInfos = await Promise.all( - baseAssetAddresses.map(async (baseAsset) => - cvg.protocol().findBaseAssetByAddress({ address: baseAsset }) - ) - ); - const oracleAddresses = oracleInfos - .map((oracleInfo) => toPriceOracle(oracleInfo).address) - .filter((address): address is PublicKey => address !== undefined); - - const allAddresses = [ - configAddress, - ...baseAssetAddresses, - ...oracleAddresses, - ]; - - return allAddresses.map((address) => ({ - pubkey: address, - isSigner: false, - isWritable: false, - })); -} diff --git a/packages/js/src/plugins/riskEngineModule/index.ts b/packages/js/src/plugins/riskEngineModule/index.ts index b5b780aad..9eb94b038 100644 --- a/packages/js/src/plugins/riskEngineModule/index.ts +++ b/packages/js/src/plugins/riskEngineModule/index.ts @@ -3,7 +3,4 @@ export * from './plugin'; export * from './RiskEngineClient'; export * from './types'; export * from './operations'; -export * from './constants'; export * from './models'; -export * from './accounts'; -export * from './cache'; diff --git a/packages/js/src/plugins/riskEngineModule/models/Config.ts b/packages/js/src/plugins/riskEngineModule/models/Config.ts deleted file mode 100644 index f84a8d99a..000000000 --- a/packages/js/src/plugins/riskEngineModule/models/Config.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { PublicKey } from '@solana/web3.js'; -import { RiskCategoryChange as SolitaRiskCategoryChange } from '@convergence-rfq/risk-engine'; -import { bignum } from '@convergence-rfq/beet'; - -import { ConfigAccount } from '../accounts'; -import { RiskCategoryInfo } from '../types'; -import { assert } from '../../../utils/assert'; -import { - RiskCategory, - toSolitaRiskCategory, -} from '../../protocolModule/models'; -import { InstrumentType, fromSolitaInstrumentType } from './InstrumentType'; - -/** - * This model captures all the relevant information about a Risk Engine Config - * on the Solana blockchain. - * - * @group Models - */ -export type Config = { - /** A model identifier to distinguish models in the SDK. */ - readonly model: 'config'; - - /** The address of the config. */ - readonly address: PublicKey; - - /** The amount of collateral required to create an RFQ with a variable size. */ - readonly minCollateralRequirement: bignum; - - /** The amount of collateral required to create an RFQ with a fixed size. */ - readonly collateralForFixedQuoteAmountRfqCreation: bignum; - - /** The number of decimals of the collateral mint. */ - readonly collateralMintDecimals: bignum; - - /** The safety price shift factor. */ - readonly safetyPriceShiftFactor: number; - - /** The overall safety factor. */ - readonly overallSafetyFactor: number; - - /** The risk categories info. */ - readonly riskCategoriesInfo: RiskCategoryInfo[]; - - /** The instrument types info. */ - readonly instrumentTypes: (InstrumentType | null)[]; -}; - -export type RiskCategoryChange = { - /** The risk category index. */ - category: RiskCategory; - - /** The risk category info. */ - value: any; -}; - -/** @group Model helpers */ -export const toSolitaRiskCategoryChange = ( - change: RiskCategoryChange -): SolitaRiskCategoryChange => { - return { - riskCategoryIndex: toSolitaRiskCategory(change.category), - newValue: change.value, - }; -}; - -/** @group Model helpers */ -export const isConfig = (value: any): value is Response => - typeof value === 'object' && value.model === 'config'; - -/** @group Model helpers */ -export function assertConfig(value: any): asserts value is Response { - assert(isConfig(value), 'Expected Config model'); -} - -/** @group Model helpers */ -export const toConfig = (account: ConfigAccount): Config => ({ - model: 'config', - address: account.publicKey, - minCollateralRequirement: account.data.minCollateralRequirement, - collateralForFixedQuoteAmountRfqCreation: - account.data.collateralForFixedQuoteAmountRfqCreation, - collateralMintDecimals: account.data.collateralMintDecimals, - safetyPriceShiftFactor: account.data.safetyPriceShiftFactor, - overallSafetyFactor: account.data.overallSafetyFactor, - riskCategoriesInfo: account.data.riskCategoriesInfo, - instrumentTypes: account.data.instrumentTypes.map((instrumentType) => - fromSolitaInstrumentType(instrumentType) - ), -}); diff --git a/packages/js/src/plugins/riskEngineModule/models/InstrumentType.ts b/packages/js/src/plugins/riskEngineModule/models/InstrumentType.ts index 1113bf246..c894afd9e 100644 --- a/packages/js/src/plugins/riskEngineModule/models/InstrumentType.ts +++ b/packages/js/src/plugins/riskEngineModule/models/InstrumentType.ts @@ -1,51 +1,5 @@ -import { - StoredInstrumentType as SolitaStoredInstrumentType, - InstrumentType as SolitaInstrumentType, -} from '@convergence-rfq/risk-engine'; - export type InstrumentType = 'spot' | 'option' | 'term-future' | 'perp-future'; -export function fromSolitaInstrumentType( - instrumentType: SolitaStoredInstrumentType -): InstrumentType | null { - switch (instrumentType) { - case SolitaStoredInstrumentType.Missing: { - return null; - } - case SolitaStoredInstrumentType.Spot: { - return 'spot'; - } - case SolitaStoredInstrumentType.Option: { - return 'option'; - } - case SolitaStoredInstrumentType.PerpFuture: { - return 'perp-future'; - } - case SolitaStoredInstrumentType.TermFuture: { - return 'term-future'; - } - } -} - -export function toSolitaInstrumentType( - instrumentType: InstrumentType -): SolitaInstrumentType { - switch (instrumentType) { - case 'spot': { - return SolitaInstrumentType.Spot; - } - case 'option': { - return SolitaInstrumentType.Option; - } - case 'perp-future': { - return SolitaInstrumentType.PerpFuture; - } - case 'term-future': { - return SolitaInstrumentType.TermFuture; - } - } -} - export function toNumberInstrumentType(instrumentType: InstrumentType): number { switch (instrumentType) { case 'spot': { diff --git a/packages/js/src/plugins/riskEngineModule/models/index.ts b/packages/js/src/plugins/riskEngineModule/models/index.ts index aabad9298..9b30a75e5 100644 --- a/packages/js/src/plugins/riskEngineModule/models/index.ts +++ b/packages/js/src/plugins/riskEngineModule/models/index.ts @@ -1,2 +1 @@ -export * from './Config'; export * from './InstrumentType'; diff --git a/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForConfirmation.ts b/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForConfirmation.ts index 59a4029f2..c14946a7c 100644 --- a/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForConfirmation.ts +++ b/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForConfirmation.ts @@ -1,7 +1,6 @@ import { PublicKey } from '@solana/web3.js'; import { Confirmation } from '../../rfqModule/models/Confirmation'; -import { CalculationCase, calculateRisk } from '../clientCollateralCalculator'; import { Convergence } from '@/Convergence'; import { Operation, @@ -9,7 +8,6 @@ import { OperationScope, useOperation, } from '@/types'; -import { extractLegsMultiplier } from '@/plugins/rfqModule/helpers'; const Key = 'CalculateCollateralForConfirmationOperation' as const; @@ -75,48 +73,10 @@ export type CalculateCollateralForConfirmationBuilderParams = export const calculateCollateralForConfirmationOperationHandler: OperationHandler = { handle: async ( - operation: CalculateCollateralForConfirmationOperation, - convergence: Convergence, - scope: OperationScope + _operation: CalculateCollateralForConfirmationOperation, + _convergence: Convergence, + _scope: OperationScope ) => { - scope.throwIfCanceled(); - - const { rfqAddress, responseAddress, confirmation } = operation.input; - - // fetching in parallel - const [rfq, response, config] = await Promise.all([ - convergence.rfqs().findRfqByAddress({ address: rfqAddress }, scope), - convergence - .rfqs() - .findResponseByAddress({ address: responseAddress }, scope), - convergence.riskEngine().fetchConfig(scope), - ]); - - const confirmedQuote = - confirmation.side == 'bid' ? response.bid : response.ask; - if (confirmedQuote === null) { - throw Error('Cannot confirm a missing quote!'); - } - const legsMultiplier = extractLegsMultiplier( - rfq, - confirmedQuote, - confirmation - ); - const calculationCase: CalculationCase = { - legsMultiplier, - authoritySide: 'taker', - quoteSide: confirmation.side, - }; - - const [requiredCollateral] = await calculateRisk( - convergence, - config, - rfq.legs, - [calculationCase], - rfq.settlingWindow, - scope.commitment - ); - - return { requiredCollateral }; + return { requiredCollateral: 0 }; }, }; diff --git a/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForResponse.ts b/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForResponse.ts index 109eb3dbe..cbf16fde5 100644 --- a/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForResponse.ts +++ b/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForResponse.ts @@ -1,6 +1,5 @@ import { PublicKey } from '@solana/web3.js'; -import { CalculationCase, calculateRisk } from '../clientCollateralCalculator'; import { Operation, OperationHandler, @@ -8,8 +7,7 @@ import { useOperation, } from '../../../types'; import { Convergence } from '../../../Convergence'; -import { Quote, ResponseSide } from '../../rfqModule'; -import { extractLegsMultiplier } from '@/plugins/rfqModule/helpers'; +import { Quote } from '../../rfqModule'; const Key = 'CalculateCollateralForResponseOperation' as const; @@ -76,44 +74,10 @@ export type CalculateCollateralForResponseBuilderParams = export const calculateCollateralForResponseOperationHandler: OperationHandler = { handle: async ( - operation: CalculateCollateralForResponseOperation, - convergence: Convergence, - scope: OperationScope + _operation: CalculateCollateralForResponseOperation, + _convergence: Convergence, + _scope: OperationScope ): Promise => { - const { rfqAddress, bid, ask } = operation.input; - - const [rfq, config] = await Promise.all([ - convergence.rfqs().findRfqByAddress({ address: rfqAddress }, scope), - convergence.riskEngine().fetchConfig(scope), - ]); - - const getCase = (quote: Quote, side: ResponseSide): CalculationCase => { - const legsMultiplier = extractLegsMultiplier(rfq, quote); - return { - legsMultiplier, - authoritySide: 'maker', - quoteSide: side, - }; - }; - - const cases: CalculationCase[] = []; - if (bid) { - cases.push(getCase(bid, 'bid')); - } - if (ask) { - cases.push(getCase(ask, 'ask')); - } - - const risks = await calculateRisk( - convergence, - config, - rfq.legs, - cases, - rfq.settlingWindow, - scope.commitment - ); - const requiredCollateral = risks.reduce((x, y) => Math.max(x, y), 0); - - return { requiredCollateral }; + return { requiredCollateral: 0 }; }, }; diff --git a/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForRfq.ts b/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForRfq.ts index de60fc0d5..1abb4a7ba 100644 --- a/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForRfq.ts +++ b/packages/js/src/plugins/riskEngineModule/operations/calculateCollateralForRfq.ts @@ -1,10 +1,3 @@ -import { - isFixedSizeBaseAsset, - isFixedSizeOpen, - isFixedSizeQuoteAsset, -} from '../../rfqModule/models'; - -import { calculateRisk, CalculationCase } from '../clientCollateralCalculator'; import { Operation, OperationHandler, @@ -13,8 +6,7 @@ import { } from '../../../types'; import { Convergence } from '../../../Convergence'; import { LegInstrument } from '../../../plugins/instrumentModule'; -import { removeDecimals } from '../../../utils/conversions'; -import { FixedSize, OrderType, ResponseSide } from '../../../plugins/rfqModule'; +import { FixedSize, OrderType } from '../../../plugins/rfqModule'; import { PrintTradeLeg } from '@/plugins/printTradeModule'; const Key = 'CalculateCollateralForRfqOperation' as const; @@ -92,69 +84,10 @@ export type CalculateCollateralForRfqBuilderParams = export const calculateCollateralForRfqOperationHandler: OperationHandler = { handle: async ( - operation: CalculateCollateralForRfqOperation, - convergence: Convergence, - scope: OperationScope + _operation: CalculateCollateralForRfqOperation, + _convergence: Convergence, + _scope: OperationScope ): Promise => { - const { - orderType, - legs, - settlementPeriod, - size: fixedSize, - } = operation.input; - - const config = await convergence.riskEngine().fetchConfig(scope); - if (isFixedSizeOpen(fixedSize)) { - return { - requiredCollateral: removeDecimals( - config.minCollateralRequirement, - Number(config.collateralMintDecimals) - ), - }; - } else if (isFixedSizeQuoteAsset(fixedSize)) { - return { - requiredCollateral: removeDecimals( - config.collateralForFixedQuoteAmountRfqCreation, - Number(config.collateralMintDecimals) - ), - }; - } else if (isFixedSizeBaseAsset(fixedSize)) { - const legsMultiplier = fixedSize.amount; - const sideToCase = (side: ResponseSide): CalculationCase => { - return { - legsMultiplier, - authoritySide: 'taker', - quoteSide: side, - }; - }; - - const cases: CalculationCase[] = []; - if (orderType == 'buy') { - cases.push(sideToCase('ask')); - } else if (orderType == 'sell') { - cases.push(sideToCase('bid')); - } else if (orderType == 'two-way') { - cases.push(sideToCase('ask')); - cases.push(sideToCase('bid')); - } else { - throw new Error('Invalid order type'); - } - - const risks = await calculateRisk( - convergence, - config, - legs, - cases, - settlementPeriod, - scope.commitment - ); - - const requiredCollateral = risks.reduce((x, y) => Math.max(x, y), 0); - return { - requiredCollateral, - }; - } - - throw new Error('Invalid fixed size'); + return { requiredCollateral: 0 }; }, }; diff --git a/packages/js/src/plugins/riskEngineModule/operations/closeConfig.ts b/packages/js/src/plugins/riskEngineModule/operations/closeConfig.ts deleted file mode 100644 index ccc2d6a55..000000000 --- a/packages/js/src/plugins/riskEngineModule/operations/closeConfig.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { createCloseConfigInstruction } from '@convergence-rfq/risk-engine'; - -import { - TransactionBuilder, - TransactionBuilderOptions, -} from '../../../utils/TransactionBuilder'; -import { Convergence } from '../../../Convergence'; -import { - Operation, - OperationHandler, - OperationScope, - Signer, - useOperation, -} from '../../../types'; -import { SendAndConfirmTransactionResponse } from '../../../plugins'; -import { riskEngineConfigCache } from '../cache'; - -const Key = 'CloseConfigOperation' as const; - -/** - * Close current rist engine configuration. - * - * ```ts - * await convergence.riskEngine().closeConfig(); - * ``` - * - * @group Operations - * @category Constructors - */ -export const closeConfigOperation = useOperation(Key); - -/** - * @group Operations - * @category Types - */ -export type CloseConfigOperation = Operation< - typeof Key, - CloseConfigInput, - CloseConfigOutput ->; - -/** - * @group Operations - * @category Inputs - */ -export type CloseConfigInput = - | { - /** The owner of the protocol. */ - authority?: Signer; - } - | undefined; - -/** - * @group Operations - * @category Outputs - */ -export type CloseConfigOutput = { - response: SendAndConfirmTransactionResponse; -}; - -/** - * @group Transaction Builders - * @category Inputs - */ -export type CloseConfigBuilderParams = CloseConfigInput; - -/** - * @group Operations - * @category Handlers - */ -export const closeConfigOperationHandler: OperationHandler = - { - handle: async ( - operation: CloseConfigOperation, - convergence: Convergence, - scope: OperationScope - ): Promise => { - scope.throwIfCanceled(); - - const builder = closeConfigBuilder(convergence, operation.input, scope); - const { response } = await builder.sendAndConfirm( - convergence, - scope.confirmOptions - ); - - riskEngineConfigCache.clear(); - - return { response }; - }, - }; - -/** - * Closes risk engine configuration. - * - * ```ts - * const transactionBuilder = convergence - * .rfqs() - * .builders() - * .closeConfig(); - * ``` - * - * @group Transaction Builders - * @category Constructors - */ -export const closeConfigBuilder = ( - convergence: Convergence, - params: CloseConfigBuilderParams, - options: TransactionBuilderOptions = {} -): TransactionBuilder => { - const { programs, payer = convergence.rpc().getDefaultFeePayer() } = options; - const { authority = payer } = params ?? {}; - - const riskEngineProgram = convergence.programs().getRiskEngine(programs); - - return TransactionBuilder.make() - .setFeePayer(payer) - .addTxPriorityFeeIx(convergence) - .add({ - instruction: createCloseConfigInstruction( - { - authority: authority.publicKey, - protocol: convergence.protocol().pdas().protocol(), - config: convergence.riskEngine().pdas().config(), - }, - riskEngineProgram.address - ), - signers: [authority], - key: 'closeConfig', - }); -}; diff --git a/packages/js/src/plugins/riskEngineModule/operations/fetchConfig.ts b/packages/js/src/plugins/riskEngineModule/operations/fetchConfig.ts deleted file mode 100644 index 8298ca6fa..000000000 --- a/packages/js/src/plugins/riskEngineModule/operations/fetchConfig.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Config } from '../models'; - -import { Convergence } from '../../../Convergence'; -import { - Operation, - OperationHandler, - OperationScope, - useOperation, -} from '../../../types'; -import { riskEngineConfigCache } from '../cache'; - -const Key = 'FetchConfigOperation' as const; - -/** - * Fetch current Rist Engine configuration - * - * ```ts - * await convergence - * .riskEngine() - * .fetchConfig(); - * ``` - * - * @group Operations - * @category Constructors - */ -export const fetchConfigOperation = useOperation(Key); - -/** - * @group Operations - * @category Types - */ -export type FetchConfigOperation = Operation< - typeof Key, - FetchConfigInput, - FetchConfigOutput ->; - -/** - * @group Operations - * @category Inputs - */ -export type FetchConfigInput = {}; - -/** - * @group Operations - * @category Outputs - */ -export type FetchConfigOutput = Config; - -/** - * @group Operations - * @category Handlers - */ -export const fetchConfigOperationHandler: OperationHandler = - { - handle: async ( - _operation: FetchConfigOperation, - convergence: Convergence, - scope: OperationScope - ): Promise => { - const { commitment } = scope; - scope.throwIfCanceled(); - - const config = await riskEngineConfigCache.get(convergence, commitment); - - return config; - }, - }; diff --git a/packages/js/src/plugins/riskEngineModule/operations/index.ts b/packages/js/src/plugins/riskEngineModule/operations/index.ts index 49b040072..c9f3f6dda 100644 --- a/packages/js/src/plugins/riskEngineModule/operations/index.ts +++ b/packages/js/src/plugins/riskEngineModule/operations/index.ts @@ -1,9 +1,3 @@ -export * from './initializeConfig'; -export * from './updateConfig'; -export * from './setInstrumentType'; export * from './calculateCollateralForConfirmation'; export * from './calculateCollateralForResponse'; export * from './calculateCollateralForRfq'; -export * from './setRiskCategoriesInfo'; -export * from './fetchConfig'; -export * from './closeConfig'; diff --git a/packages/js/src/plugins/riskEngineModule/operations/initializeConfig.ts b/packages/js/src/plugins/riskEngineModule/operations/initializeConfig.ts deleted file mode 100644 index d7bfdd752..000000000 --- a/packages/js/src/plugins/riskEngineModule/operations/initializeConfig.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { createInitializeConfigInstruction } from '@convergence-rfq/risk-engine'; - -import { SendAndConfirmTransactionResponse } from '../../rpcModule'; -import { - DEFAULT_MINT_DECIMALS, - DEFAULT_COLLATERAL_FOR_FIXED_QUOTE_AMOUNT_RFQ, - DEFAULT_SAFETY_PRICE_SHIFT_FACTOR, - DEFAULT_OVERALL_SAFETY_FACTOR, - DEFAULT_MIN_COLLATERAL_REQUIREMENT, - DEFAULT_ACCEPTED_ORACLE_STALENESS, - DEFAULT_ACCEPTED_ORACLE_CONFIDENCE_INTERVAL_PORTION, -} from '../constants'; -import { Convergence } from '../../../Convergence'; -import { - Operation, - OperationHandler, - OperationScope, - useOperation, - Signer, -} from '../../../types'; -import { - TransactionBuilder, - TransactionBuilderOptions, -} from '../../../utils/TransactionBuilder'; - -const Key = 'InitalizeConfigOperation' as const; - -/** - * Add an BaseAsset - * - * ```ts - * await convergence - * .riskEngine() - * .initializeConfig({ address }; - * ``` - * - * @group Operations - * @category Constructors - */ -export const initializeConfigOperation = - useOperation(Key); - -/** - * @group Operations - * @category Types - */ -export type InitalizeConfigOperation = Operation< - typeof Key, - InitializeConfigInput, - InitializeConfigOutput ->; - -/** - * @group Operations - * @category Inputs - */ -export type InitializeConfigInput = - | { - /** The owner of the protocol. */ - authority?: Signer; - - /** The collateral amount required to create a variable size RFQ. */ - minCollateralRequirement?: number; - - /** The collateral amount required to create a fixed quote amount RFQ. */ - collateralForFixedQuoteAmountRfqCreation?: number; - - /** The number of decimals of the collateral mint. */ - collateralMintDecimals?: number; - - /** The safety price shift factor. */ - safetyPriceShiftFactor?: number; - - /** The overall safety factor. */ - overallSafetyFactor?: number; - - /** The accepted oracle staleness. */ - acceptedOracleStaleness?: number; - - /** The accepted oracle confidence interval portion. */ - acceptedOracleConfidenceIntervalPortion: number; - } - | undefined; - -/** - * @group Operations - * @category Outputs - */ -export type InitializeConfigOutput = { - /** The blockchain response from sending and confirming the transaction. */ - response: SendAndConfirmTransactionResponse; -}; - -/** - * @group Operations - * @category Handlers - */ -export const initializeConfigOperationHandler: OperationHandler = - { - handle: async ( - operation: InitalizeConfigOperation, - convergence: Convergence, - scope: OperationScope - ): Promise => { - scope.throwIfCanceled(); - - const builder = initializeConfigBuilder( - convergence, - operation.input, - scope - ); - const { response } = await builder.sendAndConfirm( - convergence, - scope.confirmOptions - ); - - return { response }; - }, - }; - -/** - * @group Transaction Builders - * @category Inputs - */ -export type InitalizeConfigBuilderParams = InitializeConfigInput; - -/** - * Adds an BaseAsset - * - * ```ts - * const transactionBuilder = convergence - * .rfqs() - * .builders() - * .initializeConfig({ address }); - * ``` - * - * @group Transaction Builders - * @category Constructors - */ -export const initializeConfigBuilder = ( - convergence: Convergence, - params: InitalizeConfigBuilderParams, - options: TransactionBuilderOptions = {} -): TransactionBuilder => { - const { programs, payer = convergence.rpc().getDefaultFeePayer() } = options; - const { - authority = payer, - minCollateralRequirement = DEFAULT_MIN_COLLATERAL_REQUIREMENT, - collateralForFixedQuoteAmountRfqCreation = DEFAULT_COLLATERAL_FOR_FIXED_QUOTE_AMOUNT_RFQ, - collateralMintDecimals = DEFAULT_MINT_DECIMALS, - safetyPriceShiftFactor = DEFAULT_SAFETY_PRICE_SHIFT_FACTOR, - overallSafetyFactor = DEFAULT_OVERALL_SAFETY_FACTOR, - acceptedOracleStaleness = DEFAULT_ACCEPTED_ORACLE_STALENESS, - acceptedOracleConfidenceIntervalPortion = DEFAULT_ACCEPTED_ORACLE_CONFIDENCE_INTERVAL_PORTION, - } = params ?? {}; - - const riskEngineProgram = convergence.programs().getRiskEngine(programs); - const systemProgram = convergence.programs().getSystem(programs); - - return TransactionBuilder.make() - .setFeePayer(payer) - .addTxPriorityFeeIx(convergence) - .add({ - instruction: createInitializeConfigInstruction( - { - authority: authority.publicKey, - protocol: convergence.protocol().pdas().protocol(), - config: convergence.riskEngine().pdas().config(), - systemProgram: systemProgram.address, - }, - { - minCollateralRequirement, - collateralForFixedQuoteAmountRfqCreation, - collateralMintDecimals, - safetyPriceShiftFactor, - overallSafetyFactor, - acceptedOracleStaleness, - acceptedOracleConfidenceIntervalPortion, - }, - riskEngineProgram.address - ), - signers: [authority], - key: 'initializeConfig', - }); -}; diff --git a/packages/js/src/plugins/riskEngineModule/operations/setInstrumentType.ts b/packages/js/src/plugins/riskEngineModule/operations/setInstrumentType.ts deleted file mode 100644 index 2a6116b74..000000000 --- a/packages/js/src/plugins/riskEngineModule/operations/setInstrumentType.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { createSetInstrumentTypeInstruction } from '@convergence-rfq/risk-engine'; - -import { SendAndConfirmTransactionResponse } from '../../rpcModule'; -import { Config, InstrumentType, toSolitaInstrumentType } from '../models'; -import { Convergence } from '../../../Convergence'; -import { - Operation, - OperationHandler, - OperationScope, - useOperation, - Signer, - PublicKey, -} from '../../../types'; -import { - TransactionBuilder, - TransactionBuilderOptions, -} from '../../../utils/TransactionBuilder'; -import { riskEngineConfigCache } from '../cache'; -import { getInstrumentProgramIndex } from '@/plugins/instrumentModule'; - -const Key = 'SetInstrumentTypeOperation' as const; - -/** - * Set instrument type - * - * ```ts - * await convergence - * .riskEngine() - * .setInstrumentType({ ... }; - * ``` - * - * @group Operations - * @category Constructors - */ -export const setInstrumentTypeOperation = - useOperation(Key); - -/** - * @group Operations - * @category Types - */ -export type SetInstrumentTypeOperation = Operation< - typeof Key, - SetInstrumentTypeInput, - SetInstrumentTypeOutput ->; - -/** - * @group Operations - * @category Inputs - */ -export type SetInstrumentTypeInput = { - /** - * The owner of the protocol. - */ - authority?: Signer; - - /** - * The instrument type. - */ - instrumentType: InstrumentType; - - /** - * The address of the instrument program account. - */ - instrumentProgram: PublicKey; -}; - -/** - * @group Operations - * @category Outputs - */ -export type SetInstrumentTypeOutput = { - /** The blockchain response from sending and confirming the transaction. */ - response: SendAndConfirmTransactionResponse; - - /** Risk engine config. */ - config: Config; -}; - -/** - * @group Operations - * @category Handlers - */ -export const setInstrumentTypeOperationHandler: OperationHandler = - { - handle: async ( - operation: SetInstrumentTypeOperation, - convergence: Convergence, - scope: OperationScope - ): Promise => { - const protocol = await convergence.protocol().get(); - const instrumentIndex = getInstrumentProgramIndex( - protocol, - operation.input.instrumentProgram - ); - - const builder = setInstrumentTypeBuilder( - convergence, - operation.input, - instrumentIndex, - scope - ); - - const { response } = await builder.sendAndConfirm( - convergence, - scope.confirmOptions - ); - - riskEngineConfigCache.clear(); - const config = await convergence.riskEngine().fetchConfig(scope); - - return { response, config }; - }, - }; - -/** - * @group Transaction Builders - * @category Inputs - */ -export type SetInstrumentTypeBuilderParams = SetInstrumentTypeInput; - -/** - * Adds an BaseAsset - * - * ```ts - * const transactionBuilder = convergence - * .riskEngine() - * .builders() - * .setInstrumentType({ instrumentType, instrumentProgram }); - * ``` - * - * @group Transaction Builders - * @category Constructors - */ -export const setInstrumentTypeBuilder = ( - convergence: Convergence, - params: SetInstrumentTypeBuilderParams, - instrumentIndex: number, - options: TransactionBuilderOptions = {} -): TransactionBuilder => { - const { programs, payer = convergence.rpc().getDefaultFeePayer() } = options; - const { authority = payer, instrumentType } = params; - - const riskEngineProgram = convergence.programs().getRiskEngine(programs); - - const config = convergence.riskEngine().pdas().config(); - const protocol = convergence.protocol().pdas().protocol(); - - return TransactionBuilder.make() - .setFeePayer(payer) - .addTxPriorityFeeIx(convergence) - .add({ - instruction: createSetInstrumentTypeInstruction( - { - authority: authority.publicKey, - protocol, - config, - }, - { - instrumentIndex, - instrumentType: toSolitaInstrumentType(instrumentType), - }, - riskEngineProgram.address - ), - signers: [authority], - key: 'setInstrumentType', - }); -}; diff --git a/packages/js/src/plugins/riskEngineModule/operations/setRiskCategoriesInfo.ts b/packages/js/src/plugins/riskEngineModule/operations/setRiskCategoriesInfo.ts deleted file mode 100644 index cef1ecd03..000000000 --- a/packages/js/src/plugins/riskEngineModule/operations/setRiskCategoriesInfo.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { createSetRiskCategoriesInfoInstruction } from '@convergence-rfq/risk-engine'; - -import { SendAndConfirmTransactionResponse } from '../../rpcModule'; -import { - Config, - RiskCategoryChange, - toSolitaRiskCategoryChange, -} from '../models'; -import { Convergence } from '../../../Convergence'; -import { - Operation, - OperationHandler, - OperationScope, - useOperation, - Signer, -} from '../../../types'; -import { - TransactionBuilder, - TransactionBuilderOptions, -} from '../../../utils/TransactionBuilder'; -import { riskEngineConfigCache } from '../cache'; - -const Key = 'SetRiskCategoriesInfoOperation' as const; - -/** - * Set instrument type - * - * ```ts - * await convergence - * .riskEngine() - * .SetRiskCategoriesInfo({ ... }; - * ``` - * - * @group Operations - * @category Constructors - */ -export const setRiskCategoriesInfoOperation = - useOperation(Key); - -/** - * @group Operations - * @category Types - */ -export type SetRiskCategoriesInfoOperation = Operation< - typeof Key, - SetRiskCategoriesInfoInput, - SetRiskCategoriesInfoOutput ->; - -/** - * @group Operations - * @category Inputs - */ -export type SetRiskCategoriesInfoInput = { - /** - * The owner of the protocol. - */ - authority?: Signer; - - /** The risk category changes. */ - changes: RiskCategoryChange[]; -}; - -/** - * @group Operations - * @category Outputs - */ -export type SetRiskCategoriesInfoOutput = { - /** The blockchain response from sending and confirming the transaction. */ - response: SendAndConfirmTransactionResponse; - - /** Risk engine config. */ - config: Config; -}; - -/** - * @group Operations - * @category Handlers - */ -export const setRiskCategoriesInfoOperationHandler: OperationHandler = - { - handle: async ( - operation: SetRiskCategoriesInfoOperation, - convergence: Convergence, - scope: OperationScope - ): Promise => { - const builder = setRiskCategoriesInfoBuilder( - convergence, - operation.input, - scope - ); - const { response } = await builder.sendAndConfirm( - convergence, - scope.confirmOptions - ); - - riskEngineConfigCache.clear(); - const config = await convergence.riskEngine().fetchConfig(scope); - - return { response, config }; - }, - }; - -/** - * @group Transaction Builders - * @category Inputs - */ -export type SetRiskCategoriesInfoBuilderParams = SetRiskCategoriesInfoInput; - -/** - * Adds an BaseAsset - * - * ```ts - * const transactionBuilder = convergence - * .riskEngine() - * .builders() - * .setRiskCategoriesInfo({ changes }); - * ``` - * - * @group Transaction Builders - * @category Constructors - */ -export const setRiskCategoriesInfoBuilder = ( - convergence: Convergence, - params: SetRiskCategoriesInfoBuilderParams, - options: TransactionBuilderOptions = {} -): TransactionBuilder => { - const { programs, payer = convergence.rpc().getDefaultFeePayer() } = options; - const { authority = payer, changes } = params; - - const riskEngineProgram = convergence.programs().getRiskEngine(programs); - - const config = convergence.riskEngine().pdas().config(); - const protocol = convergence.protocol().pdas().protocol(); - - return TransactionBuilder.make() - .setFeePayer(payer) - .addTxPriorityFeeIx(convergence) - .add({ - instruction: createSetRiskCategoriesInfoInstruction( - { - authority: authority.publicKey, - protocol, - config, - }, - { changes: changes.map(toSolitaRiskCategoryChange) }, - riskEngineProgram.address - ), - signers: [authority], - key: 'setRiskCategoriesInfo', - }); -}; diff --git a/packages/js/src/plugins/riskEngineModule/operations/updateConfig.ts b/packages/js/src/plugins/riskEngineModule/operations/updateConfig.ts deleted file mode 100644 index b26055783..000000000 --- a/packages/js/src/plugins/riskEngineModule/operations/updateConfig.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { createUpdateConfigInstruction } from '@convergence-rfq/risk-engine'; - -import { SendAndConfirmTransactionResponse } from '../../rpcModule'; -import { Config } from '../models'; -import { - DEFAULT_MINT_DECIMALS, - DEFAULT_COLLATERAL_FOR_FIXED_QUOTE_AMOUNT_RFQ, - DEFAULT_SAFETY_PRICE_SHIFT_FACTOR, - DEFAULT_OVERALL_SAFETY_FACTOR, - DEFAULT_MIN_COLLATERAL_REQUIREMENT, - DEFAULT_ORACLE_STALENESS, - DEFAULT_ACCEPTED_ORACLE_CONFIDENCE_INTERVAL_POSITION, -} from '../constants'; -import { Convergence } from '../../../Convergence'; -import { - Operation, - OperationHandler, - OperationScope, - useOperation, - Signer, -} from '../../../types'; -import { - TransactionBuilder, - TransactionBuilderOptions, -} from '../../../utils/TransactionBuilder'; -import { riskEngineConfigCache } from '../cache'; - -const Key = 'UpdateConfigOperation' as const; - -/** - * Update risk engine config - * - * ```ts - * await convergence - * .riskEngine() - * .updateConfig({ ... }; - * ``` - * - * @group Operations - * @category Constructors - */ -export const updateConfigOperation = useOperation(Key); - -/** - * @group Operations - * @category Types - */ -export type UpdateConfigOperation = Operation< - typeof Key, - UpdateConfigInput, - UpdateConfigOutput ->; - -/** - * @group Operations - * @category Inputs - */ -export type UpdateConfigInput = - | { - /** The owner of the protocol. */ - authority?: Signer; - - /** The collateral amount required to create a variable size RFQ. */ - minCollateralRequirement?: number; - - /** The collateral amount required to create a fixed quote amount RFQ. */ - collateralForFixedQuoteAmountRfqCreation?: number; - - /** The number of decimals of the collateral mint. */ - collateralMintDecimals?: number; - - /** The safety price shift factor. */ - safetyPriceShiftFactor?: number; - - /** The overall safety factor. */ - overallSafetyFactor?: number; - - /** The accepted oracle staleness. */ - acceptedOracleStaleness?: number; - - /** The accepted oracle confidence interval portion. */ - acceptedOracleConfidenceIntervalPortion?: number; - } - | undefined; - -/** - * @group Operations - * @category Outputs - */ -export type UpdateConfigOutput = { - /** The blockchain response from sending and confirming the transaction. */ - response: SendAndConfirmTransactionResponse; - - /** Risk engine config model. */ - config: Config; -}; - -/** - * @group Operations - * @category Handlers - */ -export const updateConfigOperationHandler: OperationHandler = - { - handle: async ( - operation: UpdateConfigOperation, - convergence: Convergence, - scope: OperationScope - ): Promise => { - scope.throwIfCanceled(); - - const builder = updateConfigBuilder(convergence, operation.input, scope); - const { response } = await builder.sendAndConfirm( - convergence, - scope.confirmOptions - ); - - riskEngineConfigCache.clear(); - const config = await convergence.riskEngine().fetchConfig(scope); - - return { response, config }; - }, - }; - -/** - * @group Transaction Builders - * @category Inputs - */ -export type UpdateConfigBuilderParams = UpdateConfigInput; - -/** - * Updates risk engine config - * - * ```ts - * const transactionBuilder = convergence - * .riskEngine() - * .builders() - * .updateConfig({ ... }); - * ``` - * - * @group Transaction Builders - * @category Constructors - */ -export const updateConfigBuilder = ( - convergence: Convergence, - params: UpdateConfigBuilderParams, - options: TransactionBuilderOptions = {} -): TransactionBuilder => { - const { programs, payer = convergence.rpc().getDefaultFeePayer() } = options; - const { - authority = payer, - minCollateralRequirement = DEFAULT_MIN_COLLATERAL_REQUIREMENT, - collateralForFixedQuoteAmountRfqCreation = DEFAULT_COLLATERAL_FOR_FIXED_QUOTE_AMOUNT_RFQ, - collateralMintDecimals = DEFAULT_MINT_DECIMALS, - safetyPriceShiftFactor = DEFAULT_SAFETY_PRICE_SHIFT_FACTOR, - overallSafetyFactor = DEFAULT_OVERALL_SAFETY_FACTOR, - acceptedOracleStaleness = DEFAULT_ORACLE_STALENESS, - acceptedOracleConfidenceIntervalPortion = DEFAULT_ACCEPTED_ORACLE_CONFIDENCE_INTERVAL_POSITION, - } = params ?? {}; - - const riskEngineProgram = convergence.programs().getRiskEngine(programs); - - return TransactionBuilder.make() - .setFeePayer(payer) - .addTxPriorityFeeIx(convergence) - .add({ - instruction: createUpdateConfigInstruction( - { - authority: authority.publicKey, - protocol: convergence.protocol().pdas().protocol(), - config: convergence.riskEngine().pdas().config(), - }, - { - minCollateralRequirement, - collateralForFixedQuoteAmountRfqCreation, - collateralMintDecimals, - safetyPriceShiftFactor, - overallSafetyFactor, - acceptedOracleStaleness, - acceptedOracleConfidenceIntervalPortion, - }, - riskEngineProgram.address - ), - signers: [authority], - key: 'updateConfig', - }); -}; diff --git a/packages/js/src/plugins/riskEngineModule/plugin.ts b/packages/js/src/plugins/riskEngineModule/plugin.ts index 70fdb977e..81a49dd28 100644 --- a/packages/js/src/plugins/riskEngineModule/plugin.ts +++ b/packages/js/src/plugins/riskEngineModule/plugin.ts @@ -5,24 +5,12 @@ import type { Convergence } from '../../Convergence'; import { ProgramClient } from '../programModule'; import { RiskEngineClient } from './RiskEngineClient'; import { - initializeConfigOperation, - initializeConfigOperationHandler, - updateConfigOperation, - updateConfigOperationHandler, - setInstrumentTypeOperation, - setInstrumentTypeOperationHandler, - setRiskCategoriesInfoOperation, - setRiskCategoriesInfoOperationHandler, calculateCollateralForConfirmationOperation, calculateCollateralForConfirmationOperationHandler, calculateCollateralForResponseOperation, calculateCollateralForResponseOperationHandler, calculateCollateralForRfqOperation, calculateCollateralForRfqOperationHandler, - fetchConfigOperation, - fetchConfigOperationHandler, - closeConfigOperation, - closeConfigOperationHandler, } from './operations'; /** @group Plugins */ @@ -42,13 +30,6 @@ export const riskEngineModule = (): ConvergencePlugin => ({ }; const op = convergence.operations(); - op.register(initializeConfigOperation, initializeConfigOperationHandler); - op.register(updateConfigOperation, updateConfigOperationHandler); - op.register(setInstrumentTypeOperation, setInstrumentTypeOperationHandler); - op.register( - setRiskCategoriesInfoOperation, - setRiskCategoriesInfoOperationHandler - ); op.register( calculateCollateralForRfqOperation, calculateCollateralForRfqOperationHandler @@ -61,8 +42,6 @@ export const riskEngineModule = (): ConvergencePlugin => ({ calculateCollateralForConfirmationOperation, calculateCollateralForConfirmationOperationHandler ); - op.register(fetchConfigOperation, fetchConfigOperationHandler); - op.register(closeConfigOperation, closeConfigOperationHandler); convergence.riskEngine = function () { return new RiskEngineClient(this); diff --git a/packages/js/src/plugins/riskEngineModule/types.ts b/packages/js/src/plugins/riskEngineModule/types.ts index 85ffd1104..918f772cb 100644 --- a/packages/js/src/plugins/riskEngineModule/types.ts +++ b/packages/js/src/plugins/riskEngineModule/types.ts @@ -1,2 +1 @@ export { RiskCategory as SolitaRiskCatgory } from '@convergence-rfq/rfq'; -export type { Scenario, RiskCategoryInfo } from '@convergence-rfq/risk-engine'; diff --git a/packages/js/src/plugins/vaultOperatorModule/operations/confirmAndPrepareVault.ts b/packages/js/src/plugins/vaultOperatorModule/operations/confirmAndPrepareVault.ts index 673c646d4..a7b2e15a5 100644 --- a/packages/js/src/plugins/vaultOperatorModule/operations/confirmAndPrepareVault.ts +++ b/packages/js/src/plugins/vaultOperatorModule/operations/confirmAndPrepareVault.ts @@ -22,7 +22,6 @@ import { EscrowRfq, getEscrowPrepareSettlementRemainingAccounts, } from '@/plugins/rfqModule'; -import { getRiskEngineAccounts } from '@/plugins/riskEngineModule/helpers'; const Key = 'ConfirmAndPrepareVaultOperation' as const; @@ -95,8 +94,6 @@ export const confirmAndPrepareVaultBuilder = async ( const vaultProgram = cvg.programs().getVaultOperator(programs).address; const operator = cvg.vaultOperator().pdas().operator(vault.address); - const riskEngineAccounts = await getRiskEngineAccounts(cvg, rfq.legs); - const confirmIx = { instruction: createConfirmResponseInstruction( { @@ -116,7 +113,6 @@ export const confirmAndPrepareVaultBuilder = async ( }), riskEngine: cvg.programs().getRiskEngine(programs).address, rfqProgram: cvg.programs().getRfq(programs).address, - anchorRemainingAccounts: riskEngineAccounts, }, vaultProgram ), diff --git a/packages/js/src/plugins/vaultOperatorModule/operations/createVault.ts b/packages/js/src/plugins/vaultOperatorModule/operations/createVault.ts index 2f0824390..c9b1d0487 100644 --- a/packages/js/src/plugins/vaultOperatorModule/operations/createVault.ts +++ b/packages/js/src/plugins/vaultOperatorModule/operations/createVault.ts @@ -1,6 +1,7 @@ import { createCreateRfqInstruction } from '@convergence-rfq/vault-operator'; import { Keypair, PublicKey, SystemProgram } from '@solana/web3.js'; import BN from 'bn.js'; +import * as multisig from '@sqds/multisig'; import { SendAndConfirmTransactionResponse } from '../../rpcModule'; import { Convergence } from '../../../Convergence'; @@ -8,6 +9,7 @@ import { Operation, OperationHandler, OperationScope, + Signer, useOperation, } from '../../../types'; import { @@ -26,16 +28,13 @@ import { } from '@/plugins/instrumentModule'; import { ABSOLUTE_PRICE_DECIMALS, + LEG_MULTIPLIER_DECIMALS, calculateExpectedLegsHash, - calculateExpectedLegsSize, instrumentsToLegAccounts, legsToBaseAssetAccounts, - serializeFixedSizeData, - toSolitaFixedSize, toSolitaOrderType, } from '@/plugins/rfqModule'; import { addDecimals, getOrCreateATAtxBuilder } from '@/utils'; -import { getRiskEngineAccounts } from '@/plugins/riskEngineModule/helpers'; import { Mint } from '@/plugins/tokenModule'; const Key = 'CreateVaultOperation' as const; @@ -74,11 +73,9 @@ export const createVaultOperationHandler: OperationHandler cvg: Convergence, scope: OperationScope ) => { - const { builder, vaultAddress, rfqAddress } = await createVaultBuilder( - cvg, - operation.input, - scope - ); + const { builder, ataBuilder, vaultAddress, rfqAddress } = + await createVaultBuilder(cvg, operation.input, scope); + builder.prepend(ataBuilder); const output = await builder.sendAndConfirm(cvg, scope.confirmOptions); @@ -88,10 +85,13 @@ export const createVaultOperationHandler: OperationHandler }, }; -export type CreateVaultBuilderParams = CreateVaultInput; +export type CreateVaultBuilderParams = CreateVaultInput & { + squads?: { vaultPda: PublicKey; transactionPda: PublicKey }; +}; export type CreateVaultBuilderResult = { builder: TransactionBuilder; + ataBuilder: TransactionBuilder; vaultAddress: PublicKey; rfqAddress: PublicKey; }; @@ -109,15 +109,33 @@ export const createVaultBuilder = async ( orderDetails, activeWindow, settlingWindow, + squads, } = params; const leg = await SpotLegInstrument.create(cvg, legMint, 1, 'long'); const quote = await SpotQuoteInstrument.create(cvg, quoteMint); - const vaultProgram = cvg.programs().getVaultOperator(programs).address; const creator = cvg.identity(); - const vaultParams = Keypair.generate(); - const operator = cvg.vaultOperator().pdas().operator(vaultParams.publicKey); + + let signers: Signer[]; + let vaultParamsKey: PublicKey; + let executorKey: PublicKey; + if (squads === undefined) { + const vaultParamsSigner = Keypair.generate(); + signers = [creator, vaultParamsSigner]; + vaultParamsKey = vaultParamsSigner.publicKey; + executorKey = creator.publicKey; + } else { + signers = []; + vaultParamsKey = multisig.getEphemeralSignerPda({ + ephemeralSignerIndex: 0, + transactionPda: squads.transactionPda, + })[0]; + executorKey = squads.vaultPda; + } + + const vaultProgram = cvg.programs().getVaultOperator(programs).address; + const operator = cvg.vaultOperator().pdas().operator(vaultParamsKey); const protocol = await cvg.protocol().get(); const sendMint = @@ -128,7 +146,6 @@ export const createVaultBuilder = async ( const solitaLeg = instrumentToSolitaLeg(leg); const serializedLeg = serializeInstrumentAsSolitaLeg(leg); const expectedLegsHash = calculateExpectedLegsHash([serializedLeg]); - const expectedLegsSize = calculateExpectedLegsSize([serializedLeg]); const recentTimestamp = new BN(Math.floor(Date.now() / 1_000)); const fixedSize = orderDetails.type === 'buy' @@ -143,9 +160,9 @@ export const createVaultBuilder = async ( operator, programs ); - const creatorTokens = cvg.tokens().pdas().associatedTokenAccount({ + const executorTokens = cvg.tokens().pdas().associatedTokenAccount({ mint: sendMint, - owner: creator.publicKey, + owner: executorKey, programs, }); @@ -181,22 +198,20 @@ export const createVaultBuilder = async ( ]; const baseAssetAccounts = legsToBaseAssetAccounts(cvg, [solitaLeg]); const legAccounts = await instrumentsToLegAccounts([leg]); - const riskEngineAccounts = await getRiskEngineAccounts(cvg, [leg]); const createRfqAccounts = [ ...quoteAccounts, ...baseAssetAccounts, ...legAccounts, ]; - const allRemainingAccounts = [...createRfqAccounts, ...riskEngineAccounts]; const lamportsForOperator = 14288880; const transferLamportIx = { instruction: SystemProgram.transfer({ - fromPubkey: creator.publicKey, + fromPubkey: executorKey, toPubkey: operator, lamports: lamportsForOperator, }), - signers: [creator], + signers: [], key: 'sendLamportsToOperator', }; const acceptablePriceLimitWithDecimals = addDecimals( @@ -204,19 +219,24 @@ export const createVaultBuilder = async ( quote.decimals ).mul(new BN(10).pow(new BN(ABSOLUTE_PRICE_DECIMALS))); + const size = + fixedSize.type === 'fixed-base' + ? addDecimals(fixedSize.amount, LEG_MULTIPLIER_DECIMALS) + : addDecimals(fixedSize.amount, quote.decimals); + const builder = TransactionBuilder.make() .setFeePayer(payer) .addTxPriorityFeeIx(cvg) .add(transferLamportIx, { instruction: createCreateRfqInstruction( { - creator: creator.publicKey, - vaultParams: vaultParams.publicKey, + creator: executorKey, + vaultParams: vaultParamsKey, operator, sendMint, receiveMint, vault: vaultTokens, - vaultTokensSource: creatorTokens, + vaultTokensSource: executorTokens, protocol: cvg.protocol().pdas().protocol(), rfq: rfqPda, whitelist: vaultProgram, @@ -229,35 +249,35 @@ export const createVaultBuilder = async ( collateralMint: protocol.collateralMint, riskEngine: cvg.programs().getRiskEngine().address, rfqProgram: cvg.programs().getRfq().address, - anchorRemainingAccounts: allRemainingAccounts, + anchorRemainingAccounts: createRfqAccounts, }, { acceptablePriceLimit: acceptablePriceLimitWithDecimals, - createRfqRemainingAccountsCount: createRfqAccounts.length, - expectedLegsSize, - expectedLegsHash: Array.from(expectedLegsHash), legBaseAssetIndex: leg.getBaseAssetIndex().value, - legAmount: solitaLeg.amount, orderType: toSolitaOrderType(orderDetails.type), - fixedSize: Array.from( - serializeFixedSizeData(toSolitaFixedSize(fixedSize, quote.decimals)) - ), + size, activeWindow, settlingWindow, recentTimestamp, }, vaultProgram ), - signers: [creator, vaultParams], + signers, key: 'createVault', }); + const ataBuilder = TransactionBuilder.make().setFeePayer(payer); if (vaultAtaBuilder !== undefined) { - builder.prepend(vaultAtaBuilder); + ataBuilder.add(vaultAtaBuilder); } if (receivedAtaBuilder !== undefined) { - builder.prepend(receivedAtaBuilder); + ataBuilder.add(receivedAtaBuilder); } - return { builder, vaultAddress: vaultParams.publicKey, rfqAddress: rfqPda }; + return { + builder, + ataBuilder, + vaultAddress: vaultParamsKey, + rfqAddress: rfqPda, + }; }; diff --git a/packages/js/tests/integration/squads.spec.ts b/packages/js/tests/integration/squads.spec.ts new file mode 100644 index 000000000..246a82577 --- /dev/null +++ b/packages/js/tests/integration/squads.spec.ts @@ -0,0 +1,307 @@ +import * as multisig from '@sqds/multisig'; +import { + ComputeBudgetProgram, + Keypair, + Signer, + SystemProgram, + TransactionMessage, +} from '@solana/web3.js'; +import expect from 'expect'; +import { + CreateVaultInput, + Mint, + TransactionBuilder, + addDecimals, + createVaultBuilder, +} from '../../src'; +import { createUserCvg } from '../helpers'; +import { BASE_MINT_BTC_PK, QUOTE_MINT_PK } from '../constants'; + +const { Permission, Permissions } = multisig.types; + +describe('integration.squads', () => { + const cvg = createUserCvg('taker'); + const cvgSecond = createUserCvg('dao'); + const cvgMaker = createUserCvg('maker'); + const { connection } = cvg; + const creator = cvg.identity(); + let transactionIndex = BigInt(0); + + const createKey = Keypair.generate(); + + const [multisigPda] = multisig.getMultisigPda({ + createKey: createKey.publicKey, + }); + + const [squadsVault] = multisig.getVaultPda({ + multisigPda, + index: 0, + }); + + let baseMintBTC: Mint; + let quoteMint: Mint; + + before(async () => { + baseMintBTC = await cvg + .tokens() + .findMintByAddress({ address: BASE_MINT_BTC_PK }); + quoteMint = await cvg + .tokens() + .findMintByAddress({ address: QUOTE_MINT_PK }); + + await createAndFundSquads(); + }); + + const createAndFundSquads = async () => { + const programConfigPda = multisig.getProgramConfigPda({})[0]; + const programConfig = + await multisig.accounts.ProgramConfig.fromAccountAddress( + connection, + programConfigPda + ); + const configTreasury = programConfig.treasury; + const signature = await multisig.rpc.multisigCreateV2({ + connection, + createKey, + creator, + multisigPda, + configAuthority: null, + timeLock: 0, + members: [ + { + key: creator.publicKey, + permissions: Permissions.all(), + }, + { + key: cvgSecond.identity().publicKey, + permissions: Permissions.fromPermissions([ + Permission.Vote, + Permission.Execute, + ]), + }, + ], + threshold: 2, + rentCollector: null, + treasury: configTreasury, + }); + await connection.confirmTransaction(signature); + + await Promise.all([ + cvg.tokens().send({ + amount: { + basisPoints: addDecimals(100, baseMintBTC.decimals), + currency: baseMintBTC.currency, + }, + mintAddress: baseMintBTC.address, + toOwner: squadsVault, + }), + new TransactionBuilder() + .add({ + instruction: SystemProgram.transfer({ + fromPubkey: cvg.identity().publicKey, + toPubkey: squadsVault, + lamports: addDecimals(10, 9), + }), + signers: [cvg.identity()], + }) + .sendAndConfirm(cvg), + cvg.tokens().createToken({ mint: quoteMint.address, owner: squadsVault }), + ]); + }; + + const createProposal = async (vaultInput: CreateVaultInput) => { + transactionIndex += BigInt(1); + const transactionPda = multisig.getTransactionPda({ + multisigPda, + index: transactionIndex, + })[0]; + + const { + builder: vaultBuilder, + ataBuilder, + vaultAddress, + } = await createVaultBuilder(cvg, { + ...vaultInput, + squads: { transactionPda, vaultPda: squadsVault }, + }); + await ataBuilder.sendAndConfirm(cvg); + + const message = new TransactionMessage({ + payerKey: squadsVault, + recentBlockhash: (await connection.getLatestBlockhash()).blockhash, + instructions: [...vaultBuilder.getInstructions()], + }); + const signature1 = await multisig.rpc.vaultTransactionCreate({ + connection, + feePayer: creator, + multisigPda, + transactionIndex, + creator: creator.publicKey, + vaultIndex: 0, + ephemeralSigners: 1, + transactionMessage: message, + }); + + await connection.confirmTransaction(signature1); + const signature2 = await multisig.rpc.proposalCreate({ + connection, + feePayer: creator, + multisigPda, + transactionIndex, + creator, + }); + + await connection.confirmTransaction(signature2); + + return vaultAddress; + }; + + const approveProposal = async (member: Signer) => { + const signature = await multisig.rpc.proposalApprove({ + connection, + feePayer: member, + multisigPda, + transactionIndex: BigInt(transactionIndex), + member, + }); + + await connection.confirmTransaction(signature); + }; + + const executeProposal = async () => { + const { instruction } = await multisig.instructions.vaultTransactionExecute( + { + connection, + multisigPda, + transactionIndex, + member: cvgSecond.identity().publicKey, + } + ); + const builder = new TransactionBuilder() + .add({ + instruction: ComputeBudgetProgram.setComputeUnitLimit({ + units: 1400000, + }), + signers: [], + }) + .add({ + instruction, + signers: [cvgSecond.identity()], + }); + await builder.sendAndConfirm(cvgSecond); + }; + + const measureTokenDiff = async () => { + const measure = () => + Promise.all([ + cvg.tokens().getTokenBalance({ + mintAddress: baseMintBTC.address, + mintDecimals: baseMintBTC.decimals, + owner: squadsVault, + }), + cvg.tokens().getTokenBalance({ + mintAddress: quoteMint.address, + mintDecimals: quoteMint.decimals, + owner: squadsVault, + }), + ]); + + const [{ tokenBalance: legBefore }, { tokenBalance: quoteBefore }] = + await measure(); + + return async () => { + const [{ tokenBalance: legAfter }, { tokenBalance: quoteAfter }] = + await measure(); + + return { leg: legAfter - legBefore, quote: quoteAfter - quoteBefore }; + }; + }; + + it('Settle sell proposals through vault', async () => { + const measurer = await measureTokenDiff(); + + const vaultAddress = await createProposal({ + acceptablePriceLimit: 40000, + quoteMint, + legMint: baseMintBTC, + orderDetails: { + type: 'sell', + legAmount: 2, + }, + activeWindow: 600, + settlingWindow: 600, + }); + + await approveProposal(creator); + await approveProposal(cvgSecond.identity()); + await executeProposal(); + + const { vault, rfq } = await cvg + .vaultOperator() + .findByAddress({ address: vaultAddress }); + + const { rfqResponse: response } = await cvgMaker + .rfqs() + .respond({ rfq: rfq.address, bid: { price: 40000 } }); + const { vault: updatedVault } = await cvgMaker + .vaultOperator() + .confirmAndPrepare({ rfq, vault, response }); + await cvgMaker.rfqs().prepareSettlement({ + rfq: rfq.address, + response: response.address, + legAmountToPrepare: 1, + }); + await cvgMaker.rfqs().settle({ response: response.address }); + await cvgMaker.rfqs().cleanUpResponse({ response: response.address }); + await cvgMaker.vaultOperator().withdrawTokens({ rfq, vault: updatedVault }); + + expect(await measurer()).toMatchObject({ + leg: -2, + quote: 80000 * (1 - 0.01), + }); + }); + + it('Settle buy proposals through vault', async () => { + const measurer = await measureTokenDiff(); + + const vaultAddress = await createProposal({ + acceptablePriceLimit: 5000, + quoteMint, + legMint: baseMintBTC, + orderDetails: { + type: 'buy', + quoteAmount: 75000, + }, + activeWindow: 600, + settlingWindow: 600, + }); + + await approveProposal(creator); + await approveProposal(cvgSecond.identity()); + await executeProposal(); + + const { vault, rfq } = await cvg + .vaultOperator() + .findByAddress({ address: vaultAddress }); + + const { rfqResponse: response } = await cvgMaker + .rfqs() + .respond({ rfq: rfq.address, ask: { price: 5000 } }); + const { vault: updatedVault } = await cvgMaker + .vaultOperator() + .confirmAndPrepare({ rfq, vault, response }); + await cvgMaker.rfqs().prepareSettlement({ + rfq: rfq.address, + response: response.address, + legAmountToPrepare: 1, + }); + await cvgMaker.rfqs().settle({ response: response.address }); + await cvgMaker.rfqs().cleanUpResponse({ response: response.address }); + await cvgMaker.vaultOperator().withdrawTokens({ rfq, vault: updatedVault }); + + expect(await measurer()).toMatchObject({ + leg: 15, + quote: -75000, + }); + }); +}); diff --git a/packages/js/tests/unit/riskEngine.spec.ts b/packages/js/tests/unit/riskEngine.spec.ts index b3ff9f065..6d5f88cba 100644 --- a/packages/js/tests/unit/riskEngine.spec.ts +++ b/packages/js/tests/unit/riskEngine.spec.ts @@ -1,6 +1,5 @@ import { expect } from 'expect'; -import { DEFAULT_RISK_CATEGORIES_INFO } from '../../src'; import { createCFlyRfq, createRfq, @@ -13,112 +12,6 @@ describe('unit.riskEngine', () => { const takerCvg = createUserCvg('taker'); const makerCvg = createUserCvg('maker'); - it('fetch config', async () => { - const config = await daoCvg.riskEngine().fetchConfig(); - expect(config).toHaveProperty('address'); - }); - - it('update config', async () => { - const { config } = await daoCvg.riskEngine().updateConfig(); - expect(config).toHaveProperty('address'); - }); - - it('close config', async () => { - const { response } = await daoCvg.riskEngine().closeConfig(); - expect(response).toHaveProperty('signature'); - }); - - it('initialize config', async () => { - const { response } = await daoCvg.riskEngine().initializeConfig(); - expect(response).toHaveProperty('signature'); - }); - - it('set instrument type [spot]', async () => { - const { config } = await daoCvg.riskEngine().setInstrumentType({ - instrumentType: 'spot', - instrumentProgram: daoCvg.programs().getSpotInstrument().address, - }); - expect(config.address).toEqual(daoCvg.riskEngine().pdas().config()); - }); - - it('set instrument type [american]', async () => { - const { config } = await daoCvg.riskEngine().setInstrumentType({ - instrumentType: 'option', - instrumentProgram: daoCvg.programs().getPsyoptionsAmericanInstrument() - .address, - }); - expect(config.address).toEqual(daoCvg.riskEngine().pdas().config()); - }); - - it('set instrument type [european]', async () => { - const { config } = await daoCvg.riskEngine().setInstrumentType({ - instrumentType: 'option', - instrumentProgram: daoCvg.programs().getPsyoptionsEuropeanInstrument() - .address, - }); - expect(config.address).toEqual(daoCvg.riskEngine().pdas().config()); - }); - - it('set risk categories info [very low]', async () => { - const { config } = await daoCvg.riskEngine().setRiskCategoriesInfo({ - changes: [ - { - value: DEFAULT_RISK_CATEGORIES_INFO.veryLow, - category: 'very-low', - }, - ], - }); - expect(config.address).toEqual(daoCvg.riskEngine().pdas().config()); - }); - - it('set risk categories info [low]', async () => { - const { config } = await daoCvg.riskEngine().setRiskCategoriesInfo({ - changes: [ - { - value: DEFAULT_RISK_CATEGORIES_INFO.low, - category: 'low', - }, - ], - }); - expect(config.address).toEqual(daoCvg.riskEngine().pdas().config()); - }); - - it('set risk categories info [medium]', async () => { - const { config } = await daoCvg.riskEngine().setRiskCategoriesInfo({ - changes: [ - { - value: DEFAULT_RISK_CATEGORIES_INFO.medium, - category: 'medium', - }, - ], - }); - expect(config.address).toEqual(daoCvg.riskEngine().pdas().config()); - }); - - it('set risk categories info [high]', async () => { - const { config } = await daoCvg.riskEngine().setRiskCategoriesInfo({ - changes: [ - { - value: DEFAULT_RISK_CATEGORIES_INFO.high, - category: 'high', - }, - ], - }); - expect(config.address).toEqual(daoCvg.riskEngine().pdas().config()); - }); - - it('set risk categories info [very high]', async () => { - const { config } = await daoCvg.riskEngine().setRiskCategoriesInfo({ - changes: [ - { - value: DEFAULT_RISK_CATEGORIES_INFO.veryHigh, - category: 'very-high', - }, - ], - }); - expect(config.address).toEqual(daoCvg.riskEngine().pdas().config()); - }); - it('calculate collateral for RFQ', async () => { const { rfq } = await createRfq(takerCvg, 1.5, 'buy'); const { requiredCollateral } = await daoCvg diff --git a/packages/validator/fixtures/accounts/risk-engine-config.json b/packages/validator/fixtures/accounts/risk-engine-config.json deleted file mode 100644 index 43d8a2ca9..000000000 --- a/packages/validator/fixtures/accounts/risk-engine-config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "pubkey": "63zhouVc9DsAWsvp9CaJ7EY12CDK984Yt7heVbTsJxcN", - "account": { - "lamports": 9744000, - "data": [ - "mwyq4B76zIIAAAAAAAAAAAAAAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPMEgAAAAB7FK5H4XqEPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", - "base64" - ], - "owner": "CtfTi4TstqJaxEh8giQ7kK8CKXsJyF9CuwdcVoqGrEi1", - "executable": false, - "rentEpoch": 0 - } -} \ No newline at end of file diff --git a/packages/validator/fixtures/programs/hxro_print_trade_provider.so b/packages/validator/fixtures/programs/hxro_print_trade_provider.so index a708cb408..c7d01874e 100755 Binary files a/packages/validator/fixtures/programs/hxro_print_trade_provider.so and b/packages/validator/fixtures/programs/hxro_print_trade_provider.so differ diff --git a/packages/validator/fixtures/programs/psyoptions_american_instrument.so b/packages/validator/fixtures/programs/psyoptions_american_instrument.so index a2d95051c..75ef46ca1 100755 Binary files a/packages/validator/fixtures/programs/psyoptions_american_instrument.so and b/packages/validator/fixtures/programs/psyoptions_american_instrument.so differ diff --git a/packages/validator/fixtures/programs/psyoptions_european_instrument.so b/packages/validator/fixtures/programs/psyoptions_european_instrument.so index c13c48648..6dd9f11fb 100755 Binary files a/packages/validator/fixtures/programs/psyoptions_european_instrument.so and b/packages/validator/fixtures/programs/psyoptions_european_instrument.so differ diff --git a/packages/validator/fixtures/programs/rfq.so b/packages/validator/fixtures/programs/rfq.so index 68b36c582..e47160cb7 100755 Binary files a/packages/validator/fixtures/programs/rfq.so and b/packages/validator/fixtures/programs/rfq.so differ diff --git a/packages/validator/fixtures/programs/risk_engine.so b/packages/validator/fixtures/programs/risk_engine.so index fdcf8783c..89b3baaa1 100755 Binary files a/packages/validator/fixtures/programs/risk_engine.so and b/packages/validator/fixtures/programs/risk_engine.so differ diff --git a/packages/validator/fixtures/programs/vault_operator.so b/packages/validator/fixtures/programs/vault_operator.so index 03bd1db72..cc7b71cf2 100755 Binary files a/packages/validator/fixtures/programs/vault_operator.so and b/packages/validator/fixtures/programs/vault_operator.so differ diff --git a/packages/validator/fixtures/pubkey-naming.json b/packages/validator/fixtures/pubkey-naming.json index c99662183..b500e659a 100644 --- a/packages/validator/fixtures/pubkey-naming.json +++ b/packages/validator/fixtures/pubkey-naming.json @@ -27,7 +27,6 @@ "5Atpbyw3tBjjc8EYrbjE1a4FNqyLUszFGsNo3R5bR3y8": "rfq-mint-info-usd-quote", "AinWDnZWiEkWrNGH9jbvS2JXaBFZwnRE5ssNGyop882L": "rfq-protocol", "CtfTi4TstqJaxEh8giQ7kK8CKXsJyF9CuwdcVoqGrEi1": "risk-engine", - "63zhouVc9DsAWsvp9CaJ7EY12CDK984Yt7heVbTsJxcN": "risk-engine-config", "BMXWVaYPVJ4G8g2MMJt51CDgjHHuoirPMvsTUadv3s3v": "spot-instrument", "7J21igTMpQa18YueGJGNmp54m1VxsBHz4LEjiV6P28DJ": "spot-instrument-config", "CBVMytnrNLSMZR4kRBwpp87iNeuexMehJFMTcizW86Yy": "token-account-btc-dao", diff --git a/packages/validator/helpers.ts b/packages/validator/helpers.ts index fa4cb4d29..e281b4c44 100644 --- a/packages/validator/helpers.ts +++ b/packages/validator/helpers.ts @@ -102,6 +102,16 @@ const getBaseArgs = () => [ '--account-dir', path.join(HXRO_DEPS, 'accounts'), + // squads fixtures + '--url', + 'm', + '-c', + 'BSTq9w3kZwNwpBXJEvTZz2G9ZTNyKBvoSeXMvwb4cNZr', + '-c', + 'SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf', + '-c', + 'Fy3YMJCvwbAXUgUM5b91ucUVA3jYzwWLHL3MwBqKsh8n', + '--ledger', './test-ledger', '--reset', @@ -127,7 +137,6 @@ export class Ctx { // Protocol protocol = getAccountPk('rfq-protocol'); - riskEngine = getAccountPk('risk-engine-config'); baseAsset = getAccountPk('rfq-base-asset-btc'); quoteRegisteredMint = getAccountPk('rfq-mint-info-usd-quote'); baseRegisteredMint = getAccountPk('rfq-mint-info-btc'); diff --git a/yarn.lock b/yarn.lock index 4faaed11e..612873d18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1281,10 +1281,10 @@ bn.js "^5.2.0" debug "^4.3.3" -"@convergence-rfq/hxro-print-trade-provider@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@convergence-rfq/hxro-print-trade-provider/-/hxro-print-trade-provider-3.9.0.tgz#69ff37b155c10ec04db685ec07b85cc4fc7679a1" - integrity sha512-taK9TCm42h9BcH/IrrQ0lYa9Q6MqsyIiUWAMJNIcwRlNc93X/eNLRFtr+KcvXqt8WWPhtxCU81xgicSGf19DHQ== +"@convergence-rfq/hxro-print-trade-provider@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@convergence-rfq/hxro-print-trade-provider/-/hxro-print-trade-provider-3.10.0.tgz#cc84b62bb8dfa1bb803edfb33c5824d9193bc8cc" + integrity sha512-s+7oqL6usif8+FFWCOBQAx/crbrf51DLiONt4Zy2PKx0Ae37f+Wf02xl3vANwFhgqMlgVVn4QPQCSb+BzZ9fUw== dependencies: "@convergence-rfq/beet" "^0.7.10" "@convergence-rfq/beet-solana" "^0.4.11" @@ -1292,10 +1292,10 @@ "@solana/web3.js" "^1.56.2" bn.js "^5.2.0" -"@convergence-rfq/psyoptions-american-instrument@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@convergence-rfq/psyoptions-american-instrument/-/psyoptions-american-instrument-3.9.0.tgz#36539c537269785cd77c4fa4129d3b370c9e0b41" - integrity sha512-WHK/hnx2pduaK3DxNpf8Y7oiwVBQ6jzKerwRkQveAU3QQZR4I7FsPE79Z7uJuW8XbRyPG2Zs1J+MB4YcNxDkdw== +"@convergence-rfq/psyoptions-american-instrument@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@convergence-rfq/psyoptions-american-instrument/-/psyoptions-american-instrument-3.10.0.tgz#39ca418d63b273c52fe33569e958f4c4069e4648" + integrity sha512-mAJ9JF56oQBuGn8sTE8ZcQ7hRY+pxa947pRQVzZZWitt7OO5Pxu9kZq8oFARLglOdHEdVmCkhN05lUaSMel8rA== dependencies: "@convergence-rfq/beet" "^0.7.10" "@convergence-rfq/beet-solana" "^0.4.11" @@ -1303,10 +1303,10 @@ "@solana/web3.js" "^1.56.2" bn.js "^5.2.0" -"@convergence-rfq/psyoptions-european-instrument@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@convergence-rfq/psyoptions-european-instrument/-/psyoptions-european-instrument-3.9.0.tgz#dc0c9555534db280be9c9a2b492e293755916767" - integrity sha512-U7Lk1hLAu0A4y60LPNTjH0i7AB4qq59gKUZ+i5Yf+yh6QzVQ3rP2lRL8LVBV/dMi+4CEOonIWFCwv4hdKE3uzg== +"@convergence-rfq/psyoptions-european-instrument@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@convergence-rfq/psyoptions-european-instrument/-/psyoptions-european-instrument-3.10.0.tgz#6aa20a873cf8206dbc6e1cde2450c6a6a3f552df" + integrity sha512-Yr1JiHVadYTOeMQqxUGuSPnnlNQbrDJDxo0dCEG+wacDomiiv4ThvGovj1XQ4LNqDCorzHBEYi1JpICQXDd/QA== dependencies: "@convergence-rfq/beet" "^0.7.10" "@convergence-rfq/beet-solana" "^0.4.11" @@ -1314,10 +1314,10 @@ "@solana/web3.js" "^1.56.2" bn.js "^5.2.0" -"@convergence-rfq/rfq@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@convergence-rfq/rfq/-/rfq-3.9.0.tgz#a3b380c8017d2a6ae699ccda41498381217e8e24" - integrity sha512-/+3zEMnRUkVEHneVwxdDN3yzrzXE24O+2WRBmd6ILZeGPiS6s7RnecEudQuc2l1Ss18gCC6UwPqkvAt+8lCm4w== +"@convergence-rfq/rfq@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@convergence-rfq/rfq/-/rfq-3.10.0.tgz#53e986f89dc70690904394a008d98ab155bed6c5" + integrity sha512-RgwYMHa0Adj0XTc2yMMj4LI/VIp4JFiVsnGNuK79OfO+oV6OxnGTdVrpixDlYSfJylkH9eUobmoPmiLECK+PPg== dependencies: "@convergence-rfq/beet" "^0.7.10" "@convergence-rfq/beet-solana" "^0.4.11" @@ -1325,10 +1325,10 @@ "@solana/web3.js" "^1.56.2" bn.js "^5.2.0" -"@convergence-rfq/risk-engine@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@convergence-rfq/risk-engine/-/risk-engine-3.9.0.tgz#4254d1f9ed4b9d6dbb04342fdea223515608e0cb" - integrity sha512-brir10dX3vWsQodlBm8jFY+1RbGrYZwIAjAvxND/PjC2P7xZ32VLxIZVAEnfcc9JZgGEwWoWUOPjfsAnAVkqhg== +"@convergence-rfq/risk-engine@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@convergence-rfq/risk-engine/-/risk-engine-3.10.0.tgz#6cdf08901aaafb895e87d1db941d30d147ae5b3a" + integrity sha512-dzNcphgvvdF8g3ATu91hTf8PL5W2I3eJixhImE4xX3aDcXpA92ErYSEgSPS7QargFP+3uvB1w1I7THAzXwQJug== dependencies: "@convergence-rfq/beet" "^0.7.10" "@convergence-rfq/beet-solana" "^0.4.11" @@ -1336,10 +1336,10 @@ "@solana/web3.js" "^1.56.2" bn.js "^5.2.0" -"@convergence-rfq/spot-instrument@3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@convergence-rfq/spot-instrument/-/spot-instrument-3.9.0.tgz#f5fbe3c29db66192622fcf22c66161c4aca80453" - integrity sha512-odOtMFQ4/hpQAyxXokaJ5ZVBx+zfG7htr/IfRVX63QbPSuB4aLUisWb2cqmC+0Nj4mzlXU6rs+gWkdaBuV7Nyg== +"@convergence-rfq/spot-instrument@3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@convergence-rfq/spot-instrument/-/spot-instrument-3.10.0.tgz#57b75859c18f821f48635e48c296db13668e449a" + integrity sha512-F066GxaUpqwa7+1o5+Tj4VaK0prozQCXOuIv1N2o0FkyJI0AGfrDir2YmlQnovBii+Atj/zUVSmPrwTlZEG7+w== dependencies: "@convergence-rfq/beet" "^0.7.10" "@convergence-rfq/beet-solana" "^0.4.11" @@ -1347,10 +1347,10 @@ "@solana/web3.js" "^1.56.2" bn.js "^5.2.0" -"@convergence-rfq/vault-operator@^3.9.0": - version "3.9.0" - resolved "https://registry.yarnpkg.com/@convergence-rfq/vault-operator/-/vault-operator-3.9.0.tgz#bea35581df1bd22cf75cb1aab34933613294a70c" - integrity sha512-0E5gYdD+haVz5Cd++GcZ6UJ0ucgvakb3maviELtD6rv8mBDBy5D6nER6c135xgF84PFEt2p2V0d2sz0awa5rWw== +"@convergence-rfq/vault-operator@^3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@convergence-rfq/vault-operator/-/vault-operator-3.10.0.tgz#63616c9e0be2aa3cddc659f3ceecbb9923772ffa" + integrity sha512-d43thgKaSaFEf2khteGQ46pRU1sl65PJwfAjDLy5SnOscLPw7e1irV7ETxs97AZA0zdzv1niOejn0H2jAg/zMQ== dependencies: "@convergence-rfq/beet" "^0.7.10" "@convergence-rfq/beet-solana" "^0.4.11" @@ -2143,6 +2143,40 @@ globby "^11.0.0" read-yaml-file "^1.1.0" +"@metaplex-foundation/beet-solana@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet-solana/-/beet-solana-0.4.0.tgz#52891e78674aaa54e0031f1bca5bfbc40de12e8d" + integrity sha512-B1L94N3ZGMo53b0uOSoznbuM5GBNJ8LwSeznxBxJ+OThvfHQ4B5oMUqb+0zdLRfkKGS7Q6tpHK9P+QK0j3w2cQ== + dependencies: + "@metaplex-foundation/beet" ">=0.1.0" + "@solana/web3.js" "^1.56.2" + bs58 "^5.0.0" + debug "^4.3.4" + +"@metaplex-foundation/beet@0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet/-/beet-0.7.1.tgz#0975314211643f87b5f6f3e584fa31abcf4c612c" + integrity sha512-hNCEnS2WyCiYyko82rwuISsBY3KYpe828ubsd2ckeqZr7tl0WVLivGkoyA/qdiaaHEBGdGl71OpfWa2rqL3DiA== + dependencies: + ansicolors "^0.3.2" + bn.js "^5.2.0" + debug "^4.3.3" + +"@metaplex-foundation/beet@>=0.1.0": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/beet/-/beet-0.7.2.tgz#fa4726e4cfd4fb6fed6cddc9b5213c1c2a2d0b77" + integrity sha512-K+g3WhyFxKPc0xIvcIjNyV1eaTVJTiuaHZpig7Xx0MuYRMoJLLvhLTnUXhFdR5Tu2l2QSyKwfyXDgZlzhULqFg== + dependencies: + ansicolors "^0.3.2" + assert "^2.1.0" + bn.js "^5.2.0" + debug "^4.3.3" + +"@metaplex-foundation/cusper@^0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/cusper/-/cusper-0.0.2.tgz#dc2032a452d6c269e25f016aa4dd63600e2af975" + integrity sha512-S9RulC2fFCFOQraz61bij+5YCHhSO9llJegK8c8Y6731fSi6snUSQJdCUqYS8AIgR0TKbQvdvgSyIIdbDFZbBA== + "@mithraic-labs/psy-american@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@mithraic-labs/psy-american/-/psy-american-0.2.3.tgz#a6f3a62f96ec01f94463a7b12f5bf71a003c9942" @@ -2179,6 +2213,11 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== +"@noble/hashes@^1.3.3": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -2825,7 +2864,7 @@ "@solana/web3.js" "^1.32.0" start-server-and-test "^1.14.0" -"@solana/spl-token@^0.3.5", "@solana/spl-token@^0.3.8": +"@solana/spl-token@^0.3.5", "@solana/spl-token@^0.3.6", "@solana/spl-token@^0.3.8": version "0.3.11" resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.11.tgz#cdc10f9472b29b39c8983c92592cadd06627fb9a" integrity sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ== @@ -2881,6 +2920,43 @@ rpc-websockets "^7.5.1" superstruct "^0.14.2" +"@solana/web3.js@^1.70.3": + version "1.91.2" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.91.2.tgz#a5cb46a90076faaa284856e24464cac2b68fdc0c" + integrity sha512-WXPl5VXtfNKWM2RkGj7mvX6dKcZURDKe1lWBFAt/RqDBI9Rjr9hr7Y+U+yz2+TyViMmoinfJVlkS4gk2FPDG/g== + dependencies: + "@babel/runtime" "^7.23.4" + "@noble/curves" "^1.2.0" + "@noble/hashes" "^1.3.3" + "@solana/buffer-layout" "^4.0.1" + agentkeepalive "^4.5.0" + bigint-buffer "^1.1.5" + bn.js "^5.2.1" + borsh "^0.7.0" + bs58 "^4.0.1" + buffer "6.0.3" + fast-stable-stringify "^1.0.0" + jayson "^4.1.0" + node-fetch "^2.7.0" + rpc-websockets "^7.5.1" + superstruct "^0.14.2" + +"@sqds/multisig@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@sqds/multisig/-/multisig-2.1.1.tgz#43cf21f79a70d91a3bab508a3c819573c89ea417" + integrity sha512-bNXKnz3/12ynS6ASt8tx3u4U1HGi2i5qE6YqSJBkpIC+FBvsazBAdpCgIsjv3SeczkzkHfVhusmkrlsjtSdfCQ== + dependencies: + "@metaplex-foundation/beet" "0.7.1" + "@metaplex-foundation/beet-solana" "0.4.0" + "@metaplex-foundation/cusper" "^0.0.2" + "@solana/spl-token" "^0.3.6" + "@solana/web3.js" "^1.70.3" + "@types/bn.js" "^5.1.1" + assert "^2.0.0" + bn.js "^5.2.1" + buffer "6.0.3" + invariant "2.2.4" + "@supercharge/promise-pool@^2.1.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@supercharge/promise-pool/-/promise-pool-2.4.0.tgz#6050eea8c2d7f92ddd4ddc582ee328b15c034ad3" @@ -3698,6 +3774,17 @@ asn1.js@^5.4.1: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" +assert@^2.0.0, assert@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" + integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== + dependencies: + call-bind "^1.0.2" + is-nan "^1.3.2" + object-is "^1.1.5" + object.assign "^4.1.4" + util "^0.12.5" + async-retry@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" @@ -4135,7 +4222,7 @@ caching-transform@^4.0.0: package-hash "^4.0.0" write-file-atomic "^3.0.0" -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== @@ -6161,6 +6248,13 @@ internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +invariant@2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + is-alphabetical@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" @@ -6174,6 +6268,14 @@ is-alphanumerical@^1.0.0: is-alphabetical "^1.0.0" is-decimal "^1.0.0" +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + is-array-buffer@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" @@ -6265,6 +6367,13 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -6292,6 +6401,14 @@ is-module@^1.0.0: resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== +is-nan@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + is-negative-zero@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" @@ -6377,7 +6494,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.13: +is-typed-array@^1.1.13, is-typed-array@^1.1.3: version "1.1.13" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== @@ -7243,7 +7360,7 @@ log-update@^5.0.1: strip-ansi "^7.0.1" wrap-ansi "^8.0.1" -loose-envify@^1.1.0: +loose-envify@^1.0.0, loose-envify@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -7874,12 +7991,20 @@ object-inspect@^1.13.1: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== +object-is@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.5: +object.assign@^4.1.4, object.assign@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== @@ -9665,6 +9790,17 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +util@^0.12.5: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" @@ -9830,6 +9966,17 @@ which-typed-array@^1.1.14: gopd "^1.0.1" has-tostringtag "^1.0.1" +which-typed-array@^1.1.2: + version "1.1.15" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" + which@^1.2.14, which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"