diff --git a/api.go b/api.go index 53c8c9d9..1fb58bf3 100644 --- a/api.go +++ b/api.go @@ -145,6 +145,15 @@ func (api *API) IsProducerPaused(ctx context.Context) (out bool, err error) { return } +func (api *API) GetProducerProtocolFeatures(ctx context.Context) (out []ProtocolFeature, err error) { + err = api.call(ctx, "producer", "get_supported_protocol_features", nil, &out) + return +} + +func (api *API) ScheduleProducerProtocolFeatureActivations(ctx context.Context, protocolFeaturesToActivate []Checksum256) error { + return api.call(ctx, "producer", "schedule_protocol_feature_activations", M{"protocol_features_to_activate": protocolFeaturesToActivate}, nil) +} + func (api *API) GetAccount(ctx context.Context, name AccountName) (out *AccountResp, err error) { err = api.call(ctx, "chain", "get_account", M{"account_name": name}, &out) return diff --git a/ecc/curve.go b/ecc/curve.go index 449e9ec0..3934e1ce 100644 --- a/ecc/curve.go +++ b/ecc/curve.go @@ -1,7 +1,5 @@ package ecc -import "runtime/debug" - type CurveID uint8 const ( @@ -19,7 +17,6 @@ func (c CurveID) String() string { case CurveWA: return "WA" default: - debug.PrintStack() return "UN" // unknown } } diff --git a/responses.go b/responses.go index cca02ff3..878a0634 100644 --- a/responses.go +++ b/responses.go @@ -173,6 +173,26 @@ type SequencedTransactionResp struct { TransactionResp } +type ProtocolFeature struct { + FeatureDigest Checksum256 `json:"feature_digest"` + SubjectiveRestriction SubjectiveRestriction `json:"subjective_restrictions"` + DescriptionDigest Checksum256 `json:"description_digest"` + Dependencies []Checksum256 `json:"dependencies"` + ProtocolFeatureType string `json:"protocol_feature_type"` + Specification []ProtocolFeatureSpecification `json:"specification"` +} + +type SubjectiveRestriction struct { + Enabled bool `json:"enabled"` + PreactivationRequired bool `json:"preactivation_required"` + EarliestAllowedActivationTime JSONTime `json:"earliest_allowed_activation_time"` +} + +type ProtocolFeatureSpecification struct { + Name string `json:"name"` + Value string `json:"value"` +} + type TransactionsResp struct { Transactions []SequencedTransactionResp } diff --git a/snapshot/snapshot_test.go b/snapshot/snapshot_test.go index 27ea16b9..a5f5a7f3 100644 --- a/snapshot/snapshot_test.go +++ b/snapshot/snapshot_test.go @@ -3,17 +3,23 @@ package snapshot import ( "fmt" "io" + "os" "path/filepath" "strings" "testing" - "go.uber.org/zap" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "go.uber.org/zap" ) func TestSnapshotRead(t *testing.T) { + + if os.Getenv("READ_SNAPSHOT_FILE") != "true" { + t.Skipf("Environment varaible 'READ_SNAPSHOT_FILE' not set to true") + return + } + logger, _ := zap.NewDevelopment() tests := []struct { name string @@ -28,6 +34,12 @@ func TestSnapshotRead(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { testFile := testData(test.testFile) + + if !fileExists(testFile) { + logger.Error("test file not found", zap.String("testfile", testFile)) + return + } + r, err := NewReader(testFile) require.NoError(t, err) defer r.Close() @@ -75,6 +87,19 @@ func TestSnapshotRead(t *testing.T) { } } +func fileExists(path string) bool { + info, err := os.Stat(path) + if os.IsNotExist(err) { + return false + } + + if err != nil { + return false + } + + return !info.IsDir() +} + func testData(filename string) string { return filepath.Join("test-data", filename) } diff --git a/system/activatefeature.go b/system/activatefeature.go new file mode 100644 index 00000000..3b3550fc --- /dev/null +++ b/system/activatefeature.go @@ -0,0 +1,23 @@ +package system + +import ( + "github.com/eoscanada/eos-go" +) + +func NewActivateFeature(featureDigest eos.Checksum256) *eos.Action { + return &eos.Action{ + Account: AN("eosio"), + Name: ActN("activate"), + Authorization: []eos.PermissionLevel{ + {Actor: AN("eosio"), Permission: PN("active")}, + }, + ActionData: eos.NewActionData(Activate{ + FeatureDigest: featureDigest, + }), + } +} + +// Activate represents a `activate` action on the `eosio` contract. +type Activate struct { + FeatureDigest eos.Checksum256 `json:"feature_digest"` +} diff --git a/system/initsystem.go b/system/initsystem.go new file mode 100644 index 00000000..2261ac88 --- /dev/null +++ b/system/initsystem.go @@ -0,0 +1,30 @@ +package system + +import ( + eos "github.com/eoscanada/eos-go" +) + +// NewInitSystem returns a `init` action that lives on the +// `eosio.system` contract. +func NewInitSystem(version eos.Varuint32, core eos.Symbol) *eos.Action { + return &eos.Action{ + Account: AN("eosio"), + Name: ActN("init"), + Authorization: []eos.PermissionLevel{ + { + Actor: AN("eosio"), + Permission: eos.PermissionName("active"), + }, + }, + ActionData: eos.NewActionData(Init{ + Version: version, + Core: core, + }), + } +} + +// Init represents the `eosio.system::init` action +type Init struct { + Version eos.Varuint32 `json:"version"` + Core eos.Symbol `json:"core"` +} diff --git a/system/setcode.go b/system/setcode.go index 82308934..9d56e204 100644 --- a/system/setcode.go +++ b/system/setcode.go @@ -22,12 +22,26 @@ func NewSetContract(account eos.AccountName, wasmPath, abiPath string) (out []*e return []*eos.Action{codeAction, abiAction}, nil } +func NewSetContractContent(account eos.AccountName, wasmContent, abiContent []byte) (out []*eos.Action, err error) { + codeAction := NewSetCodeContent(account, wasmContent) + + abiAction, err := NewSetAbiContent(account, abiContent) + if err != nil { + return nil, err + } + + return []*eos.Action{codeAction, abiAction}, nil +} + func NewSetCode(account eos.AccountName, wasmPath string) (out *eos.Action, err error) { codeContent, err := ioutil.ReadFile(wasmPath) if err != nil { return nil, err } + return NewSetCodeContent(account, codeContent), nil +} +func NewSetCodeContent(account eos.AccountName, codeContent []byte) *eos.Action { return &eos.Action{ Account: AN("eosio"), Name: ActN("setcode"), @@ -43,7 +57,7 @@ func NewSetCode(account eos.AccountName, wasmPath string) (out *eos.Action, err VMVersion: 0, Code: eos.HexBytes(codeContent), }), - }, nil + } } func NewSetABI(account eos.AccountName, abiPath string) (out *eos.Action, err error) { @@ -52,6 +66,10 @@ func NewSetABI(account eos.AccountName, abiPath string) (out *eos.Action, err er return nil, err } + return NewSetAbiContent(account, abiContent) +} + +func NewSetAbiContent(account eos.AccountName, abiContent []byte) (out *eos.Action, err error) { var abiPacked []byte if len(abiContent) > 0 { var abiDef eos.ABI @@ -81,6 +99,29 @@ func NewSetABI(account eos.AccountName, abiPath string) (out *eos.Action, err er }, nil } +func NewSetAbiFromAbi(account eos.AccountName, abi eos.ABI) (out *eos.Action, err error) { + var abiPacked []byte + abiPacked, err = eos.MarshalBinary(abi) + if err != nil { + return nil, fmt.Errorf("packing ABI: %s", err) + } + + return &eos.Action{ + Account: AN("eosio"), + Name: ActN("setabi"), + Authorization: []eos.PermissionLevel{ + { + Actor: account, + Permission: eos.PermissionName("active"), + }, + }, + ActionData: eos.NewActionData(SetABI{ + Account: account, + ABI: eos.HexBytes(abiPacked), + }), + }, nil +} + // NewSetCodeTx is _deprecated_. Use NewSetContract instead, and build // your transaction yourself. func NewSetCodeTx(account eos.AccountName, wasmPath, abiPath string) (out *eos.Transaction, err error) { diff --git a/token/issue.go b/token/issue.go index ffe573ba..22ca0fa6 100644 --- a/token/issue.go +++ b/token/issue.go @@ -7,7 +7,7 @@ func NewIssue(to eos.AccountName, quantity eos.Asset, memo string) *eos.Action { Account: AN("eosio.token"), Name: ActN("issue"), Authorization: []eos.PermissionLevel{ - {Actor: AN("eosio"), Permission: PN("active")}, + {Actor: to, Permission: PN("active")}, }, ActionData: eos.NewActionData(Issue{ To: to, diff --git a/types.go b/types.go index 202e1244..f514e7ba 100644 --- a/types.go +++ b/types.go @@ -213,18 +213,21 @@ func (a Asset) String() string { if amt < 0 { amt = -amt } - strInt := fmt.Sprintf("%d", amt) - if len(strInt) < int(a.Symbol.Precision+1) { + + precisionDigitCount := int(a.Symbol.Precision) + dotAndPrecisionDigitCount := precisionDigitCount + 1 + + strInt := strconv.FormatInt(int64(amt), 10) + if len(strInt) < dotAndPrecisionDigitCount { // prepend `0` for the difference: - strInt = strings.Repeat("0", int(a.Symbol.Precision+uint8(1))-len(strInt)) + strInt + strInt = strings.Repeat("0", dotAndPrecisionDigitCount-len(strInt)) + strInt } - var result string - if a.Symbol.Precision == 0 { - result = strInt - } else { - result = strInt[:len(strInt)-int(a.Symbol.Precision)] + "." + strInt[len(strInt)-int(a.Symbol.Precision):] + result := strInt + if a.Symbol.Precision > 0 { + result = strInt[:len(strInt)-precisionDigitCount] + "." + strInt[len(strInt)-precisionDigitCount:] } + if a.Amount < 0 { result = "-" + result } diff --git a/types_test.go b/types_test.go index 10ae9956..2aa88e20 100644 --- a/types_test.go +++ b/types_test.go @@ -357,6 +357,10 @@ func TestAssetToString(t *testing.T) { Asset{-6000, Symbol{Precision: 0, Symbol: "MAMA"}}, "-6000 MAMA", }, + { + Asset{0, Symbol{Precision: 255, Symbol: "EOS"}}, + "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 EOS", + }, } for _, test := range tests {