diff --git a/src/constants/constants.ts b/src/constants/constants.ts
index f4097194..1d266731 100644
--- a/src/constants/constants.ts
+++ b/src/constants/constants.ts
@@ -2,6 +2,7 @@ import { config } from '../config';
export const HORIZON_URL = 'https://horizon.stellar.org';
export const STELLAR_BASE_FEE = '1000000';
+export const STELLAR_EPHEMERAL_STARTING_BALANCE_UNITS = '2.5'; // Amount to send to the new stellar ephemeral account created
export const PENDULUM_WSS = 'wss://rpc-pendulum.prd.pendulumchain.tech';
export const ASSETHUB_WSS = 'wss://polkadot-asset-hub-rpc.polkadot.io';
export const WALLETCONNECT_ASSETHUB_ID = 'polkadot:68d56f15f85d3136970ec16946040bc1';
diff --git a/src/main.tsx b/src/main.tsx
index db1ba3f8..f8bd8ca4 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -41,17 +41,17 @@ render(
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
diff --git a/src/pages/swap/index.tsx b/src/pages/swap/index.tsx
index 3d7916a9..d6df7dd2 100644
--- a/src/pages/swap/index.tsx
+++ b/src/pages/swap/index.tsx
@@ -433,7 +433,7 @@ export const SwapPage = () => {
) : (
)}
diff --git a/src/services/anchor/index.ts b/src/services/anchor/index.ts
index 98f1248f..9044da05 100644
--- a/src/services/anchor/index.ts
+++ b/src/services/anchor/index.ts
@@ -282,6 +282,8 @@ export async function sep24Second(
const { sep24Url } = tomlValues;
if (config.test.mockSep24) {
+ // sleep 10 secs
+ await new Promise((resolve) => setTimeout(resolve, 10000));
return {
amount: sessionParams.offrampAmount,
memo: 'MYK1722323689',
diff --git a/src/services/phases/signedTransactions.ts b/src/services/phases/signedTransactions.ts
index 745f7874..4bfd21da 100644
--- a/src/services/phases/signedTransactions.ts
+++ b/src/services/phases/signedTransactions.ts
@@ -48,6 +48,7 @@ export async function prepareTransactions(state: OfframpingState, context: Execu
const stellarFundingAccountId = (await fetchSigningServiceAccountId()).stellar.public;
const stellarEphemeralKeypair = Keypair.fromSecret(stellarEphemeralSecret);
const stellarEphemeralPublicKey = stellarEphemeralKeypair.publicKey();
+
const { offrampingTransaction, mergeAccountTransaction } = await setUpAccountAndOperations(
stellarFundingAccountId,
stellarEphemeralKeypair,
diff --git a/src/services/phases/stellar/index.tsx b/src/services/phases/stellar/index.tsx
index 73559ac9..c233fff1 100644
--- a/src/services/phases/stellar/index.tsx
+++ b/src/services/phases/stellar/index.tsx
@@ -14,7 +14,12 @@ import {
} from 'stellar-sdk';
import { OUTPUT_TOKEN_CONFIG, OutputTokenDetails, OutputTokenType } from '../../../constants/tokenConfig';
-import { HORIZON_URL, SIGNING_SERVICE_URL, STELLAR_BASE_FEE } from '../../../constants/constants';
+import {
+ HORIZON_URL,
+ SIGNING_SERVICE_URL,
+ STELLAR_BASE_FEE,
+ STELLAR_EPHEMERAL_STARTING_BALANCE_UNITS,
+} from '../../../constants/constants';
import { fetchSigningServiceAccountId } from '../../signingService';
import { OfframpingState } from '../../offrampingFlow';
import { SepResult } from '../../anchor';
@@ -22,6 +27,38 @@ import { SepResult } from '../../anchor';
const horizonServer = new Horizon.Server(HORIZON_URL);
const NETWORK_PASSPHRASE = Networks.PUBLIC;
+// This is a helper function to add a timeout to the loadAccount function and retry it.
+// The Horizon.Server class does not allow defining a custom timeout for network queries.
+async function loadAccountWithRetry(
+ ephemeralAccountId: string,
+ retries = 3,
+ timeout = 15000,
+): Promise {
+ let lastError: Error | null = null;
+
+ const loadAccountWithTimeout = (accountId: string, timeout: number): Promise => {
+ return Promise.race([
+ horizonServer.loadAccount(accountId),
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), timeout)),
+ ]);
+ };
+
+ for (let i = 0; i < retries; i++) {
+ try {
+ return await loadAccountWithTimeout(ephemeralAccountId, timeout);
+ } catch (err: any) {
+ if (err?.toString().includes('NotFoundError')) {
+ // The account does not exist
+ return null;
+ }
+ console.log(`Attempt ${i + 1} to load account ${ephemeralAccountId} failed: ${err}`);
+ lastError = err;
+ }
+ }
+
+ throw new Error(`Failed to load account ${ephemeralAccountId} after ${retries} attempts: ` + lastError?.toString());
+}
+
export interface StellarOperations {
offrampingTransaction: Transaction;
mergeAccountTransaction: Transaction;
@@ -58,10 +95,11 @@ async function isEphemeralCreated(stellarEphemeralSecret: string): Promise {
- const ephemeralAccount = await horizonServer.loadAccount(ephemeralKeypair.publicKey());
+ const ephemeralAccount = await loadAccountWithRetry(ephemeralKeypair.publicKey());
+ if (!ephemeralAccount) {
+ throw new Error('Ephemeral account does not exist on network.');
+ }
+
const { offrampingTransaction, mergeAccountTransaction } = await createOfframpAndMergeTransaction(
fundingAccountId,
sepResult,
@@ -131,7 +173,7 @@ async function setupStellarAccount(
.addOperation(
Operation.createAccount({
destination: ephemeralAccountId,
- startingBalance: '2.5',
+ startingBalance: STELLAR_EPHEMERAL_STARTING_BALANCE_UNITS,
}),
)
.addOperation(
@@ -163,8 +205,7 @@ async function setupStellarAccount(
await horizonServer.submitTransaction(createAccountTransaction);
} catch (error: unknown) {
const horizonError = error as { response: { data: { extras: any } } };
- console.log(horizonError.response.data.extras);
- console.error(horizonError.response.data.extras.toString());
+ console.error('Transaction submission to horizon failed', horizonError.toString());
throw new Error('Could not submit the account creation transaction');
}
}