Buy and Sell
The "BuySell" component allows a user to place a limit order to the SDEX orderbook.
Features
- Collects source secret key, asset, and asset quantity and price.
- Upon submission, an order is placed on the SDEX orderbook.
- Assets included with this component are XLM, BTC, ETH, AQUA, VELO and USDC.
- Provides a straightforward way to place a limit order on the SDEX.
Additional Resources
An account can create orders to buy or sell assets using the Manage Buy Offer, Manage Sell Offer, or Passive Order operations. The account must hold the asset it wants to exchange, and it must trust the issuer of the asset it is trying to buy.
All sell orders are filled to USDC and not swapped between assets in this component. For more information on buy, sell, and management of orders on Stellar review the documentation below
C#
Install the PakanaRazorSDEX NuGet package via the NuGet Package Manager Console.
.Net8.0 or greater is required.
dotnet add package PakanaRazorSDEX --version 0.0.4
Stellar Horizon Dependency will install automatically
<PakanaRazorSDEX.Component.BuySell/>
@page "/RemoveSigner"
@rendermode InteractiveAuto
@using Microsoft.JSInterop
<div class="container">
<h2>Buy | Sell</h2>
<form id="offerForm">
<label for="asset">Select Asset:</label>
<select id="asset" name="asset" required>
<option value="XLM">XLM</option>
<option value="BTC">Bitcoin</option>
<option value="AQUA">Aqua</option>
<option value="ETH">Ethereum</option>
<option value="VELO">Velo</option>
</select>
<label for="offerType">Offer Type:</label>
<select id="offerType" name="offerType" required>
<option value="sell">Sell Asset for USDC</option>
<option value="buy">Buy Asset with USDC</option>
</select>
<label for="amount">Amount:</label>
<input type="number"
id="amount"
name="amount"
placeholder="Amount to trade"
step="0.000001"
required>
<label for="price">Price:</label>
<input type="number"
id="price"
name="price"
placeholder="Price per asset (USDC/Asset)"
step="0.000001"
min="0.000001"
required>
<small>Up to 6 decimal places allowed.</small>
<label for="secretKey">Your Secret Key:</label>
<input type="password" id="secretKey" name="secretKey" placeholder="Your Stellar secret key" required>
<button type="submit">Submit Offer</button>
</form>
<p id="message"></p>
</div>
@code {
[Inject] IJSRuntime JS { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// Call the initializeChart function in the external JavaScript file
await JS.InvokeVoidAsync("offerForm");
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/stellar-sdk/13.0.0/stellar-sdk.min.js"></script>
<script src="./_content/PakanaRazorSDEX/js/buySell.js"></script>
<script src="./_content/PakanaRazorSDEX/js/global.js"></script>
Javascript
We've provided simple HTML and JavaScript that can be used in your project as partial-components or be customized and integrated into your existing codebase.
*Current Version as of 2024-24-12*
<script src="https://cdnjs.cloudflare.com/ajax/libs/stellar-sdk/13.0.0/stellar-sdk.min.js"></script>
<script>
const assetMap = {
XLM: { isNative: true }, // Mark as native
BTC: { code: 'BTC', issuer: 'GDPJALI4AZKUU2W426U5WKMAT6CN3AJRPIIRYR2YM54TL2GDWO5O2MZM' },//mainnet only
AQUA: { code: 'AQUA', issuer: 'GBNZILSTVQZ4R7IKQDGHYGY2QXL5QOFJYQMXPKWRRM5PAV7Y4M67AQUA' },//mainnet only
ETH: { code: 'ETH', issuer: 'GBFXOHVAS43OIWNIO7XLRJAHT3BICFEIKOJLZVXNT572MISM4CMGSOCC' },//mainnet only
VELO: { code: 'VELO', issuer: 'GDM4RQUQQUVSKQA7S6EM7XBZP3FCGH4Q7CL6TABQ7B2BEJ5ERARM2M5M' },//mainnet only
USDC: { code: 'USDC', issuer: 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN' }//mainnet only
};
document.getElementById('offerForm').addEventListener('submit', async (event) => {
event.preventDefault();
const selectedAsset = document.getElementById('asset').value;
const offerType = document.getElementById('offerType').value;
const amount = parseFloat(document.getElementById('amount').value.trim());
const price = parseFloat(document.getElementById('price').value.trim());
const secretKey = document.getElementById('secretKey').value.trim();
const message = document.getElementById('message');
message.textContent = "Processing...";
message.style.color = "black";
try {
const { Asset, Operation, Keypair, Account, TransactionBuilder, BASE_FEE } = window.StellarSdk;
const keypair = Keypair.fromSecret(secretKey);
const publicKey = keypair.publicKey();
const NETWORK_PASSPHRASE = "Public Global Stellar Network ; September 2015";
// Fetch account sequence
const accountResponse = await server.accounts().accountId(publicKey).call();
const account = new Account(publicKey, accountResponse.sequence);
// Select the trading asset
const assetDetails = assetMap[selectedAsset];
const tradeAsset = assetDetails.isNative
? Asset.native()
: new Asset(assetDetails.code, assetDetails.issuer);
// USDC asset definition with issuer
const usdcAsset = new Asset('USDC', 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN'); // Replace with the correct issuer
// Ensure amount and price are valid
if (isNaN(amount) || amount <= 0) {
message.style.color = 'red';
message.textContent = "Invalid amount.";
return;
}
if (isNaN(price) || price <= 0) {
message.style.color = 'red';
message.textContent = "Invalid price.";
return;
}
// Build the transaction
const transaction = new TransactionBuilder(account, {
fee: BASE_FEE,
networkPassphrase: NETWORK_PASSPHRASE
});
// Add operation based on offer type
if (offerType === 'sell') {
transaction.addOperation(Operation.manageSellOffer({
selling: tradeAsset,
buying: usdcAsset,
amount: amount.toFixed(7).toString(), // Ensure correct precision
price: price.toFixed(7).toString(), // Ensure correct precision
offerId: undefined // Omit offerId, let network assign
}));
} else {
transaction.addOperation(Operation.manageBuyOffer({
selling: usdcAsset,
buying: tradeAsset,
buyAmount: amount.toFixed(7).toString(),
price: price.toFixed(7).toString(),
offerId: undefined // Omit offerId, let network assign
}));
}
const builtTransaction = transaction.setTimeout(30).build();
builtTransaction.sign(keypair);
// Submit transaction
const result = await server.submitTransaction(builtTransaction);
message.style.color = 'green';
message.textContent = "Offer submitted successfully!";
} catch (error) {
message.style.color = 'red';
message.textContent = `Error: ${error.message}`;
}
});
</script>
<body>
<div class="container">
<h2>Buy | Sell</h2>
<form id="offerForm">
<label for="asset">Select Asset:</label>
<select id="asset" name="asset" required>
<option value="XLM">XLM</option>
<option value="BTC">Bitcoin</option>
<option value="AQUA">Aqua</option>
<option value="ETH">Ethereum</option>
<option value="VELO">Velo</option>
</select>
<label for="offerType">Offer Type:</label>
<select id="offerType" name="offerType" required>
<option value="sell">Sell Asset for USDC</option>
<option value="buy">Buy Asset with USDC</option>
</select>
<label for="amount">Amount:</label>
<input type="number"
id="amount"
name="amount"
placeholder="Amount to trade"
step="0.000001"
required>
<label for="price">Price:</label>
<input type="number"
id="price"
name="price"
placeholder="Price per asset (USDC/Asset)"
step="0.000001"
min="0.000001"
required>
<small>Up to 6 decimal places allowed.</small>
<label for="secretKey">Your Secret Key:</label>
<input type="password" id="secretKey" name="secretKey" placeholder="Your Stellar secret key" required>
<button type="submit">Submit Offer</button>
</form>
<p id="message"></p>
</div>
</body>