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.
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);
}
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
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.
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.
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.
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