@@ -3,17 +3,20 @@ package fusionplus
33import (
44 "bytes"
55 "encoding/binary"
6+ "encoding/hex"
67 "fmt"
8+ "log"
79 "math/big"
10+ "strings"
811
12+ "github.com/1inch/1inch-sdk-go/internal/bytesiterator"
913 "github.com/1inch/1inch-sdk-go/internal/hexadecimal"
10- "github.com/1inch/1inch-sdk-go/sdk-clients/fusion"
1114 "github.com/1inch/1inch-sdk-go/sdk-clients/orderbook"
1215 "github.com/ethereum/go-ethereum/common"
1316)
1417
1518type EscrowExtension struct {
16- fusion. Extension
19+ ExtensionFusion
1720 HashLock * HashLock
1821 DstChainId float32
1922 DstToken common.Address
@@ -24,13 +27,13 @@ type EscrowExtension struct {
2427
2528func NewEscrowExtension (escrowParams EscrowExtensionParams ) (* EscrowExtension , error ) {
2629
27- extension , err := fusion . NewExtension (escrowParams .ExtensionParams )
30+ extension , err := NewExtensionFusion (escrowParams .ExtensionParamsFusion )
2831 if err != nil {
2932 return nil , err
3033 }
3134
3235 escrowExtension := & EscrowExtension {
33- Extension : * extension ,
36+ ExtensionFusion : * extension ,
3437 HashLock : escrowParams .HashLock ,
3538 DstChainId : escrowParams .DstChainId ,
3639 DstToken : escrowParams .DstToken ,
@@ -83,6 +86,132 @@ func (e *EscrowExtension) ConvertToOrderbookExtension() (*orderbook.Extension, e
8386 }, nil
8487}
8588
89+ // DecodeEscrowExtension decodes the input byte slice into an Extension struct using reflection.
90+ func DecodeEscrowExtension (data []byte ) (* EscrowExtension , error ) {
91+
92+ const extraDataCharacterLength = 320
93+
94+ // Create one extension that will be used for the Escrow extension data
95+ orderbookExtensionTruncated , err := orderbook .Decode (data )
96+ if err != nil {
97+ return nil , fmt .Errorf ("error decoding extension: %v" , err )
98+ }
99+
100+ // Remove the Fusion Plus Extension data before decoding
101+ orderbookExtensionTruncated .PostInteraction = orderbookExtensionTruncated .PostInteraction [:len (orderbookExtensionTruncated .PostInteraction )- extraDataCharacterLength ]
102+ fusionExtension , err := FromLimitOrderExtension (orderbookExtensionTruncated )
103+ if err != nil {
104+ return & EscrowExtension {}, fmt .Errorf ("error decoding escrow extension: %v" , err )
105+ }
106+
107+ // Create a second extension that will be used as a Fusion extension
108+ orderbookExtension , err := orderbook .Decode (data )
109+ if err != nil {
110+ return nil , fmt .Errorf ("error decoding extension: %v" , err )
111+ }
112+ extraDataRaw := orderbookExtension .PostInteraction [len (orderbookExtension .PostInteraction )- extraDataCharacterLength :]
113+ extraDataBytes , err := hex .DecodeString (extraDataRaw )
114+ if err != nil {
115+ return nil , fmt .Errorf ("error decoding escrow extension extra data: %v" , err )
116+ }
117+
118+ // Send the final 160 bytes of the postInteraction to decodeExtraData
119+ extraData , err := decodeExtraData (extraDataBytes )
120+ if err != nil {
121+ return nil , fmt .Errorf ("error decoding escrow extension extra data: %v" , err )
122+ }
123+
124+ return & EscrowExtension {
125+ ExtensionFusion : * fusionExtension ,
126+ HashLock : extraData .HashLock ,
127+ DstChainId : extraData .DstChainId ,
128+ DstToken : extraData .DstToken ,
129+ SrcSafetyDeposit : fmt .Sprintf ("%x" , extraData .SrcSafetyDeposit ),
130+ DstSafetyDeposit : fmt .Sprintf ("%x" , extraData .DstSafetyDeposit ),
131+ TimeLocks : * extraData .TimeLocks ,
132+ }, nil
133+ }
134+
135+ func decodeExtraData (data []byte ) (* EscrowExtraData , error ) {
136+ iter := bytesiterator .New (data )
137+ hashlockData , err := iter .NextUint256 ()
138+ if err != nil {
139+ log .Fatalf ("Failed to read first uint256: %v" , err )
140+ }
141+
142+ dstChainIdData , err := iter .NextUint256 ()
143+ if err != nil {
144+ log .Fatalf ("Failed to read second uint256: %v" , err )
145+ }
146+
147+ addressBig , err := iter .NextUint256 ()
148+ if err != nil {
149+ log .Fatalf ("Failed to read address: %v" , err )
150+ }
151+
152+ addressHex := strings .ToLower (common .BigToAddress (addressBig ).Hex ())
153+
154+ safetyDepositData , err := iter .NextUint256 ()
155+ if err != nil {
156+ log .Fatalf ("Failed to read third uint256: %v" , err )
157+ }
158+
159+ // Define a 128-bit mask (2^128 - 1)
160+ mask := new (big.Int )
161+ mask .Exp (big .NewInt (2 ), big .NewInt (128 ), nil ).Sub (mask , big .NewInt (1 ))
162+
163+ srcSafetyDeposit := new (big.Int ).And (safetyDepositData , mask )
164+ dstSafetyDeposit := new (big.Int ).Rsh (safetyDepositData , 128 )
165+
166+ timelocksData , err := iter .NextUint256 ()
167+ if err != nil {
168+ log .Fatalf ("Failed to read fourth uint256: %v" , err )
169+ }
170+
171+ timelocks , err := decodeTimeLocks (timelocksData )
172+ if err != nil {
173+ log .Fatalf ("Failed to decode timelocks: %v" , err )
174+ }
175+
176+ return & EscrowExtraData {
177+ HashLock : & HashLock {
178+ hashlockData .String (),
179+ },
180+ DstChainId : float32 (dstChainIdData .Uint64 ()),
181+ DstToken : common .HexToAddress (addressHex ),
182+ SrcSafetyDeposit : srcSafetyDeposit ,
183+ DstSafetyDeposit : dstSafetyDeposit ,
184+ TimeLocks : timelocks ,
185+ }, nil
186+ }
187+
188+ // decodeTimeLocks takes a *big.Int containing the raw hex data and returns a TimeLocks struct.
189+ func decodeTimeLocks (value * big.Int ) (* TimeLocks , error ) {
190+ tl := & TimeLocks {}
191+
192+ // Convert big.Int to byte slice
193+ data := value .Bytes ()
194+
195+ if len (data ) < 32 {
196+ padded := make ([]byte , 32 )
197+ copy (padded [32 - len (data ):], data )
198+ data = padded
199+ }
200+
201+ //TODO big.Int cannot preserve leading zeroes, so decoding the deploy time is impossible atm
202+
203+ // tl.DeployTime = float32(binary.BigEndian.Uint32((data[0:4])))
204+ tl .DstCancellation = float32 (binary .BigEndian .Uint32 ((data [4 :8 ])))
205+ tl .DstPublicWithdrawal = float32 (binary .BigEndian .Uint32 ((data [8 :12 ])))
206+ tl .DstWithdrawal = float32 (binary .BigEndian .Uint32 ((data [12 :16 ])))
207+ tl .SrcPublicCancellation = float32 (binary .BigEndian .Uint32 ((data [16 :20 ])))
208+ tl .SrcCancellation = float32 (binary .BigEndian .Uint32 ((data [20 :24 ])))
209+ tl .SrcPublicWithdrawal = float32 (binary .BigEndian .Uint32 ((data [24 :28 ])))
210+ tl .SrcWithdrawal = float32 (binary .BigEndian .Uint32 ((data [28 :32 ])))
211+
212+ return tl , nil
213+ }
214+
86215type EscrowExtraData struct {
87216 HashLock * HashLock
88217 DstChainId float32
0 commit comments