Estimate full derivation path from xpub
This commit is contained in:
parent
266b0575b6
commit
64c8ae9a62
2
Gopkg.lock
generated
2
Gopkg.lock
generated
@ -95,7 +95,7 @@
|
|||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/martinboehm/btcutil"
|
name = "github.com/martinboehm/btcutil"
|
||||||
packages = [".","base58","bech32","chaincfg","hdkeychain","txscript"]
|
packages = [".","base58","bech32","chaincfg","hdkeychain","txscript"]
|
||||||
revision = "520c2dbb6e0420531b6ae148845280378516e971"
|
revision = "63034958e64b209cb9294128309dbaed497cde7b"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
|||||||
25
api/xpub.go
25
api/xpub.go
@ -45,6 +45,7 @@ type xpubAddress struct {
|
|||||||
|
|
||||||
type xpubData struct {
|
type xpubData struct {
|
||||||
gap int
|
gap int
|
||||||
|
basePath string
|
||||||
dataHeight uint32
|
dataHeight uint32
|
||||||
dataHash string
|
dataHash string
|
||||||
txs uint32
|
txs uint32
|
||||||
@ -208,7 +209,7 @@ func (w *Worker) xpubScanAddresses(xpub string, data *xpubData, addresses []xpub
|
|||||||
return lastUsed, addresses, nil
|
return lastUsed, addresses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worker) tokenFromXpubAddress(ad *xpubAddress, changeIndex int, index int) Token {
|
func (w *Worker) tokenFromXpubAddress(data *xpubData, ad *xpubAddress, changeIndex int, index int) Token {
|
||||||
a, _, _ := w.chainParser.GetAddressesFromAddrDesc(ad.addrDesc)
|
a, _, _ := w.chainParser.GetAddressesFromAddrDesc(ad.addrDesc)
|
||||||
var address string
|
var address string
|
||||||
if len(a) > 0 {
|
if len(a) > 0 {
|
||||||
@ -220,7 +221,7 @@ func (w *Worker) tokenFromXpubAddress(ad *xpubAddress, changeIndex int, index in
|
|||||||
Decimals: w.chainParser.AmountDecimals(),
|
Decimals: w.chainParser.AmountDecimals(),
|
||||||
BalanceSat: (*Amount)(&ad.balance.BalanceSat),
|
BalanceSat: (*Amount)(&ad.balance.BalanceSat),
|
||||||
Transfers: int(ad.balance.Txs),
|
Transfers: int(ad.balance.Txs),
|
||||||
Contract: fmt.Sprintf("%d/%d", changeIndex, index),
|
Contract: fmt.Sprintf("%s/%d/%d", data.basePath, changeIndex, index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,6 +245,7 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
data, found := cachedXpubs[xpub]
|
data, found := cachedXpubs[xpub]
|
||||||
cachedXpubsMux.Unlock()
|
cachedXpubsMux.Unlock()
|
||||||
var (
|
var (
|
||||||
|
txc xpubTxids
|
||||||
txm []string
|
txm []string
|
||||||
txs []*Tx
|
txs []*Tx
|
||||||
txids []string
|
txids []string
|
||||||
@ -265,6 +267,11 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
fork := false
|
fork := false
|
||||||
if !found || data.gap != gap {
|
if !found || data.gap != gap {
|
||||||
data = &xpubData{gap: gap}
|
data = &xpubData{gap: gap}
|
||||||
|
data.basePath, err = w.chainParser.DerivationBasePath(xpub)
|
||||||
|
if err != nil {
|
||||||
|
glog.Warning("DerivationBasePath error", err)
|
||||||
|
data.basePath = "unknown"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
hash, err := w.db.GetBlockHash(data.dataHeight)
|
hash, err := w.db.GetBlockHash(data.dataHeight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -276,9 +283,12 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
processedHash = besthash
|
processedHash = besthash
|
||||||
if data.dataHeight < bestheight {
|
if data.dataHeight < bestheight || fork {
|
||||||
data.dataHeight = bestheight
|
data.dataHeight = bestheight
|
||||||
data.dataHash = besthash
|
data.dataHash = besthash
|
||||||
|
data.balanceSat = *new(big.Int)
|
||||||
|
data.sentSat = *new(big.Int)
|
||||||
|
data.txs = 0
|
||||||
var lastUsedIndex int
|
var lastUsedIndex int
|
||||||
lastUsedIndex, data.addresses, err = w.xpubScanAddresses(xpub, data, data.addresses, gap, 0, 0, fork)
|
lastUsedIndex, data.addresses, err = w.xpubScanAddresses(xpub, data, data.addresses, gap, 0, 0, fork)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -288,6 +298,7 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
glog.Info("Scanned ", len(data.addresses)+len(data.changeAddresses), " addresses in ", time.Since(start))
|
||||||
}
|
}
|
||||||
if option >= TxidHistory {
|
if option >= TxidHistory {
|
||||||
for i := range data.addresses {
|
for i := range data.addresses {
|
||||||
@ -307,7 +318,7 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
cachedXpubsMux.Unlock()
|
cachedXpubsMux.Unlock()
|
||||||
// TODO mempool
|
// TODO mempool
|
||||||
if option >= TxidHistory {
|
if option >= TxidHistory {
|
||||||
txc := make(xpubTxids, 0, 32)
|
txc = make(xpubTxids, 0, 32)
|
||||||
var addTxids func(ad *xpubAddress)
|
var addTxids func(ad *xpubAddress)
|
||||||
if filter.FromHeight == 0 && filter.ToHeight == 0 && filter.Vout == AddressFilterVoutOff {
|
if filter.FromHeight == 0 && filter.ToHeight == 0 && filter.Vout == AddressFilterVoutOff {
|
||||||
addTxids = func(ad *xpubAddress) {
|
addTxids = func(ad *xpubAddress) {
|
||||||
@ -383,7 +394,7 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
if ad.balance != nil {
|
if ad.balance != nil {
|
||||||
totalTokens++
|
totalTokens++
|
||||||
if filter.AllTokens || !IsZeroBigInt(&ad.balance.BalanceSat) {
|
if filter.AllTokens || !IsZeroBigInt(&ad.balance.BalanceSat) {
|
||||||
t := w.tokenFromXpubAddress(ad, 0, i)
|
t := w.tokenFromXpubAddress(data, ad, 0, i)
|
||||||
tokens = append(tokens, t)
|
tokens = append(tokens, t)
|
||||||
xpubAddresses[t.Name] = struct{}{}
|
xpubAddresses[t.Name] = struct{}{}
|
||||||
} else {
|
} else {
|
||||||
@ -399,7 +410,7 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
if ad.balance != nil {
|
if ad.balance != nil {
|
||||||
totalTokens++
|
totalTokens++
|
||||||
if filter.AllTokens || !IsZeroBigInt(&ad.balance.BalanceSat) {
|
if filter.AllTokens || !IsZeroBigInt(&ad.balance.BalanceSat) {
|
||||||
t := w.tokenFromXpubAddress(ad, 1, i)
|
t := w.tokenFromXpubAddress(data, ad, 1, i)
|
||||||
tokens = append(tokens, t)
|
tokens = append(tokens, t)
|
||||||
xpubAddresses[t.Name] = struct{}{}
|
xpubAddresses[t.Name] = struct{}{}
|
||||||
} else {
|
} else {
|
||||||
@ -427,6 +438,6 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
Tokens: tokens,
|
Tokens: tokens,
|
||||||
XPubAddresses: xpubAddresses,
|
XPubAddresses: xpubAddresses,
|
||||||
}
|
}
|
||||||
glog.Info("GetAddressForXpub ", xpub[:16], ", ", len(data.addresses)+len(data.changeAddresses), " derived addresses, ", data.txs, " total txs finished in ", time.Since(start))
|
glog.Info("GetAddressForXpub ", xpub[:16], ", ", len(data.addresses)+len(data.changeAddresses), " derived addresses, ", data.txs, " total txs, loaded ", len(txc), " txids, finished in ", time.Since(start))
|
||||||
return &addr, nil
|
return &addr, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -267,6 +267,11 @@ func (p *BaseParser) UnpackTx(buf []byte) (*Tx, uint32, error) {
|
|||||||
return &tx, pt.Height, nil
|
return &tx, pt.Height, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DerivationBasePath is unsupported
|
||||||
|
func (p *BaseParser) DerivationBasePath(xpub string) (string, error) {
|
||||||
|
return "", errors.New("Not supported")
|
||||||
|
}
|
||||||
|
|
||||||
// DeriveAddressDescriptors is unsupported
|
// DeriveAddressDescriptors is unsupported
|
||||||
func (p *BaseParser) DeriveAddressDescriptors(xpub string, change uint32, indexes []uint32) ([]AddressDescriptor, error) {
|
func (p *BaseParser) DeriveAddressDescriptors(xpub string, change uint32, indexes []uint32) ([]AddressDescriptor, error) {
|
||||||
return nil, errors.New("Not supported")
|
return nil, errors.New("Not supported")
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
vlq "github.com/bsm/go-vlq"
|
vlq "github.com/bsm/go-vlq"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
@ -28,6 +29,7 @@ type BitcoinParser struct {
|
|||||||
XPubMagic uint32
|
XPubMagic uint32
|
||||||
XPubMagicSegwitP2sh uint32
|
XPubMagicSegwitP2sh uint32
|
||||||
XPubMagicSegwitNative uint32
|
XPubMagicSegwitNative uint32
|
||||||
|
Slip44 uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBitcoinParser returns new BitcoinParser instance
|
// NewBitcoinParser returns new BitcoinParser instance
|
||||||
@ -41,6 +43,7 @@ func NewBitcoinParser(params *chaincfg.Params, c *Configuration) *BitcoinParser
|
|||||||
XPubMagic: c.XPubMagic,
|
XPubMagic: c.XPubMagic,
|
||||||
XPubMagicSegwitP2sh: c.XPubMagicSegwitP2sh,
|
XPubMagicSegwitP2sh: c.XPubMagicSegwitP2sh,
|
||||||
XPubMagicSegwitNative: c.XPubMagicSegwitNative,
|
XPubMagicSegwitNative: c.XPubMagicSegwitNative,
|
||||||
|
Slip44: c.Slip44,
|
||||||
}
|
}
|
||||||
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
|
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
|
||||||
return p
|
return p
|
||||||
@ -349,3 +352,29 @@ func (p *BitcoinParser) DeriveAddressDescriptorsFromTo(xpub string, change uint3
|
|||||||
}
|
}
|
||||||
return ad, nil
|
return ad, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DerivationBasePath returns base path of xpub
|
||||||
|
func (p *BitcoinParser) DerivationBasePath(xpub string) (string, error) {
|
||||||
|
extKey, err := hdkeychain.NewKeyFromString(xpub)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var c, bip string
|
||||||
|
cn := extKey.ChildNum()
|
||||||
|
if cn >= 0x80000000 {
|
||||||
|
cn -= 0x80000000
|
||||||
|
c = "'"
|
||||||
|
}
|
||||||
|
c = strconv.Itoa(int(cn)) + c
|
||||||
|
if extKey.Depth() != 3 {
|
||||||
|
return "unknown/" + c, nil
|
||||||
|
}
|
||||||
|
if extKey.Version() == p.XPubMagicSegwitP2sh {
|
||||||
|
bip = "49"
|
||||||
|
} else if extKey.Version() == p.XPubMagicSegwitNative {
|
||||||
|
bip = "84"
|
||||||
|
} else {
|
||||||
|
bip = "44"
|
||||||
|
}
|
||||||
|
return "m/" + bip + "'/" + strconv.Itoa(int(p.Slip44)) + "'/" + c, nil
|
||||||
|
}
|
||||||
|
|||||||
@ -590,3 +590,72 @@ func BenchmarkDeriveAddressDescriptorsFromToZpub(b *testing.B) {
|
|||||||
btcMainParser.DeriveAddressDescriptorsFromTo("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs", 1, 0, 100)
|
btcMainParser.DeriveAddressDescriptorsFromTo("zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs", 1, 0, 100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBitcoinParser_DerivationBasePath(t *testing.T) {
|
||||||
|
btcMainParser := NewBitcoinParser(GetChainParams("main"), &Configuration{XPubMagic: 76067358, XPubMagicSegwitP2sh: 77429938, XPubMagicSegwitNative: 78792518, Slip44: 0})
|
||||||
|
btcTestnetsParser := NewBitcoinParser(GetChainParams("test"), &Configuration{XPubMagic: 70617039, XPubMagicSegwitP2sh: 71979618, XPubMagicSegwitNative: 73342198, Slip44: 1})
|
||||||
|
zecMainParser := NewBitcoinParser(GetChainParams("main"), &Configuration{XPubMagic: 76067358, Slip44: 133})
|
||||||
|
type args struct {
|
||||||
|
xpub string
|
||||||
|
parser *BitcoinParser
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "m/84'/0'/0'",
|
||||||
|
args: args{
|
||||||
|
xpub: "zpub6rFR7y4Q2AijBEqTUquhVz398htDFrtymD9xYYfG1m4wAcvPhXNfE3EfH1r1ADqtfSdVCToUG868RvUUkgDKf31mGDtKsAYz2oz2AGutZYs",
|
||||||
|
parser: btcMainParser,
|
||||||
|
},
|
||||||
|
want: "m/84'/0'/0'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "m/49'/0'/55 - not hardened account",
|
||||||
|
args: args{
|
||||||
|
xpub: "ypub6XKbB5DJRAbW4TRJLp4uXQXG3ob5BtByXsNZFBjq9qcbzrczjVXfCz5cEo1SFDexmeWRnbCMDaRgaW4m9d2nBaa8FvUQCu3n9G1UBR8WhbT",
|
||||||
|
parser: btcMainParser,
|
||||||
|
},
|
||||||
|
want: "m/49'/0'/55",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "m/49'/0' - incomplete path, without account",
|
||||||
|
args: args{
|
||||||
|
xpub: "ypub6UzM8PUqxcSoqC9gumfoiFhE8Qt84HbGpCD4eVJfJAojXTVtBxeddvTWJGJhGoaVBNJLmEgMdLXHgaLVJa4xEvk2tcokkdZhFdkxMLUE9sB",
|
||||||
|
parser: btcMainParser,
|
||||||
|
},
|
||||||
|
want: "unknown/0'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "m/49'/1'/0'",
|
||||||
|
args: args{
|
||||||
|
xpub: "upub5DR1Mg5nykixzYjFXWW5GghAU7dDqoPVJ2jrqFbL8sJ7Hs7jn69MP7KBnnmxn88GeZtnH8PRKV9w5MMSFX8AdEAoXY8Qd8BJPoXtpMeHMxJ",
|
||||||
|
parser: btcTestnetsParser,
|
||||||
|
},
|
||||||
|
want: "m/49'/1'/0'",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "m/44'/133'/12'",
|
||||||
|
args: args{
|
||||||
|
xpub: "xpub6CQdEahwhKRTLYpP6cyb7ZaGb3r4tVdyPX6dC1PfrNuByrCkWDgUkmpD28UdV9QccKgY1ZiAbGv1Fakcg2LxdFVSTNKHcjdRjqhjPK8Trkb",
|
||||||
|
parser: zecMainParser,
|
||||||
|
},
|
||||||
|
want: "m/44'/133'/12'",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := tt.args.parser.DerivationBasePath(tt.args.xpub)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("BitcoinParser.DerivationBasePath() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("BitcoinParser.DerivationBasePath() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -54,6 +54,7 @@ type Configuration struct {
|
|||||||
XPubMagic uint32 `json:"xpub_magic,omitempty"`
|
XPubMagic uint32 `json:"xpub_magic,omitempty"`
|
||||||
XPubMagicSegwitP2sh uint32 `json:"xpub_magic_segwit_p2sh,omitempty"`
|
XPubMagicSegwitP2sh uint32 `json:"xpub_magic_segwit_p2sh,omitempty"`
|
||||||
XPubMagicSegwitNative uint32 `json:"xpub_magic_segwit_native,omitempty"`
|
XPubMagicSegwitNative uint32 `json:"xpub_magic_segwit_native,omitempty"`
|
||||||
|
Slip44 uint32 `json:"slip44,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBitcoinRPC returns new BitcoinRPC instance.
|
// NewBitcoinRPC returns new BitcoinRPC instance.
|
||||||
|
|||||||
@ -264,6 +264,7 @@ type BlockChainParser interface {
|
|||||||
UnpackBlockHash(buf []byte) (string, error)
|
UnpackBlockHash(buf []byte) (string, error)
|
||||||
ParseBlock(b []byte) (*Block, error)
|
ParseBlock(b []byte) (*Block, error)
|
||||||
// xpub
|
// xpub
|
||||||
|
DerivationBasePath(xpub string) (string, error)
|
||||||
DeriveAddressDescriptors(xpub string, change uint32, indexes []uint32) ([]AddressDescriptor, error)
|
DeriveAddressDescriptors(xpub string, change uint32, indexes []uint32) ([]AddressDescriptor, error)
|
||||||
DeriveAddressDescriptorsFromTo(xpub string, change uint32, fromIndex uint32, toIndex uint32) ([]AddressDescriptor, error)
|
DeriveAddressDescriptorsFromTo(xpub string, change uint32, fromIndex uint32, toIndex uint32) ([]AddressDescriptor, error)
|
||||||
// EthereumType specific
|
// EthereumType specific
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
{{if .Blockbook.BlockChain.XPubMagic}} "xpub_magic": {{.Blockbook.BlockChain.XPubMagic}},
|
{{if .Blockbook.BlockChain.XPubMagic}} "xpub_magic": {{.Blockbook.BlockChain.XPubMagic}},
|
||||||
{{end}}{{if .Blockbook.BlockChain.XPubMagicSegwitP2sh}} "xpub_magic_segwit_p2sh": {{.Blockbook.BlockChain.XPubMagicSegwitP2sh}},
|
{{end}}{{if .Blockbook.BlockChain.XPubMagicSegwitP2sh}} "xpub_magic_segwit_p2sh": {{.Blockbook.BlockChain.XPubMagicSegwitP2sh}},
|
||||||
{{end}}{{if .Blockbook.BlockChain.XPubMagicSegwitNative}} "xpub_magic_segwit_native": {{.Blockbook.BlockChain.XPubMagicSegwitNative}},
|
{{end}}{{if .Blockbook.BlockChain.XPubMagicSegwitNative}} "xpub_magic_segwit_native": {{.Blockbook.BlockChain.XPubMagicSegwitNative}},
|
||||||
|
{{end}}{{if .Blockbook.BlockChain.Slip44}} "slip44": {{.Blockbook.BlockChain.Slip44}},
|
||||||
{{end}}
|
{{end}}
|
||||||
"mempool_workers": {{.Blockbook.BlockChain.MempoolWorkers}},
|
"mempool_workers": {{.Blockbook.BlockChain.MempoolWorkers}},
|
||||||
"mempool_sub_workers": {{.Blockbook.BlockChain.MempoolSubWorkers}},
|
"mempool_sub_workers": {{.Blockbook.BlockChain.MempoolSubWorkers}},
|
||||||
|
|||||||
@ -70,6 +70,7 @@ type Config struct {
|
|||||||
XPubMagic uint32 `json:"xpub_magic,omitempty"`
|
XPubMagic uint32 `json:"xpub_magic,omitempty"`
|
||||||
XPubMagicSegwitP2sh uint32 `json:"xpub_magic_segwit_p2sh,omitempty"`
|
XPubMagicSegwitP2sh uint32 `json:"xpub_magic_segwit_p2sh,omitempty"`
|
||||||
XPubMagicSegwitNative uint32 `json:"xpub_magic_segwit_native,omitempty"`
|
XPubMagicSegwitNative uint32 `json:"xpub_magic_segwit_native,omitempty"`
|
||||||
|
Slip44 uint32 `json:"slip44,omitempty"`
|
||||||
|
|
||||||
AdditionalParams map[string]json.RawMessage `json:"additional_params"`
|
AdditionalParams map[string]json.RawMessage `json:"additional_params"`
|
||||||
} `json:"block_chain"`
|
} `json:"block_chain"`
|
||||||
|
|||||||
@ -27,6 +27,7 @@ type trezorCommonDef struct {
|
|||||||
XPubMagic uint32 `json:"xpub_magic"`
|
XPubMagic uint32 `json:"xpub_magic"`
|
||||||
XPubMagicSegwitP2sh uint32 `json:"xpub_magic_segwit_p2sh"`
|
XPubMagicSegwitP2sh uint32 `json:"xpub_magic_segwit_p2sh"`
|
||||||
XPubMagicSegwitNative uint32 `json:"xpub_magic_segwit_native"`
|
XPubMagicSegwitNative uint32 `json:"xpub_magic_segwit_native"`
|
||||||
|
Slip44 uint32 `json:"slip44,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTrezorCommonDef(coin string) (*trezorCommonDef, error) {
|
func getTrezorCommonDef(coin string) (*trezorCommonDef, error) {
|
||||||
@ -109,6 +110,9 @@ func main() {
|
|||||||
if tcd.XPubMagicSegwitNative != 0 {
|
if tcd.XPubMagicSegwitNative != 0 {
|
||||||
config.Blockbook.BlockChain.XPubMagicSegwitNative = tcd.XPubMagicSegwitNative
|
config.Blockbook.BlockChain.XPubMagicSegwitNative = tcd.XPubMagicSegwitNative
|
||||||
}
|
}
|
||||||
|
if tcd.Slip44 != 0 {
|
||||||
|
config.Blockbook.BlockChain.Slip44 = tcd.Slip44
|
||||||
|
}
|
||||||
err = writeConfig(coin, config)
|
err = writeConfig(coin, config)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Printf("%v updated\n", coin)
|
fmt.Printf("%v updated\n", coin)
|
||||||
|
|||||||
@ -55,6 +55,7 @@
|
|||||||
"mempool_sub_workers": 2,
|
"mempool_sub_workers": 2,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
|
"slip44": 145,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -55,6 +55,7 @@
|
|||||||
"mempool_sub_workers": 2,
|
"mempool_sub_workers": 2,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 70617039,
|
"xpub_magic": 70617039,
|
||||||
|
"slip44": 1,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -250,6 +250,7 @@
|
|||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
"xpub_magic_segwit_p2sh": 77429938,
|
"xpub_magic_segwit_p2sh": 77429938,
|
||||||
|
"slip44": 156,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -58,6 +58,7 @@
|
|||||||
"xpub_magic": 70617039,
|
"xpub_magic": 70617039,
|
||||||
"xpub_magic_segwit_p2sh": 71979618,
|
"xpub_magic_segwit_p2sh": 71979618,
|
||||||
"xpub_magic_segwit_native": 73342198,
|
"xpub_magic_segwit_native": 73342198,
|
||||||
|
"slip44": 1,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -57,6 +57,7 @@
|
|||||||
"mempool_sub_workers": 2,
|
"mempool_sub_workers": 2,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 50221772,
|
"xpub_magic": 50221772,
|
||||||
|
"slip44": 5,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -57,6 +57,7 @@
|
|||||||
"mempool_sub_workers": 2,
|
"mempool_sub_workers": 2,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 70617039,
|
"xpub_magic": 70617039,
|
||||||
|
"slip44": 1,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -57,6 +57,7 @@
|
|||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
"xpub_magic_segwit_p2sh": 77429938,
|
"xpub_magic_segwit_p2sh": 77429938,
|
||||||
|
"slip44": 20,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -59,6 +59,7 @@
|
|||||||
"mempool_sub_workers": 2,
|
"mempool_sub_workers": 2,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 49990397,
|
"xpub_magic": 49990397,
|
||||||
|
"slip44": 3,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -54,6 +54,7 @@
|
|||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
"xpub_magic_segwit_p2sh": 77429938,
|
"xpub_magic_segwit_p2sh": 77429938,
|
||||||
"xpub_magic_segwit_native": 78792518,
|
"xpub_magic_segwit_native": 78792518,
|
||||||
|
"slip44": 75,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -57,6 +57,7 @@
|
|||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 27106558,
|
"xpub_magic": 27106558,
|
||||||
"xpub_magic_segwit_p2sh": 28471030,
|
"xpub_magic_segwit_p2sh": 28471030,
|
||||||
|
"slip44": 101,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -59,6 +59,7 @@
|
|||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
"xpub_magic_segwit_p2sh": 77429938,
|
"xpub_magic_segwit_p2sh": 77429938,
|
||||||
"xpub_magic_segwit_native": 78792518,
|
"xpub_magic_segwit_native": 78792518,
|
||||||
|
"slip44": 17,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -59,6 +59,7 @@
|
|||||||
"xpub_magic": 70617039,
|
"xpub_magic": 70617039,
|
||||||
"xpub_magic_segwit_p2sh": 71979618,
|
"xpub_magic_segwit_p2sh": 71979618,
|
||||||
"xpub_magic_segwit_native": 73342198,
|
"xpub_magic_segwit_native": 73342198,
|
||||||
|
"slip44": 1,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -58,6 +58,7 @@
|
|||||||
"mempool_sub_workers": 8,
|
"mempool_sub_workers": 8,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
|
"slip44": 510,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -57,6 +57,7 @@
|
|||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 27108450,
|
"xpub_magic": 27108450,
|
||||||
"xpub_magic_segwit_p2sh": 28471030,
|
"xpub_magic_segwit_p2sh": 28471030,
|
||||||
|
"slip44": 2,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -56,6 +56,7 @@
|
|||||||
"mempool_sub_workers": 2,
|
"mempool_sub_workers": 2,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 70617039,
|
"xpub_magic": 70617039,
|
||||||
|
"slip44": 1,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -57,6 +57,7 @@
|
|||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
"xpub_magic_segwit_p2sh": 77429938,
|
"xpub_magic_segwit_p2sh": 77429938,
|
||||||
|
"slip44": 22,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -56,6 +56,7 @@
|
|||||||
"mempool_sub_workers": 2,
|
"mempool_sub_workers": 2,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
|
"slip44": 90,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -63,6 +63,7 @@
|
|||||||
"mempool_sub_workers": 2,
|
"mempool_sub_workers": 2,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
|
"slip44": 7,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -55,6 +55,7 @@
|
|||||||
"block_addresses_to_keep": 1000,
|
"block_addresses_to_keep": 1000,
|
||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
"xpub_magic_segwit_p2sh": 77429938,
|
"xpub_magic_segwit_p2sh": 77429938,
|
||||||
|
"slip44": 28,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -56,6 +56,7 @@
|
|||||||
"mempool_sub_workers": 8,
|
"mempool_sub_workers": 8,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
|
"slip44": 133,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -56,6 +56,7 @@
|
|||||||
"mempool_sub_workers": 8,
|
"mempool_sub_workers": 8,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 70617039,
|
"xpub_magic": 70617039,
|
||||||
|
"slip44": 1,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -67,6 +67,7 @@
|
|||||||
"mempool_sub_workers": 2,
|
"mempool_sub_workers": 2,
|
||||||
"block_addresses_to_keep": 300,
|
"block_addresses_to_keep": 300,
|
||||||
"xpub_magic": 76067358,
|
"xpub_magic": 76067358,
|
||||||
|
"slip44": 136,
|
||||||
"additional_params": {}
|
"additional_params": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -39,14 +39,14 @@
|
|||||||
<th style="width: 50%;">Address</th>
|
<th style="width: 50%;">Address</th>
|
||||||
<th>Balance</th>
|
<th>Balance</th>
|
||||||
<th style="width: 8%;">Txs</th>
|
<th style="width: 8%;">Txs</th>
|
||||||
<th style="width: 8%;">Path</th>
|
<th style="width: 18%;">Path</th>
|
||||||
</tr>
|
</tr>
|
||||||
{{- range $t := $addr.Tokens -}}
|
{{- range $t := $addr.Tokens -}}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="data ellipsis"><a href="/address/{{$t.Name}}">{{$t.Name}}</a></td>
|
<td class="data ellipsis"><a href="/address/{{$t.Name}}">{{$t.Name}}</a></td>
|
||||||
<td class="data">{{formatAmount $t.BalanceSat}} {{$cs}}</td>
|
<td class="data">{{formatAmount $t.BalanceSat}} {{$cs}}</td>
|
||||||
<td class="data">{{$t.Transfers}}</td>
|
<td class="data">{{$t.Transfers}}</td>
|
||||||
<td class="data">{{$t.Contract}}</td>
|
<td>{{$t.Contract}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- if not $data.AllTokens -}}
|
{{- if not $data.AllTokens -}}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user