/
contract.go
200 lines (173 loc) · 8.56 KB
/
contract.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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
* Copyright 2018 The openwallet Authors
* This file is part of the openwallet library.
*
* The openwallet library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The openwallet library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
package openwallet
import (
"encoding/base64"
"fmt"
"strings"
"github.com/blocktree/openwallet/v2/crypto"
)
const (
// 0:未知协议,1:ERC20协议,2:ERC721协议,3:ERC1155协议
InterfaceTypeUnknown = ""
InterfaceTypeERC20 = "erc20"
InterfaceTypeERC721 = "erc721"
InterfaceTypeERC1155 = "erc1155"
)
type SmartContract struct {
ContractID string `json:"contractID" storm:"id"` //计算ID:base64(sha256({symbol}_{address})) 主链symbol
Symbol string `json:"symbol"` //主币的symbol
Address string `json:"address"`
Token string `json:"token"` //合约的symbol
Protocol string `json:"protocol"`
Name string `json:"name"`
Decimals uint64 `json:"decimals"`
abi string
}
// GetABI
func (contract *SmartContract) GetABI() string {
return contract.abi
}
// SetABI
func (contract *SmartContract) SetABI(abiJson string) {
contract.abi = abiJson
}
// GenContractID 合约ID
func GenContractID(symbol, address string) string {
if !strings.HasPrefix(address, "0x") {
address = "0x" + address
}
return base64.StdEncoding.EncodeToString(crypto.SHA256([]byte(fmt.Sprintf("%v_%v", symbol, address))))
}
const (
// 0:hex字符串,1:json字符串,2:base64字符串
TxRawTypeHex = 0
TxRawTypeJSON = 1
TxRawTypeBase64 = 2
)
// SmartContractRawTransaction 智能合约原始交易单
type SmartContractRawTransaction struct {
Coin Coin `json:"coin"` //@required 区块链类型标识
TxID string `json:"txID"` //交易单ID,广播后会生成
Sid string `json:"sid"` //@required 业务订单号,保证业务不重复交易而用
Account *AssetsAccount `json:"account"` //@required 创建交易单的账户
Signatures map[string][]*KeySignature `json:"signatures"` //拥有者accountID: []未花签名
IsBuilt bool `json:"isBuilt"` //是否完成构建建议单
IsCompleted bool `json:"isComplete"` //是否完成所有签名
IsSubmit bool `json:"isSubmit"` //是否已广播
Raw string `json:"raw"` //交易单调用参数,根据RawType填充数据
RawType uint64 `json:"rawType"` // 0:hex字符串,1:json字符串,2:base64字符串
ABIParam []string `json:"abiParam"` //abi调用参数,[method, arg1, arg2, args...]
Value string `json:"value"` //主币数量
FeeRate string `json:"feeRate"` //自定义费率
Fees string `json:"fees"` //手续费
TxFrom string `json:"txFrom"` //调用地址
TxTo string `json:"txTo"` //调用地址,与合约地址一致
AwaitResult bool `json:"awaitResult"` //是否广播后同时等待结果
AwaitTimeout uint64 `json:"awaitTimeout"` //广播后等待超时秒,0 = 默认超时90秒
}
type SmartContractReceipt struct {
Coin Coin `json:"coin"` //@required 区块链类型标识
WxID string `json:"wxid" storm:"id"` //@required 通过GenTransactionWxID计算
TxID string `json:"txid"` //@required
From string `json:"from"` //@required 调用者
To string `json:"to"` //@required 调用地址,与合约地址一致
Value string `json:"value"` //主币数量
Fees string `json:"fees"` //手续费
RawReceipt string `json:"rawReceipt"` //@required 原始交易回执,一般为json
Events []*SmartContractEvent `json:"events"` //@required 执行事件, 例如:event Transfer
BlockHash string `json:"blockHash"` //@required
BlockHeight uint64 `json:"blockHeight"` //@required
ConfirmTime int64 `json:"confirmTime"` //@required
Status string `json:"status"` //@required 链上状态,0:失败,1:成功
Reason string `json:"reason"` //失败原因,失败状态码
ExtParam string `json:"extParam"` //扩展参数,用于调用智能合约,json结构
}
func (tx *SmartContractReceipt) GenWxID() {
tx.WxID = GenTransactionWxID2(tx.TxID, tx.Coin.Symbol, tx.Coin.ContractID)
}
// SmartContractEvent 事件记录
type SmartContractEvent struct {
Contract *SmartContract `json:"contract"` //合约
Event string `json:"event"` //记录事件
Value string `json:"value"` //结果参数,json字符串
}
const (
SmartContractCallResultStatusFail = 0
SmartContractCallResultStatusSuccess = 1
)
// SmartContractCallResult 调用结果,不产生交易
type SmartContractCallResult struct {
Method string `json:"method"` //调用方法
Value string `json:"value"` //json结果
RawHex string `json:"rawHex"` //16进制字符串结果
Status uint64 `json:"status"` //0:成功,1:失败
Exception string `json:"exception"` //异常错误
}
// SmartContractDecoder 智能合约解析器
type SmartContractDecoder interface {
ABIDAI
//GetTokenBalanceByAddress 查询地址token余额列表
GetTokenBalanceByAddress(contract SmartContract, address ...string) ([]*TokenBalance, error)
//调用合约ABI方法
CallSmartContractABI(wrapper WalletDAI, rawTx *SmartContractRawTransaction) (*SmartContractCallResult, *Error)
//创建原始交易单
CreateSmartContractRawTransaction(wrapper WalletDAI, rawTx *SmartContractRawTransaction) *Error
//SubmitRawTransaction 广播交易单
SubmitSmartContractRawTransaction(wrapper WalletDAI, rawTx *SmartContractRawTransaction) (*SmartContractReceipt, *Error)
//GetTokenMetadata 根据合约地址查询token元数据
GetTokenMetadata(contract string) (*SmartContract, error)
}
type SmartContractDecoderBase struct {
}
func (decoder *SmartContractDecoderBase) GetTokenBalanceByAddress(contract SmartContract, address ...string) ([]*TokenBalance, error) {
return nil, fmt.Errorf("GetTokenBalanceByAddress not implement")
}
// 调用合约ABI方法
func (decoder *SmartContractDecoderBase) CallSmartContractABI(wrapper WalletDAI, rawTx *SmartContractRawTransaction) (*SmartContractCallResult, *Error) {
return nil, Errorf(ErrSystemException, "CallSmartContractABI not implement")
}
// 创建原始交易单
func (decoder *SmartContractDecoderBase) CreateSmartContractRawTransaction(wrapper WalletDAI, rawTx *SmartContractRawTransaction) *Error {
return Errorf(ErrSystemException, "CreateSmartContractRawTransaction not implement")
}
// SubmitRawTransaction 广播交易单
func (decoder *SmartContractDecoderBase) SubmitSmartContractRawTransaction(wrapper WalletDAI, rawTx *SmartContractRawTransaction) (*SmartContractReceipt, *Error) {
return nil, Errorf(ErrSystemException, "SubmitSmartContractRawTransaction not implement")
}
// GetABIInfo get abi
func (decoder *SmartContractDecoderBase) GetABIInfo(address string) (*ABIInfo, error) {
return nil, fmt.Errorf("GetABIInfo not implement")
}
// SetABIInfo set abi
func (decoder *SmartContractDecoderBase) SetABIInfo(address string, abi ABIInfo) error {
return fmt.Errorf("GetABIInfo not implement")
}
// GetTokenMetadata 根据合约地址查询token元数据
func (decoder *SmartContractDecoderBase) GetTokenMetadata(contract string) (*SmartContract, error) {
return nil, fmt.Errorf("GetTokenMetadata not implement")
}
// ABIDAI abi data access interface
type ABIDAI interface {
//@require
GetABIInfo(address string) (*ABIInfo, error)
//@require
SetABIInfo(address string, abi ABIInfo) error
}
// ABIInfo abi model
type ABIInfo struct {
Address string `json:"address"`
ABI interface{} `json:"abi"`
}