Kanalabs aggregator sdk
Description
- SDK to interact and integrate Kana aggregator platform
SDK Usage
1. Solana
2. Aptos
3. CrossChain
Installation
npm i kana-aggregator-sdk
For complete example 0f cross chain swaps using SDK and API please refer to
https://github.com/kanalabs/kanalabs-aggregator-sdk/tree/code-update/example
GitBook
https://kana-labs.gitbook.io/kana-labs/
(Complete Documentation will be available soon on GitBook)
Testnet TokenList
import {
getTokenByChainID,
kanaChainIdList,
kanaNetworkId,
} from 'kana-aggregator-sdk'
const devTokens = await getTokenByChainID(
kanaChainIdList.solana,
kanaNetworkId.mainnet
)
Aptos Aggregator
Using SDK - SOLANA
/* Swap using solana SDK */
import {
Connection,
Keypair,
VersionedTransaction,
clusterApiUrl,
} from '@solana/web3.js'
import { kanaChainIdList, kanaNetworkId } from 'kana-aggregator-sdk'
import { bs58 } from '@project-serum/anchor/dist/cjs/utils/bytes'
import 'dotenv/config'
import { getSwapQuote, getSwapInstruction } from 'kana-aggregator-sdk'
const payer = Keypair.fromSecretKey(bs58.decode(process.env.SOLANA_PAYER || ''))
const connection = new Connection(clusterApiUrl('mainnet-beta'))
/**
* SWAP on solana chain
*/
const swapOnSolana = async () => {
const inputMint = 'So11111111111111111111111111111111111111112'
const outputmint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
const amount = 1000
const slippage = 1
const chainId = kanaChainIdList.solana
const networkId = kanaNetworkId.mainnet
const isCrossChain = false
const directRoute = false
// get quotes for solana swap
console.log('Getting swap routes for solana .......')
const routes = await getSwapQuote(
isCrossChain,
chainId,
networkId,
inputMint,
outputmint,
amount,
slippage,
undefined,
directRoute
)
console.log(routes.data)
const optimaRoute = routes.data[0]
console.log('Selecting optimal route ....')
const instruction = await getSwapInstruction(
networkId,
chainId,
optimaRoute,
payer.publicKey.toString()
)
console.log('Getting swap Instruction ....')
const executableInstruction = instruction.data.swapInstruction
const swapTransactionBuf = Buffer.from(executableInstruction, 'base64')
const transaction = VersionedTransaction.deserialize(swapTransactionBuf)
console.log('Signing swap transaction ....')
transaction.sign([payer])
// Execute the transaction
const rawTransaction = transaction.serialize()
const txid = await connection.sendRawTransaction(rawTransaction, {
skipPreflight: true,
maxRetries: 2,
})
await connection.confirmTransaction(txid)
console.log('confirmed swap transaction successfully ...')
console.log(`https://solscan.io/tx/${txid}`)
}
swapOnSolana()
Using SDK - APTOS
import { kanaChainIdList, kanaNetworkId } from '../../common/types'
import * as aptos from 'aptos'
import 'dotenv/config'
import { getSwapQuote, getSwapInstruction } from 'kana-aggregator-sdk'
const NODE_URL_TEST = 'https://fullnode.mainnet.aptoslabs.com/v1'
const client = new aptos.AptosClient(NODE_URL_TEST)
const account = aptos.AptosAccount.fromAptosAccountObject({
address: process.env.APTOS_ADDRESS || '',
publicKeyHex: process.env.APTOS_PUBLICKEY || '',
privateKeyHex: process.env.APTOS_PRIVATEKEY || '',
})
const swapOnAptos = async () => {
const inputCoin =
'0xdd89c0e695df0692205912fb69fc290418bed0dbe6e4573d744a6d5e6bab6c13::coin::T'
const outputCoin =
'0xc91d826e29a3183eb3b6f6aa3a722089fdffb8e9642b94c5fcd4c48d035c0080::coin::T'
const amount = 100
const slippage = 5
const chain = kanaChainIdList.aptos
console.log('getting swap routes for Aptos .....')
//also you can add filter options if needed
const routes = await getSwapQuote(
apiKey,
chain,
inputCoin,
outputCoin,
amount,
slippage,
'0xc7cac4b062a5c56d86651adb2d04ed4d7456786b8fe3a084072f8fe741273907',
undefined,
undefined,
{
providers: [AmmProvider.Pontem, AmmProvider.Aux],
},
Environment.PROD
)
const optimalRoute = routes.data[0] as ParseAptosRoute
console.log('optimal route for swap found .....')
const instruction = await getSwapInstruction(
apiKey,
chain,
optimalRoute,
account.address().toString(),
AptosTxType.EntryFunction,
undefined,
undefined,
Environment.PROD
)
const swapPayload = instruction.data.swapInstruction
console.log('Getting payload for optimal route .....')
const txnRequest = await client.generateTransaction(
account.address(),
swapPayload,
{
max_gas_amount: '20000',
gas_unit_price: '100',
}
)
console.log('signing swap transaction .....')
const txn = await client.signTransaction(account, txnRequest)
const submit = await client.submitTransaction(txn)
console.log(submit.hash)
}
swapOnAptos()
crossChain (APTOS - POLYGON)
/**
* NOTE : This is just a basic example Implementation , Please Implement the SDK according to your usecases
*/
import {
getQuotesforCrossChainSwap,
getBridgeinstruction,
getClaimSwappedInstruction,
kanaChainIdList,
Environment,
ParseCrossChainQuote,
getVaaForWormholeAptos,
AptosTxType,
CheckAllowance,
AmmProvider,
} from 'kana-aggregator-sdk'
import * as aptos from 'aptos'
import { ethers } from 'ethers'
import 'dotenv/config'
import { bs58 } from '@project-serum/anchor/dist/cjs/utils/bytes'
import { crosschainClaimSwapOnEvm } from 'kana-aggregator-sdk'
const NODE_URL_TEST = 'https://fullnode.mainnet.aptoslabs.com/v1'
const client = new aptos.AptosClient(NODE_URL_TEST)
const privateKey = process.env.EVM_PRIVATE_KEY || ''
const polygonRPC = `https://polygon-mainnet.g.alchemy.com/v2/${process.env.POLYGON_KEY}` //Polygon
const provider = new ethers.providers.JsonRpcProvider(polygonRPC)
const signer = new ethers.Wallet(privateKey, provider)
console.log('signer address', signer.address)
const account = aptos.AptosAccount.fromAptosAccountObject({
address: process.env.APTOS_ADDRESS || '',
publicKeyHex: process.env.APTOS_PUBLICKEY || '',
privateKeyHex: process.env.APTOS_PRIVATEKEY || '',
})
console.log('account', account.toPrivateKeyObject())
const apiKey = process.env.KANAAPI_KEY || ''
const transferFromAptosToPolygon = async () => {
// //Required paramameters to be passed to get quote for APTOS to SOLANA
const swapRequestParams = {
apiKey: apiKey,
isCrossChain: true,
sourceChainId: kanaChainIdList.aptos,
targetChainId: kanaChainIdList.polygon,
sourceToken: '0x1::aptos_coin::AptosCoin',
targetToken: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f',
inAmount: 1000,
slippage: 1,
networkId: 1,
}
// // error handling requited
const swapQuotes = (
await getQuotesforCrossChainSwap(
swapRequestParams.apiKey,
swapRequestParams.sourceChainId,
swapRequestParams.targetChainId,
swapRequestParams.sourceToken,
swapRequestParams.targetToken,
swapRequestParams.inAmount,
swapRequestParams.slippage,
undefined, //network ID can be undefined (currently no support for multiple networks)
{
providers: [AmmProvider.Pontem, AmmProvider.Aux],
},
Environment.DEV
)
).data[0] as ParseCrossChainQuote
console.log('AptosToPolygon swapQuotes', swapQuotes.targetRoute)
const bridgeRequestParams = {
apiKey: apiKey,
crossRoute: swapQuotes,
sourceAddress: account.address().toString(),
targetAddress: signer.address,
}
let isAllowed = false
const allowance = await CheckAllowance(
3,
swapQuotes.targetBridgeToken,
signer.address
)
console.log('target allowance polygon ', allowance)
if (Number(allowance) >= Number(swapQuotes.bridgeAmount)) {
isAllowed = true
}
const bridgeInstruction = await getBridgeinstruction(
bridgeRequestParams.apiKey,
bridgeRequestParams.crossRoute, //this is just to handle type conversions will be fixed in upcoming version
bridgeRequestParams.sourceAddress, //this has to be a valid and active solana address
bridgeRequestParams.targetAddress, //this has to be a valid and active aptos address
undefined,
isAllowed,
Environment.DEV
)
console.log({ bridgeInstruction })
//Bridge instruction has to be executed in the respective chains based on their Chain ID's
const serializedInstruction = bridgeInstruction.data.transferInstruction
const transferHash: any[] = []
for (let i = 0; i < serializedInstruction.length; i++) {
if (serializedInstruction[i].type == AptosTxType.BcsSerialized) {
const transferSerializedPayload =
aptos.TxnBuilderTypes.RawTransaction.deserialize(
new aptos.BCS.Deserializer(
new Uint8Array(bs58.decode(serializedInstruction[i].transaction))
)
)
const swapTxn = await client.signTransaction(
account,
transferSerializedPayload
)
const submitSwapTxn = await client.submitTransaction(swapTxn)
transferHash.push(submitSwapTxn.hash)
}
}
const vaa: Uint8Array = await getVaaForWormholeAptos(
transferHash[transferHash.length - 1],
client
)
console.log('vaa', vaa)
const claimRequestParams = {
apiKey: apiKey,
crossRoute: swapQuotes,
targetAddress: signer.address,
vaaBytes: vaa,
}
const claimInstruction = await getClaimSwappedInstruction(
claimRequestParams.apiKey,
claimRequestParams.crossRoute,
claimRequestParams.targetAddress,
claimRequestParams.vaaBytes,
undefined,
undefined,
Environment.DEV
)
const tx = await crosschainClaimSwapOnEvm(claimInstruction, signer, vaa)
console.log(tx)
}
transferFromAptosToPolygon()