-
Notifications
You must be signed in to change notification settings - Fork 11
/
ibc_hook.go
168 lines (144 loc) · 5.76 KB
/
ibc_hook.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package keeper
import (
"context"
"fmt"
erc721types "github.com/UptickNetwork/evm-nft-convert/types"
erc20Types "github.com/UptickNetwork/uptick/x/erc20/types"
cw721Types "github.com/UptickNetwork/wasm-nft-convert/types"
// erc721Types "github.com/UptickNetwork/uptick/x/evmIBC/types"
erc721Types "github.com/UptickNetwork/evm-nft-convert/types"
"github.com/bianjieai/nft-transfer/types"
sdk "github.com/cosmos/cosmos-sdk/types"
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
"github.com/cosmos/ibc-go/v7/modules/core/exported"
"strings"
)
// OnRecvPacket processes a cross chain fungible token transfer. If the
// convertType 0:erc721 1:cw721
func (k Keeper) OnRecvPacket(
ctx sdk.Context,
packet channeltypes.Packet,
receiver string,
convertType uint) exported.Acknowledgement {
fmt.Printf("xxl OnRecvPacket 0001 \n")
k.Logger(ctx).Info("OnRecvPacket ", "convertType", convertType)
event := &erc20Types.EventIBCERC20{
Status: erc20Types.STATUS_UNKNOWN,
Message: "",
Sequence: packet.Sequence,
SourceChannel: packet.SourceChannel,
DestinationChannel: packet.DestinationChannel,
}
cctx, write := ctx.CacheContext()
var data types.NonFungibleTokenPacketData
if err := types.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil {
event.Status = erc20Types.STATUS_FAILED
event.Message = err.Error()
_ = ctx.EventManager().EmitTypedEvent(event)
return nil
}
// add the prefix class check for the case of class id
var voucherClassID string
if types.IsAwayFromOrigin(packet.GetSourcePort(), packet.GetSourceChannel(), data.ClassId) {
voucherClassID = k.GetVoucherClassID(packet.GetDestPort(), packet.GetDestChannel(), data.ClassId)
} else {
voucherClassID, _ = types.RemoveClassPrefix(packet.GetSourcePort(), packet.GetSourceChannel(), data.ClassId)
}
k.Logger(ctx).Info("OnRecvPacket ", "voucherClassID", voucherClassID)
// use cctx to ConvertCoin
context := sdk.WrapSDKContext(cctx)
var err error
if convertType == 0 {
err = k.ConvertNFTFromErc721(context, voucherClassID, data.TokenIds, receiver)
} else if convertType == 1 {
err = k.ConvertNFTFromCw721(context, voucherClassID, data.TokenIds, receiver)
}
if err != nil {
event.Status = erc20Types.STATUS_FAILED
event.Message = err.Error()
k.Logger(ctx).Error("OnRecvPacket ", "err ", err.Error())
_ = ctx.EventManager().EmitTypedEvent(event)
return nil
}
write()
ctx.EventManager().EmitEvents(cctx.EventManager().Events())
event.Status = erc20Types.STATUS_SUCCESS
_ = ctx.EventManager().EmitTypedEvent(event)
k.Logger(ctx).Info("OnRecvPacket ", "finish OK")
return nil
}
func (k Keeper) ConvertNFTFromErc721(context context.Context, voucherClassID string, tokenIds []string, receiver string) error {
fmt.Printf("xxl 001 ConvertNFTFromErc721 \n")
msg := erc721types.MsgConvertNFT{
EvmContractAddress: "",
EvmTokenIds: nil,
ClassId: voucherClassID,
CosmosTokenIds: tokenIds,
CosmosSender: erc721Types.AccModuleAddress.String(),
EvmReceiver: receiver,
}
fmt.Printf("xxl 002 ConvertNFTFromErc721 msg %v:\n", msg)
_, err := k.erc721keeper.ConvertNFT(context, &msg)
if err != nil {
return err
}
return nil
}
func (k Keeper) ConvertNFTFromCw721(context context.Context, voucherClassID string, tokenIds []string, receiver string) error {
msg := cw721Types.MsgConvertNFT{
ClassId: voucherClassID,
NftIds: tokenIds,
Receiver: receiver,
Sender: erc721Types.AccModuleAddress.String(),
ContractAddress: "",
TokenIds: nil,
}
_, err := k.cw721Keeper.ConvertNFT(context, &msg)
if err != nil {
return err
}
return nil
}
// OnAcknowledgementPacket responds to the success or failure of a packet
// acknowledgement written on the receiving chain. If the acknowledgement
// was a success then nothing occurs. If the acknowledgement failed, then
// the sender is refunded their tokens using the refundPacketToken function.
func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Packet, data types.NonFungibleTokenPacketData, ack channeltypes.Acknowledgement) error {
switch ack.Response.(type) {
case *channeltypes.Acknowledgement_Error:
if strings.Contains(data.Memo, erc721Types.TransferERC721Memo) {
data.ClassId = k.getRefundClassId(packet, data)
k.RefundPacketToken(ctx, data)
} else if strings.Contains(data.Memo, cw721Types.TransferCW721Memo) {
data.ClassId = k.getRefundClassId(packet, data)
k.cw721Keeper.RefundPacketToken(ctx, data)
}
default:
// the acknowledgement succeeded on the receiving chain so nothing
// needs to be executed and no error needs to be returned
}
return nil
}
// OnTimeoutPacket refunds the sender since the original packet sent was
// never received and has been timed out.
func (k Keeper) OnTimeoutPacket(ctx sdk.Context, packet channeltypes.Packet, data types.NonFungibleTokenPacketData) error {
if strings.Contains(data.Memo, erc721Types.TransferERC721Memo) {
data.ClassId = k.getRefundClassId(packet, data)
k.RefundPacketToken(ctx, data)
} else if strings.Contains(data.Memo, cw721Types.TransferCW721Memo) {
data.ClassId = k.getRefundClassId(packet, data)
k.cw721Keeper.RefundPacketToken(ctx, data)
}
return nil
}
func (k Keeper) getRefundClassId(packet channeltypes.Packet, data types.NonFungibleTokenPacketData) string {
var voucherClassID string
if strings.Contains(data.ClassId, "nft-transfer/") {
// if types.IsAwayFromOrigin(packet.GetSourcePort(), packet.GetSourceChannel(), data.ClassId) {
orgClass, _ := types.RemoveClassPrefix(packet.GetSourcePort(), packet.GetSourceChannel(), data.ClassId)
voucherClassID = k.GetVoucherClassID(packet.GetSourcePort(), packet.GetSourceChannel(), orgClass)
} else {
voucherClassID = data.ClassId
}
return voucherClassID
}