11import {
22 type CurrencyQueryOptions ,
33 DEFAULT_QUERY_OPTIONS ,
4- errAsync ,
54 ValidationError ,
65} from '@aave/client' ;
76import {
87 cancelSwap ,
8+ preparePositionSwap ,
99 prepareSwap ,
1010 prepareSwapCancel ,
11+ supplySwapQuote ,
1112 swap ,
1213 swapQuote ,
1314 swapStatus ,
1415} from '@aave/client/actions' ;
15- import type {
16- CancelError ,
17- SigningError ,
18- TimeoutError ,
19- TransactionError ,
16+ import {
17+ type CancelError ,
18+ type SigningError ,
19+ type TimeoutError ,
20+ type TransactionError ,
2021 UnexpectedError ,
2122} from '@aave/core' ;
2223import type {
2324 InsufficientBalanceError ,
2425 PaginatedUserSwapsResult ,
26+ PositionSwapApproval ,
27+ PrepareSupplySwapRequest ,
2528 PrepareSwapCancelRequest ,
26- SwapByIntentTypedData ,
2729 SwapByIntentWithApprovalRequired ,
2830 SwapCancelled ,
2931 SwapExecutionPlan ,
@@ -34,24 +36,28 @@ import type {
3436 UserSwapsRequest ,
3537} from '@aave/graphql' ;
3638import {
37- type CancelSwapTypedData ,
3839 type ERC20PermitSignature ,
40+ type PreparePositionSwapRequest ,
3941 type PrepareTokenSwapRequest ,
4042 type SwapApprovalRequired ,
43+ type SwapByIntent ,
4144 SwappableTokensQuery ,
4245 type SwappableTokensRequest ,
4346 SwapQuoteQuery ,
47+ type SwapTypedData ,
4448 type Token ,
4549 type TransactionRequest ,
4650 UserSwapsQuery ,
4751} from '@aave/graphql' ;
4852import {
4953 invariant ,
54+ isSignature ,
5055 type NullishDeep ,
5156 okAsync ,
5257 type Prettify ,
53- type ResultAsync ,
58+ ResultAsync ,
5459 ResultAwareError ,
60+ type Signature ,
5561} from '@aave/types' ;
5662import { useCallback } from 'react' ;
5763import { useAaveClient } from './context' ;
@@ -404,22 +410,179 @@ export function useUserSwaps({
404410 } ) ;
405411}
406412
407- export type UseSwapTokensRequest = Prettify <
413+ // ------------------------------------------------------------
414+
415+ export type SwapHandlerOptions = {
416+ cancel : CancelOperation ;
417+ } ;
418+
419+ // ------------------------------------------------------------
420+
421+ /**
422+ * @experimental
423+ */
424+ export type UseSwapSignerRequest = TransactionRequest ; // TODO add other types to this union
425+
426+ /**
427+ * @experimental
428+ */
429+ export type SwapSignerError = CancelError | SigningError | UnexpectedError ;
430+
431+ /**
432+ * @experimental
433+ */
434+ export type UseSwapSignerResult = UseAsyncTask <
435+ UseSwapSignerRequest ,
436+ PendingTransaction | Signature ,
437+ SwapSignerError
438+ > ;
439+
440+ // ------------------------------------------------------------
441+
442+ export type PositionSwapPlan = PositionSwapApproval | SwapByIntent ;
443+
444+ export type PositionSwapHandler = (
445+ plan : PositionSwapPlan ,
446+ options : SwapHandlerOptions ,
447+ ) => ResultAsync < PendingTransaction | Signature , SwapSignerError > ;
448+
449+ export type PositionSwapValue = {
450+ quote ?: SwapQuote ;
451+ } ;
452+
453+ // ------------------------------------------------------------
454+
455+ /**
456+ * @experimental
457+ */
458+ export type UseSupplySwapRequest = Prettify <
459+ PrepareSupplySwapRequest & CurrencyQueryOptions
460+ > ;
461+
462+ /**
463+ * @experimental
464+ */
465+ export function useSupplySwap (
466+ handler : PositionSwapHandler ,
467+ ) : UseAsyncTask <
468+ PrepareSupplySwapRequest ,
469+ SwapReceipt ,
470+ | SwapSignerError
471+ | SendTransactionError
472+ | PendingTransactionError
473+ | ValidationError < InsufficientBalanceError >
474+ > {
475+ const client = useAaveClient ( ) ;
476+
477+ const processApprovals = useCallback (
478+ ( approvals : PositionSwapApproval [ ] ) => {
479+ return ResultAsync . combine (
480+ approvals . map ( ( approval ) =>
481+ handler ( approval , { cancel } ) . map ( ( value ) => ( {
482+ __typename : approval . __typename ,
483+ value,
484+ } ) ) ,
485+ ) ,
486+ ) ;
487+ } ,
488+ [ handler ] ,
489+ ) ;
490+
491+ return useAsyncTask (
492+ ( {
493+ currency = DEFAULT_QUERY_OPTIONS . currency ,
494+ ...request
495+ } : UseSupplySwapRequest ) => {
496+ return supplySwapQuote ( client , request , { currency } ) . andThen (
497+ ( result ) => {
498+ invariant (
499+ result . __typename === 'PositionSwapByIntentApprovalsRequired' ,
500+ 'Unsupported swap plan' ,
501+ ) ;
502+
503+ return processApprovals ( result . approvals )
504+ . map (
505+ ( results ) : PreparePositionSwapRequest =>
506+ results . reduce (
507+ (
508+ request : PreparePositionSwapRequest ,
509+ { __typename, value } ,
510+ ) => {
511+ if ( value ) {
512+ switch ( __typename ) {
513+ case 'PositionSwapAdapterContractApproval' :
514+ request . adapterContractSignature = isSignature ( value )
515+ ? value
516+ : null ;
517+ break ;
518+ case 'PositionSwapPositionManagerApproval' :
519+ request . positionManagerSignature = isSignature ( value )
520+ ? value
521+ : null ;
522+ break ;
523+ }
524+ }
525+ return request ;
526+ } ,
527+ {
528+ quoteId : result . quote . quoteId ,
529+ adapterContractSignature : null ,
530+ positionManagerSignature : null ,
531+ } ,
532+ ) ,
533+ )
534+ . andThen ( ( request ) =>
535+ preparePositionSwap ( client , request , { currency } ) ,
536+ )
537+ . andThen ( ( result ) => {
538+ invariant (
539+ result . __typename === 'SwapByIntent' ,
540+ `Unsupported swap plan: ${ result . __typename } . Upgrade to a newer version of the @aave/react package.` ,
541+ ) ;
542+
543+ return handler ( result , { cancel } ) ;
544+ } )
545+ . andThen ( ( signature ) => {
546+ invariant ( isSignature ( signature ) , 'Invalid signature' ) ;
547+
548+ return swap ( client , {
549+ intent : {
550+ quoteId : result . quote . quoteId ,
551+ signature,
552+ } ,
553+ } ) ;
554+ } )
555+ . andThen ( ( plan ) => {
556+ switch ( plan . __typename ) {
557+ case 'SwapReceipt' :
558+ return okAsync ( plan ) ;
559+ case 'InsufficientBalanceError' :
560+ return ValidationError . fromGqlNode ( plan ) . asResultAsync ( ) ;
561+ default :
562+ return UnexpectedError . from ( plan ) . asResultAsync ( ) ;
563+ }
564+ } ) ;
565+ } ,
566+ ) ;
567+ } ,
568+ [ client , handler , processApprovals ] ,
569+ ) ;
570+ }
571+
572+ // ------------------------------------------------------------
573+
574+ export type UseTokenSwapRequest = Prettify <
408575 PrepareTokenSwapRequest & CurrencyQueryOptions
409576> ;
410577
411- export type SwapIntent =
412- | SwapByIntentTypedData
578+ export type TokenSwapPlan =
579+ | SwapTypedData
413580 | SwapByIntentWithApprovalRequired
414581 | SwapTransactionRequest
415582 | SwapApprovalRequired ;
416583
417- export type SwapHandlerOptions = {
418- cancel : CancelOperation ;
419- } ;
420-
421- export type SwapHandler = (
422- intent : SwapIntent ,
584+ export type TokenSwapHandler = (
585+ plan : TokenSwapPlan ,
423586 options : SwapHandlerOptions ,
424587) => ResultAsync <
425588 ERC20PermitSignature | SwapReceipt ,
@@ -445,9 +608,9 @@ function isERC20PermitSignature(
445608 * const [sendTransaction, sending] = useSendTransaction(wallet);
446609 * const [signSwapByIntentWith, signing] = useSignSwapByIntentWith(wallet);
447610 *
448- * const [swap, swapping] = useSwapTokens ((plan) => {
611+ * const [swap, swapping] = useTokenSwap ((plan) => {
449612 * switch (plan.__typename) {
450- * case 'SwapByIntentTypedData ':
613+ * case 'SwapTypedData ':
451614 * return signSwapByIntentWith(plan);
452615 *
453616 * case 'SwapApprovalRequired':
@@ -478,10 +641,10 @@ function isERC20PermitSignature(
478641 * // result.value: SwapReceipt
479642 * ```
480643 */
481- export function useSwapTokens (
482- handler : SwapHandler ,
644+ export function useTokenSwap (
645+ handler : TokenSwapHandler ,
483646) : UseAsyncTask <
484- PrepareTokenSwapRequest ,
647+ UseTokenSwapRequest ,
485648 SwapReceipt ,
486649 | SendTransactionError
487650 | PendingTransactionError
@@ -517,7 +680,7 @@ export function useSwapTokens(
517680 return okAsync ( plan . originalTransaction . orderReceipt ) ;
518681 } ) ;
519682 case 'InsufficientBalanceError' :
520- return errAsync ( ValidationError . fromGqlNode ( plan ) ) ;
683+ return ValidationError . fromGqlNode ( plan ) . asResultAsync ( ) ;
521684 case 'SwapReceipt' :
522685 return okAsync ( plan ) ;
523686 }
@@ -529,7 +692,7 @@ export function useSwapTokens(
529692 ( {
530693 currency = DEFAULT_QUERY_OPTIONS . currency ,
531694 ...request
532- } : UseSwapTokensRequest ) =>
695+ } : UseTokenSwapRequest ) =>
533696 prepareSwap ( client , request , { currency } ) . andThen ( ( preparePlan ) => {
534697 switch ( preparePlan . __typename ) {
535698 case 'SwapByTransaction' :
@@ -575,15 +738,15 @@ export function useSwapTokens(
575738 } ) ;
576739
577740 case 'InsufficientBalanceError' :
578- return errAsync ( ValidationError . fromGqlNode ( preparePlan ) ) ;
741+ return ValidationError . fromGqlNode ( preparePlan ) . asResultAsync ( ) ;
579742 }
580743 } ) ,
581744 [ client , handler , executeSwap ] ,
582745 ) ;
583746}
584747
585748export type CancelSwapHandler = (
586- data : CancelSwapTypedData | TransactionRequest ,
749+ data : SwapTypedData | TransactionRequest ,
587750) => ResultAsync <
588751 ERC20PermitSignature | PendingTransaction ,
589752 SigningError | UnexpectedError
@@ -609,12 +772,12 @@ export type CancelSwapError =
609772 * const [sendTransaction] = useSendTransaction(wallet);
610773 * const [signSwapCancelWith] = useSignSwapCancelWith(wallet);
611774 *
612- * const [cancelSwap, {loading, error}] = useCancelSwap((plan: CancelSwapTypedData | TransactionRequest) => {
775+ * const [cancelSwap, {loading, error}] = useCancelSwap((plan: SwapTypedData | TransactionRequest) => {
613776 * switch (plan.__typename) {
614777 * case 'TransactionRequest':
615778 * return sendTransaction(plan);
616779 *
617- * case 'CancelSwapTypedData ':
780+ * case 'SwapTypedData ':
618781 * return signSwapCancelWith(plan);
619782 * }
620783 * });
@@ -670,9 +833,9 @@ export function useCancelSwap(
670833 if ( status . __typename === 'SwapCancelled' ) {
671834 return okAsync ( status ) ;
672835 }
673- return errAsync (
674- new CannotCancelSwapError ( 'Failed to cancel swap' ) ,
675- ) ;
836+ return new CannotCancelSwapError (
837+ 'Failed to cancel swap' ,
838+ ) . asResultAsync ( ) ;
676839 } )
677840 ) ;
678841 } ) ;
@@ -681,9 +844,9 @@ export function useCancelSwap(
681844 return okAsync ( status ) ;
682845
683846 default :
684- return errAsync (
685- new CannotCancelSwapError ( 'Swap cannot longer be cancelled' ) ,
686- ) ;
847+ return new CannotCancelSwapError (
848+ 'Swap cannot longer be cancelled' ,
849+ ) . asResultAsync ( ) ;
687850 }
688851 } ) ,
689852 [ client , handler ] ,
0 commit comments