refactor connect/disconnect asset

pull/541/head
sidhujag 2020-09-04 18:51:03 -07:00
parent 7e5cbeff84
commit ce3c77632c
11 changed files with 42 additions and 139 deletions

View File

@ -96,7 +96,6 @@ type Vout struct {
// Contains SyscoinSpecific asset information hex decoded and pertinent to API display
type AssetSpecific struct {
AssetGuid uint32 `json:"assetGuid"`
AddrStr string `json:"addrStr,omitempty"`
Contract string `json:"contract,omitempty"`
Symbol string `json:"symbol"`
PubData map[string]interface{} `json:"pubData"`
@ -115,7 +114,6 @@ type AssetSpecific struct {
// Contains SyscoinSpecific assets information when searching for assets
type AssetsSpecific struct {
AssetGuid uint32 `json:"assetGuid"`
AddrStr string `json:"addrStr,omitempty"`
Contract string `json:"contract"`
Symbol string `json:"symbol"`
PubData map[string]interface{} `json:"pubData"`

View File

@ -1097,34 +1097,11 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco
}
if ba.AssetBalances != nil && option > AccountDetailsBasic {
tokens = make(bchain.Tokens, 0, len(ba.AssetBalances)+1)
var ownerFound bool = false
for k, v := range ba.AssetBalances {
dbAsset, errAsset := w.db.GetAsset(uint32(k), nil)
if errAsset != nil || dbAsset == nil {
return nil, errAsset
}
if !ownerFound {
// add token as unallocated if address matches asset owner address
if bytes.Equal(addrDesc, dbAsset.AddrDesc) {
ownerBalance := big.NewInt(dbAsset.AssetObj.Balance)
totalOwnerAssetReceived := bchain.ReceivedSatFromBalances(ownerBalance, v.SentSat)
assetGuid := strconv.FormatUint(uint64(k), 10)
tokens = append(tokens, &bchain.Token{
Type: bchain.SPTUnallocatedTokenType,
AddrStr: dbAsset.AddrDesc.String(),
Name: assetGuid + " (" + dbAsset.AssetObj.Symbol + ")",
Decimals: int(dbAsset.AssetObj.Precision),
Symbol: dbAsset.AssetObj.Symbol,
BalanceSat: (*bchain.Amount)(ownerBalance),
TotalReceivedSat: (*bchain.Amount)(totalOwnerAssetReceived),
TotalSentSat: (*bchain.Amount)(v.SentSat),
Contract: assetGuid,
Transfers: v.Transfers,
ContractIndex: assetGuid,
})
ownerFound = true
}
}
totalAssetReceived := bchain.ReceivedSatFromBalances(v.BalanceSat, v.SentSat)
assetGuid := strconv.FormatUint(uint64(k), 10)
tokens = append(tokens, &bchain.Token{
@ -1307,7 +1284,6 @@ func (w *Worker) GetAsset(asset string, page int, txsOnPage int, option AccountD
AssetDetails: &AssetSpecific{
AssetGuid: assetGuid,
Symbol: dbAsset.AssetObj.Symbol,
AddrStr: dbAsset.AddrDesc.String(),
Contract: "0x" + hex.EncodeToString(dbAsset.AssetObj.Contract),
Balance: (*bchain.Amount)(big.NewInt(dbAsset.AssetObj.Balance)),
TotalSupply: (*bchain.Amount)(big.NewInt(dbAsset.AssetObj.TotalSupply)),
@ -1734,7 +1710,6 @@ func (w *Worker) GetAddressUtxo(address string, onlyConfirmed bool) (Utxos, erro
assetDetails := &AssetSpecific{
AssetGuid: a.AssetInfo.AssetGuid,
Symbol: dbAsset.AssetObj.Symbol,
AddrStr: dbAsset.AddrDesc.String(),
Contract: "0x" + hex.EncodeToString(dbAsset.AssetObj.Contract),
Balance: (*bchain.Amount)(big.NewInt(dbAsset.AssetObj.Balance)),
TotalSupply: (*bchain.Amount)(big.NewInt(dbAsset.AssetObj.TotalSupply)),

View File

@ -241,11 +241,9 @@ func (w *Worker) tokenFromXpubAddress(data *xpubData, ad *xpubAddress, changeInd
a, _, _ := w.chainParser.GetAddressesFromAddrDesc(ad.addrDesc)
numAssetBalances := 0
if ad.balance != nil {
// + 1 for owner asset for unallocated token
numAssetBalances = 1 + len(ad.balance.AssetBalances)
numAssetBalances = len(ad.balance.AssetBalances)
}
// +1 for base token always appended
tokens := make(bchain.Tokens, 0, 1+numAssetBalances)
tokens := make(bchain.Tokens, 0, numAssetBalances)
var address string
if len(a) > 0 {
address = a[0]
@ -258,37 +256,12 @@ func (w *Worker) tokenFromXpubAddress(data *xpubData, ad *xpubAddress, changeInd
balance = &ad.balance.BalanceSat
totalSent = &ad.balance.SentSat
totalReceived = ad.balance.ReceivedSat()
// for asset tokens
var ownerFound bool = false
for k, v := range ad.balance.AssetBalances {
dbAsset, errAsset := w.db.GetAsset(k, nil)
if errAsset != nil || dbAsset == nil {
return nil, errAsset
}
if !ownerFound {
// add token as unallocated if address matches asset owner address
if bytes.Equal(ad.addrDesc, dbAsset.AddrDesc) {
ownerBalance := big.NewInt(dbAsset.AssetObj.Balance)
totalOwnerAssetReceived := bchain.ReceivedSatFromBalances(ownerBalance, v.SentSat)
assetGuid := strconv.FormatUint(uint64(k), 10)
tokens = append(tokens, &bchain.Token{
Type: bchain.SPTUnallocatedTokenType,
Name: address,
Decimals: int(dbAsset.AssetObj.Precision),
Symbol: dbAsset.AssetObj.Symbol,
BalanceSat: (*bchain.Amount)(ownerBalance),
TotalReceivedSat: (*bchain.Amount)(totalOwnerAssetReceived),
TotalSentSat: (*bchain.Amount)(v.SentSat),
Path: fmt.Sprintf("%s/%d/%d", data.basePath, changeIndex, index),
Contract: assetGuid,
Transfers: v.Transfers,
ContractIndex: assetGuid,
})
ownerFound = true
}
}
totalAssetReceived := bchain.ReceivedSatFromBalances(v.BalanceSat, v.SentSat)
// add token as unallocated if address matches asset owner address other wise its allocated
assetGuid := strconv.FormatUint(uint64(k), 10)
tokens = append(tokens, &bchain.Token{
Type: bchain.SPTTokenType,
@ -710,7 +683,6 @@ func (w *Worker) GetXpubUtxo(xpub string, onlyConfirmed bool, gap int) (Utxos, e
assetDetails := &AssetSpecific{
AssetGuid: a.AssetInfo.AssetGuid,
Symbol: dbAsset.AssetObj.Symbol,
AddrStr: dbAsset.AddrDesc.String(),
Contract: "0x" + hex.EncodeToString(dbAsset.AssetObj.Contract),
Balance: (*bchain.Amount)(big.NewInt(dbAsset.AssetObj.Balance)),
TotalSupply: (*bchain.Amount)(big.NewInt(dbAsset.AssetObj.TotalSupply)),

View File

@ -359,6 +359,9 @@ func (p *BaseParser) UnpackAssetTxIndex(buf []byte) []*TxAssetIndex {
func (p *BaseParser) GetAssetFromData(sptData []byte) (*Asset, error) {
return nil, errors.New("Not supported")
}
func (p *SyscoinParser) GetAssetFromDesc(addrDesc *bchain.AddressDescriptor) (*bchain.Asset, error) {
return nil, errors.New("Not supported")
}
func (p *BaseParser) GetAllocationFromTx(tx *Tx) (*AssetAllocation, error) {
return nil, errors.New("Not supported")
}

View File

@ -279,6 +279,25 @@ func (p *SyscoinParser) GetAllocationFromTx(tx *bchain.Tx) (*bchain.AssetAllocat
return &assetAllocation, nil
}
func (p *SyscoinParser) GetAssetFromDesc(addrDesc *bchain.AddressDescriptor) (*bchain.Asset, error) {
script, err := p.GetScriptFromAddrDesc(addrDesc)
if err != nil {
return nil, err
}
sptData := p.TryGetOPReturn(script)
if sptData == nil {
return nil, errors.New("OP_RETURN empty")
}
var asset bchain.Asset
r := bytes.NewReader(sptData)
err := asset.AssetObj.Deserialize(r)
if err != nil {
return nil, err
}
return &asset, nil
}
func (p *SyscoinParser) GetAssetFromData(sptData []byte) (*bchain.Asset, error) {
var asset bchain.Asset
r := bytes.NewReader(sptData)

View File

@ -450,7 +450,6 @@ const XPUBAddressTokenType TokenType = "XPUBAddress"
// Syscoin SPT transaction
const SPTNoneType TokenType = "Syscoin"
const SPTTokenType TokenType = "SPTAllocated"
const SPTUnallocatedTokenType TokenType = "SPTUnallocated"
const SPTUnknownType TokenType = "SPTUnknown"
const SPTAssetActivateType TokenType = "SPTAssetActivate"
const SPTAssetUpdateType TokenType = "SPTAssetUpdate"
@ -520,7 +519,6 @@ type AssetAllocation struct {
type Asset struct {
Transactions uint32
AssetObj wire.AssetType
AddrDesc AddressDescriptor
}
// Assets is array of Asset
type Assets []Asset
@ -762,6 +760,7 @@ type BlockChainParser interface {
PackAsset(asset *Asset) ([]byte, error)
UnpackAsset(buf []byte) (*Asset, error)
GetAssetFromData(sptData []byte) (*Asset, error)
GetAssetFromDesc(addrDesc *AddressDescriptor) (*Asset, error)
GetAllocationFromTx(tx *Tx) (*AssetAllocation, error)
LoadAssets(tx *Tx) error
AppendAssetInfo(assetInfo *AssetInfo, buf []byte, varBuf []byte) []byte

View File

@ -512,10 +512,8 @@ func (d *RocksDB) processAddressesBitcoinType(block *bchain.Block, addresses bch
blockTxAssetAddresses := make(bchain.TxAssetAddressMap)
// first process all outputs so that inputs can refer to txs in this block
for txi := range block.Txs {
var addrDescData *bchain.AddressDescriptor = nil
var addrDescOwner *bchain.AddressDescriptor = nil
var assetGuid uint32 = 0
tx := &block.Txs[txi]
var asset *bchain.Asset = nil
isActivate := d.chainParser.IsAssetActivateTx(tx.Version)
isAssetTx := d.chainParser.IsAssetTx(tx.Version)
btxID, err := d.chainParser.PackTxid(tx.Txid)
@ -593,19 +591,13 @@ func (d *RocksDB) processAddressesBitcoinType(block *bchain.Block, addresses bch
if err != nil {
return err
}
// replace asset ownership with this addrDesc in ConnectAssetOutput, this should be the change address
if isAssetTx && assetGuid == 0 && tao.AssetInfo.ValueSat.Int64() == 0 {
assetGuid = tao.AssetInfo.AssetGuid
addrDescOwner = &addrDesc
}
}
} else if isAssetTx && addrDesc[0] == txscript.OP_RETURN {
// if opreturn save data for later disconnecting output
addrDescData = &addrDesc
} else if isAssetTx && asset == nil && addrDesc[0] == txscript.OP_RETURN {
asset = d.chainParser.GetAssetFromDesc(addrDesc)
}
}
if assetGuid > 0 && addrDescOwner != nil && addrDescData != nil {
err := d.ConnectAssetOutput(addrDescData, addrDescOwner, isActivate, isAssetTx, assetGuid, assets)
if asset != nil {
err := d.ConnectAssetOutput(asset, isActivate, isAssetTx, assets)
if err != nil {
return err
}
@ -1026,7 +1018,6 @@ func (d *RocksDB) disconnectTxAddressesInputs(wb *gorocksdb.WriteBatch, btxID []
var err error
var addrDesc *bchain.AddressDescriptor = nil
isAssetTx := d.chainParser.IsAssetTx(txa.Version)
var assetGuid uint32 = 0
for i, t := range txa.Inputs {
if len(t.AddrDesc) > 0 {
input := &inputs[i]
@ -1081,11 +1072,6 @@ func (d *RocksDB) disconnectTxAddressesInputs(wb *gorocksdb.WriteBatch, btxID []
if err != nil {
return err
}
// if asset tx save ownership addrDesc for later disconnect when we replace the addrDesc of asset to this one
if isAssetTx && assetGuid == 0 && t.AssetInfo.ValueSat.Int64() == 0 {
assetGuid = t.AssetInfo.AssetGuid
addrDesc = &t.AddrDesc
}
}
} else {
ad, _, _ := d.chainParser.GetAddressesFromAddrDesc(t.AddrDesc)
@ -1094,12 +1080,6 @@ func (d *RocksDB) disconnectTxAddressesInputs(wb *gorocksdb.WriteBatch, btxID []
}
}
}
if addrDesc != nil {
err := d.DisconnectAssetInput(addrDesc, assets, assetGuid)
if err != nil {
return err
}
}
return nil
}
@ -1110,8 +1090,6 @@ func (d *RocksDB) disconnectTxAddressesOutputs(wb *gorocksdb.WriteBatch, btxID [
assets map[uint32]*bchain.Asset, blockTxAssetAddresses bchain.TxAssetAddressMap) error {
var addrDesc *bchain.AddressDescriptor = nil
isActivate := d.chainParser.IsAssetActivateTx(txa.Version)
isAssetTx := d.chainParser.IsAssetTx(txa.Version)
var assetGuid uint32 = 0
for i, t := range txa.Outputs {
if len(t.AddrDesc) > 0 {
exist := addressFoundInTx(t.AddrDesc, btxID)
@ -1142,30 +1120,24 @@ func (d *RocksDB) disconnectTxAddressesOutputs(wb *gorocksdb.WriteBatch, btxID [
if err != nil {
return err
}
// save it for later
if assetGuid == 0 {
assetGuid = t.AssetInfo.AssetGuid
}
}
} else {
ad, _, _ := d.chainParser.GetAddressesFromAddrDesc(t.AddrDesc)
glog.Warningf("Balance for address %s (%s) not found", ad, t.AddrDesc)
}
} else if isAssetTx && t.AddrDesc[0] == txscript.OP_RETURN {
// if opreturn save data for later disconnecting output
addrDesc = &t.AddrDesc
} else if isAssetTx && asset == nil && t.AddrDesc[0] == txscript.OP_RETURN {
asset = d.chainParser.GetAssetFromDesc(&t.AddrDesc)
}
}
}
if assetGuid > 0 && addrDesc != nil {
err := d.DisconnectAssetOutput(addrDesc, isActivate, assets, assetGuid)
if asset != nil {
err := d.DisconnectAssetOutput(asset, isActivate, assets)
if err != nil {
return err
}
}
return nil
}
func (d *RocksDB) disconnectBlock(height uint32, blockTxs []bchain.BlockTxs) error {
wb := gorocksdb.NewWriteBatch()
defer wb.Destroy()

View File

@ -157,20 +157,9 @@ func (d *RocksDB) ConnectAllocationOutput(addrDesc* bchain.AddressDescriptor, he
return nil
}
func (d *RocksDB) ConnectAssetOutput(addrDescData *bchain.AddressDescriptor, addrDesc *bchain.AddressDescriptor, isActivate bool, isAssetTx bool, assetGuid uint32, assets map[uint32]*bchain.Asset) error {
script, err := d.chainParser.GetScriptFromAddrDesc(*addrDescData)
if err != nil {
return err
}
sptData := d.chainParser.TryGetOPReturn(script)
if sptData == nil {
return errors.New("ConnectAssetOutput could not parse opreturn")
}
asset, err := d.chainParser.GetAssetFromData(sptData)
if err != nil {
return err
}
func (d *RocksDB) ConnectAssetOutput(asset *bchain.Asset, isActivate bool, isAssetTx bool, assets map[uint32]*bchain.Asset) error {
var dBAsset* bchain.Asset = nil
assetGuid := asset.Allocation.VoutAssets[0].AssetGuid
if !isActivate {
dBAsset, err = d.GetAsset(assetGuid, assets)
if err != nil {
@ -188,7 +177,6 @@ func (d *RocksDB) ConnectAssetOutput(addrDescData *bchain.AddressDescriptor, add
if err != nil {
return err
}
dBAsset.AddrDesc = *addrDesc
}
assets[assetGuid] = dBAsset
} else {
@ -226,19 +214,8 @@ func (d *RocksDB) DisconnectAllocationOutput(addrDesc *bchain.AddressDescriptor,
assets[assetInfo.AssetGuid] = dBAsset
return nil
}
func (d *RocksDB) DisconnectAssetOutput(addrDesc *bchain.AddressDescriptor, isActivate bool, assets map[uint32]*bchain.Asset, assetGuid uint32) error {
script, err := d.chainParser.GetScriptFromAddrDesc(*addrDesc)
if err != nil {
return err
}
sptData := d.chainParser.TryGetOPReturn(script)
if sptData == nil {
return errors.New(fmt.Sprint("DisconnectAssetOutput could not parse opreturn"))
}
asset, err := d.chainParser.GetAssetFromData(sptData)
if err != nil {
return err
}
func (d *RocksDB) DisconnectAssetOutput(asset *bchain.Asset, isActivate bool, assets map[uint32]*bchain.Asset) error {
assetGuid := asset.Allocation.VoutAssets[0].AssetGuid
dBAsset, err := d.GetAsset(assetGuid, assets)
if dBAsset == nil || err != nil {
if dBAsset == nil {
@ -279,18 +256,7 @@ func (d *RocksDB) DisconnectAllocationInput(addrDesc *bchain.AddressDescriptor,
assets[assetInfo.AssetGuid] = dBAsset
return nil
}
func (d *RocksDB) DisconnectAssetInput(addrDesc *bchain.AddressDescriptor, assets map[uint32]*bchain.Asset, assetGuid uint32) error {
dBAsset, err := d.GetAsset(assetGuid, assets)
if dBAsset == nil || err != nil {
if dBAsset == nil {
return errors.New(fmt.Sprint("DisconnectAssetInput could not read asset " , assetGuid))
}
return err
}
dBAsset.AddrDesc = *addrDesc
assets[assetGuid] = dBAsset
return nil
}
func (d *RocksDB) SetupAssetCache() error {
start := time.Now()
if AssetCache == nil {

View File

@ -630,7 +630,6 @@ func (s *SocketIoServer) getAssetHistory(asset string, opts *assetOpts) (res res
res.Result.AssetDetails = &api.AssetSpecific{
AssetGuid: assetGuid,
Symbol: dbAsset.AssetObj.Symbol,
AddrStr: dbAsset.AddrDesc.String(),
Contract: "0x" + hex.EncodeToString(dbAsset.AssetObj.Contract),
Balance: (*bchain.Amount)(big.NewInt(dbAsset.AssetObj.Balance)),
TotalSupply: (*bchain.Amount)(big.NewInt(dbAsset.AssetObj.TotalSupply)),

View File

@ -85,7 +85,7 @@
<td class="data ellipsis">{{if $t.Contract}}<a href="/asset/{{$t.Contract}}">{{$t.Contract}}</a>{{else}}{{$t.Name}}{{end}}</td>
<td class="data ellipsis">{{formatAmountWithDecimals $t.TotalReceivedSat $t.Decimals}} {{$t.Symbol}}</td>
<td class="data ellipsis">{{formatAmountWithDecimals $t.TotalSentSat $t.Decimals}} {{$t.Symbol}}</td>
<td class="data ellipsis">{{formatAmountWithDecimals $t.BalanceSat $t.Decimals}} {{$t.Symbol}}{{- if eq $t.Type "SPTUnallocated" -}}<span title="Unallocated balance, owned by asset"> ⚠️</span>{{- end -}}</td>
<td class="data ellipsis">{{formatAmountWithDecimals $t.BalanceSat $t.Decimals}} {{$t.Symbol}}</td>
<td class="data">{{$t.Transfers}}</td>
</tr>
{{- end -}}{{- end -}}

View File

@ -79,8 +79,8 @@
{{- range $tokenTransfer := $tx.TokenTransferSummary -}}{{if $tokenTransfer}}
<tr>
<td class="data ellipsis"><a href="/asset/{{$tokenTransfer.Token}}">{{$tokenTransfer.Token}}</a></td>
<td class="data ellipsis">{{formatAmountWithDecimals $tokenTransfer.Value $tokenTransfer.Decimals}} {{$tokenTransfer.Symbol}}{{- if eq $tokenTransfer.Type "SPTUnallocated" -}}<span title="Unallocated balance, owned by asset"> ⚠️</span>{{- end -}}</td>
<td class="data ellipsis">{{formatAmountWithDecimals $tokenTransfer.ValueOut $tokenTransfer.Decimals}} {{$tokenTransfer.Symbol}}{{- if eq $tokenTransfer.Type "SPTUnallocated" -}}<span title="Unallocated balance, owned by asset"> ⚠️</span>{{- end -}}</td>
<td class="data ellipsis">{{formatAmountWithDecimals $tokenTransfer.Value $tokenTransfer.Decimals}} {{$tokenTransfer.Symbol}}</td>
<td class="data ellipsis">{{formatAmountWithDecimals $tokenTransfer.ValueOut $tokenTransfer.Decimals}} {{$tokenTransfer.Symbol}}</td>
</tr>
{{- end -}}{{- end -}}
</tbody>