ts-xdbchain-sdk
Version:
A TypeScript SDK for interacting with XDBCHAIN - a Stellar-based blockchain network
1,170 lines • 65.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.XDBChainSDK = exports.OPERATION_TYPE = exports.ASSET_TYPE = exports.ACCOUNT_FLAGS = exports.XDBOfferError = exports.XDBAssetError = exports.XDBTransactionError = exports.XDBValidationError = exports.XDBNetworkError = exports.XDBChainError = void 0;
exports.createXDBChainSDK = createXDBChainSDK;
exports.createMainnetSDK = createMainnetSDK;
exports.createFuturenetSDK = createFuturenetSDK;
exports.xdbToStroops = xdbToStroops;
exports.stroopsToXdb = stroopsToXdb;
exports.isValidAmount = isValidAmount;
exports.formatAmount = formatAmount;
exports.generateNonce = generateNonce;
exports.isValidMemo = isValidMemo;
exports.calculateFee = calculateFee;
exports.accountExists = accountExists;
const stellar_sdk_1 = require("stellar-sdk");
class XDBChainError extends Error {
constructor(message, code, details) {
super(message);
this.code = code;
this.details = details;
this.name = 'XDBChainError';
}
}
exports.XDBChainError = XDBChainError;
class XDBNetworkError extends XDBChainError {
constructor(message, details) {
super(message, 'NETWORK_ERROR', details);
this.name = 'XDBNetworkError';
}
}
exports.XDBNetworkError = XDBNetworkError;
class XDBValidationError extends XDBChainError {
constructor(message, details) {
super(message, 'VALIDATION_ERROR', details);
this.name = 'XDBValidationError';
}
}
exports.XDBValidationError = XDBValidationError;
class XDBTransactionError extends XDBChainError {
constructor(message, details) {
super(message, 'TRANSACTION_ERROR', details);
this.name = 'XDBTransactionError';
}
}
exports.XDBTransactionError = XDBTransactionError;
class XDBAssetError extends XDBChainError {
constructor(message, details) {
super(message, 'ASSET_ERROR', details);
this.name = 'XDBAssetError';
}
}
exports.XDBAssetError = XDBAssetError;
class XDBOfferError extends XDBChainError {
constructor(message, details) {
super(message, 'OFFER_ERROR', details);
this.name = 'XDBOfferError';
}
}
exports.XDBOfferError = XDBOfferError;
exports.ACCOUNT_FLAGS = {
AUTH_REQUIRED_FLAG: 0x1,
AUTH_REVOCABLE_FLAG: 0x2,
AUTH_IMMUTABLE_FLAG: 0x4,
AUTH_CLAWBACK_ENABLED_FLAG: 0x8
};
exports.ASSET_TYPE = {
NATIVE: 'native',
CREDIT_ALPHANUM4: 'credit_alphanum4',
CREDIT_ALPHANUM12: 'credit_alphanum12'
};
exports.OPERATION_TYPE = {
CREATE_ACCOUNT: 'create_account',
PAYMENT: 'payment',
PATH_PAYMENT_STRICT_RECEIVE: 'path_payment_strict_receive',
PATH_PAYMENT_STRICT_SEND: 'path_payment_strict_send',
MANAGE_SELL_OFFER: 'manage_sell_offer',
MANAGE_BUY_OFFER: 'manage_buy_offer',
CREATE_PASSIVE_SELL_OFFER: 'create_passive_sell_offer',
SET_OPTIONS: 'set_options',
CHANGE_TRUST: 'change_trust',
ALLOW_TRUST: 'allow_trust',
ACCOUNT_MERGE: 'account_merge',
INFLATION: 'inflation',
MANAGE_DATA: 'manage_data',
BUMP_SEQUENCE: 'bump_sequence',
CREATE_CLAIMABLE_BALANCE: 'create_claimable_balance',
CLAIM_CLAIMABLE_BALANCE: 'claim_claimable_balance',
BEGIN_SPONSORING_FUTURE_RESERVES: 'begin_sponsoring_future_reserves',
END_SPONSORING_FUTURE_RESERVES: 'end_sponsoring_future_reserves',
REVOKE_SPONSORSHIP: 'revoke_sponsorship',
CLAWBACK: 'clawback',
CLAWBACK_CLAIMABLE_BALANCE: 'clawback_claimable_balance',
SET_TRUST_LINE_FLAGS: 'set_trust_line_flags'
};
class XDBChainSDK {
constructor(config) {
this.config = {
...XDBChainSDK.DEFAULT_CONFIGS[config.network],
...config
};
this.server = new stellar_sdk_1.Horizon.Server(this.config.horizonUrl, {
allowHttp: this.config.allowHttp
});
this.networkPassphrase = this.config.networkPassphrase;
}
async createWallet() {
try {
const keypair = stellar_sdk_1.Keypair.random();
const wallet = {
publicKey: keypair.publicKey(),
secretKey: keypair.secret(),
network: this.config.network
};
console.log('✅ Wallet created successfully:', wallet.publicKey);
return wallet;
}
catch (error) {
throw new XDBChainError(`Failed to create wallet: ${error}`);
}
}
async loadWallet(secretKey) {
try {
if (!this.isValidSecretKey(secretKey)) {
throw new XDBValidationError('Invalid secret key format');
}
const keypair = stellar_sdk_1.Keypair.fromSecret(secretKey);
const account = await this.server.loadAccount(keypair.publicKey());
return {
publicKey: keypair.publicKey(),
secretKey: secretKey,
network: this.config.network,
account: account
};
}
catch (error) {
throw new XDBChainError(`Failed to load wallet: ${error}`);
}
}
async createWalletFromSeed(seed) {
try {
const keypair = stellar_sdk_1.Keypair.fromRawEd25519Seed(typeof seed === 'string' ? Buffer.from(seed, 'hex') : seed);
const wallet = {
publicKey: keypair.publicKey(),
secretKey: keypair.secret(),
network: this.config.network
};
return wallet;
}
catch (error) {
throw new XDBChainError(`Failed to create wallet from seed: ${error}`);
}
}
isValidAddress(address) {
try {
return stellar_sdk_1.StrKey.isValidEd25519PublicKey(address);
}
catch {
return false;
}
}
isValidSecretKey(secretKey) {
try {
return stellar_sdk_1.StrKey.isValidEd25519SecretSeed(secretKey);
}
catch {
return false;
}
}
generateKeypair() {
return stellar_sdk_1.Keypair.random();
}
keypairFromSecret(secretKey) {
return stellar_sdk_1.Keypair.fromSecret(secretKey);
}
keypairFromPublicKey(publicKey) {
return stellar_sdk_1.Keypair.fromPublicKey(publicKey);
}
async loadAccount(publicKey) {
try {
if (!this.isValidAddress(publicKey)) {
throw new XDBValidationError('Invalid public key');
}
return await this.server.loadAccount(publicKey);
}
catch (error) {
throw new XDBChainError(`Failed to load account: ${error}`);
}
}
async createAccount(source, destination, startingBalance = this.config.startingBalance) {
try {
if (!this.isValidSecretKey(source)) {
throw new XDBValidationError('Invalid source secret key');
}
if (!this.isValidAddress(destination)) {
throw new XDBValidationError('Invalid destination address');
}
const sourceKeypair = stellar_sdk_1.Keypair.fromSecret(source);
const sourceAccount = await this.server.loadAccount(sourceKeypair.publicKey());
const transaction = new stellar_sdk_1.TransactionBuilder(sourceAccount, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.createAccount({
destination: destination,
startingBalance: startingBalance
}))
.setTimeout(this.config.timeout)
.build();
transaction.sign(sourceKeypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Account created successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Failed to create account: ${error}`);
}
}
async setAccountOptions(secretKey, options) {
try {
if (!this.isValidSecretKey(secretKey)) {
throw new XDBValidationError('Invalid secret key');
}
const keypair = stellar_sdk_1.Keypair.fromSecret(secretKey);
const account = await this.server.loadAccount(keypair.publicKey());
const operation = {};
if (options.homeDomain !== undefined)
operation.homeDomain = options.homeDomain;
if (options.inflationDest !== undefined)
operation.inflationDest = options.inflationDest;
if (options.masterWeight !== undefined)
operation.masterWeight = options.masterWeight;
if (options.lowThreshold !== undefined)
operation.lowThreshold = options.lowThreshold;
if (options.medThreshold !== undefined)
operation.medThreshold = options.medThreshold;
if (options.highThreshold !== undefined)
operation.highThreshold = options.highThreshold;
if (options.setFlags !== undefined)
operation.setFlags = options.setFlags;
if (options.clearFlags !== undefined)
operation.clearFlags = options.clearFlags;
if (options.signer !== undefined)
operation.signer = options.signer;
const transaction = new stellar_sdk_1.TransactionBuilder(account, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.setOptions(operation))
.setTimeout(this.config.timeout)
.build();
transaction.sign(keypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Account options set successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Failed to set account options: ${error}`);
}
}
async mergeAccount(sourceSecret, destination) {
try {
if (!this.isValidSecretKey(sourceSecret)) {
throw new XDBValidationError('Invalid source secret key');
}
if (!this.isValidAddress(destination)) {
throw new XDBValidationError('Invalid destination address');
}
const sourceKeypair = stellar_sdk_1.Keypair.fromSecret(sourceSecret);
const sourceAccount = await this.server.loadAccount(sourceKeypair.publicKey());
const transaction = new stellar_sdk_1.TransactionBuilder(sourceAccount, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.accountMerge({
destination: destination
}))
.setTimeout(this.config.timeout)
.build();
transaction.sign(sourceKeypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Account merged successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Failed to merge account: ${error}`);
}
}
async bumpSequence(secretKey, bumpTo) {
try {
if (!this.isValidSecretKey(secretKey)) {
throw new XDBValidationError('Invalid secret key');
}
const keypair = stellar_sdk_1.Keypair.fromSecret(secretKey);
const account = await this.server.loadAccount(keypair.publicKey());
const transaction = new stellar_sdk_1.TransactionBuilder(account, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.bumpSequence({
bumpTo: bumpTo
}))
.setTimeout(this.config.timeout)
.build();
transaction.sign(keypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Sequence bumped successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Failed to bump sequence: ${error}`);
}
}
async getBalances(publicKey) {
try {
if (!this.isValidAddress(publicKey)) {
throw new XDBValidationError('Invalid public key');
}
const account = await this.server.loadAccount(publicKey);
return account.balances.map((balance) => ({
assetType: balance.asset_type,
assetCode: balance.asset_code || 'XDB',
assetIssuer: balance.asset_issuer || null,
balance: balance.balance,
limit: balance.limit || null,
buyingLiabilities: balance.buying_liabilities,
sellingLiabilities: balance.selling_liabilities,
lastModifiedLedger: balance.last_modified_ledger,
isAuthorized: balance.is_authorized,
isAuthorizedToMaintainLiabilities: balance.is_authorized_to_maintain_liabilities
}));
}
catch (error) {
throw new XDBChainError(`Failed to get balances: ${error}`);
}
}
async getXDBBalance(publicKey) {
const balances = await this.getBalances(publicKey);
const xdbBalance = balances.find(b => b.assetCode === 'XDB');
return xdbBalance?.balance || '0';
}
watchBalances(publicKey, callback) {
if (!this.isValidAddress(publicKey)) {
throw new XDBValidationError('Invalid public key');
}
const accountCallBuilder = this.server.accounts();
const closeHandler = accountCallBuilder
.accountId(publicKey)
.stream({
onmessage: (account) => {
const balances = account.balances.map((balance) => ({
assetType: balance.asset_type,
assetCode: balance.asset_code || 'XDB',
assetIssuer: balance.asset_issuer || null,
balance: balance.balance,
limit: balance.limit || null,
buyingLiabilities: balance.buying_liabilities,
sellingLiabilities: balance.selling_liabilities,
lastModifiedLedger: balance.last_modified_ledger,
isAuthorized: balance.is_authorized,
isAuthorizedToMaintainLiabilities: balance.is_authorized_to_maintain_liabilities
}));
callback(balances);
},
onerror: (error) => {
console.error('Balance stream error:', error);
}
});
return closeHandler;
}
async sendPayment(senderSecret, options) {
try {
if (!this.isValidSecretKey(senderSecret)) {
throw new XDBValidationError('Invalid sender secret key');
}
if (!this.isValidAddress(options.destination)) {
throw new XDBValidationError('Invalid destination address');
}
const senderKeypair = stellar_sdk_1.Keypair.fromSecret(senderSecret);
const senderAccount = await this.server.loadAccount(senderKeypair.publicKey());
const asset = this.createAsset(options.asset);
const transactionBuilder = new stellar_sdk_1.TransactionBuilder(senderAccount, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
});
transactionBuilder.addOperation(stellar_sdk_1.Operation.payment({
destination: options.destination,
asset: asset,
amount: options.amount,
source: options.source
}));
if (options.memo) {
const memo = this.createMemo(options.memo, options.memoType);
transactionBuilder.addMemo(memo);
}
const transaction = transactionBuilder.setTimeout(this.config.timeout).build();
transaction.sign(senderKeypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Payment sent successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Payment failed: ${error}`);
}
}
async sendPathPaymentStrictReceive(senderSecret, options) {
try {
if (!this.isValidSecretKey(senderSecret)) {
throw new XDBValidationError('Invalid sender secret key');
}
if (!this.isValidAddress(options.destination)) {
throw new XDBValidationError('Invalid destination address');
}
const senderKeypair = stellar_sdk_1.Keypair.fromSecret(senderSecret);
const senderAccount = await this.server.loadAccount(senderKeypair.publicKey());
const sendAsset = this.createAsset(options.sendAsset);
const destAsset = this.createAsset(options.destAsset);
const path = options.path ? options.path.map(asset => this.createAsset(asset)) : [];
const transactionBuilder = new stellar_sdk_1.TransactionBuilder(senderAccount, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
});
transactionBuilder.addOperation(stellar_sdk_1.Operation.pathPaymentStrictReceive({
sendAsset: sendAsset,
sendMax: options.sendMax,
destination: options.destination,
destAsset: destAsset,
destAmount: options.destAmount,
path: path,
source: options.source
}));
if (options.memo) {
const memo = this.createMemo(options.memo, options.memoType);
transactionBuilder.addMemo(memo);
}
const transaction = transactionBuilder.setTimeout(this.config.timeout).build();
transaction.sign(senderKeypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Path payment sent successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Path payment failed: ${error}`);
}
}
async sendPathPaymentStrictSend(senderSecret, options) {
try {
if (!this.isValidSecretKey(senderSecret)) {
throw new XDBValidationError('Invalid sender secret key');
}
if (!this.isValidAddress(options.destination)) {
throw new XDBValidationError('Invalid destination address');
}
const senderKeypair = stellar_sdk_1.Keypair.fromSecret(senderSecret);
const senderAccount = await this.server.loadAccount(senderKeypair.publicKey());
const sendAsset = this.createAsset(options.sendAsset);
const destAsset = this.createAsset(options.destAsset);
const path = options.path ? options.path.map(asset => this.createAsset(asset)) : [];
const transactionBuilder = new stellar_sdk_1.TransactionBuilder(senderAccount, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
});
transactionBuilder.addOperation(stellar_sdk_1.Operation.pathPaymentStrictSend({
sendAsset: sendAsset,
sendAmount: options.sendMax,
destination: options.destination,
destAsset: destAsset,
destMin: options.destAmount,
path: path,
source: options.source
}));
if (options.memo) {
const memo = this.createMemo(options.memo, options.memoType);
transactionBuilder.addMemo(memo);
}
const transaction = transactionBuilder.setTimeout(this.config.timeout).build();
transaction.sign(senderKeypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Path payment (strict send) sent successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Path payment (strict send) failed: ${error}`);
}
}
async sendBatchPayments(senderSecret, payments) {
try {
if (!this.isValidSecretKey(senderSecret)) {
throw new XDBValidationError('Invalid sender secret key');
}
if (!payments.length) {
throw new XDBValidationError('No payments provided');
}
const senderKeypair = stellar_sdk_1.Keypair.fromSecret(senderSecret);
const senderAccount = await this.server.loadAccount(senderKeypair.publicKey());
const transactionBuilder = new stellar_sdk_1.TransactionBuilder(senderAccount, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
});
for (const payment of payments) {
if (!this.isValidAddress(payment.destination)) {
throw new XDBValidationError(`Invalid destination address: ${payment.destination}`);
}
const asset = this.createAsset(payment.asset);
transactionBuilder.addOperation(stellar_sdk_1.Operation.payment({
destination: payment.destination,
asset: asset,
amount: payment.amount,
source: payment.source
}));
}
const transaction = transactionBuilder.setTimeout(this.config.timeout).build();
transaction.sign(senderKeypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Batch payments sent successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Batch payment failed: ${error}`);
}
}
async addTrustline(walletSecret, options) {
try {
if (!this.isValidSecretKey(walletSecret)) {
throw new XDBValidationError('Invalid wallet secret key');
}
const keypair = stellar_sdk_1.Keypair.fromSecret(walletSecret);
const account = await this.server.loadAccount(keypair.publicKey());
const asset = new stellar_sdk_1.Asset(options.assetCode, options.assetIssuer);
const transaction = new stellar_sdk_1.TransactionBuilder(account, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.changeTrust({
asset: asset,
limit: options.limit,
source: options.source
}))
.setTimeout(this.config.timeout)
.build();
transaction.sign(keypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Trustline added successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Failed to add trustline: ${error}`);
}
}
async removeTrustline(walletSecret, options) {
return this.addTrustline(walletSecret, { ...options, limit: '0' });
}
async getTrustlines(publicKey) {
try {
if (!this.isValidAddress(publicKey)) {
throw new XDBValidationError('Invalid public key');
}
const account = await this.server.loadAccount(publicKey);
return account.balances.filter((balance) => balance.asset_type !== 'native');
}
catch (error) {
throw new XDBChainError(`Failed to get trustlines: ${error}`);
}
}
async allowTrust(trustorSecret, trusteePublicKey, assetCode, authorize) {
try {
if (!this.isValidSecretKey(trustorSecret)) {
throw new XDBValidationError('Invalid trustor secret key');
}
if (!this.isValidAddress(trusteePublicKey)) {
throw new XDBValidationError('Invalid trustee public key');
}
const trustorKeypair = stellar_sdk_1.Keypair.fromSecret(trustorSecret);
const trustorAccount = await this.server.loadAccount(trustorKeypair.publicKey());
const transaction = new stellar_sdk_1.TransactionBuilder(trustorAccount, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.allowTrust({
trustor: trusteePublicKey,
assetCode: assetCode,
authorize: authorize
}))
.setTimeout(this.config.timeout)
.build();
transaction.sign(trustorKeypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Trust authorization updated successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Failed to update trust authorization: ${error}`);
}
}
createAssetObject(code, issuer) {
if (code === 'XDB' || code === 'native') {
const nativeAsset = stellar_sdk_1.Asset.native();
nativeAsset.code = 'XDB';
return nativeAsset;
}
if (!issuer) {
throw new XDBAssetError('Asset issuer is required for non-native assets');
}
return new stellar_sdk_1.Asset(code, issuer);
}
async issueAsset(issuerSecret, distributorPublicKey, assetCode, amount) {
try {
if (!this.isValidSecretKey(issuerSecret)) {
throw new XDBValidationError('Invalid issuer secret key');
}
if (!this.isValidAddress(distributorPublicKey)) {
throw new XDBValidationError('Invalid distributor public key');
}
const issuerKeypair = stellar_sdk_1.Keypair.fromSecret(issuerSecret);
const issuerAccount = await this.server.loadAccount(issuerKeypair.publicKey());
const asset = new stellar_sdk_1.Asset(assetCode, issuerKeypair.publicKey());
const transaction = new stellar_sdk_1.TransactionBuilder(issuerAccount, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.payment({
destination: distributorPublicKey,
asset: asset,
amount: amount
}))
.setTimeout(this.config.timeout)
.build();
transaction.sign(issuerKeypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Asset issued successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Failed to issue asset: ${error}`);
}
}
async createSellOffer(secretKey, options) {
try {
if (!this.isValidSecretKey(secretKey)) {
throw new XDBValidationError('Invalid secret key');
}
const keypair = stellar_sdk_1.Keypair.fromSecret(secretKey);
const account = await this.server.loadAccount(keypair.publicKey());
const selling = this.createAsset(options.selling);
const buying = this.createAsset(options.buying);
const transaction = new stellar_sdk_1.TransactionBuilder(account, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.manageSellOffer({
selling: selling,
buying: buying,
amount: options.amount,
price: options.price,
offerId: options.offerId || '0',
source: options.source
}))
.setTimeout(this.config.timeout)
.build();
transaction.sign(keypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Sell offer created successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBOfferError(`Failed to create sell offer: ${error}`);
}
}
async createBuyOffer(secretKey, options) {
try {
if (!this.isValidSecretKey(secretKey)) {
throw new XDBValidationError('Invalid secret key');
}
const keypair = stellar_sdk_1.Keypair.fromSecret(secretKey);
const account = await this.server.loadAccount(keypair.publicKey());
const selling = this.createAsset(options.selling);
const buying = this.createAsset(options.buying);
const transaction = new stellar_sdk_1.TransactionBuilder(account, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.manageBuyOffer({
selling: selling,
buying: buying,
buyAmount: options.amount,
price: options.price,
offerId: options.offerId || '0',
source: options.source
}))
.setTimeout(this.config.timeout)
.build();
transaction.sign(keypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Buy offer created successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBOfferError(`Failed to create buy offer: ${error}`);
}
}
async createPassiveSellOffer(secretKey, options) {
try {
if (!this.isValidSecretKey(secretKey)) {
throw new XDBValidationError('Invalid secret key');
}
const keypair = stellar_sdk_1.Keypair.fromSecret(secretKey);
const account = await this.server.loadAccount(keypair.publicKey());
const selling = this.createAsset(options.selling);
const buying = this.createAsset(options.buying);
const transaction = new stellar_sdk_1.TransactionBuilder(account, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.createPassiveSellOffer({
selling: selling,
buying: buying,
amount: options.amount,
price: options.price,
source: options.source
}))
.setTimeout(this.config.timeout)
.build();
transaction.sign(keypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Passive sell offer created successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBOfferError(`Failed to create passive sell offer: ${error}`);
}
}
async cancelOffer(secretKey, offerId, selling, buying) {
try {
if (!this.isValidSecretKey(secretKey)) {
throw new XDBValidationError('Invalid secret key');
}
const keypair = stellar_sdk_1.Keypair.fromSecret(secretKey);
const account = await this.server.loadAccount(keypair.publicKey());
const sellingAsset = this.createAsset(selling);
const buyingAsset = this.createAsset(buying);
const transaction = new stellar_sdk_1.TransactionBuilder(account, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.manageSellOffer({
selling: sellingAsset,
buying: buyingAsset,
amount: '0',
price: '1',
offerId: offerId
}))
.setTimeout(this.config.timeout)
.build();
transaction.sign(keypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Offer cancelled successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBOfferError(`Failed to cancel offer: ${error}`);
}
}
async manageData(secretKey, options) {
try {
if (!this.isValidSecretKey(secretKey)) {
throw new XDBValidationError('Invalid secret key');
}
const keypair = stellar_sdk_1.Keypair.fromSecret(secretKey);
const account = await this.server.loadAccount(keypair.publicKey());
const transaction = new stellar_sdk_1.TransactionBuilder(account, {
fee: (await this.server.fetchBaseFee()).toString(),
networkPassphrase: this.networkPassphrase
})
.addOperation(stellar_sdk_1.Operation.manageData({
name: options.name,
value: options.value,
source: options.source
}))
.setTimeout(this.config.timeout)
.build();
transaction.sign(keypair);
const result = await this.server.submitTransaction(transaction);
console.log('✅ Data managed successfully:', result.hash);
return result;
}
catch (error) {
throw new XDBTransactionError(`Failed to manage data: ${error}`);
}
}
async getTransactionHistory(publicKey, options = {}) {
try {
if (!this.isValidAddress(publicKey)) {
throw new XDBValidationError('Invalid public key');
}
const { limit = 10, order = 'desc', cursor, includeFailed = false } = options;
let transactionBuilder = this.server
.transactions()
.forAccount(publicKey)
.order(order)
.limit(limit);
if (cursor) {
transactionBuilder = transactionBuilder.cursor(cursor);
}
if (includeFailed) {
transactionBuilder = transactionBuilder.includeFailed(true);
}
const result = await transactionBuilder.call();
return result.records.map((tx) => ({
hash: tx.hash,
ledger: tx.ledger_attr,
createdAt: tx.created_at,
fee: tx.fee_charged,
operationCount: tx.operation_count,
memo: tx.memo,
memoType: tx.memo_type,
successful: tx.successful,
pagingToken: tx.paging_token,
sourceAccount: tx.source_account,
sourceAccountSequence: tx.source_account_sequence,
feeAccount: tx.fee_account,
feeCharged: tx.fee_charged,
maxFee: tx.max_fee,
timeBounds: tx.time_bounds
}));
}
catch (error) {
throw new XDBChainError(`Failed to get transaction history: ${error}`);
}
}
async getTransactionsForLedger(ledgerSequence, options = {}) {
try {
const { limit = 10, order = 'desc', cursor, includeFailed = false } = options;
let transactionBuilder = this.server
.transactions()
.forLedger(ledgerSequence)
.order(order)
.limit(limit);
if (cursor) {
transactionBuilder = transactionBuilder.cursor(cursor);
}
if (includeFailed) {
transactionBuilder = transactionBuilder.includeFailed(true);
}
const result = await transactionBuilder.call();
return result.records.map((tx) => ({
hash: tx.hash,
ledger: tx.ledger_attr,
createdAt: tx.created_at,
fee: tx.fee_charged,
operationCount: tx.operation_count,
memo: tx.memo,
memoType: tx.memo_type,
successful: tx.successful,
pagingToken: tx.paging_token,
sourceAccount: tx.source_account,
sourceAccountSequence: tx.source_account_sequence,
feeAccount: tx.fee_account,
feeCharged: tx.fee_charged,
maxFee: tx.max_fee,
timeBounds: tx.time_bounds
}));
}
catch (error) {
throw new XDBChainError(`Failed to get transactions for ledger: ${error}`);
}
}
watchTransactions(publicKey, callback) {
if (!this.isValidAddress(publicKey)) {
throw new XDBValidationError('Invalid public key');
}
const closeHandler = this.server
.transactions()
.forAccount(publicKey)
.cursor('now')
.stream({
onmessage: (transaction) => {
const xdbTransaction = {
hash: transaction.hash,
ledger: transaction.ledger_attr,
createdAt: transaction.created_at,
fee: transaction.fee_charged,
operationCount: transaction.operation_count,
memo: transaction.memo,
memoType: transaction.memo_type,
successful: transaction.successful,
pagingToken: transaction.paging_token,
sourceAccount: transaction.source_account,
sourceAccountSequence: transaction.source_account_sequence,
feeAccount: transaction.fee_account,
feeCharged: transaction.fee_charged,
maxFee: transaction.max_fee,
timeBounds: transaction.time_bounds
};
callback(xdbTransaction);
},
onerror: (error) => {
console.error('Transaction stream error:', error);
}
});
return closeHandler;
}
async getOperations(publicKey, options = {}) {
try {
if (!this.isValidAddress(publicKey)) {
throw new XDBValidationError('Invalid public key');
}
const { limit = 10, order = 'desc', cursor, includeFailed = false } = options;
let operationBuilder = this.server
.operations()
.forAccount(publicKey)
.order(order)
.limit(limit);
if (cursor) {
operationBuilder = operationBuilder.cursor(cursor);
}
if (includeFailed) {
operationBuilder = operationBuilder.includeFailed(true);
}
const result = await operationBuilder.call();
return result.records;
}
catch (error) {
throw new XDBChainError(`Failed to get operations: ${error}`);
}
}
async getOperationsForLedger(ledgerSequence, options = {}) {
try {
const { limit = 10, order = 'desc', cursor, includeFailed = false } = options;
let operationBuilder = this.server
.operations()
.forLedger(ledgerSequence)
.order(order)
.limit(limit);
if (cursor) {
operationBuilder = operationBuilder.cursor(cursor);
}
if (includeFailed) {
operationBuilder = operationBuilder.includeFailed(true);
}
const result = await operationBuilder.call();
return result.records;
}
catch (error) {
throw new XDBChainError(`Failed to get operations for ledger: ${error}`);
}
}
async getOperationsForTransaction(transactionHash, options = {}) {
try {
const { limit = 10, order = 'desc', cursor } = options;
let operationBuilder = this.server
.operations()
.forTransaction(transactionHash)
.order(order)
.limit(limit);
if (cursor) {
operationBuilder = operationBuilder.cursor(cursor);
}
const result = await operationBuilder.call();
return result.records;
}
catch (error) {
throw new XDBChainError(`Failed to get operations for transaction: ${error}`);
}
}
async getPayments(publicKey, options = {}) {
try {
if (!this.isValidAddress(publicKey)) {
throw new XDBValidationError('Invalid public key');
}
const { limit = 10, order = 'desc', cursor, includeFailed = false } = options;
let paymentBuilder = this.server
.payments()
.forAccount(publicKey)
.order(order)
.limit(limit);
if (cursor) {
paymentBuilder = paymentBuilder.cursor(cursor);
}
if (includeFailed) {
paymentBuilder = paymentBuilder.includeFailed(true);
}
const result = await paymentBuilder.call();
return result.records.map((payment) => ({
id: payment.id,
pagingToken: payment.paging_token,
transactionSuccessful: payment.transaction_successful,
sourceAccount: payment.source_account,
type: payment.type,
createdAt: payment.created_at,
transactionHash: payment.transaction_hash,
assetType: payment.asset_type,
assetCode: payment.asset_code,
assetIssuer: payment.asset_issuer,
from: payment.from,
to: payment.to,
amount: payment.amount,
memo: payment.memo,
memoType: payment.memo_type
}));
}
catch (error) {
throw new XDBChainError(`Failed to get payments: ${error}`);
}
}
watchPayments(publicKey, callback) {
if (!this.isValidAddress(publicKey)) {
throw new XDBValidationError('Invalid public key');
}
const closeHandler = this.server
.payments()
.forAccount(publicKey)
.cursor('now')
.stream({
onmessage: (payment) => {
const xdbPayment = {
id: payment.id,
pagingToken: payment.paging_token,
transactionSuccessful: payment.transaction_successful,
sourceAccount: payment.source_account,
type: payment.type,
createdAt: payment.created_at,
transactionHash: payment.transaction_hash,
assetType: payment.asset_type,
assetCode: payment.asset_code,
assetIssuer: payment.asset_issuer,
from: payment.from,
to: payment.to,
amount: payment.amount,
memo: payment.memo,
memoType: payment.memo_type
};
callback(xdbPayment);
},
onerror: (error) => {
console.error('Payment stream error:', error);
}
});
return closeHandler;
}
async getEffects(publicKey, options = {}) {
try {
if (!this.isValidAddress(publicKey)) {
throw new XDBValidationError('Invalid public key');
}
const { limit = 10, order = 'desc', cursor } = options;
let effectBuilder = this.server
.effects()
.forAccount(publicKey)
.order(order)
.limit(limit);
if (cursor) {
effectBuilder = effectBuilder.cursor(cursor);
}
const result = await effectBuilder.call();
return result.records.map((effect) => ({
id: effect.id,
type: effect.type,
account: effect.account,
createdAt: effect.created_at,
operationId: effect.operation_id,
details: effect
}));
}
catch (error) {
throw new XDBChainError(`Failed to get effects: ${error}`);
}
}
async getEffectsForOperation(operationId, options = {}) {
try {
const { limit = 10, order = 'desc', cursor } = options;
let effectBuilder = this.server
.effects()
.forOperation(operationId)
.order(order)
.limit(limit);
if (cursor) {
effectBuilder = effectBuilder.cursor(cursor);
}
const result = await effectBuilder.call();
return result.records.map((effect) => ({
id: effect.id,
type: effect.type,
account: effect.account,
createdAt: effect.created_at,
operationId: effect.operation_id,
details: effect
}));
}
catch (error) {
throw new XDBChainError(`Failed to get effects for operation: ${error}`);
}
}
async getTrades(publicKey, options = {}) {
try {
if (!this.isValidAddress(publicKey)) {
throw new XDBValidationError('Invalid public key');
}
const { limit = 10, order = 'desc', cursor } = options;
let tradeBuilder = this.server
.trades()
.forAccount(publicKey)
.order(order)
.limit(limit);
if (cursor) {
tradeBuilder = tradeBuilder.cursor(cursor);
}
const result = await tradeBuilder.call();
return result.records.map((trade) => ({
id: trade.id,
pagingToken: trade.paging_token,
ledgerCloseTime: trade.ledger_close_time,
offerIds: trade.offer_ids,
baseAccount: trade.base_account,
baseAmount: trade.base_amount,
baseAssetType: trade.base_asset_type,
baseAssetCode: trade.base_asset_code,
baseAssetIssuer: trade.base_asset_issuer,
counterAccount: trade.counter_account,
counterAmount: trade.counter_amount,
counterAssetType: trade.counter_asset_type,
counterAssetCode: trade.counter_asset_code,
counterAssetIssuer: trade.counter_asset_issuer,
baseIsSeller: trade.base_is_seller,
price: trade.price
}));
}
catch (error) {
throw new XDBChainError(`Failed to get trades: ${error}`);
}
}
async getTradesForAssetPair(baseAsset, counterAsset, options = {}) {
try {
const { limit = 10, order = 'desc', cursor } = options;
const base = this.createAsset(baseAsset);
const counter = this.createAsset(counterAsset);
let tradeBuilder = this.server
.trades()
.forAssetPair(base, counter)
.order(order)
.limit(limit);
if (cursor) {
tradeBuilder = tradeBuilder.cursor(cursor);
}
const result = await tradeBuilder.call();
return result.records.map((trade) => ({
id: trade.id,
pagingToken: trade.paging_token,
ledgerCloseTime: trade.ledger_close_time,
offerIds: trade.offer_ids,
baseAccount: trade.base_account,
baseAmount: trade.base_amount,
baseAssetType: trade.base_asset_type,
baseAssetCode: trade.base_asset_code,
baseAssetIssuer: trade.base_asset_issuer,
counterAccount: trade.counter_account,
counterAmount: trade.counter_amount,
counterAssetType: trade.counter_asset_type,
counterAssetCode: trade.counter_asset_code,
counterAssetIssuer: trade.counter_asset_issuer,
baseIsSeller: trade.base_is_seller,
price: trade.price
}));
}
catch (error) {
throw new XDBChainError(`Failed to get trades for asset pair: ${error}`);
}
}
async getOrderbook(selling, buying, limit = 10) {
try {
const sellingAsset = this.createAsset(selling);
const buyingAsset = th