Symmetry APIs
Symmetry APIs simplifies integration with on-chain programs without the need of installing or interacting with external libraries.
Getting Started
To interact with Symmetry API, you'll need to make POST requests to https://api.symmetry.fi/baskets/XXXX
with specific parameters based on the operation you want to perform. Each operation, such as minting, burning, or creating a new basket, has its own command path and required parameters.
Currently users can use symmetry API endpoints to
Create a new Basket
Description: Creates a new basket.
Endpoint:
POST https://api.symmetry.fi/baskets/create
Parameters:
symbol
: Basket Symbol/Ticker (3-10 characters).name
: Basket name (3-60 characters).uri
: URI containing desired metadata in JSON format (Max 300 characters).hostPlatform
: A project integrating Symmetry may receive hostPlatformFees.hostPlatformFees
: Fee in bps (0.1% = 10) for host platform wallet.creator
: Wallet PublicKey of a user creating a basket.depositFee
: Fee charged on deposits for creator (in bps).type
: Basket type: 0 = Immutable, 1 = Mutable, 2 = Permissioned.rebalanceInterval
: Frequency of rebalance checks in seconds.rebalanceThreshold
: Allowed deviation from target weights before rebalancing,slippage
: Maximum allowed slippage for rebalance transactions, in bps.lpOffsetThreshold
: EXPERIMENTAL: Defines liquidity pool behavior for rebalancing. 0 disables this feature.disableRebalance
: Controls automatic rebalancing: 0 = enabled, 1 = disabled.disableLp
: Controls liquidity pool functionality: 0 = enabled, 1 = disabled.composition
: Array of desired basket composition
Ts Example:
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Transaction } from "@solana/web3.js";
const wallet = useWallet();
const { connection } = useConnection();
/*
By using this publickey as host platform, your basket will
be available for public @ https://app.symmetry.fi/explore/
Host platforms can set any address they want to collect fees at
*/
const symmetryHost = "4Vry5hGDmbwGwhjgegHmoitjMHniSotpjBFkRuDYHcDG";
const creator = wallet.publicKey.toBase58();
const basketParameters = {
symbol: "FAVTOKENS", // 3-10 ['a'-'z','A'-'Z','0'-'9'] characters
name: "My Portfolio Basket", // 3-60 characters
uri: "", // can be left as empty and configured later.
hostPlatform: symmetryHost, // publicKey - string.
hostPlatformFee: 10, // Fee in basis points (bps). 10 bps = 0.1%
creator: creator, // wallet publickey of creator (string) .
depositFee: 50, // Fee on deposits, paid to the basket creator - 0.5% .
type: 1, // 1 = Mutable, Creator has authority to edit basket.
rebalanceInterval: 3600, // Rebalance checks are done every hour.
rebalanceThreshold: 300, // Rebalance will be triggered when asset weights deviate from their target weights by 3% .
slippage: 100, // Maximum allowed slippage for rebalance transactions, in bps 100 = 1%.
lpOffsetThreshold: 0, // EXPERIMENTAL: Defines liquidity pool behavior for rebalancing. 0 disables this feature.
disableRebalance: 0, // 0 - Automatic rebalances are enabled.
disableLp: 1, // 1 - Liquidity pool functionality is disabled.
composition: [
{ token: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", weight: 40 }, // USDC
{ token: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263", weight: 60 }, // BONK
],
};
let request = await fetch('https://api.symmetry.fi/baskets/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(basketParameters),
});
let response = await request.json();
if (response.success) {
const {
createTransaction,
compositionTransaction,
restructureTransaction
} = response;
// Decode the base64 encoded transactions provided by the API.
const createTx = Transaction.from(Buffer.from(createTransaction, 'base64'));
const compositionTx = Transaction.from(Buffer.from(compositionTransaction, 'base64'));
const restructureTx = Transaction.from(Buffer.from(restructureTransaction, 'base64'));
// Sign and send each transaction to the Solana blockchain.
let signedCreate = await wallet.signTransaction(createTx);
let createTxid = await connection.sendRawTransaction(signedCreate.serialize(), { skipPreflight: true });
console.log('createTxid', createTxid);
// Transactions need to be executed in the correct order, so make sure each transaction is confirmed before sending the next one.
// Repeat the process for composition and restructure transactions.
let signedComposition = await wallet.signTransaction(compositionTx);
let compositionTxid = await connection.sendRawTransaction(signedComposition.serialize(), { skipPreflight: true });
console.log('compositionTxid', compositionTxid);
let signedRestructure = await wallet.signTransaction(restructureTx);
let restructureTxid = await connection.sendRawTransaction(signedRestructure.serialize(), { skipPreflight: true });
console.log('restructureTxid', restructureTxid);
console.log('Basket created successfully');
} else {
console.error('Something went wrong', response);
}
Edit Basket
Description: Edit a basket.
Endpoint:
POST https://api.symmetry.fi/baskets/edit
Parameters:
basket
: PublicKey of basket to be edited (string).creator
: Wallet PublicKey of the basket creator.depositFee
: Fee charged on deposits for creator (in bps).rebalanceInterval
: Frequency of rebalance checks in seconds.rebalanceThreshold
: Allowed deviation from target weights before rebalancing,slippage
: Maximum allowed slippage for rebalance transactions, in bps.lpOffsetThreshold
: EXPERIMENTAL: Defines liquidity pool behavior for rebalancing. 0 disables this feature.disableRebalance
: Controls automatic rebalancing: 0 = enabled, 1 = disabled.disableLp
: Controls liquidity pool functionality: 0 = enabled, 1 = disabled.composition
: Array of desired basket composition
Ts Example:
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Transaction } from "@solana/web3.js";
const wallet = useWallet();
const { connection } = useConnection();
const editParameters = {
creator: wallet.publicKey.toBase58(), // string
basket: "4RofqKG4d6jfUD2HjtWb2F9UkLJvJ7P3kFmyuhX7H88d", // Publickey of the basket
depositFee: 40, // Fee on deposits, paid to the basket creator - 0.4% .
rebalanceInterval: 7200, // Rebalance checks are done every 2 hours.
rebalanceThreshold: 500, // Rebalance will be triggered when asset weights deviate from their target weights by 5% .
slippage: 100, // Maximum allowed slippage for rebalance transactions, in bps 100 = 1%.
lpOffsetThreshold: 0, // EXPERIMENTAL: Defines liquidity pool behavior for rebalancing. 0 disables this feature.
disableRebalance: 0, // 0 - Automatic rebalances are enabled.
disableLp: 1, // 1 - Liquidity pool functionality is disabled.
composition: [
{ token: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", weight: 20 }, // USDC
{ token: "So11111111111111111111111111111111111111112", weight: 50 }, // SOL
{ token: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263", weight: 30 }, // BONK
],
};
let request = await fetch('https://api.symmetry.fi/baskets/edit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(editParameters),
});
let response = await request.json();
if (response.success) {
const { editTransaction } = response;
// Decode the base64 encoded transactions provided by the API.
const editTx = Transaction.from(Buffer.from(editTransaction, 'base64'));
// Sign and send transaction to the Solana blockchain.
let signedEdit = await wallet.signTransaction(editTx);
let editTxid = await connection.sendRawTransaction(signedEdit.serialize(), { skipPreflight: true });
console.log('createTxid', editTxid);
console.log('Basket edited successfully');
} else {
console.error('Something went wrong', response);
}
Deposit into Basket
Description: Deposit USDC to on-chain account. Automation will rebalance USDC to baskets current composition assets and basket tokens will be automatically minted for user within 3 minutes
Endpoint:
POST https://api.symmetry.fi/baskets/deposit
Parameters:
user
: PublicKey of the user depositing USDC.basket
: PublicKey of the basket on-chain account.amount
: amount of USDC to be deposited.
Ts Example:
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Transaction } from "@solana/web3.js";
const wallet = useWallet();
const { connection } = useConnection();
const depositParameters = {
user: wallet.publicKey.toBase58(), // string
basket: "4RofqKG4d6jfUD2HjtWb2F9UkLJvJ7P3kFmyuhX7H88d", // ySOL Basket
amount: 100 // 100 USDC
};
let request = await fetch('https://api.symmetry.fi/baskets/deposit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(depositParameters),
});
let response = await request.json();
if (response.success) {
const { transaction } = response;
// Decode the base64 encoded transactions provided by the API.
const depositTx = Transaction.from(Buffer.from(transaction, 'base64'));
// Sign and send transaction to the Solana blockchain.
let signedDeposit = await wallet.signTransaction(depositTx);
let dopositTxId = await connection.sendRawTransaction(signedDeposit.serialize(), { skipPreflight: true });
console.log('depositTxId', dopositTxId);
console.log('Deposited successfully');
} else {
console.error('Something went wrong', response);
}
Withdraw and Claim Tokens
Description: Burn Basket Tokens and Withdraw underlying assets to the new on-chain account. Underlying assets from the new account can be claimed by using Claim API.
Withdraw - Endpoint:
POST https://api.symmetry.fi/baskets/withdraw
Withdraw - Parameters:
user
: PublicKey of the user depositing USDC.basket
: PublicKey of the basket on-chain account.amount
: amount of Basket Tokens to be withdrawn.
Claim - Endpoint:
POST https://api.symmetry.fi/baskets/withdraw
Claim - Parameters:
user
: PublicKey of the user depositing USDC.basket
: PublicKey of the on-chain account created during Withdraw.
Ts Example:
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Transaction } from "@solana/web3.js";
const wallet = useWallet();
const { connection } = useConnection();
const withdrawParameters = {
user: wallet.publicKey.toBase58(), // string
basket: "4RofqKG4d6jfUD2HjtWb2F9UkLJvJ7P3kFmyuhX7H88d", // ySOL Basket
amount: 0.1 // 0.1 ySOL
};
let request = await fetch('https://api.symmetry.fi/baskets/withdraw', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(withdrawParameters),
});
let response = await request.json();
if (response.success) {
const { transaction } = response;
// Decode the base64 encoded transactions provided by the API.
const withdrawTx = Transaction.from(Buffer.from(transaction, 'base64'));
// Sign and send transaction to the Solana blockchain.
let signedWithdraw = await wallet.signTransaction(withdrawTx);
let withdrawTxId = await connection.sendRawTransaction(signedWithdraw.serialize(), { skipPreflight: true });
console.log('withdrawTxId', withdrawTxId);
console.log('Withdrawn successfully');
} else {
console.error('Something went wrong', response);
}
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Transaction } from "@solana/web3.js";
const wallet = useWallet();
const { connection } = useConnection();
const claimParameters = {
user: wallet.publicKey.toBase58(), // string
basket: "PublicKey of the account created on the previous step",
};
let request = await fetch('https://api.symmetry.fi/baskets/claim', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(claimParameters),
});
let response = await request.json();
if (response.success) {
const {
createATAsTx,
claimTokensTx
} = response;
// User might not have some token accounts from baskets composition
// First transaction will initialize those accounts.
const createTx = Transaction.from(Buffer.from(createATAsTx, 'base64'));
let signedCreate = await wallet.signTransaction(createTx);
let createTxId = await connection.sendRawTransaction(signedCreate.serialize(), { skipPreflight: true });
console.log('createTxId', createTxId);
const claimTx = Transaction.from(Buffer.from(claimTokensTx, 'base64'));
let signedClaim = await wallet.signTransaction(claimTx);
let claimTxId = await connection.sendRawTransaction(signedClaim.serialize(), { skipPreflight: true });
console.log('claimTxId', claimTxId);
console.log('Claimed successfully');
} else {
console.error('Something went wrong', response);
}
Deposit single Asset
Description: Users also have an option to deposit an arbitrary asset to Buy/Mint Basket tokens. Only constraint is - asset should be in the baskets current composition.
Endpoint:
POST https://api.symmetry.fi/baskets/mint
Parameters:
user
: PublicKey of the user depositing asset.basket
: PublicKey of the basket on-chain account.tokenMint
: Mint address of the Asset to be deposited.amount
: amount of Asset to be deposited.
Ts Example:
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Transaction } from "@solana/web3.js";
const wallet = useWallet();
const { connection } = useConnection();
// Deposit mSOL tokens and receive ySOL basket tokens
const depositParameters = {
user: wallet.publicKey.toBase58(), // string
basket: "4RofqKG4d6jfUD2HjtWb2F9UkLJvJ7P3kFmyuhX7H88d", // ySOL Basket
tokenMint: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So", // mSOL
amount: 0.5 // 0.5 mSOL
};
let request = await fetch('https://api.symmetry.fi/baskets/mint', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(depositParameters),
});
let response = await request.json();
if (response.success) {
const { transaction } = response;
// Decode the base64 encoded transactions provided by the API.
const depositTx = Transaction.from(Buffer.from(transaction, 'base64'));
// Sign and send transaction to the Solana blockchain.
let signedDeposit = await wallet.signTransaction(depositTx);
let dopositTxId = await connection.sendRawTransaction(signedDeposit.serialize(), { skipPreflight: true });
console.log('depositTxId', dopositTxId);
console.log('Deposited and Minted successfully');
} else {
console.error('Something went wrong', response);
}
Redeem Single Asset
Description: Users also have an option to sell/burn Basket tokens and withdraw to an arbitrary asset. Only constraint is - asset should be in the baskets current composition.
Endpoint:
POST https://api.symmetry.fi/baskets/burn
Parameters:
user
: PublicKey of the user selling a basket token.basket
: PublicKey of the basket on-chain account.tokenMint
: Mint address of the Asset to sell Basket Tokens to.amount
: amount of Basket tokens to be withdrawn.
Ts Example:
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Transaction } from "@solana/web3.js";
const wallet = useWallet();
const { connection } = useConnection();
/* Withdraw ySOL basket tokens and receive mSOL
Make sure to check that there are enough tokens (mSOL in this example)
in the funds current composition.
*/
const withdrawParameters = {
user: wallet.publicKey.toBase58(), // string
basket: "4RofqKG4d6jfUD2HjtWb2F9UkLJvJ7P3kFmyuhX7H88d", // ySOL Basket
tokenMint: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So", // mSOL
amount: 0.1 // sell 0.1 ySOL
};
let request = await fetch('https://api.symmetry.fi/baskets/burn', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(withdrawParameters),
});
let response = await request.json();
if (response.success) {
const { transaction } = response;
// Decode the base64 encoded transactions provided by the API.
const withdrawTx = Transaction.from(Buffer.from(transaction, 'base64'));
// Sign and send transaction to the Solana blockchain.
let signedWithdraw = await wallet.signTransaction(withdrawTx);
let withdrawTxId = await connection.sendRawTransaction(signedWithdraw.serialize(), { skipPreflight: true });
console.log('withdrawTxId', withdrawTxId);
console.log('Burned and Withdrawn successfully');
} else {
console.error('Something went wrong', response);
}
Set Basket Metadata
Description: Creators can set metadata for their Basket Token. In that case, token will get easily detected by Wallet Extensions and Solana Blockchain Explorers
Endpoint:
POST https://api.symmetry.fi/baskets/set-metadata
Parameters:
basket
: PublicKey of the basket on-chain account.creator
: Wallet PublicKey of the basket creator.symbol
: new Symbol/Ticker of Basket Tokenname
: new Name of Basket Tokenuri
: new Symbol/Ticker of Basket Token
Ts Example:
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Transaction } from "@solana/web3.js";
const wallet = useWallet();
const { connection } = useConnection();
/* This is an example how ySOL creator could change ySOL token metadata */
const setMetadataParameters = {
basket: "4RofqKG4d6jfUD2HjtWb2F9UkLJvJ7P3kFmyuhX7H88d", // ySOL Basket
creator: "EXBMgGA4teyMA161LdfefmKbDBcFufuSQsuHM5Aw5mXL", // ySOL Creator
symbol: "ySOL", // new symbol
name: "Solana LSD", // new name,
// new uri. check the example URI to understand what metadata json should contain
uri: "https://raw.githubusercontent.com/symmetry-protocol/markets/master/ysol-metadata.json"
};
let request = await fetch('https://api.symmetry.fi/baskets/set-metadata', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(setMetadataParameters),
});
let response = await request.json();
if (response.success) {
const { transaction } = response;
const setMetadataTx = Transaction.from(Buffer.from(transaction, 'base64'));
let signedSetMetadata = await wallet.signTransaction(setMetadataTx);
let setMetadataTxId = await connection.sendRawTransaction(signedSetMetadata.serialize(), { skipPreflight: true });
console.log('setMetadataTxId', setMetadataTxId);
console.log('Metadata Created/Edited successfully');
} else {
console.error('Something went wrong', response);
}
More API Endpoints are Coming...
If you have any questions or issues, please join our Discord, we're happy to help!
Last updated