From 200acff73bb51dab8c0f3d5b3184655f0399293c Mon Sep 17 00:00:00 2001 From: Gianfranco Date: Fri, 13 Dec 2024 15:48:36 -0300 Subject: [PATCH 01/10] reorder contexts --- src/main.tsx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) 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( - - - - - + + + + + - - - - - + + + + + From 4a2c67cdece3722aabfc8641cc2a38b295ae5be8 Mon Sep 17 00:00:00 2001 From: Gianfranco Date: Fri, 13 Dec 2024 16:44:03 -0300 Subject: [PATCH 02/10] mock reply --- src/config/index.ts | 2 +- src/services/anchor/index.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/config/index.ts b/src/config/index.ts index ee38a279..64926f03 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -19,7 +19,7 @@ export const config = { projectId: '299fda67fbf3b60a31ba8695524534cd', }, test: { - mockSep24: false, + mockSep24: true, overwriteMinimumTransferAmount: false, }, supportUrl: 'https://forms.gle/bgH4XTTbQ3YbwQ3t7', 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', From 70333af67f73b54615a2dd80379117b2488e2248 Mon Sep 17 00:00:00 2001 From: Gianfranco Date: Mon, 16 Dec 2024 10:54:54 -0300 Subject: [PATCH 03/10] disable confirm button when pre-checks fail --- src/pages/swap/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 = () => { ) : ( )} From 107bc48d3afadb7932358bd977daa07e5491a639 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Tue, 17 Dec 2024 13:01:31 +0100 Subject: [PATCH 04/10] Reduce funding amount to `0` --- signer-service/src/constants/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/signer-service/src/constants/constants.js b/signer-service/src/constants/constants.js index ebac4e53..ad3a68d0 100644 --- a/signer-service/src/constants/constants.js +++ b/signer-service/src/constants/constants.js @@ -6,7 +6,7 @@ const STELLAR_FUNDING_AMOUNT_UNITS = '10'; // 10 XLM. Minimum balance of fundin const MOONBEAM_FUNDING_AMOUNT_UNITS = '10'; // 10 GLMR. Minimum balance of funding account const SUBSIDY_MINIMUM_RATIO_FUND_UNITS = '10'; // 10 Subsidies considering maximum subsidy amount use on each (worst case scenario) const MOONBEAM_RECEIVER_CONTRACT_ADDRESS = '0x2AB52086e8edaB28193172209407FF9df1103CDc'; -const STELLAR_EPHEMERAL_STARTING_BALANCE_UNITS = '2.5'; // Amount to send to the new stellar ephemeral account created +const STELLAR_EPHEMERAL_STARTING_BALANCE_UNITS = '0'; // Amount to send to the new stellar ephemeral account created const PENDULUM_EPHEMERAL_STARTING_BALANCE_UNITS = '0.1'; // Amount to send to the new pendulum ephemeral account created const DEFAULT_LOGIN_EXPIRATION_TIME_HOURS = 7 * 24; const VALID_SIWE_CHAINS = [137]; // 137: Polygon From d14af8903803be668c02282e85a812171a7a7c78 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Tue, 17 Dec 2024 13:02:26 +0100 Subject: [PATCH 05/10] Add logs --- src/services/phases/signedTransactions.ts | 10 ++++++++++ src/services/phases/stellar/index.tsx | 2 ++ src/services/signingService.tsx | 2 ++ 3 files changed, 14 insertions(+) diff --git a/src/services/phases/signedTransactions.ts b/src/services/phases/signedTransactions.ts index 745f7874..644cd778 100644 --- a/src/services/phases/signedTransactions.ts +++ b/src/services/phases/signedTransactions.ts @@ -39,15 +39,23 @@ export async function prepareTransactions(state: OfframpingState, context: Execu const { pendulumNode } = context; + console.log('prepareTransactions', state, context); const spacewalkRedeemTransaction = await prepareSpacewalkRedeemTransaction(state, context); const nablaApproveTransaction = await prepareNablaApproveTransaction(state, context); const nablaSwapTransaction = await prepareNablaSwapTransaction(state, context); + console.log('after preparing some transactions'); + // Fund Stellar ephemeral only after all other transactions are prepared await stellarCreateEphemeral(stellarEphemeralSecret, outputTokenType); + console.log('after stellarCreateEphemeral'); const stellarFundingAccountId = (await fetchSigningServiceAccountId()).stellar.public; + console.log('after fetchSigningServiceAccountId'); const stellarEphemeralKeypair = Keypair.fromSecret(stellarEphemeralSecret); const stellarEphemeralPublicKey = stellarEphemeralKeypair.publicKey(); + + console.log('after stellar transactions'); + const { offrampingTransaction, mergeAccountTransaction } = await setUpAccountAndOperations( stellarFundingAccountId, stellarEphemeralKeypair, @@ -55,6 +63,8 @@ export async function prepareTransactions(state: OfframpingState, context: Execu outputTokenType, ); + console.log('after setting up account and operations'); + const transactions = { stellarOfframpingTransaction: offrampingTransaction.toEnvelope().toXDR().toString('base64'), stellarCleanupTransaction: mergeAccountTransaction.toEnvelope().toXDR().toString('base64'), diff --git a/src/services/phases/stellar/index.tsx b/src/services/phases/stellar/index.tsx index 73559ac9..86004130 100644 --- a/src/services/phases/stellar/index.tsx +++ b/src/services/phases/stellar/index.tsx @@ -37,6 +37,7 @@ export async function stellarCreateEphemeral( stellarEphemeralSecret: string, outputTokenType: OutputTokenType, ): Promise { + console.log('in stellarCreateEphemeral'); const fundingAccountId = (await fetchSigningServiceAccountId()).stellar.public; const ephemeralAccountExists = await isEphemeralCreated(stellarEphemeralSecret); @@ -45,6 +46,7 @@ export async function stellarCreateEphemeral( // eslint-disable-next-line no-constant-condition while (true) { + console.log('waiting for ephemeral account to be created in loop'); if (await isEphemeralCreated(stellarEphemeralSecret)) { break; } diff --git a/src/services/signingService.tsx b/src/services/signingService.tsx index d70237a5..2fe1c5ac 100644 --- a/src/services/signingService.tsx +++ b/src/services/signingService.tsx @@ -28,7 +28,9 @@ export interface SignerServiceSep10Request { // @todo: implement @tanstack/react-query export const fetchSigningServiceAccountId = async (): Promise => { try { + console.log('awaiting serviceResponse'); const serviceResponse: SigningServiceStatus = await (await fetch(`${SIGNING_SERVICE_URL}/v1/status`)).json(); + console.log('serviceResponse', serviceResponse); const allServicesActive = Object.values(serviceResponse).every((service: AccountStatusResponse) => service.status); if (allServicesActive) { From 07f474df7a5dfde6e14648bea3e83e1faceabff2 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Tue, 17 Dec 2024 18:55:12 +0100 Subject: [PATCH 06/10] Wrap call to loadAccount --- src/services/phases/stellar/index.tsx | 37 ++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/services/phases/stellar/index.tsx b/src/services/phases/stellar/index.tsx index 86004130..003c0de6 100644 --- a/src/services/phases/stellar/index.tsx +++ b/src/services/phases/stellar/index.tsx @@ -60,13 +60,39 @@ async function isEphemeralCreated(stellarEphemeralSecret: string): Promise { + let lastError: Error | null = null; + for (let i = 0; i < retries; i++) { + try { + return await Promise.race([ + horizonServer.loadAccount(ephemeralAccountId), + new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 10000)), + ]); + } 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 async function setUpAccountAndOperations( fundingAccountId: string, ephemeralKeypair: Keypair, @@ -165,8 +191,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'); } } From c9ed8f8ac1ebb72f0e06dee597b42c507c354c27 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Tue, 17 Dec 2024 19:36:04 +0100 Subject: [PATCH 07/10] Refactor --- src/services/phases/stellar/index.tsx | 65 ++++++++++++++++----------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/src/services/phases/stellar/index.tsx b/src/services/phases/stellar/index.tsx index 003c0de6..f2419144 100644 --- a/src/services/phases/stellar/index.tsx +++ b/src/services/phases/stellar/index.tsx @@ -22,6 +22,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 = 5, + timeout = 10000, +): 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; @@ -60,7 +92,7 @@ async function isEphemeralCreated(stellarEphemeralSecret: string): Promise { - let lastError: Error | null = null; - for (let i = 0; i < retries; i++) { - try { - return await Promise.race([ - horizonServer.loadAccount(ephemeralAccountId), - new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 10000)), - ]); - } 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 async function setUpAccountAndOperations( fundingAccountId: string, ephemeralKeypair: Keypair, sepResult: SepResult, outputTokenType: OutputTokenType, ): 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, From 893e7c6f99a6c63f76d8c18bd28f44891b94d875 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Tue, 17 Dec 2024 19:40:21 +0100 Subject: [PATCH 08/10] Amend refactor --- src/constants/constants.ts | 1 + src/services/phases/stellar/index.tsx | 15 ++++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) 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/services/phases/stellar/index.tsx b/src/services/phases/stellar/index.tsx index f2419144..2d12e2f2 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'; @@ -92,9 +97,9 @@ async function isEphemeralCreated(stellarEphemeralSecret: string): Promise Date: Wed, 18 Dec 2024 09:50:16 +0100 Subject: [PATCH 09/10] Revert temporary changes --- signer-service/src/constants/constants.js | 2 +- src/config/index.ts | 2 +- src/services/phases/signedTransactions.ts | 9 --------- src/services/signingService.tsx | 2 -- 4 files changed, 2 insertions(+), 13 deletions(-) diff --git a/signer-service/src/constants/constants.js b/signer-service/src/constants/constants.js index ad3a68d0..ebac4e53 100644 --- a/signer-service/src/constants/constants.js +++ b/signer-service/src/constants/constants.js @@ -6,7 +6,7 @@ const STELLAR_FUNDING_AMOUNT_UNITS = '10'; // 10 XLM. Minimum balance of fundin const MOONBEAM_FUNDING_AMOUNT_UNITS = '10'; // 10 GLMR. Minimum balance of funding account const SUBSIDY_MINIMUM_RATIO_FUND_UNITS = '10'; // 10 Subsidies considering maximum subsidy amount use on each (worst case scenario) const MOONBEAM_RECEIVER_CONTRACT_ADDRESS = '0x2AB52086e8edaB28193172209407FF9df1103CDc'; -const STELLAR_EPHEMERAL_STARTING_BALANCE_UNITS = '0'; // Amount to send to the new stellar ephemeral account created +const STELLAR_EPHEMERAL_STARTING_BALANCE_UNITS = '2.5'; // Amount to send to the new stellar ephemeral account created const PENDULUM_EPHEMERAL_STARTING_BALANCE_UNITS = '0.1'; // Amount to send to the new pendulum ephemeral account created const DEFAULT_LOGIN_EXPIRATION_TIME_HOURS = 7 * 24; const VALID_SIWE_CHAINS = [137]; // 137: Polygon diff --git a/src/config/index.ts b/src/config/index.ts index 64926f03..ee38a279 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -19,7 +19,7 @@ export const config = { projectId: '299fda67fbf3b60a31ba8695524534cd', }, test: { - mockSep24: true, + mockSep24: false, overwriteMinimumTransferAmount: false, }, supportUrl: 'https://forms.gle/bgH4XTTbQ3YbwQ3t7', diff --git a/src/services/phases/signedTransactions.ts b/src/services/phases/signedTransactions.ts index 644cd778..4bfd21da 100644 --- a/src/services/phases/signedTransactions.ts +++ b/src/services/phases/signedTransactions.ts @@ -39,23 +39,16 @@ export async function prepareTransactions(state: OfframpingState, context: Execu const { pendulumNode } = context; - console.log('prepareTransactions', state, context); const spacewalkRedeemTransaction = await prepareSpacewalkRedeemTransaction(state, context); const nablaApproveTransaction = await prepareNablaApproveTransaction(state, context); const nablaSwapTransaction = await prepareNablaSwapTransaction(state, context); - console.log('after preparing some transactions'); - // Fund Stellar ephemeral only after all other transactions are prepared await stellarCreateEphemeral(stellarEphemeralSecret, outputTokenType); - console.log('after stellarCreateEphemeral'); const stellarFundingAccountId = (await fetchSigningServiceAccountId()).stellar.public; - console.log('after fetchSigningServiceAccountId'); const stellarEphemeralKeypair = Keypair.fromSecret(stellarEphemeralSecret); const stellarEphemeralPublicKey = stellarEphemeralKeypair.publicKey(); - console.log('after stellar transactions'); - const { offrampingTransaction, mergeAccountTransaction } = await setUpAccountAndOperations( stellarFundingAccountId, stellarEphemeralKeypair, @@ -63,8 +56,6 @@ export async function prepareTransactions(state: OfframpingState, context: Execu outputTokenType, ); - console.log('after setting up account and operations'); - const transactions = { stellarOfframpingTransaction: offrampingTransaction.toEnvelope().toXDR().toString('base64'), stellarCleanupTransaction: mergeAccountTransaction.toEnvelope().toXDR().toString('base64'), diff --git a/src/services/signingService.tsx b/src/services/signingService.tsx index 2fe1c5ac..d70237a5 100644 --- a/src/services/signingService.tsx +++ b/src/services/signingService.tsx @@ -28,9 +28,7 @@ export interface SignerServiceSep10Request { // @todo: implement @tanstack/react-query export const fetchSigningServiceAccountId = async (): Promise => { try { - console.log('awaiting serviceResponse'); const serviceResponse: SigningServiceStatus = await (await fetch(`${SIGNING_SERVICE_URL}/v1/status`)).json(); - console.log('serviceResponse', serviceResponse); const allServicesActive = Object.values(serviceResponse).every((service: AccountStatusResponse) => service.status); if (allServicesActive) { From f2f06edc8e98a8640ebab2b15ea5b5b4429f265b Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Wed, 18 Dec 2024 09:50:35 +0100 Subject: [PATCH 10/10] Set default retries to 3 and timeout to 15s --- src/services/phases/stellar/index.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/services/phases/stellar/index.tsx b/src/services/phases/stellar/index.tsx index 2d12e2f2..c233fff1 100644 --- a/src/services/phases/stellar/index.tsx +++ b/src/services/phases/stellar/index.tsx @@ -31,8 +31,8 @@ const NETWORK_PASSPHRASE = Networks.PUBLIC; // The Horizon.Server class does not allow defining a custom timeout for network queries. async function loadAccountWithRetry( ephemeralAccountId: string, - retries = 5, - timeout = 10000, + retries = 3, + timeout = 15000, ): Promise { let lastError: Error | null = null; @@ -74,7 +74,6 @@ export async function stellarCreateEphemeral( stellarEphemeralSecret: string, outputTokenType: OutputTokenType, ): Promise { - console.log('in stellarCreateEphemeral'); const fundingAccountId = (await fetchSigningServiceAccountId()).stellar.public; const ephemeralAccountExists = await isEphemeralCreated(stellarEphemeralSecret); @@ -83,7 +82,6 @@ export async function stellarCreateEphemeral( // eslint-disable-next-line no-constant-condition while (true) { - console.log('waiting for ephemeral account to be created in loop'); if (await isEphemeralCreated(stellarEphemeralSecret)) { break; }