Quick Start
This section gives you a working example on how to quickly open and close a position.
import { SudoAPI, OracleAPI, SudoDataAPI, IPositionInfo, IPositionConfig, getConsts, parseSymbolKey, joinSymbol } from 'sudo-sdk';
import { Transaction } from '@mysten/sui/transactions';
import { SuiClient } from '@mysten/sui/client';
import { decodeSuiPrivateKey } from '@mysten/sui.js/cryptography';
import {
Ed25519Keypair,
} from '@mysten/sui.js/keypairs/ed25519';
import { useCallback, useEffect, useState } from 'react';
type SudoApiCall = (api: SudoAPI) => Promise<Transaction>;
interface ITokenBalance {
symbol: string;
balance: string;
objectId: string;
}
const privateKey = <yourPrivateKey>;
const rpc = <yourRpc>;
const network = 'mainnet';
const GAS_BUDGET = 100000000;
const { secretKey } = decodeSuiPrivateKey(privateKey);
const kpImport0 = Ed25519Keypair.fromSecretKey(secretKey);
const pk = kpImport0.getPublicKey();
const signer = pk.toSuiAddress();
const provider = new SuiClient({ url: rpc });
const consts = getConsts(network);
const openPosition = true;
const mode = 'long';
const orderType = 'limit';
const collateralToken = 'USDC';
const indexToken = 'SUI';
const leverage = 10;
const payAmount = 100;
const symbol = joinSymbol(mode, indexToken);
const amountToDecrease = 100;
const indexPrice = 100;
const priceSlippage = 0.003;
const collateralSlippage = 0.5;
const RELAYER_FEE = 1;
export function sudo_sdk_sample() {
const [prices, setPrices] = useState<{ [key: string]: number }>({});
const [positions, setPositions] = useState<IPositionInfo[]>([]);
const [positionConfigMap, setPositionConfigMap] = useState<{
[key: string]: IPositionConfig;
}>({});
useEffect(() => {
const oracleAPI = new OracleAPI(network);
Promise.all([
oracleAPI.subOraclePrices(
Array.from(
new Set([...Object.keys(oracleAPI.consts.pythFeeder.feeder)]),
),
priceInfo => {
setPrices(prevPrice => ({
...prevPrice,
[priceInfo.id]: priceInfo
.getPriceUnchecked()
.getPriceAsNumberUnchecked(),
}));
},
),
]);
}, [network]);
const fetchPositions = useCallback(async () => {
const dataAPI = new SudoDataAPI(network, provider);
const capInfoList = await dataAPI.getPositionCapInfoList(signer);
const infoList = await dataAPI.getPositionInfoList(
capInfoList,
signer,
);
setPositions(infoList);
}, [signer, network, setPositions]);
useEffect(() => {
fetchPositions();
}, [fetchPositions]);
const fetchPositionConfigs = useCallback(async () => {
const symbols = Object.keys(consts.sudoCore.symbols),
if (symbols.length === 0) return;
const dataAPI = new SudoDataAPI(network, provider);
await Promise.all([
...symbols.map(async symbol => {
const [direction, indexToken] = parseSymbolKey(symbol);
const config = await dataAPI.getPositionConfig(
indexToken,
direction === 'long',
);
setPositionConfigMap(prevMap => ({
...prevMap,
[`sudo-${symbol}`]: config,
}));
}),
]);
}, [
network,
setPositionConfigMap,
]);
useEffect(() => {
fetchPositionConfigs();
}, [fetchPositionConfigs]);
const executeSudoApiCall = async (
apiCall: SudoApiCall,
) => {
const sudoAPI = new SudoAPI(network, provider);
const txb = await apiCall(sudoAPI);
txb.setSender(signer);
txb.setGasBudget(GAS_BUDGET);
const bytes = await txb.build({ client: provider });
const serializedSignature = (await kpImport0.signTransactionBlock(bytes)).signature;
const res = await provider.executeTransactionBlock({
transactionBlock: bytes,
signature: serializedSignature,
options: {
showEffects: false,
showEvents: false,
},
});
};
async function getCoins(
owner: string,
coinType: string,
) {
let _continue = true;
let cursor = null;
let coins: ITokenBalance[] = [];
while (_continue) {
const tmp: any = await provider.getCoins({ owner, coinType, cursor });
if (tmp.hasNextPage) {
cursor = tmp.nextCursor;
} else {
_continue = false;
}
coins = coins.concat(
tmp.data.map((coin: any) => ({
// eslint-disable-next-line
symbol: coin.coinType.split('::')[2],
balance: coin.balance.toString(),
objectId: coin.coinObjectId,
})),
);
}
return coins;
}
if (openPosition) {
const coins = await getCoins(
signer,
consts.coins[collateralToken].module,
);
const coinObjects = coins.map(e => e.objectId);
executeSudoApiCall(
async sudoApi => {
return sudoApi.openPosition(
collateralToken,
indexToken,
leverage,
payAmount,
positionConfigMap[`sudo-${symbol}`],
coinObjects,
mode === 'long',
prices[indexToken],
prices[collateralToken],
priceSlippage,
collateralSlippage,
orderType === 'limit',
false,
orderType === 'limit' ? BigInt(RELAYER_FEE * 1e9) : BigInt(1),
);
}
).finally(() => {});
} else {
executeSudoApiCall(
async sudoApi => {
return sudoApi.decreasePosition(
positions[0].id,
positions[0].collateralToken,
positions[0].indexToken,
positions[0].positionAmount,
amountToDecrease,
positions[0].long,
prices[positions[0].indexToken],
indexPrice || 0,
prices[positions[0].collateralToken],
orderType === 'limit',
false,
priceSlippage,
collateralSlippage,
orderType === 'limit' ? BigInt(RELAYER_FEE * 1e9) : BigInt(1),
);
}
).finally(() => {});
}
}
Last updated