Skip to content

Commit

Permalink
Merge pull request #256 from convergence-rfq/eng-1370-add-response-ex…
Browse files Browse the repository at this point in the history
…piry-on-sdk

add latest repsonse expiration to sdk
  • Loading branch information
pindaroso authored Nov 2, 2023
2 parents 74d9d88 + 8581639 commit 8d29a2c
Show file tree
Hide file tree
Showing 21 changed files with 202 additions and 42 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
node: ["18.x"]
solana: ["1.14.11"]
solana: ["1.14.18"]
steps:
- name: Git checkout
uses: actions/checkout@v3
Expand Down Expand Up @@ -52,4 +52,4 @@ jobs:
run: yarn validator & sleep 3

- name: Test
run: yarn test
run: yarn test
7 changes: 7 additions & 0 deletions packages/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @convergence-rfq/cli

## 4.5.17

### Patch Changes

- Updated dependencies
- @convergence-rfq/sdk@4.5.17

## 4.5.16

### Patch Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@convergence-rfq/cli",
"description": "Official Convergence CLI",
"version": "4.5.16",
"version": "4.5.17",
"license": "MIT",
"publishConfig": {
"access": "public"
Expand Down Expand Up @@ -47,7 +47,7 @@
"cli": "ts-node src/index.ts"
},
"dependencies": {
"@convergence-rfq/sdk": "4.5.16",
"@convergence-rfq/sdk": "4.5.17",
"@solana/web3.js": "^1.73.0",
"@types/cookie": "^0.5.1",
"commander": "^10.0.0"
Expand Down
7 changes: 7 additions & 0 deletions packages/js/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @convergence-rfq/sdk

## 4.5.17

### Patch Changes

- Add expirationTimestamp to Response Model
Update CPL solita packages to version 2.2.14

## 4.5.16

### Patch Changes
Expand Down
12 changes: 6 additions & 6 deletions packages/js/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@convergence-rfq/sdk",
"description": "Official Convergence RFQ SDK",
"version": "4.5.16",
"version": "4.5.17",
"license": "MIT",
"publishConfig": {
"access": "public"
Expand Down Expand Up @@ -51,11 +51,11 @@
"@bundlr-network/client": "^0.8.8",
"@convergence-rfq/beet": "0.7.10",
"@convergence-rfq/beet-solana": "0.4.11",
"@convergence-rfq/psyoptions-american-instrument": "2.2.13",
"@convergence-rfq/psyoptions-european-instrument": "2.2.13",
"@convergence-rfq/rfq": "2.2.13",
"@convergence-rfq/risk-engine": "2.2.13",
"@convergence-rfq/spot-instrument": "2.2.13",
"@convergence-rfq/psyoptions-american-instrument": "2.2.14",
"@convergence-rfq/psyoptions-european-instrument": "2.2.14",
"@convergence-rfq/rfq": "2.2.14",
"@convergence-rfq/risk-engine": "2.2.14",
"@convergence-rfq/spot-instrument": "2.2.14",
"@coral-xyz/borsh": "^0.26.0",
"@mithraic-labs/psy-american": "^0.2.3",
"@mithraic-labs/tokenized-euros": "^0.2.3",
Expand Down
15 changes: 13 additions & 2 deletions packages/js/src/plugins/rfqModule/models/Response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { PublicKey } from '@solana/web3.js';
import { DefaultingParty as SolitaDefaultingParty } from '@convergence-rfq/rfq';

import { ResponseAccount } from '../accounts';
import { removeDecimals } from '../../../utils/conversions';
import {
convertTimestampToMilliSeconds,
removeDecimals,
} from '../../../utils/conversions';
import { assert } from '../../../utils/assert';
import { Confirmation, fromSolitaConfirmation } from './Confirmation';
import { AuthoritySide, fromSolitaAuthoritySide } from './AuthoritySide';
Expand Down Expand Up @@ -34,6 +37,9 @@ export type Response = {
/** The timestamp at which this response was created. */
readonly creationTimestamp: number;

/** The timestamp at which this response will expire. */
readonly expirationTimestamp: number;

/** The bid required for sell and optionally two-way order types. */
readonly bid: Quote | null;

Expand Down Expand Up @@ -89,7 +95,12 @@ export const toResponse = (
address: account.publicKey,
maker: account.data.maker,
rfq: account.data.rfq,
creationTimestamp: Number(account.data.creationTimestamp) * 1_000,
creationTimestamp: convertTimestampToMilliSeconds(
account.data.creationTimestamp
),
expirationTimestamp: convertTimestampToMilliSeconds(
account.data.expirationTimestamp
),
makerCollateralLocked: removeDecimals(
account.data.makerCollateralLocked,
collateralDecimals
Expand Down
9 changes: 7 additions & 2 deletions packages/js/src/plugins/rfqModule/models/Rfq.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { PublicKey } from '@solana/web3.js';
import { RfqAccount } from '../accounts';
import { assert } from '../../../utils/assert';
import { convertTimestamp, removeDecimals } from '../../../utils/conversions';
import {
convertTimestampToMilliSeconds,
removeDecimals,
} from '../../../utils/conversions';
import {
SpotLegInstrument,
SpotQuoteInstrument,
Expand Down Expand Up @@ -114,7 +117,9 @@ export const toRfq = async (
quoteMint: SpotLegInstrument.deserializeInstrumentData(
Buffer.from(account.data.quoteAsset.instrumentData)
).mintAddress,
creationTimestamp: convertTimestamp(account.data.creationTimestamp),
creationTimestamp: convertTimestampToMilliSeconds(
account.data.creationTimestamp
),
activeWindow: account.data.activeWindow,
settlingWindow: account.data.settlingWindow,
expectedLegsSize: account.data.expectedLegsSize,
Expand Down
17 changes: 14 additions & 3 deletions packages/js/src/plugins/rfqModule/operations/confirmResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
TransactionBuilder,
TransactionBuilderOptions,
} from '../../../utils/TransactionBuilder';
import { Response } from '../models';
import { ResponseSide, toSolitaQuoteSide } from '../models/ResponseSide';
import { toSolitaOverrideLegMultiplierBps } from '../models/Confirmation';

Expand Down Expand Up @@ -181,13 +182,19 @@ export const confirmResponseBuilder = async (
}),
} = params;

const responseModel = await convergence
.rfqs()
.findResponseByAddress({ address: response });

if (isResponseExpired(responseModel)) {
throw new Error('Response is expired');
}

const { overrideLegMultiplier = null } = params;
const overrideLegMultiplierBps =
overrideLegMultiplier &&
toSolitaOverrideLegMultiplierBps(overrideLegMultiplier);
const responseModel = await convergence
.rfqs()
.findResponseByAddress({ address: response });

const makerCollateralInfo = convergence.collateral().pdas().collateralInfo({
user: responseModel.maker,
programs,
Expand Down Expand Up @@ -264,3 +271,7 @@ export const confirmResponseBuilder = async (
}
);
};

const isResponseExpired = (response: Response): boolean => {
return Date.now() > response.expirationTimestamp;
};
30 changes: 30 additions & 0 deletions packages/js/src/plugins/rfqModule/operations/respondToRfq.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createRespondToRfqInstruction } from '@convergence-rfq/rfq';
import { PublicKey, AccountMeta, ComputeBudgetProgram } from '@solana/web3.js';

import BN from 'bn.js';
import { SendAndConfirmTransactionResponse } from '../../rpcModule';
import { assertResponse, Response } from '../models/Response';
import { Convergence } from '../../../Convergence';
Expand All @@ -17,6 +18,7 @@ import {
} from '../../../utils/TransactionBuilder';
import { Quote, Rfq } from '../models';
import { toSolitaQuote } from '../models/Quote';
import { convertTimestampToSeconds } from '@/utils';

const getNextResponsePdaAndDistinguisher = async (
cvg: Convergence,
Expand Down Expand Up @@ -99,6 +101,11 @@ export type RespondToRfqInput = {
*/
ask?: Quote;

/**
* The optional response expirationTimestamp in seconds.
*/
expirationTimestamp?: number;

/**
* The address of the RFQ account.
*/
Expand Down Expand Up @@ -239,6 +246,7 @@ export const respondToRfqBuilder = async (
user: maker.publicKey,
programs,
}),
expirationTimestamp,
} = params;

if (!bid && !ask) {
Expand All @@ -247,6 +255,27 @@ export const respondToRfqBuilder = async (

const rfqModel = await convergence.rfqs().findRfqByAddress({ address: rfq });

const rfqExpirationTimestampSeconds =
convertTimestampToSeconds(rfqModel.creationTimestamp) +
rfqModel.activeWindow;

const currentTimestampSeconds = convertTimestampToSeconds(Date.now());

let expirationTimestampBn: BN;

if (!expirationTimestamp) {
expirationTimestampBn = new BN(rfqExpirationTimestampSeconds);
} else {
if (expirationTimestamp < currentTimestampSeconds) {
throw new Error('Expiration timestamp must be in the future');
}
if (expirationTimestamp > rfqExpirationTimestampSeconds) {
throw new Error('Response expiration must be less than RFQ expiration');
}

expirationTimestampBn = new BN(expirationTimestamp);
}

const { response, pdaDistinguisher } =
await getNextResponsePdaAndDistinguisher(
convergence,
Expand Down Expand Up @@ -323,6 +352,7 @@ export const respondToRfqBuilder = async (
bid: bid && toSolitaQuote(bid, rfqModel.quoteAsset.getDecimals()),
ask: ask && toSolitaQuote(ask, rfqModel.quoteAsset.getDecimals()),
pdaDistinguisher,
expirationTimestamp: expirationTimestampBn,
}
),
signers: [maker],
Expand Down
14 changes: 13 additions & 1 deletion packages/js/src/utils/conversions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,22 @@ export const addDecimals = (value: number, decimals: number = 0): BN => {
* @param timestamp {bignum} Solita timestamp
* @returns {number} timestamp in milliseconds
*/
export function convertTimestamp(timestamp: bignum): number {
export function convertTimestampToMilliSeconds(
timestamp: bignum | number
): number {
if (typeof timestamp === 'number') {
return timestamp * 1_000;
}
return Number(timestamp) * 1_000;
}

export function convertTimestampToSeconds(timestamp: bignum | number): number {
if (typeof timestamp === 'number') {
return Math.floor(timestamp / 1_000);
}
return Math.floor(Number(timestamp) / 1_000);
}

/**
* Used to roundUp values to a certain amount of decimals.
*
Expand Down
19 changes: 19 additions & 0 deletions packages/js/tests/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,9 +404,11 @@ export const createRfq = async (
cvg: Convergence,
amount: number,
orderType: OrderType,
activeWindow?: number,
rfqType: 'open' | 'fixed-base' | 'fixed-quote' = 'fixed-base',
quoteMintPk = QUOTE_MINT_PK,
baseMintPk = BASE_MINT_BTC_PK
// 10 minutes
) => {
let instrumentAmount = 1;
let fixedSizeAmount = 1;
Expand All @@ -429,6 +431,7 @@ export const createRfq = async (
orderType,
fixedSize: { type: rfqType, amount: fixedSizeAmount },
quoteAsset: await SpotQuoteInstrument.create(cvg, quoteMint),
activeWindow,
});
return { rfq, response };
};
Expand All @@ -438,6 +441,7 @@ export const respondToRfq = async (
rfq: Rfq,
bid?: number,
ask?: number,
responseExpirationTimestamp?: number,
legsMultiplier?: number
) => {
if (!bid && !ask) {
Expand All @@ -448,6 +452,7 @@ export const respondToRfq = async (
rfq: rfq.address,
bid: bid ? { price: bid, legsMultiplier } : undefined,
ask: ask ? { price: ask, legsMultiplier } : undefined,
expirationTimestamp: responseExpirationTimestamp,
});
};

Expand Down Expand Up @@ -663,3 +668,17 @@ export const createEuropeanIronCondor = async (

return { rfq };
};

export const expectError = async (promise: Promise<any>, errorText: string) => {
try {
await promise;
throw new Error('No error thrown!');
} catch (e) {
if (
!e?.message.includes(errorText) &&
!e?.logs?.some((e: string) => e.includes(errorText))
) {
throw e;
}
}
};
2 changes: 2 additions & 0 deletions packages/js/tests/integration/psyoptionsAmerican.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ describe('integration.psyoptionsAmerican', () => {
rfq,
undefined,
150_123,
undefined,
5
);
expect(rfqResponse).toHaveProperty('address');
Expand Down Expand Up @@ -209,6 +210,7 @@ describe('integration.psyoptionsAmerican', () => {
rfq,
220_111,
150_123,
undefined,
5
);
expect(rfqResponse).toHaveProperty('address');
Expand Down
3 changes: 3 additions & 0 deletions packages/js/tests/integration/psyoptionsEuropean.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ describe('integration.psyoptionsEuropean', () => {
rfq,
undefined,
150_123,
undefined,
5
);
expect(rfqResponse).toHaveProperty('address');
Expand Down Expand Up @@ -208,6 +209,7 @@ describe('integration.psyoptionsEuropean', () => {
rfq,
220_111,
150_123,
undefined,
5
);
expect(rfqResponse).toHaveProperty('address');
Expand Down Expand Up @@ -290,6 +292,7 @@ describe('integration.psyoptionsEuropean', () => {
rfq,
150_123,
undefined,
undefined,
5
);
expect(rfqResponse).toHaveProperty('address');
Expand Down
Loading

0 comments on commit 8d29a2c

Please sign in to comment.