From 053167b6796c6390267ab06cab5374c18836bfa2 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Tue, 16 Apr 2024 19:47:34 +0200 Subject: [PATCH 1/3] Fix 'no-async-promise-executor' issue --- src/services/polkadot/spacewalk.tsx | 105 ++++++++++++++-------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/src/services/polkadot/spacewalk.tsx b/src/services/polkadot/spacewalk.tsx index 8f26fac8..30771330 100644 --- a/src/services/polkadot/spacewalk.tsx +++ b/src/services/polkadot/spacewalk.tsx @@ -5,6 +5,7 @@ import { parseEventRedeemRequest } from './eventParsers'; import { Api } from './polkadotApi'; import { SpacewalkPrimitivesVaultId } from '@polkadot/types/lookup'; import { Buffer } from 'buffer'; +import { ISubmittableResult } from '@polkadot/types/types'; export function extractAssetFromWrapped(wrapped: any) { if (wrapped.Stellar === 'StellarNative') { @@ -73,63 +74,63 @@ export class VaultService { this.api = api; } - // we should probably refactor to move the promse to only the requestRedeem call, - // and avoid using an async promise executor - - // eslint-disable-next-line no-async-promise-executor - async requestRedeem(uri: string, amount: string, stellarPkBytes: Buffer): Promise { - return new Promise(async (resolve, reject) => { - const keyring = new Keyring({ type: 'sr25519' }); - keyring.setSS58Format(this.api!.ss58Format); - const origin = keyring.addFromUri(uri); - - const release = await this.api!.mutex.lock(origin.address); - const nonce = await this.api!.api.rpc.system.accountNextIndex(origin.publicKey); - await this.api!.api.tx.redeem.requestRedeem(amount, stellarPkBytes, this.vaultId!) - .signAndSend(origin, { nonce }, (submissionResult) => { - const { status, events, dispatchError } = submissionResult; - - if (status.isFinalized) { - console.log( - `Requested redeem of ${amount} for vault ${prettyPrintVaultId(this.vaultId)} with status ${status.type}`, - ); + async requestRedeem(uri: string, amount: string, stellarPkBytes: Buffer) { + const keyring = new Keyring({ type: 'sr25519' }); + keyring.setSS58Format(this.api!.ss58Format); + const origin = keyring.addFromUri(uri); - // Try to find a 'system.ExtrinsicFailed' event - const systemExtrinsicFailedEvent = events.find((record) => { - return record.event.section === 'system' && record.event.method === 'ExtrinsicFailed'; - }); + const release = await this.api!.mutex.lock(origin.address); + const nonce = await this.api!.api.rpc.system.accountNextIndex(origin.publicKey); + + // The result will be assigned in the callback + let result = undefined; + + await this.api!.api.tx.redeem.requestRedeem(amount, stellarPkBytes, this.vaultId!) + .signAndSend(origin, { nonce }, (submissionResult: ISubmittableResult) => { + const { status, events, dispatchError } = submissionResult; + + if (status.isFinalized) { + console.log( + `Requested redeem of ${amount} for vault ${prettyPrintVaultId(this.vaultId)} with status ${status.type}`, + ); - if (dispatchError) { - return reject(this.handleDispatchError(dispatchError, systemExtrinsicFailedEvent, 'Redeem Request')); - } - //find all redeem request events and filter the one that matches the requester - const redeemEvents = events.filter((event) => { - return ( - event.event.section.toLowerCase() === 'redeem' && event.event.method.toLowerCase() === 'requestredeem' - ); + // Try to find a 'system.ExtrinsicFailed' event + const systemExtrinsicFailedEvent = events.find((record) => { + return record.event.section === 'system' && record.event.method === 'ExtrinsicFailed'; + }); + + if (dispatchError) { + throw this.handleDispatchError(dispatchError, systemExtrinsicFailedEvent, 'Redeem Request'); + } + //find all redeem request events and filter the one that matches the requester + const redeemEvents = events.filter((event) => { + return ( + event.event.section.toLowerCase() === 'redeem' && event.event.method.toLowerCase() === 'requestredeem' + ); + }); + + const event = redeemEvents + .map((event) => parseEventRedeemRequest(event)) + .filter((event) => { + return event.redeemer === origin.address; }); - const event = redeemEvents - .map((event) => parseEventRedeemRequest(event)) - .filter((event) => { - return event.redeemer === origin.address; - }); - - if (event.length == 0) { - reject(new Error(`No redeem event found for account ${origin.address}`)); - } - //we should only find one event corresponding to the issue request - if (event.length != 1) { - reject(new Error('Inconsistent amount of redeem request events for account')); - } - resolve(event[0]); + if (event.length == 0) { + throw new Error(`No redeem event found for account ${origin.address}`); + } + //we should only find one event corresponding to the issue request + if (event.length != 1) { + throw new Error('Inconsistent amount of redeem request events for account'); } - }) - .catch((error) => { - reject(new Error(`Failed to request redeem: ${error}`)); - }) - .finally(() => release()); - }); + result = event[0]; + } + }) + .catch((error) => { + throw new Error(`Failed to request redeem: ${error}`); + }) + .finally(() => release()); + + return result; } // We first check if dispatchError is of type "module", From ce670327a3553d9ce09c6468d957c5f5fc5bde74 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Tue, 16 Apr 2024 19:58:25 +0200 Subject: [PATCH 2/3] Fix missing hook deps --- src/pages/landing/index.tsx | 41 ++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/pages/landing/index.tsx b/src/pages/landing/index.tsx index 6db4fd92..14854a1f 100644 --- a/src/pages/landing/index.tsx +++ b/src/pages/landing/index.tsx @@ -14,6 +14,7 @@ import { import { executeSpacewalkRedeem } from '../../services/polkadot'; import Sep24 from '../../components/Sep24Component'; import { TOML_FILE_URL } from '../../constants/constants'; +import { useCallback } from 'preact/compat'; enum OperationStatus { Idle, @@ -84,19 +85,27 @@ function Landing() { setStatus(OperationStatus.Redeeming); }; - const executeRedeem = async (sepResult: ISep24Result) => { - try { - await executeSpacewalkRedeem(getEphemeralKeys().publicKey(), sepResult.amount, secrets!.pendulumSecret, addEvent); - } catch (error) { - return; - } - addEvent('Redeem process completed, executing offramp transaction', EventStatus.Waiting); + const executeRedeem = useCallback( + async (sepResult: ISep24Result) => { + try { + await executeSpacewalkRedeem( + getEphemeralKeys().publicKey(), + sepResult.amount, + secrets!.pendulumSecret, + addEvent, + ); + } catch (error) { + return; + } + addEvent('Redeem process completed, executing offramp transaction', EventStatus.Waiting); - //this will trigger finalizeOfframp - setStatus(OperationStatus.FinalizingOfframp); - }; + //this will trigger finalizeOfframp + setStatus(OperationStatus.FinalizingOfframp); + }, + [secrets], + ); - const finalizeOfframp = async () => { + const finalizeOfframp = useCallback(async () => { try { await submitOfframpTransaction(secrets!.stellarFundingSecret, stellarOperations!.offrampingTransaction, addEvent); } catch (error) { @@ -112,7 +121,7 @@ function Landing() { // and successful // This will not affect the user await cleanupStellarEphemeral(secrets!.stellarFundingSecret, stellarOperations!.mergeAccountTransaction, addEvent); - }; + }, [secrets, stellarOperations]); const addEvent = (message: string, status: EventStatus) => { setEvents((prevEvents) => [...prevEvents, { value: message, status }]); @@ -142,19 +151,19 @@ function Landing() { } }; - initiate(); + initiate().catch(console.error); }, []); useEffect(() => { switch (status) { case OperationStatus.Redeeming: - executeRedeem(sep24Result!); + executeRedeem(sep24Result!).catch(console.error); return; case OperationStatus.FinalizingOfframp: - finalizeOfframp(); + finalizeOfframp().catch(console.error); return; } - }, [status]); // eslint-disable-line react-hooks/exhaustive-deps + }, [status, executeRedeem, finalizeOfframp, sep24Result]); return (
From b57d0a15e41a21d74ab74e56b7c45b75e59cd052 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Wed, 17 Apr 2024 10:23:32 +0200 Subject: [PATCH 3/3] Fix bad refactoring of promise --- src/services/polkadot/eventParsers.tsx | 2 + src/services/polkadot/spacewalk.tsx | 85 +++++++++++++------------- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/src/services/polkadot/eventParsers.tsx b/src/services/polkadot/eventParsers.tsx index b23aecef..90ace7a3 100644 --- a/src/services/polkadot/eventParsers.tsx +++ b/src/services/polkadot/eventParsers.tsx @@ -1,5 +1,7 @@ import { stellarHexToPublic, hexToString } from './convert.js'; +export type SpacewalkRedeemRequestEvent = ReturnType; + export function parseEventRedeemRequest(event: any) { const rawEventData = JSON.parse(event.event.data.toString()); const mappedData = { diff --git a/src/services/polkadot/spacewalk.tsx b/src/services/polkadot/spacewalk.tsx index 30771330..98872e23 100644 --- a/src/services/polkadot/spacewalk.tsx +++ b/src/services/polkadot/spacewalk.tsx @@ -1,7 +1,7 @@ import { Keyring } from '@polkadot/api'; import { Asset } from 'stellar-sdk'; import { stellarHexToPublic } from './convert'; -import { parseEventRedeemRequest } from './eventParsers'; +import { parseEventRedeemRequest, SpacewalkRedeemRequestEvent } from './eventParsers'; import { Api } from './polkadotApi'; import { SpacewalkPrimitivesVaultId } from '@polkadot/types/lookup'; import { Buffer } from 'buffer'; @@ -82,55 +82,52 @@ export class VaultService { const release = await this.api!.mutex.lock(origin.address); const nonce = await this.api!.api.rpc.system.accountNextIndex(origin.publicKey); - // The result will be assigned in the callback - let result = undefined; + return new Promise((resolve, reject) => + this.api!.api.tx.redeem.requestRedeem(amount, stellarPkBytes, this.vaultId!) + .signAndSend(origin, { nonce }, (submissionResult: ISubmittableResult) => { + const { status, events, dispatchError } = submissionResult; - await this.api!.api.tx.redeem.requestRedeem(amount, stellarPkBytes, this.vaultId!) - .signAndSend(origin, { nonce }, (submissionResult: ISubmittableResult) => { - const { status, events, dispatchError } = submissionResult; - - if (status.isFinalized) { - console.log( - `Requested redeem of ${amount} for vault ${prettyPrintVaultId(this.vaultId)} with status ${status.type}`, - ); - - // Try to find a 'system.ExtrinsicFailed' event - const systemExtrinsicFailedEvent = events.find((record) => { - return record.event.section === 'system' && record.event.method === 'ExtrinsicFailed'; - }); - - if (dispatchError) { - throw this.handleDispatchError(dispatchError, systemExtrinsicFailedEvent, 'Redeem Request'); - } - //find all redeem request events and filter the one that matches the requester - const redeemEvents = events.filter((event) => { - return ( - event.event.section.toLowerCase() === 'redeem' && event.event.method.toLowerCase() === 'requestredeem' + if (status.isFinalized) { + console.log( + `Requested redeem of ${amount} for vault ${prettyPrintVaultId(this.vaultId)} with status ${status.type}`, ); - }); - const event = redeemEvents - .map((event) => parseEventRedeemRequest(event)) - .filter((event) => { - return event.redeemer === origin.address; + // Try to find a 'system.ExtrinsicFailed' event + const systemExtrinsicFailedEvent = events.find((record) => { + return record.event.section === 'system' && record.event.method === 'ExtrinsicFailed'; }); - if (event.length == 0) { - throw new Error(`No redeem event found for account ${origin.address}`); - } - //we should only find one event corresponding to the issue request - if (event.length != 1) { - throw new Error('Inconsistent amount of redeem request events for account'); + if (dispatchError) { + reject(this.handleDispatchError(dispatchError, systemExtrinsicFailedEvent, 'Redeem Request')); + } + //find all redeem request events and filter the one that matches the requester + const redeemEvents = events.filter((event) => { + return ( + event.event.section.toLowerCase() === 'redeem' && event.event.method.toLowerCase() === 'requestredeem' + ); + }); + + const event = redeemEvents + .map((event) => parseEventRedeemRequest(event)) + .filter((event) => { + return event.redeemer === origin.address; + }); + + if (event.length == 0) { + reject(new Error(`No redeem event found for account ${origin.address}`)); + } + //we should only find one event corresponding to the issue request + if (event.length != 1) { + reject(new Error('Inconsistent amount of redeem request events for account')); + } + resolve(event[0]); } - result = event[0]; - } - }) - .catch((error) => { - throw new Error(`Failed to request redeem: ${error}`); - }) - .finally(() => release()); - - return result; + }) + .catch((error) => { + reject(new Error(`Failed to request redeem: ${error}`)); + }) + .finally(() => release()), + ); } // We first check if dispatchError is of type "module",