4
4
package substrate
5
5
6
6
import (
7
+ "errors"
7
8
"fmt"
8
9
"math/big"
9
10
10
11
"github.com/ChainSafe/log15"
11
- events "github.com/centrifuge/chainbridge-substrate-events"
12
12
"github.com/centrifuge/chainbridge-utils/msg"
13
+ "github.com/centrifuge/go-substrate-rpc-client/v4/types"
14
+ "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec"
13
15
)
14
16
15
17
type eventName string
16
- type eventHandler func (interface {} , log15.Logger ) (msg.Message , error )
18
+ type eventHandler func (map [ string ] any , log15.Logger ) (msg.Message , error )
17
19
18
- const FungibleTransfer eventName = "FungibleTransfer"
19
- const NonFungibleTransfer eventName = "NonFungibleTransfer"
20
- const GenericTransfer eventName = "GenericTransfer"
20
+ const FungibleTransfer eventName = "ChainBridge. FungibleTransfer"
21
+ const NonFungibleTransfer eventName = "ChainBridge. NonFungibleTransfer"
22
+ const GenericTransfer eventName = "ChainBridge. GenericTransfer"
21
23
22
24
var Subscriptions = []struct {
23
25
name eventName
@@ -28,57 +30,250 @@ var Subscriptions = []struct {
28
30
{GenericTransfer , genericTransferHandler },
29
31
}
30
32
31
- func fungibleTransferHandler (evtI interface {} , log log15.Logger ) (msg.Message , error ) {
32
- evt , ok := evtI .(events. EventFungibleTransfer )
33
- if ! ok {
34
- return msg.Message {}, fmt . Errorf ( "failed to cast EventFungibleTransfer type" )
33
+ func fungibleTransferHandler (eventFields map [ string ] any , log log15.Logger ) (msg.Message , error ) {
34
+ chainID , err := getFieldValueAsType [types. U8 ]( "ChainId" , eventFields )
35
+ if err != nil {
36
+ return msg.Message {}, err
35
37
}
36
38
37
- resourceId := msg .ResourceId (evt .ResourceId )
38
- log .Info ("Got fungible transfer event!" , "destination" , evt .Destination , "resourceId" , resourceId .Hex (), "amount" , evt .Amount )
39
+ depositNonce , err := getFieldValueAsType [types.U64 ]("DepositNonce" , eventFields )
40
+ if err != nil {
41
+ return msg.Message {}, err
42
+ }
43
+
44
+ resID , err := getFieldValueAsSliceOfType [types.U8 ]("ResourceId" , eventFields )
45
+ if err != nil {
46
+ return msg.Message {}, err
47
+ }
48
+
49
+ resourceID , err := to32Bytes (resID )
50
+ if err != nil {
51
+ return msg.Message {}, err
52
+ }
53
+
54
+ amount , err := getU256 (eventFields )
55
+ if err != nil {
56
+ return msg.Message {}, err
57
+ }
58
+
59
+ recipient , err := getFieldValueAsByteSlice ("Vec<u8>" , eventFields )
60
+ if err != nil {
61
+ return msg.Message {}, err
62
+ }
63
+
64
+ log .Info ("Got fungible transfer event!" , "destination" , recipient , "resourceId" , fmt .Sprintf ("%x" , resourceID ), "amount" , amount )
39
65
40
66
return msg .NewFungibleTransfer (
41
67
0 , // Unset
42
- msg .ChainId (evt . Destination ),
43
- msg .Nonce (evt . DepositNonce ),
44
- evt . Amount .Int ,
45
- resourceId ,
46
- evt . Recipient ,
68
+ msg .ChainId (chainID ),
69
+ msg .Nonce (depositNonce ),
70
+ amount .Int ,
71
+ resourceID ,
72
+ recipient ,
47
73
), nil
48
74
}
49
75
50
- func nonFungibleTransferHandler (evtI interface {}, log log15.Logger ) (msg.Message , error ) {
51
- evt , ok := evtI .(events.EventNonFungibleTransfer )
52
- if ! ok {
53
- return msg.Message {}, fmt .Errorf ("failed to cast EventNonFungibleTransfer type" )
76
+ func nonFungibleTransferHandler (_ map [string ]any , log log15.Logger ) (msg.Message , error ) {
77
+ log .Warn ("Got non-fungible transfer event!" )
78
+
79
+ return msg.Message {}, errors .New ("non-fungible transfer not supported" )
80
+ }
81
+
82
+ func genericTransferHandler (eventFields map [string ]any , log log15.Logger ) (msg.Message , error ) {
83
+ chainID , err := getFieldValueAsType [types.U8 ]("ChainId" , eventFields )
84
+ if err != nil {
85
+ return msg.Message {}, err
54
86
}
55
87
56
- log .Info ("Got non-fungible transfer event!" , "destination" , evt .Destination , "resourceId" , evt .ResourceId )
88
+ depositNonce , err := getFieldValueAsType [types.U64 ]("DepositNonce" , eventFields )
89
+ if err != nil {
90
+ return msg.Message {}, err
91
+ }
57
92
58
- return msg .NewNonFungibleTransfer (
59
- 0 , // Unset
60
- msg .ChainId (evt .Destination ),
61
- msg .Nonce (evt .DepositNonce ),
62
- msg .ResourceId (evt .ResourceId ),
63
- big .NewInt (0 ).SetBytes (evt .TokenId [:]),
64
- evt .Recipient ,
65
- evt .Metadata ,
66
- ), nil
67
- }
93
+ resID , err := getFieldValueAsSliceOfType [types.U8 ]("ResourceId" , eventFields )
94
+ if err != nil {
95
+ return msg.Message {}, err
96
+ }
97
+
98
+ resourceID , err := to32Bytes (resID )
99
+ if err != nil {
100
+ return msg.Message {}, err
101
+ }
68
102
69
- func genericTransferHandler (evtI interface {}, log log15.Logger ) (msg.Message , error ) {
70
- evt , ok := evtI .(events.EventGenericTransfer )
71
- if ! ok {
72
- return msg.Message {}, fmt .Errorf ("failed to cast EventGenericTransfer type" )
103
+ metadata , err := getFieldValueAsByteSlice ("Vec<u8>" , eventFields )
104
+ if err != nil {
105
+ return msg.Message {}, err
73
106
}
74
107
75
- log .Info ("Got generic transfer event!" , "destination" , evt . Destination , "resourceId" , evt . ResourceId )
108
+ log .Info ("Got generic transfer event!" , "destination" , chainID , "resourceId" , fmt . Sprintf ( "%x" , resourceID ) )
76
109
77
110
return msg .NewGenericTransfer (
78
111
0 , // Unset
79
- msg .ChainId (evt . Destination ),
80
- msg .Nonce (evt . DepositNonce ),
81
- msg . ResourceId ( evt . ResourceId ) ,
82
- evt . Metadata ,
112
+ msg .ChainId (chainID ),
113
+ msg .Nonce (depositNonce ),
114
+ resourceID ,
115
+ metadata ,
83
116
), nil
84
117
}
118
+
119
+ func to32Bytes (array []types.U8 ) ([32 ]byte , error ) {
120
+ var res [32 ]byte
121
+
122
+ if len (array ) != 32 {
123
+ return res , errors .New ("array length mismatch" )
124
+ }
125
+
126
+ for i , item := range array {
127
+ res [i ] = byte (item )
128
+ }
129
+
130
+ return res , nil
131
+ }
132
+
133
+ func getFieldValueAsType [T any ](fieldName string , eventFields map [string ]any ) (T , error ) {
134
+ var t T
135
+
136
+ for name , value := range eventFields {
137
+ if name == fieldName {
138
+ if v , ok := value .(T ); ok {
139
+ return v , nil
140
+ }
141
+
142
+ return t , fmt .Errorf ("field type mismatch, expected %T, got %T" , t , value )
143
+ }
144
+ }
145
+
146
+ return t , fmt .Errorf ("field with name '%s' not found" , fieldName )
147
+ }
148
+
149
+ func getFieldValueAsSliceOfType [T any ](fieldName string , eventFields map [string ]any ) ([]T , error ) {
150
+ for name , value := range eventFields {
151
+ if name == fieldName {
152
+ value , ok := value .([]any )
153
+
154
+ if ! ok {
155
+ return nil , errors .New ("field value not an array" )
156
+ }
157
+
158
+ res , err := convertSliceToType [T ](value )
159
+
160
+ if err != nil {
161
+ return nil , err
162
+ }
163
+
164
+ return res , nil
165
+ }
166
+ }
167
+
168
+ return nil , fmt .Errorf ("field with name '%s' not found" , fieldName )
169
+ }
170
+
171
+ func getFieldValueAsByteSlice (fieldName string , eventFields map [string ]any ) ([]byte , error ) {
172
+ for name , value := range eventFields {
173
+ if name == fieldName {
174
+ value , ok := value .([]any )
175
+
176
+ if ! ok {
177
+ return nil , errors .New ("field value not an array" )
178
+ }
179
+
180
+ slice , err := convertSliceToType [types.U8 ](value )
181
+
182
+ if err != nil {
183
+ return nil , err
184
+ }
185
+
186
+ res , err := convertToByteSlice (slice )
187
+
188
+ if err != nil {
189
+ return nil , err
190
+ }
191
+
192
+ return res , nil
193
+ }
194
+ }
195
+
196
+ return nil , fmt .Errorf ("field with name '%s' not found" , fieldName )
197
+ }
198
+
199
+ func convertSliceToType [T any ](array []any ) ([]T , error ) {
200
+ res := make ([]T , 0 )
201
+
202
+ for _ , item := range array {
203
+ if v , ok := item .(T ); ok {
204
+ res = append (res , v )
205
+ continue
206
+ }
207
+
208
+ var t T
209
+
210
+ return nil , fmt .Errorf ("couldn't cast '%T' to '%T'" , item , t )
211
+ }
212
+
213
+ return res , nil
214
+ }
215
+
216
+ func convertToByteSlice (array []types.U8 ) ([]byte , error ) {
217
+ res := make ([]byte , 0 )
218
+
219
+ for _ , item := range array {
220
+ res = append (res , byte (item ))
221
+ }
222
+
223
+ return res , nil
224
+ }
225
+
226
+ func getU256 (eventFields map [string ]any ) (types.U256 , error ) {
227
+ for fieldName , fieldValue := range eventFields {
228
+ if fieldName != "primitive_types.U256.U256" {
229
+ continue
230
+ }
231
+
232
+ innerField , ok := fieldValue .(map [string ]any )
233
+ if ! ok {
234
+ return types .NewU256 (* big .NewInt (0 )), errors .New ("unexpected amount field structure" )
235
+ }
236
+
237
+ innerFieldVal , ok := innerField ["[u64; 4]" ]
238
+ if ! ok {
239
+ return types .NewU256 (* big .NewInt (0 )), errors .New ("amount field key not found" )
240
+ }
241
+
242
+ slice , ok := innerFieldVal .([]any )
243
+ if ! ok {
244
+ return types .NewU256 (* big .NewInt (0 )), errors .New ("inner field value not a slice" )
245
+ }
246
+
247
+ val , err := convertSliceToType [types.U64 ](slice )
248
+
249
+ if err != nil {
250
+ return types .NewU256 (* big .NewInt (0 )), err
251
+ }
252
+
253
+ if len (val ) != 4 {
254
+ return types .NewU256 (* big .NewInt (0 )), errors .New ("slice length mismatch" )
255
+ }
256
+
257
+ var r [4 ]types.U64
258
+
259
+ for i , item := range val {
260
+ r [i ] = item
261
+ }
262
+
263
+ encVal , err := codec .Encode (r )
264
+
265
+ if err != nil {
266
+ return types .NewU256 (* big .NewInt (0 )), errors .New ("couldn't encode amount val" )
267
+ }
268
+
269
+ var res types.U256
270
+
271
+ if err := codec .Decode (encVal , & res ); err != nil {
272
+ return types .NewU256 (* big .NewInt (0 )), errors .New ("couldn't decode amount" )
273
+ }
274
+
275
+ return res , nil
276
+ }
277
+
278
+ return types .NewU256 (* big .NewInt (0 )), errors .New ("amount field not found" )
279
+ }
0 commit comments