A client for OrcaSwap, written in Swift
- Import library
import OrcaSwapSwift
- Create instance of orca
let orcaSwap = OrcaSwap(
apiClient: APIClient(configsProvider: NetworkConfigsProvider(network: "mainnet")),
solanaClient: solanaSDK,
accountProvider: solanaSDK,
notificationHandler: solanaSDK
)
- Swap
// load any dependencies for swap to work
try await orcaSwap.load()
// find any destination that can be swapped to from a defined token mint
orcaSwap.findPosibleDestinationMints(fromMint: btcMint)
// get multiple tradable pools pairs (or routes) for a token pair (each pool pairs contains 1 or 2 pools for swapping)
orcaSwap.getTradablePoolsPairs(fromMint: btcMint, toMint: ethMint)
// get bestPool pair for swapping from tradable pools pairs that got from getTradablePoolsPair method, this method return a pool pair that can be used for swapping
orcaSwap.findBestPoolsPairForInputAmount(inputAmount, from: poolsPairs)
orcaSwap.findBestPoolsPairForEstimatedAmount(estimatedAmount, from: poolsPairs)
// swap
let result = try await orcaSwap.swap(
fromWalletPubkey: <BTC wallet>,
toWalletPubkey: <ETH wallet>?,
bestPoolsPair: <best pool pair>,
amount: amount,
slippage: 0.05,
isSimulation: false
)
There are 2 unit testings that are available: OrcaSwapAPIClientTests
and OrcaSwapPreparationTests
, the other tests are intergration tests
Integration tests now works only on mainnet, devnet and testnet would be added later
Create a json file direct-swap-tests.json
inside Resources
folder that contains following content:
{
"solToCreatedSpl": {
"endpoint": <String, Solana api endpoint>,
"endpointAdditionalQuery": <String?>,
"seedPhrase": <String, Solana account seed phrase>,
"fromMint": "So11111111111111111111111111111111111111112",
"toMint": <String, Mint of token that you want to swap to>,
"sourceAddress": <String, Owner address>,
"destinationAddress": <String, Destination token address>,
"poolsPair": [
{
"name": <String, Name of pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
}
],
"inputAmount": <Double, Input amount>,
"slippage": <Double>
},
"solToNonCreatedSpl": {
"endpoint": <String, Solana api endpoint>,
"endpointAdditionalQuery": <String?>,
"seedPhrase": <String, Solana account seed phrase>,
"fromMint": "So11111111111111111111111111111111111111112",
"toMint": <String, Mint of token that you want to swap to>,
"sourceAddress": <String, Owner address>,
"destinationAddress": null,
"poolsPair": [
{
"name": <String, Name of pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
}
],
"inputAmount": <Double, Input amount>,
"slippage": <Double>
},
"splToSol": {
"endpoint": <String, Solana api endpoint>,
"endpointAdditionalQuery": <String?>,
"seedPhrase": <String, Solana account seed phrase>,
"fromMint": <String, Mint of token that you want to swap from>,
"toMint": "So11111111111111111111111111111111111111112",
"sourceAddress": <String, Source token address>,
"destinationAddress": <String, Owner address>,
"poolsPair": [
{
"name": <String, Name of pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
}
],
"inputAmount": <Double, Input amount>,
"slippage": <Double>
},
"splToCreatedSpl": {
"endpoint": <String, Solana api endpoint>,
"endpointAdditionalQuery": <String?>,
"seedPhrase": <String, Solana account seed phrase>,
"fromMint": <String, Mint of token that you want to swap from>,
"toMint": <String, Mint of token that you want to swap to>,
"sourceAddress": <String, Source token address>,
"destinationAddress": <String, Destination token address>,
"poolsPair": [
{
"name": <String, Name of pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
}
],
"inputAmount": 1,
"slippage": 0.05
},
"splToNonCreatedSpl": {
"endpoint": <String, Solana api endpoint>,
"endpointAdditionalQuery": <String?>,
"seedPhrase": <String, Solana account seed phrase>,
"fromMint": <String, Mint of token that you want to swap from>,
"toMint": <String, Mint of token that you want to swap to>,
"sourceAddress": <String, Source token address>,
"destinationAddress": null,
"poolsPair": [
{
"name": <String, Name of pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
}
],
"inputAmount": 1,
"slippage": 0.05
}
}
Create a json file transitive-swap-tests.json
inside Resources
folder that contains following content:
{
"solToCreatedSpl": {
"endpoint": <String, Solana api endpoint>,
"endpointAdditionalQuery": <String?>,
"seedPhrase": <String, Solana account seed phrase>,
"fromMint": "So11111111111111111111111111111111111111112",
"toMint": <String, Mint of token that you want to swap to>,
"sourceAddress": <String, Owner address>,
"destinationAddress": <String, Destination token address>,
"poolsPair": [
{
"name": <String, Name of first pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
},
{
"name": <String, Name of second pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
}
]
"inputAmount": <Double, Input amount>,
"slippage": <Double>
},
"solToNonCreatedSpl": {
"endpoint": <String, Solana api endpoint>,
"endpointAdditionalQuery": <String?>,
"seedPhrase": <String, Solana account seed phrase>,
"fromMint": "So11111111111111111111111111111111111111112",
"toMint": <String, Mint of token that you want to swap to>,
"sourceAddress": <String, Owner address>,
"destinationAddress": null,
"poolsPair": [
{
"name": <String, Name of first pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
},
{
"name": <String, Name of second pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
}
]
"inputAmount": <Double, Input amount>,
"slippage": <Double>
},
"splToSol": {
"endpoint": <String, Solana api endpoint>,
"endpointAdditionalQuery": <String?>,
"seedPhrase": <String, Solana account seed phrase>,
"fromMint": <String, Mint of token that you want to swap from>,
"toMint": "So11111111111111111111111111111111111111112",
"sourceAddress": <String, Source token address>,
"destinationAddress": <String, Owner address>,
"poolsPair": [
{
"name": <String, Name of first pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
},
{
"name": <String, Name of second pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
}
]
"inputAmount": <Double, Input amount>,
"slippage": <Double>
},
"splToCreatedSpl": {
"endpoint": <String, Solana api endpoint>,
"endpointAdditionalQuery": <String?>,
"seedPhrase": <String, Solana account seed phrase>,
"fromMint": <String, Mint of token that you want to swap from>,
"toMint": <String, Mint of token that you want to swap to>,
"sourceAddress": <String, Source token address>,
"destinationAddress": <String, Destination token address>,
"poolsPair": [
{
"name": <String, Name of first pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
},
{
"name": <String, Name of second pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
}
],
"inputAmount": <Double, Input amount>,
"slippage": <Double>
},
"splToNonCreatedSpl": {
"endpoint": <String, Solana api endpoint>,
"endpointAdditionalQuery": <String?>,
"seedPhrase": <String, Solana account seed phrase>,
"fromMint": <String, Mint of token that you want to swap from>,
"toMint": <String, Mint of token that you want to swap to>,
"sourceAddress": <String, Source token address>,
"destinationAddress": null,
"poolsPair": [
{
"name": <String, Name of first pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
},
{
"name": <String, Name of second pool, for example: SOCN/SOL[stable][aquafarm], see Resources/pools/orca-pools-mainnet.json>,
"reversed": <Bool, For example: if pool name equals to SOCN/SOL, and the swap is SOL to SOCN, then reversed == true>
}
],
"inputAmount": <Double, Input amount>,
"slippage": <Double>
}
}
Direct swap
{
"solToCreatedSpl": {
"comment": "Swap from SOL to USDC",
"endpoint": "https://api.mainnet-beta.solana.com/",
"endpointAdditionalQuery": null,
"seedPhrase": "<secret>",
"fromMint": "So11111111111111111111111111111111111111112",
"toMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"sourceAddress": "5bYReP8iw5UuLVS5wmnXfEfrYCKdiQ1FFAZQao8JqY7V",
"destinationAddress": "mCZrAFuPfBDPUW45n5BSkasRLpPZpmqpY7vs3XSYE7x",
"poolsPair": [
{
"name": "SOL/USDC",
"reversed": false
}
],
"inputAmount": 0.0001,
"slippage": 0.05
},
"solToNonCreatedSpl": {
"comment": "Swap from SOL to USDT (non created)",
"endpoint": "https://api.mainnet-beta.solana.com/",
"endpointAdditionalQuery": null,
"seedPhrase": "<secret>",
"fromMint": "So11111111111111111111111111111111111111112",
"toMint": "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
"sourceAddress": "5bYReP8iw5UuLVS5wmnXfEfrYCKdiQ1FFAZQao8JqY7V",
"destinationAddress": null,
"poolsPair": [
{
"name": "SOL/USDT[aquafarm]",
"reversed": false
}
],
"inputAmount": 0.0001,
"slippage": 0.05
},
"splToSol": {
"comment": "Swap from USDC to SOL",
"endpoint": "https://api.mainnet-beta.solana.com/",
"endpointAdditionalQuery": null,
"seedPhrase": "<secret>",
"fromMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"toMint": "So11111111111111111111111111111111111111112",
"sourceAddress": "mCZrAFuPfBDPUW45n5BSkasRLpPZpmqpY7vs3XSYE7x",
"destinationAddress": "5bYReP8iw5UuLVS5wmnXfEfrYCKdiQ1FFAZQao8JqY7V",
"poolsPair": [
{
"name": "SOL/USDC",
"reversed": true
}
],
"inputAmount": 1,
"slippage": 0.05
},
"splToCreatedSpl": {
"comment": "Swap from USDC to KURO",
"endpoint": "https://api.mainnet-beta.solana.com/",
"endpointAdditionalQuery": null,
"seedPhrase": "<secret>",
"fromMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"toMint": "2Kc38rfQ49DFaKHQaWbijkE7fcymUMLY5guUiUsDmFfn",
"sourceAddress": "mCZrAFuPfBDPUW45n5BSkasRLpPZpmqpY7vs3XSYE7x",
"destinationAddress": "C5B13tQA4pq1zEVSVkWbWni51xdWB16C2QsC72URq9AJ",
"poolsPair": [
{
"name": "KURO/USDC[aquafarm]",
"reversed": true
}
],
"inputAmount": 1,
"slippage": 0.05
},
"splToNonCreatedSpl": {
"comment": "Swap from USDC to MNGO (non created)",
"endpoint": "https://api.mainnet-beta.solana.com/",
"endpointAdditionalQuery": null,
"seedPhrase": "<secret>",
"fromMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"toMint": "MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac",
"sourceAddress": "mCZrAFuPfBDPUW45n5BSkasRLpPZpmqpY7vs3XSYE7x",
"destinationAddress": null,
"poolsPair": [
{
"name": "MNGO/USDC[aquafarm]",
"reversed": true
}
],
"inputAmount": 1,
"slippage": 0.05
}
}
Transitive swap
{
"solToCreatedSpl": {
"comment": "Swap from SOL to created KURO",
"endpoint": "https://api.mainnet-beta.solana.com/",
"endpointAdditionalQuery": null,
"seedPhrase": "<secret>",
"fromMint": "So11111111111111111111111111111111111111112",
"toMint": "2Kc38rfQ49DFaKHQaWbijkE7fcymUMLY5guUiUsDmFfn",
"sourceAddress": "5bYReP8iw5UuLVS5wmnXfEfrYCKdiQ1FFAZQao8JqY7V",
"destinationAddress": "C5B13tQA4pq1zEVSVkWbWni51xdWB16C2QsC72URq9AJ",
"poolsPair": [
{
"name": "SOL/USDC[aquafarm]",
"reversed": false
},
{
"name": "KURO/USDC[aquafarm]",
"reversed": true
}
],
"inputAmount": 0.0001,
"slippage": 0.05
},
"solToNonCreatedSpl": {
"comment": "Swap from SOL to NON-Created LIQ",
"endpoint": "https://api.mainnet-beta.solana.com/",
"endpointAdditionalQuery": null,
"seedPhrase": "<secret>",
"fromMint": "So11111111111111111111111111111111111111112",
"toMint": "4wjPQJ6PrkC4dHhYghwJzGBVP78DkBzA2U3kHoFNBuhj",
"sourceAddress": "5bYReP8iw5UuLVS5wmnXfEfrYCKdiQ1FFAZQao8JqY7V",
"destinationAddress": null,
"poolsPair": [
{
"name": "SOL/USDC[aquafarm]",
"reversed": false
},
{
"name": "LIQ/USDC[aquafarm]",
"reversed": true
}
],
"inputAmount": 0.0001,
"slippage": 0.05
},
"splToSol": {
"comment": "Swap from KURO to SOL",
"endpoint": "https://api.mainnet-beta.solana.com/",
"endpointAdditionalQuery": null,
"seedPhrase": "<secret>",
"fromMint": "2Kc38rfQ49DFaKHQaWbijkE7fcymUMLY5guUiUsDmFfn",
"toMint": "So11111111111111111111111111111111111111112",
"sourceAddress": "C5B13tQA4pq1zEVSVkWbWni51xdWB16C2QsC72URq9AJ",
"destinationAddress": "5bYReP8iw5UuLVS5wmnXfEfrYCKdiQ1FFAZQao8JqY7V",
"poolsPair": [
{
"name": "KURO/USDC[aquafarm]",
"reversed": false
},
{
"name": "SOL/USDC[aquafarm]",
"reversed": true
}
],
"inputAmount": 100,
"slippage": 0.05
},
"splToCreatedSpl": {
"comment": "Swap from KURO to created SLIM",
"endpoint": "https://api.mainnet-beta.solana.com/",
"endpointAdditionalQuery": null,
"seedPhrase": "<secret>",
"fromMint": "2Kc38rfQ49DFaKHQaWbijkE7fcymUMLY5guUiUsDmFfn",
"toMint": "xxxxa1sKNGwFtw2kFn8XauW9xq8hBZ5kVtcSesTT9fW",
"sourceAddress": "C5B13tQA4pq1zEVSVkWbWni51xdWB16C2QsC72URq9AJ",
"destinationAddress": "FH58UXMZnj9HTAWusB9zmYCtqUCCLP351ao4S687pxD6",
"poolsPair": [
{
"name": "KURO/USDC[aquafarm]",
"reversed": false
},
{
"name": "SLIM/USDC[aquafarm]",
"reversed": true
}
],
"inputAmount": 100,
"slippage": 0.05
},
"splToNonCreatedSpl": {
"comment": "Swap from KURO to Non-Created SNY",
"endpoint": "https://api.mainnet-beta.solana.com/",
"endpointAdditionalQuery": null,
"seedPhrase": "<secret>",
"fromMint": "2Kc38rfQ49DFaKHQaWbijkE7fcymUMLY5guUiUsDmFfn",
"toMint": "4dmKkXNHdgYsXqBHCuMikNQWwVomZURhYvkkX5c4pQ7y",
"sourceAddress": "C5B13tQA4pq1zEVSVkWbWni51xdWB16C2QsC72URq9AJ",
"destinationAddress": null,
"poolsPair": [
{
"name": "KURO/USDC[aquafarm]",
"reversed": false
},
{
"name": "SNY/USDC[aquafarm]",
"reversed": true
}
],
"inputAmount": 100,
"slippage": 0.05
}
}