Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Dev add cli commad to add all jupiter tokens as base assets #270

Merged
merged 12 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.30

### Patch Changes

- Updated dependencies
- @convergence-rfq/[email protected]

## 4.5.29

### Patch Changes
Expand Down
6 changes: 3 additions & 3 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.29",
"version": "4.5.30",
"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.29",
"@convergence-rfq/sdk": "4.5.30",
"@solana/web3.js": "^1.87.6",
"@types/cookie": "^0.5.1",
"commander": "^10.0.0"
Expand All @@ -61,4 +61,4 @@
"sinon": "^15.0.1",
"ts-mocha": "^10.0.0"
}
}
}
135 changes: 134 additions & 1 deletion packages/cli/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ import {
PriceOracle,
SpotLegInstrument,
SpotQuoteInstrument,
addBaseAssetBuilder,
registerMintBuilder,
TransactionBuilder,
} from '@convergence-rfq/sdk';

import { createCvg, Opts } from './cvg';
import { getInstrumentType, getSize } from './helpers';
import { getInstrumentType, getSigConfirmation, getSize } from './helpers';
import {
logPk,
logResponse,
Expand All @@ -27,6 +30,7 @@ import {
logToken,
logMint,
} from './logger';
import { CoinGeckoResponse, JupTokenList } from './types';

export const createMint = async (opts: Opts) => {
const cvg = await createCvg(opts);
Expand Down Expand Up @@ -163,6 +167,40 @@ export const addBaseAsset = async (opts: Opts) => {
}
};

export const updateBaseAsset = async (opts: Opts) => {
const cvg = await createCvg(opts);
const {
enabled,
index,
oracleSource,
oraclePrice,
oracleAddress,
riskCategory,
} = opts;
if (!oraclePrice && !oracleAddress) {
throw new Error('Either oraclePrice or oracleAddress must be provided');
}
if (!riskCategory) {
throw new Error('riskCategory must be provided');
}
try {
const { response } = await cvg.protocol().updateBaseAsset({
authority: cvg.rpc().getDefaultFeePayer(),
enabled,
index,
priceOracle: {
source: oracleSource,
price: oraclePrice,
address: oracleAddress ? new PublicKey(opts.oracleAddress) : undefined,
},
riskCategory,
});
logResponse(response);
} catch (e) {
logError(e);
}
};

export const registerMint = async (opts: Opts) => {
const getMintArgs = () => {
const mint = new PublicKey(opts.mint);
Expand Down Expand Up @@ -460,3 +498,98 @@ export const airdropDevnetTokens = async (opts: Opts) => {
logError(e);
}
};

export const addBaseAssetsFromJupiter = async (opts: Opts) => {
try {
const cvg = await createCvg(opts);

const baseAssets = await cvg.protocol().getBaseAssets();
// eslint-disable-next-line no-console
console.log('Base assets:', baseAssets);
const baseAssetsSymbols = baseAssets.map((b) => b.ticker);
const res = await fetch('https://token.jup.ag/all');
const jupTokens: JupTokenList[] = await res.json();
const jupTokensToAdd = jupTokens.filter(
(t) => !baseAssetsSymbols.includes(t.symbol)
);
let baseAssetIndexToStart = Math.max(...baseAssets.map((b) => b.index)) + 1;
// eslint-disable-next-line no-console
console.log('last baseAssetIndex', baseAssetIndexToStart - 1);
for (const token of jupTokensToAdd) {
try {
const coingeckoId = token?.extensions?.coingeckoId;
if (!coingeckoId || coingeckoId === '') {
// eslint-disable-next-line no-console
console.log(
'skipping token: because missing coingecko id',
token.symbol
);
continue;
}
const coinGeckoAPIKey = opts.coinGeckoApiKey;
const tokenPriceResponse = await fetch(
`https://pro-api.coingecko.com/api/v3/simple/price?ids=${coingeckoId}&vs_currencies=usd&x_cg_pro_api_key=${coinGeckoAPIKey}`
);
const tokenPriceJson: CoinGeckoResponse =
await tokenPriceResponse.json();

const tokenPrice = tokenPriceJson[coingeckoId]?.usd;
if (!tokenPrice) {
// eslint-disable-next-line no-console
console.log(
'skipping token: because missing price',
token.symbol,
tokenPrice
);
continue;
}
// eslint-disable-next-line no-console
console.log('Adding token:', token.symbol, 'with price:', tokenPrice);

//mint should already exists on mainnet
const addBaseAssetTxBuilder = addBaseAssetBuilder(cvg, {
authority: cvg.rpc().getDefaultFeePayer(),
ticker: token.symbol,
riskCategory: 'high',
index: baseAssetIndexToStart,
priceOracle: {
source: 'in-place',
price: tokenPrice,
},
});
// eslint-disable-next-line no-console
console.log('Adding base asset:', token.symbol);
// eslint-disable-next-line no-console
console.log(' current baseAssetIndex:', baseAssetIndexToStart);
const registerMintTxBuilder = await registerMintBuilder(cvg, {
mint: new PublicKey(token.address),
baseAssetIndex: baseAssetIndexToStart,
});

const mergedTxBuiler = TransactionBuilder.make()
.setFeePayer(cvg.rpc().getDefaultFeePayer())
.add(addBaseAssetTxBuilder)
.add(registerMintTxBuilder);
const output = await mergedTxBuiler.sendAndConfirm(cvg);
logResponse(output.response);

const signatureStatus = await getSigConfirmation(
cvg.connection,
output.response.signature
);
const { commitment } = cvg.connection;
if (signatureStatus && signatureStatus === commitment) {
// eslint-disable-next-line no-console
console.log('Transaction confirmed');
baseAssetIndexToStart++;
}
} catch (e) {
// eslint-disable-next-line no-console
console.log('error:', e);
continue;
}
}
} catch (e) {
logError(e);
}
};
45 changes: 45 additions & 0 deletions packages/cli/src/groups/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
getProtocol,
getBaseAssets,
closeProtocol,
addBaseAssetsFromJupiter,
updateBaseAsset,
} from '../actions';

import { addCmd } from '../helpers';
Expand Down Expand Up @@ -136,6 +138,47 @@ const getCmd = (c: Command) =>
const getBaseAssetsCmd = (c: Command) =>
addCmd(c, 'get-base-assets', 'gets protocol base assets', getBaseAssets);

const addBaseAssetsFromJupiterCmd = (c: Command) =>
addCmd(
c,
'add-base-asset-from-jupiter',
'adds baseAssets from jupiter',
addBaseAssetsFromJupiter,
[
{
flags: '--coin-gecko-api-key <string>',
description: 'coin gecko api key',
},
]
);

const updateBaseAssetCmd = (c: Command) =>
addCmd(c, 'update-base-asset', 'updates base asset', updateBaseAsset, [
{
flags: '--index <number>',
description: 'index',
},
{
flags: '--oracle-source <string>',
description: 'oracle source - in-place | switchboard | pyth,',
},
{
flags: '--oracle-price <number>',
description: 'oracle price',
defaultValue: null,
},
{
flags: '--oracle-address <string>',
description: 'oracle address',
defaultValue: null,
},
{
flags: '--risk-category <string>',
description:
'risk category - "very-low" | "low" | "medium" | "high" | "very-high" | "custom-1" | "custom-2" | "custom-3"',
},
]);

export const protocolGroup = (c: Command) => {
const group = c.command('protocol');
initializeProtocolCmd(group);
Expand All @@ -146,4 +189,6 @@ export const protocolGroup = (c: Command) => {
getCmd(group);
getBaseAssetsCmd(group);
closeCmd(group);
addBaseAssetsFromJupiterCmd(group);
updateBaseAssetCmd(group);
};
11 changes: 11 additions & 0 deletions packages/cli/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from '@convergence-rfq/sdk';
import { Command } from 'commander';

import { Connection } from '@solana/web3.js';
import { Instrument } from './types';
import { DEFAULT_KEYPAIR_FILE, DEFAULT_RPC_ENDPOINT } from './constants';

Expand Down Expand Up @@ -97,3 +98,13 @@ export const addCmd = (

return cmd;
};

export const getSigConfirmation = async (
connection: Connection,
tx: string
) => {
const result = await connection.getSignatureStatus(tx, {
searchTransactionHistory: true,
});
return result?.value?.confirmationStatus;
};
1 change: 0 additions & 1 deletion packages/cli/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ export const logRfq = (r: Rfq) => {
l('Taker:', r.taker.toString());
l('Order type:', r.orderType);
l('Size:', r.size.type === 'open' ? 'open' : 'fixed');
l('Quote asset:', r.quoteMint.toString());
Copy link
Contributor

Choose a reason for hiding this comment

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

Add back in

Copy link
Contributor

Choose a reason for hiding this comment

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

@Nagaprasadvr Need to add this back int

l('Created:', new Date(created).toString());
l(`Active window: ${r.activeWindow} seconds`);
l(`Settlement window: ${r.settlingWindow} seconds`);
Expand Down
19 changes: 19 additions & 0 deletions packages/cli/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,22 @@ export type Instrument =
| SpotLegInstrument
| PsyoptionsAmericanInstrument
| PsyoptionsEuropeanInstrument;

export type JupTokenList = {
address: string;
chainId: number;
decimals: number;
name: string;
symbol: string;
logoURI: string;
tags: string[];
extensions: {
coingeckoId: string;
};
};

export type CoinGeckoResponse = {
[key: string]: {
usd: number;
};
};
6 changes: 6 additions & 0 deletions packages/js/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @convergence-rfq/sdk

## 4.5.30

### Patch Changes

- add UpdateBaseAsset operation to sdk

## 4.5.29

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion 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.29",
"version": "4.5.30",
"license": "MIT",
"publishConfig": {
"access": "public"
Expand Down
9 changes: 9 additions & 0 deletions packages/js/src/plugins/protocolModule/ProtocolClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
getRegisteredMintsOperation,
closeProtocolOperation,
CloseProtocolInput,
updateBaseAssetOperation,
UpdateBaseAssetInput,
} from './operations';
import { ProtocolPdasClient } from './ProtocolPdasClient';
import { OperationOptions } from '@/types';
Expand Down Expand Up @@ -128,4 +130,11 @@ export class ProtocolClient {
.operations()
.execute(findBaseAssetByAddressOperation(input), options);
}

/** {@inheritDoc updateBaseAssetOperation} */
updateBaseAsset(input: UpdateBaseAssetInput, options?: OperationOptions) {
return this.convergence
.operations()
.execute(updateBaseAssetOperation(input), options);
}
}
31 changes: 31 additions & 0 deletions packages/js/src/plugins/protocolModule/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { COption } from '@convergence-rfq/beet';
import { CustomOptionalF64, CustomOptionalPubkey } from '@convergence-rfq/rfq';
import { PublicKey } from '@solana/web3.js';

export const toCustomOptionalF64 = (
input: COption<number>
): CustomOptionalF64 => {
if (input !== null) {
return {
__kind: 'Some',
value: input,
};
}
return {
__kind: 'None',
};
};

export const toCustomOptionalPubkey = (
input: COption<PublicKey>
): CustomOptionalPubkey => {
if (input !== null) {
return {
__kind: 'Some',
value: input,
};
}
return {
__kind: 'None',
};
};
1 change: 1 addition & 0 deletions packages/js/src/plugins/protocolModule/operations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from './getRegisteredMints';
export * from './findRegisteredMintByAddress';
export * from './findBaseAssetByAddress';
export * from './closeProtocol';
export * from './updateBaseAssets';
Loading
Loading