import (
"context"
+ "crypto/ed25519"
"encoding/hex"
"fmt"
log "github.com/sirupsen/logrus"
- "github.com/bytom/account"
- "github.com/bytom/blockchain/query"
- "github.com/bytom/blockchain/signers"
- "github.com/bytom/consensus"
- "github.com/bytom/crypto/ed25519/chainkd"
- chainjson "github.com/bytom/encoding/json"
- "github.com/bytom/errors"
- "github.com/bytom/protocol/bc"
- "github.com/bytom/protocol/bc/types"
+ "github.com/bytom/bytom/account"
+ "github.com/bytom/bytom/asset"
+ "github.com/bytom/bytom/blockchain/query"
+ "github.com/bytom/bytom/blockchain/signers"
+ "github.com/bytom/bytom/blockchain/txbuilder"
+ "github.com/bytom/bytom/consensus"
+ "github.com/bytom/bytom/crypto/ed25519/chainkd"
+ chainjson "github.com/bytom/bytom/encoding/json"
+ "github.com/bytom/bytom/errors"
+ "github.com/bytom/bytom/protocol/bc"
+ "github.com/bytom/bytom/protocol/bc/types"
)
// POST /list-accounts
func (a *API) listAccounts(ctx context.Context, filter struct {
- ID string `json:"id"`
+ ID string `json:"id"`
+ Alias string `json:"alias"`
}) Response {
- accounts, err := a.wallet.AccountMgr.ListAccounts(filter.ID)
+ accountID := filter.ID
+ if filter.Alias != "" {
+ acc, err := a.wallet.AccountMgr.FindByAlias(filter.Alias)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+ accountID = acc.ID
+ }
+
+ accounts, err := a.wallet.AccountMgr.ListAccounts(accountID)
if err != nil {
log.Errorf("listAccounts: %v", err)
return NewErrorResponse(err)
func (a *API) getAsset(ctx context.Context, filter struct {
ID string `json:"id"`
}) Response {
- asset, err := a.wallet.AssetReg.GetAsset(filter.ID)
+ ass, err := a.wallet.AssetReg.GetAsset(filter.ID)
if err != nil {
log.Errorf("getAsset: %v", err)
return NewErrorResponse(err)
}
- return NewSuccessResponse(asset)
+ annotatedAsset, err := asset.Annotated(ass)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+ return NewSuccessResponse(annotatedAsset)
}
// POST /list-assets
return NewErrorResponse(err)
}
- return NewSuccessResponse(assets)
+ annotatedAssets := []*query.AnnotatedAsset{}
+ for _, ass := range assets {
+ annotatedAsset, err := asset.Annotated(ass)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+ annotatedAssets = append(annotatedAssets, annotatedAsset)
+ }
+ return NewSuccessResponse(annotatedAssets)
}
// POST /list-balances
-func (a *API) listBalances(ctx context.Context) Response {
- balances, err := a.wallet.GetAccountBalances("")
+func (a *API) listBalances(ctx context.Context, filter struct {
+ AccountID string `json:"account_id"`
+ AccountAlias string `json:"account_alias"`
+}) Response {
+ accountID := filter.AccountID
+ if filter.AccountAlias != "" {
+ acc, err := a.wallet.AccountMgr.FindByAlias(filter.AccountAlias)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+ accountID = acc.ID
+ }
+
+ balances, err := a.wallet.GetAccountBalances(accountID, "")
if err != nil {
return NewErrorResponse(err)
}
transaction, err = a.wallet.GetTransactionByTxID(filter.ID)
if err != nil && filter.Unconfirmed {
transaction, err = a.wallet.GetUnconfirmedTxByTxID(filter.ID)
- if err != nil {
- return NewErrorResponse(err)
- }
+ }
+
+ if err != nil {
+ return NewErrorResponse(err)
}
transactions = []*query.AnnotatedTx{transaction}
} else {
}
tx := &BlockTx{
- ID: txDesc.Tx.ID,
- Version: txDesc.Tx.Version,
- Size: txDesc.Tx.SerializedSize,
- TimeRange: txDesc.Tx.TimeRange,
- Inputs: []*query.AnnotatedInput{},
- Outputs: []*query.AnnotatedOutput{},
- StatusFail: false,
+ ID: txDesc.Tx.ID,
+ Version: txDesc.Tx.Version,
+ Size: txDesc.Tx.SerializedSize,
+ TimeRange: txDesc.Tx.TimeRange,
+ Inputs: []*query.AnnotatedInput{},
+ Outputs: []*query.AnnotatedOutput{},
+ }
+
+ resOutID := txDesc.Tx.ResultIds[0]
+ resOut := txDesc.Tx.Entries[*resOutID]
+ switch out := resOut.(type) {
+ case *bc.Output:
+ tx.MuxID = *out.Source.Ref
+ case *bc.Retirement:
+ tx.MuxID = *out.Source.Ref
}
for i := range txDesc.Tx.Inputs {
TimeRange uint64 `json:"time_range"`
Inputs []*query.AnnotatedInput `json:"inputs"`
Outputs []*query.AnnotatedOutput `json:"outputs"`
- Fee int64 `json:"fee"`
+ Fee uint64 `json:"fee"`
}
// POST /decode-raw-transaction
tx.Outputs = append(tx.Outputs, a.wallet.BuildAnnotatedOutput(&ins.Tx, i))
}
- totalInputBtm := uint64(0)
- totalOutputBtm := uint64(0)
- for _, input := range tx.Inputs {
- if input.AssetID.String() == consensus.BTMAssetID.String() {
- totalInputBtm += input.Amount
- }
- }
-
- for _, output := range tx.Outputs {
- if output.AssetID.String() == consensus.BTMAssetID.String() {
- totalOutputBtm += output.Amount
- }
- }
-
- tx.Fee = int64(totalInputBtm) - int64(totalOutputBtm)
+ tx.Fee = txbuilder.CalculateTxFee(&ins.Tx)
return NewSuccessResponse(tx)
}
// POST /list-unspent-outputs
func (a *API) listUnspentOutputs(ctx context.Context, filter struct {
+ AccountID string `json:"account_id"`
+ AccountAlias string `json:"account_alias"`
ID string `json:"id"`
Unconfirmed bool `json:"unconfirmed"`
SmartContract bool `json:"smart_contract"`
From uint `json:"from"`
Count uint `json:"count"`
}) Response {
- accountUTXOs := a.wallet.GetAccountUtxos(filter.ID, filter.Unconfirmed, filter.SmartContract)
+ accountID := filter.AccountID
+ if filter.AccountAlias != "" {
+ acc, err := a.wallet.AccountMgr.FindByAlias(filter.AccountAlias)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+ accountID = acc.ID
+ }
+ accountUTXOs := a.wallet.GetAccountUtxos(accountID, filter.ID, filter.Unconfirmed, filter.SmartContract)
UTXOs := []query.AnnotatedUTXO{}
for _, utxo := range accountUTXOs {
PubKeyInfos []PubKeyInfo `json:"pubkey_infos"`
}
+func getPubkey(account *account.Account, change bool, index uint64) (*ed25519.PublicKey, []chainjson.HexBytes, error) {
+ rawPath, err := signers.Path(account.Signer, signers.AccountKeySpace, change, index)
+ if err != nil {
+ return nil, nil, err
+ }
+ derivedXPub := account.XPubs[0].Derive(rawPath)
+ pubkey := derivedXPub.PublicKey()
+ var path []chainjson.HexBytes
+ for _, p := range rawPath {
+ path = append(path, chainjson.HexBytes(p))
+ }
+
+ return &pubkey, path, nil
+}
+
// POST /list-pubkeys
func (a *API) listPubKeys(ctx context.Context, ins struct {
AccountID string `json:"account_id"`
}
pubKeyInfos := []PubKeyInfo{}
- idx := a.wallet.AccountMgr.GetContractIndex(account.ID)
- for i := uint64(1); i <= idx; i++ {
- rawPath := signers.Path(account.Signer, signers.AccountKeySpace, i)
- derivedXPub := account.XPubs[0].Derive(rawPath)
- pubkey := derivedXPub.PublicKey()
-
- if ins.PublicKey != "" && ins.PublicKey != hex.EncodeToString(pubkey) {
- continue
+ if account.DeriveRule == signers.BIP0032 {
+ idx := a.wallet.AccountMgr.GetContractIndex(account.ID)
+ for i := uint64(1); i <= idx; i++ {
+ pubkey, path, err := getPubkey(account, false, i)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+ if ins.PublicKey != "" && ins.PublicKey != hex.EncodeToString(*pubkey) {
+ continue
+ }
+ pubKeyInfos = append(pubKeyInfos, PubKeyInfo{
+ Pubkey: hex.EncodeToString(*pubkey),
+ Path: path,
+ })
}
-
- var path []chainjson.HexBytes
- for _, p := range rawPath {
- path = append(path, chainjson.HexBytes(p))
+ } else if account.DeriveRule == signers.BIP0044 {
+ idx := a.wallet.AccountMgr.GetBip44ContractIndex(account.ID, true)
+ for i := uint64(1); i <= idx; i++ {
+ pubkey, path, err := getPubkey(account, true, i)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+ if ins.PublicKey != "" && ins.PublicKey != hex.EncodeToString(*pubkey) {
+ continue
+ }
+ pubKeyInfos = append(pubKeyInfos, PubKeyInfo{
+ Pubkey: hex.EncodeToString(*pubkey),
+ Path: path,
+ })
}
- pubKeyInfos = append(pubKeyInfos, PubKeyInfo{
- Pubkey: hex.EncodeToString(pubkey),
- Path: path,
- })
+ idx = a.wallet.AccountMgr.GetBip44ContractIndex(account.ID, false)
+ for i := uint64(1); i <= idx; i++ {
+ pubkey, path, err := getPubkey(account, false, i)
+ if err != nil {
+ return NewErrorResponse(err)
+ }
+ if ins.PublicKey != "" && ins.PublicKey != hex.EncodeToString(*pubkey) {
+ continue
+ }
+ pubKeyInfos = append(pubKeyInfos, PubKeyInfo{
+ Pubkey: hex.EncodeToString(*pubkey),
+ Path: path,
+ })
+ }
}
if len(pubKeyInfos) == 0 {