@@ -10,11 +10,12 @@ import type {
1010 TokenRawAmount ,
1111 UniversalChainId ,
1212} from "@unionlabs/sdk/schema"
13- import { Effect , Match , Option , ParseResult , pipe } from "effect"
13+ import { Effect , Either , flow , Match , Option , ParseResult , pipe } from "effect"
1414import * as A from "effect/Array"
1515import type { NoSuchElementException , UnknownException } from "effect/Cause"
1616import * as S from "effect/Schema"
1717import { fromHex , isHex } from "viem"
18+ import { GenericFlowError } from "../../errors"
1819import type { TransferArgs } from "./check-filling"
1920
2021export type Intent = {
@@ -51,17 +52,35 @@ export const createContext = Effect.fn((
5152 args : TransferArgs ,
5253) : Effect . Effect <
5354 TransferContext ,
54- NoSuchElementException | ParseResult . ParseError | UnknownException ,
55+ ParseResult . ParseError | GenericFlowError | UnknownException | NoSuchElementException ,
5556 never
5657> =>
5758 Effect . gen ( function * ( ) {
5859 console . debug ( "[createContext] args:" , args )
5960
61+ const baseAmount = yield * parseBaseAmount ( args . baseAmount ) . pipe (
62+ Effect . mapError ( ( cause ) =>
63+ new GenericFlowError ( {
64+ message : "Could not parse base amount" ,
65+ cause,
66+ } )
67+ ) ,
68+ )
69+
70+ const quoteAmount = yield * parseBaseAmount ( args . quoteAmount ) . pipe (
71+ Effect . mapError ( ( cause ) =>
72+ new GenericFlowError ( {
73+ message : "Could not parse quote amount" ,
74+ cause,
75+ } )
76+ ) ,
77+ )
78+
6079 const sendOrder = yield * TokenOrder . make ( {
61- baseAmount : Option . getOrThrow ( parseBaseAmount ( args . baseAmount ) ) ,
80+ baseAmount,
6281 baseToken : args . baseToken ,
6382 quoteToken : args . quoteToken ,
64- quoteAmount : Option . getOrThrow ( parseBaseAmount ( args . quoteAmount ) ) ,
83+ quoteAmount,
6584 destination : args . destinationChain ,
6685 receiver : args . receiver ,
6786 sender : args . sender ,
@@ -78,43 +97,67 @@ export const createContext = Effect.fn((
7897 } )
7998
8099 // on destination chain tokens, find wrappings[] such that one exists where unwrapped_denom matches basetoken and unwrapped_chain and wrapped_chain universal ids match
81- const encodedFeeBaseToken = S . encodeSync ( Token . AnyFromEncoded ( args . sourceChain . rpc_type ) ) (
100+ const encodedFeeBaseToken = yield * pipe (
82101 args . fee . baseToken ,
102+ S . encode ( Token . AnyFromEncoded ( args . sourceChain . rpc_type ) ) ,
103+ Effect . mapError ( ( cause ) =>
104+ new GenericFlowError ( {
105+ message : "Could not base token" ,
106+ cause,
107+ } )
108+ ) ,
83109 )
84110
85- const shouldIncludeFees = shouldChargeFees ( args . fee , uiStore . edition , args . sourceChain )
111+ const shouldIncludeFees = shouldChargeFees (
112+ args . fee ,
113+ uiStore . edition ,
114+ args . sourceChain ,
115+ args . destinationChain ,
116+ )
117+
118+ console . log ( { shouldIncludeFees } )
86119
87120 const produceBatch = Effect . gen ( function * ( ) {
88121 if ( shouldIncludeFees ) {
89- const feeQuoteToken = yield * maybeFeeQuoteToken . pipe (
90- Option . orElse ( ( ) =>
122+ const feeQuoteToken = yield * Effect . if ( args . baseToken . address === "au" , {
123+ onTrue : ( ) => Effect . succeed ( args . quoteToken ) ,
124+ onFalse : ( ) =>
91125 pipe (
92- tokensStore . getData ( args . destinationChain . universal_chain_id ) ,
93- Option . flatMap (
94- A . findFirst ( ( token ) =>
95- A . filter ( token . wrapping , ( x ) =>
96- x . unwrapped_denom === encodedFeeBaseToken
97- && x . unwrapped_chain . universal_chain_id === args . sourceChain . universal_chain_id
98- && x . wrapped_chain . universal_chain_id
99- === args . destinationChain . universal_chain_id )
100- . length
101- === 1
102- ) ,
126+ maybeFeeQuoteToken ,
127+ Either . fromOption ( ( ) => "No fee quote token" ) ,
128+ Either . orElse ( ( ) =>
129+ pipe (
130+ tokensStore . getData ( args . destinationChain . universal_chain_id ) ,
131+ Either . fromOption ( ( ) => "No matching token in token store" ) ,
132+ Either . flatMap ( flow (
133+ A . findFirst ( ( token ) =>
134+ A . filter ( token . wrapping , ( x ) =>
135+ x . unwrapped_denom === encodedFeeBaseToken
136+ && x . unwrapped_chain . universal_chain_id
137+ === args . sourceChain . universal_chain_id
138+ && x . wrapped_chain . universal_chain_id
139+ === args . destinationChain . universal_chain_id )
140+ . length
141+ === 1
142+ ) ,
143+ Either . fromOption ( ( ) =>
144+ `No quote token wrapping found for ${ args . destinationChain . universal_chain_id } given ${ args . fee . baseToken } `
145+ ) ,
146+ ) ) ,
147+ Either . map ( x => x . denom ) ,
148+ Either . flatMap ( ( raw ) =>
149+ S . decodeEither ( Token . AnyFromEncoded ( args . destinationChain . rpc_type ) ) ( raw )
150+ ) ,
151+ )
103152 ) ,
104- Option . map ( x => x . denom ) ,
105- Option . flatMap ( ( raw ) =>
106- S . decodeOption ( Token . AnyFromEncoded ( args . destinationChain . rpc_type ) ) ( raw )
153+ Effect . mapError ( ( cause ) =>
154+ new GenericFlowError ( {
155+ message : "Could not determine fee quote token" ,
156+ cause,
157+ } )
107158 ) ,
108- )
109- ) ,
110- Option . orElse ( ( ) => {
111- if ( args . baseToken . address === "au" ) {
112- return Option . some ( args . quoteToken )
113- }
114- console . error ( "Could not determine fee quote token." )
115- return Option . none ( )
116- } ) ,
117- )
159+ ) ,
160+ } )
118161
119162 const feeOrder = yield * TokenOrder . make ( {
120163 baseAmount : args . fee . baseAmount ,
@@ -130,7 +173,8 @@ export const createContext = Effect.fn((
130173 version : args . version ,
131174 } )
132175
133- return Batch . make ( [ sendOrder , feeOrder ] ) . pipe (
176+ return pipe (
177+ Batch . make ( [ sendOrder , feeOrder ] ) ,
134178 Batch . optimize ,
135179 )
136180 } else {
@@ -150,19 +194,17 @@ export const createContext = Effect.fn((
150194 Option . some ,
151195 )
152196
153- const ctx = yield * parseBaseAmount ( args . baseAmount ) . pipe (
154- Option . flatMap ( ( baseAmount ) => {
155- const intents = createIntents ( args , baseAmount )
156-
157- return intents . length > 0
197+ const ctx = yield * pipe (
198+ createIntents ( args , baseAmount ) ,
199+ ( intents ) =>
200+ intents . length > 0
158201 ? Option . some ( {
159202 intents,
160203 allowances : Option . none ( ) ,
161204 request : Option . none ( ) ,
162205 message : Option . none ( ) ,
163206 } )
164- : Option . none ( )
165- } ) ,
207+ : Option . none ( ) ,
166208 )
167209
168210 return {
@@ -173,7 +215,12 @@ export const createContext = Effect.fn((
173215)
174216
175217const createIntents = ( args : TransferArgs , baseAmount : TokenRawAmount ) : Intent [ ] => {
176- const shouldIncludeFees = shouldChargeFees ( args . fee , uiStore . edition , args . sourceChain )
218+ const shouldIncludeFees = shouldChargeFees (
219+ args . fee ,
220+ uiStore . edition ,
221+ args . sourceChain ,
222+ args . destinationChain ,
223+ )
177224 const baseIntent = createBaseIntent ( args , baseAmount )
178225
179226 return Match . value ( args . sourceChain . rpc_type ) . pipe (
@@ -241,13 +288,25 @@ const createBaseIntent = (
241288} )
242289
243290// Fee strategy: BTC edition only charges fees when going FROM Babylon
244- const shouldChargeFees = ( fee : FeeIntent , edition : string , sourceChain : Chain ) : boolean => {
291+ const shouldChargeFees = (
292+ fee : FeeIntent ,
293+ edition : string ,
294+ sourceChain : Chain ,
295+ destinationChain : Chain ,
296+ ) : boolean => {
245297 if ( fee . baseAmount === 0n ) {
246298 return false
247299 }
248300 if ( sourceChain . testnet ) {
249301 return true
250302 }
303+ // skip fees babylon to bsc for now
304+ if (
305+ destinationChain . universal_chain_id === "bsc.56"
306+ && sourceChain . universal_chain_id === "babylon.bbn-1"
307+ ) {
308+ return false
309+ }
251310 return sourceChain . universal_chain_id === "babylon.bbn-1"
252311}
253312
0 commit comments