Я пытаюсь сохранить идентификатор контракта hederea типа * hedera.ContractID в поле Gorm, но получаю сообщение об ошибке «недопустимое поле найдено для поля struct github.com/hashgraph/hedera-sdk-go/v2.AccountID AliasKey: определите действительный внешний ключ для отношений или реализовать интерфейс Valuer"
пакетный контракт
import (
"fmt"
"github.com/.../scanner/controllers/blockchain"
database "github.com/.../scanner/db"
model "github.com/.../scanner/models"
"github.com/rs/xid"
"gorm.io/gorm"
)
func DeployContract() *gorm.DB {
//connect to database
db, err := database.ConnectToDB()
//if db connection fails
if err != nil {
panic(err)
}
//init model
var modelContract model.Contract
//check if a contract has been deployed
if err := db.First(&modelContract); err.Error != nil {
//no deployment found
//Migrate the schema
db.AutoMigrate(&model.Contract{})
//deploy contract
contract, _ := blockchain.DeployContract()
//create record
// generate random id
id := xid.New()
// Create
db.Create(&model.Contract{
Id: id.String(),
ContractId: contract.Receipt.ContractID,
GasUsed: contract.CallResult.GasUsed,
TransactionId: fmt.Sprint(contract.TransactionID),
Timestamp: contract.ConsensusTimestamp,
ChargeFee: fmt.Sprint(contract.TransactionFee),
PayerAccount: fmt.Sprint(contract.TransactionID.AccountID),
Status: fmt.Sprint(contract.Receipt.Status),
})
}
return db
}
Модель Горма
package models
import (
"time"
"github.com/hashgraph/hedera-sdk-go/v2"
"gorm.io/gorm"
)
type Contract struct {
gorm.Model
Id string
ContractId *hedera.ContractID
GasUsed uint64
TransactionId string
Timestamp time.Time
ChargeFee string
PayerAccount string
Status string
}
Для пользовательских типов данных вам необходимо указать, как значение будет храниться и извлекаться из вашей базы данных. Это делается путем реализации интерфейсов Scanner
и Valuer
.
Однако, поскольку hedera.ContractID
определен в другом пакете, вам нужно будет создать свой собственный ContractID
и реализовать эти интерфейсы. Что-то вроде этого:
type ContractID hedera.ContractID
type Contract struct {
gorm.Model
Id string
ContractId *ContractID
GasUsed uint64
TransactionId string
Timestamp time.Time
ChargeFee string
PayerAccount string
Status string
}
func (c *ContractID) Scan(value interface{}) error {
bytes, ok := value.([]byte)
if !ok {
return errors.New(fmt.Sprint("Failed to unmarshal ContractID value:", value))
}
return json.Unmarshal(bytes, c)
}
func (c ContractID) Value() (driver.Value, error) {
return json.Marshal(c)
}
Кроме того, вставьте hedera.ContractID
в model.ContractID
, где бы оно ни использовалось. Например:
cID := model.ContractID(*contract.Receipt.ContractID)
// Create
db.Create(&model.Contract{
Id: id.String(),
ContractId: &cID,
GasUsed: contract.CallResult.GasUsed,
TransactionId: fmt.Sprint(contract.TransactionID),
Timestamp: contract.ConsensusTimestamp,
ChargeFee: fmt.Sprint(contract.TransactionFee),
PayerAccount: fmt.Sprint(contract.TransactionID.AccountID),
Status: fmt.Sprint(contract.Receipt.Status),
})
Добавьте этот код в свой код (возможно, там, где определена ваша структура Contract
).
Спасибо за ответ. Все еще не могу заставить его работать. Вот что я сделал play.golang.com/p/id4GlSqi0-a
Я обновил свой код пользовательским определением ContractID
.
Спасибо за сообщение, сканер/оценщик работает, но при попытке создать экземпляр БД с помощью db.Create я получаю сообщение об ошибке IncompileAssign для ContractId (сохранение значения contract.Receipt.ContractID), так как теперь он должен иметь тип ContractID hedera .ContractID
В ответ добавлен дополнительный код, потому что вам нужно преобразовать hedera.ContractID
в models.ContractID
.
Можно ли преобразовать ContractId, прочитанный из БД. вернуться к *hedera.ContractID
вы должны быть в состоянии сделать что-то вроде hederaContractID := hedera.ContractID(cID)
, где cID
имеет тип model.ContractID
.
Большое спасибо, все получилось. В итоге я сделал hederaContractID := hedera.ContractID(*cID); еще раз спасибо.
Спасибо за сообщение, но как я могу его применить.