├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── assets ├── README.md ├── assets.go ├── bytom │ ├── api.go │ ├── bytom.go │ ├── config.go │ ├── manager.go │ ├── manager_test.go │ ├── merchant.go │ └── models.go ├── cardano │ ├── api.go │ ├── cardano.go │ ├── config.go │ ├── manager.go │ ├── manager_test.go │ └── models.go ├── decred │ ├── api.go │ ├── blockscan.go │ ├── blockscan_test.go │ ├── config.go │ ├── decred.go │ ├── manager.go │ ├── manager_test.go │ ├── merchant.go │ └── models.go ├── hypercash │ ├── api.go │ ├── blockscan.go │ ├── blockscan_test.go │ ├── config.go │ ├── hypercash.go │ ├── manager.go │ ├── manager_test.go │ ├── merchant.go │ └── models.go ├── icon │ ├── api.go │ ├── config.go │ ├── icon.go │ ├── manager.go │ ├── manager_test.go │ └── models.go ├── luxapla │ └── luxapla.go ├── monero │ └── manager_addrRef.go ├── obyte │ ├── config.go │ ├── manager.go │ ├── manager_test.go │ ├── model.go │ ├── obyte.go │ └── rpc_api.go ├── sia │ ├── api.go │ ├── config.go │ ├── manager.go │ ├── manager_test.go │ ├── model.go │ └── sia.go └── tezos │ ├── api.go │ ├── base58.go │ ├── config.go │ ├── manager.go │ ├── manager_test.go │ ├── models.go │ ├── prikeyEncryption.go │ └── tezos.go ├── cmd ├── utils │ ├── customflags.go │ ├── flags.go │ └── log.go └── wmd │ ├── commands │ ├── config.go │ ├── fullnode.go │ ├── merchant.go │ ├── newwallet.go │ └── version.go │ └── main.go ├── common ├── bool.go ├── bytes.go ├── check.go ├── check_test.go ├── file │ ├── copy.go │ ├── copy_test.go │ ├── file.go │ └── file_test.go ├── float.go ├── int.go ├── math.go ├── math_test.go ├── slice.go ├── slice_test.go ├── string.go ├── string_test.go ├── time.go └── time_test.go ├── concurrent └── concurrent.go ├── console ├── inputer.go └── prompter.go ├── crypto ├── aes_utils.go ├── crypto_utils.go ├── crypto_utils_test.go └── sha3 │ ├── LICENSE │ ├── PATENTS │ ├── doc.go │ ├── hashes.go │ ├── keccakf.go │ ├── keccakf_amd64.go │ ├── keccakf_amd64.s │ ├── register.go │ ├── sha3.go │ ├── sha3_test.go │ ├── shake.go │ ├── testdata │ └── keccakKats.json.deflate │ ├── xor.go │ ├── xor_generic.go │ └── xor_unaligned.go ├── go.mod ├── hdkeystore ├── hdkey.go ├── hdkey_test.go ├── hdkeystore.go └── hdkeystore_test.go ├── log ├── README.md ├── log.go ├── log_test.go ├── logger.go ├── owlogger.go └── owlogger_test.go ├── main.go ├── openw ├── README.md ├── account_manager.go ├── address_batch_test.go ├── app_wrapper.go ├── assets_manager.go ├── block_manager.go ├── config.go ├── contract_manager.go ├── database.go ├── manager.go ├── manager_test.go ├── subscribe.go ├── transaction_manager.go ├── transaction_manager_test.go ├── tx_wrapper.go ├── wallet_manager.go ├── wallet_wrapper.go └── wrapper.go ├── openwallet ├── accounts.go ├── address.go ├── address_batch.go ├── app.go ├── assets.go ├── balance.go ├── blockchain.go ├── blockchain_test.go ├── blockscanner.go ├── cache.go ├── config.go ├── constants.go ├── contract.go ├── contract_test.go ├── directory.go ├── docs │ ├── README.md │ ├── assets.md │ ├── blockscanner.md │ └── wallet.md ├── endpoint.go ├── error_test.go ├── errors.go ├── nft.go ├── openwallet.go ├── signer.go ├── symbol.go ├── tx.go ├── tx_decoder.go ├── type.go ├── wallet.go └── wallet_test.go ├── owtp ├── README.md ├── auth.go ├── auth_test.go ├── http_client.go ├── http_client_test.go ├── http_listener.go ├── mq_client.go ├── mq_client_test.go ├── mq_data.go ├── multi_connect_test.go ├── mux.go ├── mux_test.go ├── owtp.go ├── owtp_test.go ├── peer.go ├── peerstore.go ├── session_store.go ├── session_store_test.go ├── ws_client.go ├── ws_client_test.go └── ws_listener.go ├── session ├── README.md ├── couchbase │ └── sess_couchbase.go ├── ledis │ └── ledis_session.go ├── memcache │ └── sess_memcache.go ├── mysql │ └── sess_mysql.go ├── postgres │ └── sess_postgresql.go ├── redis │ └── sess_redis.go ├── redis_cluster │ └── redis_cluster.go ├── sess_cookie.go ├── sess_cookie_test.go ├── sess_file.go ├── sess_mem.go ├── sess_mem_test.go ├── sess_test.go ├── sess_utils.go ├── session.go └── ssdb │ └── sess_ssdb.go ├── timer ├── task_timer.go └── task_timer_test.go ├── walletnode ├── README.md ├── config.go ├── config_init.go ├── config_init_test.go ├── config_load.go ├── config_load_test.go ├── config_update.go ├── config_update_test.go ├── manager.go ├── manager_copy.go ├── manager_copy_test.go ├── manager_create.go ├── manager_logs.go ├── manager_remove.go ├── manager_restart.go ├── manager_start.go ├── manager_status.go ├── manager_stop.go ├── manager_test.go ├── wallet_create.go └── walletnode.go └── wmd ├── README.md └── assets.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.ini 2 | *.log 3 | *.txt 4 | *.crt 5 | *.key 6 | *.pem 7 | *.exe 8 | *.test 9 | *.json 10 | *.prof 11 | *.swp 12 | .idea/ 13 | build 14 | .vscode/ 15 | *.db 16 | go.sum 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | .PHONY: wmd 3 | .PHONY: deps 4 | 5 | # Check for required command tools to build or stop immediately 6 | EXECUTABLES = git go find pwd 7 | K := $(foreach exec,$(EXECUTABLES),\ 8 | $(if $(shell which $(exec)),some string,$(error "No $(exec) in PATH))) 9 | 10 | GO ?= latest 11 | 12 | # wmd 13 | WMDVERSION = $(shell git describe --tags `git rev-list --tags --max-count=1`) 14 | WMDBINARY = wmd 15 | WMDMAIN = cmd/wmd/main.go 16 | 17 | BUILDDIR = build 18 | GITREV = $(shell git rev-parse --short HEAD) 19 | BUILDTIME = $(shell date +'%Y-%m-%d_%T') 20 | 21 | WMDLDFLAGS="-X github.com/blocktree/openwallet/cmd/wmd/commands.Version=${WMDVERSION} \ 22 | -X github.com/blocktree/openwallet/cmd/wmd/commands.GitRev=${GITREV} \ 23 | -X github.com/blocktree/openwallet/cmd/wmd/commands.BuildTime=${BUILDTIME}" 24 | 25 | # OS platfom 26 | # options: windows-6.0/*,darwin-10.10/amd64,linux/amd64,linux/386,linux/arm64,linux/mips64, linux/mips64le 27 | TARGETS="darwin-10.10/amd64,linux/amd64" 28 | 29 | deps: 30 | go get -u github.com/gythialy/xgo 31 | 32 | build: 33 | GO111MODULE=on go build -ldflags $(WMDLDFLAGS) -i -o $(shell pwd)/$(BUILDDIR)/$(WMDBINARY) $(shell pwd)/$(WMDMAIN) 34 | @echo "Build $(WMDBINARY) done." 35 | 36 | 37 | all: wmd 38 | 39 | clean: 40 | rm -rf $(shell pwd)/$(BUILDDIR)/ 41 | 42 | wmd: 43 | xgo --dest=$(BUILDDIR) --ldflags=$(WMDLDFLAGS) --out=$(WMDBINARY)-$(WMDVERSION)-$(GITREV) --targets=$(TARGETS) \ 44 | --pkg=$(WMDMAIN) . 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenWallet 2 | 3 | [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg?style=flat-square)](https://www.gnu.org/licenses/gpl-3.0) 4 | [![Slack](https://img.shields.io/badge/Slack-blocktree-green.svg?style=flat-square)](https://join.slack.com/t/blocktreeworkspace/shared_invite/enQtODE0OTY1ODA5MjM3LTIwNDJjNDA2ZDYyMjE1YTRiMDUyYTg5NDljMTU0NTY4NmE5ZDM2ZGI3NjcxYzMzN2NiZTZjNzIyMjVjYmRiY2E) 5 | 6 | ## Contents 7 | 8 | - [Introduction](#Introduction) 9 | - [Features](#Features) 10 | - [Protocol](./openwallet/docs/README.md) 11 | - [Resources](#Resources) 12 | - [Contributing](#Contributing) 13 | - [Sponsors](#Sponsors) 14 | - [LICENSE](LICENSE) 15 | 16 | ## Introduction 17 | 18 | openwallet框架定义了一套规范化的钱包体系开发模型,应用开发者无需了解区块链底层协议,即可支持多种区块链资产管理功能。 19 | 区块链底层协议开发者也可以实现openwallet框架资产适配器协议,开发者便可利用该区块链生态实现更多落地应用。 20 | openwallet框架,未来将进化成为一个去中心化系统开发框架,跟随不断发展的区块链生态,提供更多应用开发组件库。 21 | 22 | ## Features 23 | 24 | ### v1 25 | 26 | 细节上,openwallet框架有以下特性: 27 | 28 | - **规范化的钱包体系模型**。我们把钱包体系划分为3层模型:钱包,资产账户,地址。**钱包**:理论上就是一个32字节的种子,可通过用户口令加密保存keystore文件。种子相当重要,它基于BIP32协议衍生子代密钥,丢失将失去所有子代密钥。**资产账户**:一个钱包可以创建不同区块链协议的资产账户。这是因为openwallet的扩展密钥算法已经实现了多种ECC曲线的支持,例如:secp256k1,ed25519等。资产账户主要提供一个非强化版的扩展公钥,用于生成更多的地址。**地址**:真正用于接收区块链资产的是地址模型。业务应用可以根据需求去组织自己的钱包。例如:普通用户创建一个onchain钱包,他分别创建了多种区块链的资产账户,账户默认都只创建一个地址,解决各种支付方式。 29 | - **区块链资产适配器协议**。区块链协议各有不同,如果应用开发者把每种区块链协议都弄明白并实现落地应用,将会是一个漫长艰难复杂的开发过程。经过多时间的研究,openwallet钱包体系模型适用于大量主流的区块链协议。为此,我们定义一个规范化的区块链资产适配器协议,让区块链协议适配者实现:主链基本信息,配置加载过程,地址解析器,交易单解析器,区块链扫描器,智能合约解析器,日志管理工具等等方法。区块链资产适配器实现后,可通过openw包提供的功能进行测试。 30 | - **OWTP通信协议**。openwallet定义自己的加密通信协议,内置SM2协商密码机制,可以在非https环境下开启加密通信。 31 | 32 | ### v2 33 | 34 | 兼容v1功能,扩展智能合约解析器,支持与合约进行交互,监听合约的事件日志。 35 | 36 | ## openwallet V2升级 37 | 38 | v2版本完全兼容v1版本,只需在go.mod中依赖v2最新版本 39 | 40 | ```go script 41 | 42 | require ( 43 | github.com/blocktree/openwallet/v2 latest 44 | .... 45 | ) 46 | 47 | ``` 48 | 49 | 50 | 已依赖v1库的项目,可以安装[Mod](https://github.com/marwan-at-work/mod/) 51 | 52 | ```shell script 53 | 54 | GO111MODULE=on go get github.com/marwan-at-work/mod/cmd/mod 55 | 56 | # 在你的项目的根目录,执行命令,import openwallet库相关的文件都会更新到v2包 57 | mod upgrade --mod-name=github.com/blocktree/openwallet 58 | 59 | ``` 60 | 61 | ## Resources 62 | 63 | ### Assets-Adapter 区块链资产适配器 64 | 65 | #### v1 66 | 67 | - [bitcoin-adapter](https://github.com/blocktree/bitcoin-adapter) 68 | - [litecoin-adapter](https://github.com/blocktree/litecoin-adapter)(继承bitcoin-adapter) 69 | - [ethereum-adapter](https://github.com/blocktree/ethereum-adapter) 70 | - [truechain-adapter](https://github.com/blocktree/truechain-adapter)(继承ethereum-adapter) 71 | - [qtum-adapter](https://github.com/blocktree/qtum-adapter) 72 | - [tron-adapter](https://github.com/blocktree/tron-adapter) 73 | - [more...](https://github.com/blocktree?utf8=%E2%9C%93&q=adapter) 74 | 75 | #### v2 76 | 77 | - [quorum-adapter](https://github.com/blocktree/quorum-adapter) 78 | 79 | ### 钱包开发者平台 80 | 81 | - [openwallet钱包服务开放平台](https://www.openwallet.cn) 82 | - [go-openw-sdk](https://github.com/blocktree/go-openw-sdk) 83 | - [go-openw-cli](https://github.com/blocktree/go-openw-cli) 84 | 85 | ## Contributing 86 | 87 | 如果你对项目有非常感兴趣,可创建[issue](https://github.com/blocktree/openwallet/issues/new) 分享你的想法和创意。 88 | 89 | ## Sponsors 90 | 91 | ## License 92 | 93 | openwallet is licensed under the GNU General Public License v3.0. See [LICENSE](LICENSE) for the full license text. 94 | -------------------------------------------------------------------------------- /assets/README.md: -------------------------------------------------------------------------------- 1 | # assets 区块链资产适配指引 2 | 3 | assets包下的各个子模块是实现区块链资产适配器。 4 | 5 | ## 资产适配器使用说明 6 | 7 | ```go 8 | 9 | // 注册适配器 10 | assets.RegAssets(bitcoin.Symbol, bitcoin.NewWalletManager()) 11 | 12 | // 注册适配器,并加载配置文件 13 | absFile := filepath.Join(configFilePath, symbol+".ini") 14 | c, _ := config.NewConfig("ini", absFile) 15 | assets.RegAssets(bitcoin.Symbol, bitcoin.NewWalletManager(), c) 16 | 17 | // 获取资产适配器对象 18 | adapter := assets.GetAssets(symbol) 19 | if adapter == nil { 20 | return nil, fmt.Errorf("assets: %s is not support", symbol) 21 | } 22 | 23 | ``` -------------------------------------------------------------------------------- /assets/assets.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package assets 17 | 18 | import ( 19 | "github.com/astaxie/beego/config" 20 | "github.com/blocktree/openwallet/v2/log" 21 | "github.com/blocktree/openwallet/v2/openwallet" 22 | "strings" 23 | ) 24 | 25 | //钱包管理器组 26 | var managers = make(map[string]interface{}) 27 | 28 | // RegAssets 注册资产 29 | // @param name 资产别名 30 | // @param manager 资产适配器或管理器 31 | // @param config 加载配置 32 | // 资产适配器实现了openwallet.AssetsConfig,可以传入配置接口完成预加载配置 33 | // usage: 34 | // RegAssets(cardano.Symbol, &cardano.WalletManager{}, c) 35 | // RegAssets(bytom.Symbol, &bytom.WalletManager{}, c) 36 | func RegAssets(name string, manager interface{}, config ...config.Configer) { 37 | name = strings.ToUpper(name) 38 | if manager == nil { 39 | panic("assets: Register adapter is nil") 40 | } 41 | if _, ok := managers[name]; ok { 42 | log.Error("assets: Register called twice for adapter ", name) 43 | return 44 | } 45 | 46 | managers[name] = manager 47 | 48 | //如果有配置则加载所有配置 49 | if ac, ok := manager.(openwallet.AssetsConfig); ok && config != nil { 50 | for _, c := range config { 51 | ac.LoadAssetsConfig(c) 52 | } 53 | } 54 | } 55 | 56 | // GetAssets 根据币种类型获取已注册的管理者 57 | func GetAssets(symbol string) interface{} { 58 | symbol = strings.ToUpper(symbol) 59 | manager, ok := managers[symbol] 60 | if !ok { 61 | return nil 62 | } 63 | return manager 64 | } 65 | -------------------------------------------------------------------------------- /assets/bytom/api.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package bytom 17 | 18 | import ( 19 | "encoding/base64" 20 | "github.com/imroc/req" 21 | "log" 22 | ) 23 | 24 | // A Client is a Bitcoin RPC client. It performs RPCs over HTTP using JSON 25 | // request and responses. A Client must be configured with a secret token 26 | // to authenticate with other Cores on the network. 27 | type Client struct { 28 | BaseURL string 29 | AccessToken string 30 | Debug bool 31 | 32 | //Client *req.Req 33 | } 34 | 35 | type Response struct { 36 | Code int `json:"code,omitempty"` 37 | Error interface{} `json:"error,omitempty"` 38 | Result interface{} `json:"result,omitempty"` 39 | Message string `json:"message,omitempty"` 40 | Id string `json:"id,omitempty"` 41 | } 42 | 43 | // Call calls a remote procedure on another node, specified by the path. 44 | func (c *Client) Call(path string, request interface{}) ([]byte, error) { 45 | 46 | //var ( 47 | // body = make(map[string]interface{}, 0) 48 | //) 49 | 50 | //authHeader := req.Header{ 51 | // "Accept": "application/json", 52 | // "Authorization": "Basic " + basicAuth(rpcuser, rpcpassword), 53 | //} 54 | 55 | //json-rpc 56 | //body["jsonrpc"] = "2.0" 57 | //body["id"] = "1" 58 | //body["method"] = path 59 | //body["params"] = request 60 | 61 | url := c.BaseURL + "/" + path 62 | 63 | if c.Debug {log.Println("Start Request API...")} 64 | 65 | r, err := req.Post(url, req.BodyJSON(&request)) 66 | if err != nil { 67 | log.Printf("unexpected err: %v\n", err) 68 | return nil, err 69 | } 70 | 71 | if c.Debug {log.Println("Request API Completed")} 72 | 73 | if c.Debug { 74 | log.Printf("%+v\n", r) 75 | } 76 | 77 | return r.Bytes(), nil 78 | } 79 | 80 | // See 2 (end of page 4) http://www.ietf.org/rfc/rfc2617.txt 81 | // "To receive authorization, the client sends the userid and password, 82 | // separated by a single colon (":") character, within a base64 83 | // encoded string in the credentials." 84 | // It is not meant to be urlencoded. 85 | func basicAuth(username, password string) string { 86 | auth := username + ":" + password 87 | return base64.StdEncoding.EncodeToString([]byte(auth)) 88 | } 89 | -------------------------------------------------------------------------------- /assets/bytom/merchant.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package bytom 17 | 18 | import ( 19 | "github.com/blocktree/openwallet/v2/common/file" 20 | "github.com/blocktree/openwallet/v2/openwallet" 21 | "path/filepath" 22 | ) 23 | 24 | //CreateMerchantWallet 创建钱包 25 | func (w *WalletManager) CreateMerchantWallet(alias string, password string) (*openwallet.Wallet, error) { 26 | 27 | wallet, err := CreateNewWallet(alias, password) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | //创建钱包第一个账户 33 | account, err := CreateNormalAccount(wallet.PublicKey, alias) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | //创建钱包资源文件夹 39 | walletDataFolder := filepath.Join(dbPath, account.FileName()+".db") 40 | file.MkdirAll(walletDataFolder) 41 | 42 | owWallet := openwallet.Wallet{ 43 | Alias: account.Alias, 44 | RootPub: wallet.PublicKey, 45 | DBFile: walletDataFolder, 46 | } 47 | return &owWallet, nil 48 | } 49 | 50 | //GetMerchantWalletList 获取钱包列表 51 | func (w *WalletManager) GetMerchantWalletList() ([]*openwallet.Wallet, error) { 52 | 53 | return nil, nil 54 | } 55 | 56 | //ConfigMerchantWallet 钱包工具配置接口 57 | func (w *WalletManager) ConfigMerchantWallet(wallet *openwallet.Wallet) error { 58 | 59 | return nil 60 | } 61 | 62 | //ImportMerchantAddress 导入地址 63 | func (w *WalletManager) ImportMerchantAddress(addresses []*openwallet.Address) error { 64 | 65 | //写入到数据库中 66 | 67 | return nil 68 | } 69 | 70 | //CreateMerchantAddress 创建钱包地址 71 | func (w *WalletManager) CreateMerchantAddress(walletID string, count int) ([]*openwallet.Address, error) { 72 | return nil, nil 73 | } 74 | 75 | //GetMerchantAddressList 获取钱包地址 76 | func (w *WalletManager) GetMerchantAddressList(walletID string, offset uint64, limit uint64) ([]*openwallet.Address, error) { 77 | return nil, nil 78 | } 79 | -------------------------------------------------------------------------------- /assets/icon/models.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package icon 17 | 18 | import ( 19 | "os" 20 | "strings" 21 | ) 22 | 23 | type Key struct { 24 | Address string `storm:"id"` 25 | PublicKey []byte 26 | PrivateKey []byte 27 | } 28 | 29 | type Transaction struct { 30 | From string 31 | To string 32 | Value string //0x + Hex string 33 | Timestamp string 34 | Nonce string 35 | StepLimit string 36 | Tx_hash string 37 | } 38 | 39 | // skipKeyFile ignores editor backups, hidden files and folders/symlinks. 40 | func skipKeyFile(fi os.FileInfo) bool { 41 | // Skip editor backups and UNIX-style hidden files. 42 | if strings.HasSuffix(fi.Name(), "~") || strings.HasPrefix(fi.Name(), ".") { 43 | return true 44 | } 45 | // Skip misc special files, directories (yes, symlinks too). 46 | if fi.IsDir() || fi.Mode()&os.ModeType != 0 { 47 | return true 48 | } 49 | return false 50 | } -------------------------------------------------------------------------------- /assets/luxapla/luxapla.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package luxapla 17 | 18 | import ( 19 | "github.com/blocktree/openwallet/v2/assets/obyte" 20 | "github.com/blocktree/openwallet/v2/log" 21 | ) 22 | 23 | const ( 24 | //币种 25 | Symbol = "LAC" 26 | ) 27 | 28 | type WalletManager struct { 29 | *obyte.WalletManager 30 | } 31 | 32 | func NewWalletManager() *WalletManager { 33 | wm := WalletManager{} 34 | wm.WalletManager = obyte.NewWalletManager() 35 | wm.Config = obyte.NewConfig(Symbol) 36 | wm.Log = log.NewOWLogger(wm.Symbol()) 37 | return &wm 38 | } 39 | 40 | //FullName 币种全名 41 | func (wm *WalletManager) FullName() string { 42 | return "Luxapla" 43 | } 44 | -------------------------------------------------------------------------------- /assets/monero/manager_addrRef.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package monero 17 | -------------------------------------------------------------------------------- /assets/obyte/manager_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package obyte 17 | 18 | import ( 19 | "github.com/blocktree/openwallet/v2/log" 20 | "testing" 21 | ) 22 | 23 | func testNewWalletManager() *WalletManager { 24 | 25 | tw := NewWalletManager() 26 | 27 | tw.Config.ServerAPI = "" 28 | tw.WalletClient = NewClient(tw.Config.ServerAPI, "", true) 29 | 30 | return tw 31 | } 32 | 33 | func TestWalletManager_GetInfo(t *testing.T) { 34 | tw := testNewWalletManager() 35 | b, err := tw.GetInfo() 36 | if err != nil { 37 | t.Errorf("GetInfo failed unexpected error: %v\n", err) 38 | } else { 39 | log.Infof("GetInfo info: %v", b) 40 | } 41 | } 42 | 43 | func TestWalletManager_GetNewAddress(t *testing.T) { 44 | tw := testNewWalletManager() 45 | b, err := tw.GetNewAddress() 46 | if err != nil { 47 | t.Errorf("GetNewAddress failed unexpected error: %v\n", err) 48 | } else { 49 | log.Infof("GetNewAddress: %+v", b) 50 | } 51 | } 52 | 53 | func TestWalletManager_GetChangeAddress(t *testing.T) { 54 | tw := testNewWalletManager() 55 | b, err := tw.GetChangeAddress() 56 | if err != nil { 57 | t.Errorf("GetChangeAddress failed unexpected error: %v\n", err) 58 | } else { 59 | log.Infof("GetChangeAddress: %+v", b) 60 | } 61 | } 62 | 63 | func TestWalletManager_GetBalance(t *testing.T) { 64 | tw := testNewWalletManager() 65 | b, err := tw.GetBalance() 66 | if err != nil { 67 | t.Errorf("GetBalance failed unexpected error: %v\n", err) 68 | } else { 69 | log.Infof("GetBalance: %+v", b) 70 | } 71 | } 72 | 73 | func TestWalletManager_SendToAddress(t *testing.T) { 74 | tw := testNewWalletManager() 75 | b, err := tw.SendToAddress("I4CEUEFL7BOWXJUHE7XYKCDP4AA2QG3Z", 100) 76 | if err != nil { 77 | t.Errorf("SendToAddress failed unexpected error: %v\n", err) 78 | } else { 79 | log.Infof("SendToAddress: %+v", b) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /assets/obyte/model.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package obyte 17 | 18 | import "github.com/tidwall/gjson" 19 | 20 | type Address struct { 21 | Address string 22 | } 23 | 24 | func NewAddress(r gjson.Result) *Address { 25 | obj := &Address{} 26 | obj.Address = r.String() 27 | return obj 28 | } 29 | 30 | type Balance struct { 31 | Stable string 32 | Pending string 33 | } 34 | 35 | func NewBalance(r gjson.Result) *Balance { 36 | obj := &Balance{} 37 | obj.Stable = r.Get("stable").String() 38 | obj.Pending = r.Get("pending").String() 39 | return obj 40 | } 41 | -------------------------------------------------------------------------------- /assets/sia/api.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package sia 17 | 18 | import ( 19 | "encoding/base64" 20 | "fmt" 21 | "github.com/imroc/req" 22 | "github.com/pkg/errors" 23 | "github.com/tidwall/gjson" 24 | "log" 25 | "net/http" 26 | ) 27 | 28 | // A Client is a Bitcoin RPC client. It performs RPCs over HTTP using JSON 29 | // request and responses. A Client must be configured with a secret token 30 | // to authenticate with other Cores on the network. 31 | type Client struct { 32 | BaseURL string 33 | Auth string 34 | Debug bool 35 | 36 | //Client *req.Req 37 | } 38 | 39 | type Response struct { 40 | Code int `json:"code,omitempty"` 41 | Error interface{} `json:"error,omitempty"` 42 | Result interface{} `json:"result,omitempty"` 43 | Message string `json:"message,omitempty"` 44 | Id string `json:"id,omitempty"` 45 | } 46 | 47 | // Call calls for batch address 48 | func (c *Client) CallBatchAddress(path, method string, request interface{}) ([]byte, error) { 49 | 50 | url := c.BaseURL + "/" + path 51 | 52 | authHeader := req.Header{ 53 | "Accept": "application/json", 54 | "User-Agent": "Sia-Agent", 55 | "Authorization": "Basic " + basicAuth("", c.Auth), 56 | } 57 | 58 | r, err := req.Do( 59 | method, 60 | url, 61 | request, 62 | authHeader) 63 | 64 | if err != nil { 65 | return nil, err 66 | } 67 | 68 | return r.Bytes(), nil 69 | } 70 | 71 | func (c *Client) Call(path, method string, request interface{}) ([]byte, error) { 72 | 73 | url := c.BaseURL + "/" + path 74 | 75 | authHeader := req.Header{ 76 | "Accept": "application/json", 77 | "User-Agent": "Sia-Agent", 78 | "Authorization": "Basic " + basicAuth("", c.Auth), 79 | } 80 | 81 | if c.Debug { 82 | log.Println("Start Request API...") 83 | } 84 | 85 | r, err := req.Do( 86 | method, 87 | url, 88 | request, 89 | authHeader) 90 | 91 | if c.Debug { 92 | log.Println("Request API Completed") 93 | } 94 | 95 | if c.Debug { 96 | log.Printf("%+v\n", r) 97 | } 98 | 99 | if err != nil { 100 | return nil, err 101 | } 102 | 103 | if r.Response().StatusCode != http.StatusOK { 104 | message := gjson.GetBytes(r.Bytes(), "message").String() 105 | message = fmt.Sprintf("[%s]%s", r.Response().Status, message) 106 | return nil, errors.New(message) 107 | } 108 | 109 | return r.Bytes(), nil 110 | } 111 | 112 | // See 2 (end of page 4) http://www.ietf.org/rfc/rfc2617.txt 113 | // "To receive authorization, the client sends the userid and password, 114 | // separated by a single colon (":") character, within a base64 115 | // encoded string in the credentials." 116 | // It is not meant to be urlencoded. 117 | func basicAuth(username, password string) string { 118 | auth := username + ":" + password 119 | return base64.StdEncoding.EncodeToString([]byte(auth)) 120 | } 121 | -------------------------------------------------------------------------------- /assets/sia/model.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package sia 17 | 18 | import ( 19 | "github.com/asdine/storm" 20 | "github.com/blocktree/openwallet/v2/common/file" 21 | "github.com/tidwall/gjson" 22 | "path/filepath" 23 | ) 24 | 25 | //Wallet 钱包模型 26 | type Wallet struct { 27 | WalletID string `json:"rootid"` 28 | Alias string `json:"alias"` 29 | Balance string `json:"balance"` 30 | Password string `json:"password"` 31 | RootPub string `json:"rootpub"` 32 | KeyFile string 33 | 34 | ConfirmBalance string `json:"confirmedsiacoinbalance"` 35 | 36 | OutgoingSC string `json:"unconfirmedoutgoingsiacoins"` 37 | IncomingSC string `json:"unconfirmedincomingsiacoins"` 38 | 39 | SiaFundBalance string `json:"siafundbalance"` 40 | SiaCoinClaimBalance string `json:"siacoinclaimbalance"` 41 | 42 | Rescanning bool `json:"rescanning"` 43 | Unlocked bool `json:"unlocked"` 44 | Encrypted bool `json:"encrypted"` 45 | } 46 | 47 | //NewWallet 创建钱包 48 | func NewWallet(json gjson.Result) *Wallet { 49 | w := &Wallet{} 50 | //解析json 51 | w.ConfirmBalance = gjson.Get(json.Raw, "confirmedsiacoinbalance").String() 52 | 53 | w.OutgoingSC = gjson.Get(json.Raw, "unconfirmedoutgoingsiacoins").String() 54 | w.IncomingSC = gjson.Get(json.Raw, "unconfirmedincomingsiacoins").String() 55 | 56 | w.SiaFundBalance = gjson.Get(json.Raw, "siafundbalance").String() 57 | w.SiaCoinClaimBalance = gjson.Get(json.Raw, "siacoinclaimbalance").String() 58 | 59 | w.Rescanning = gjson.Get(json.Raw, "rescanning").Bool() 60 | w.Unlocked = gjson.Get(json.Raw, "unlocked").Bool() 61 | w.Encrypted = gjson.Get(json.Raw, "encrypted").Bool() 62 | 63 | return w 64 | } 65 | 66 | //HDKey 获取钱包密钥,需要密码 67 | //func (w *Wallet) HDKey(password string) (*keystore.HDKey, error) { 68 | // key, err := storage.GetKey(w.WalletID, w.KeyFile, password) 69 | // if err != nil { 70 | // return nil, err 71 | // } 72 | // return key, err 73 | //} 74 | 75 | //openDB 打开钱包数据库 76 | func (w *Wallet) OpenDB() (*storm.DB, error) { 77 | file.MkdirAll(dbPath) 78 | file := filepath.Join(dbPath, w.FileName()+".db") 79 | return storm.Open(file) 80 | 81 | } 82 | 83 | //FileName 该钱包定义的文件名规则 84 | func (w *Wallet) FileName() string { 85 | return w.Alias + "-" + w.WalletID 86 | } 87 | 88 | type Account struct { 89 | Alias string `json:"alias"` 90 | ID string `json:"id"` 91 | KeyIndex int64 `json:"key_index"` 92 | Quorum int64 `json:"quorum"` 93 | XPubs []string `json:"xpubs"` 94 | } 95 | 96 | type Address struct { 97 | //Alias string 98 | //AccountId string 99 | Address string 100 | } 101 | 102 | func NewAddress(json gjson.Result) *Address { 103 | 104 | a := &Address{} 105 | //解析json 106 | a.Address = gjson.Get(json.Raw, "address").String() 107 | return a 108 | } 109 | -------------------------------------------------------------------------------- /assets/tezos/api.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package tezos 17 | 18 | import ( 19 | "github.com/imroc/req" 20 | "log" 21 | ) 22 | 23 | type Client struct { 24 | BaseURL string 25 | Debug bool 26 | Client *req.Req 27 | Header req.Header 28 | } 29 | 30 | func NewClient(url string, debug bool) *Client { 31 | c := Client{ 32 | BaseURL: url, 33 | Debug: debug, 34 | } 35 | 36 | api := req.New() 37 | 38 | c.Client = api 39 | c.Header = req.Header{"Content-Type": "application/json"} 40 | 41 | return &c 42 | } 43 | 44 | func (c *Client) CallGetHeader() []byte { 45 | url := c.BaseURL + "/chains/main/blocks/head/header" 46 | param := make(req.QueryParam, 0) 47 | 48 | r, err := c.Client.Get(url, param) 49 | if err != nil { 50 | log.Println(err) 51 | return nil 52 | } 53 | 54 | return r.Bytes() 55 | } 56 | 57 | func (c *Client) CallGetCounter(pkh string) []byte { 58 | url := c.BaseURL + "/chains/main/blocks/head/context/contracts/" + pkh + "/counter" 59 | 60 | r, err := c.Client.Get(url) 61 | if err != nil { 62 | log.Println(err) 63 | return nil 64 | } 65 | 66 | //因为结果为"number"\n ,所以去掉双引号和\n 67 | lenght := len(r.Bytes()) 68 | return r.Bytes()[1:lenght-2] 69 | } 70 | 71 | func (c *Client) CallGetManagerKey(pkh string) []byte { 72 | url := c.BaseURL + "/chains/main/blocks/head/context/contracts/" + pkh + "/manager_key" 73 | 74 | r, err := c.Client.Get(url) 75 | if err != nil { 76 | log.Println(err) 77 | return nil 78 | } 79 | 80 | return r.Bytes() 81 | } 82 | 83 | func (c *Client) CallForgeOps(chain_id string, head_hash string, body interface{}) string { 84 | url := c.BaseURL + "/chains/" + chain_id + "/blocks/" + head_hash + "/helpers/forge/operations" 85 | param := make(req.Param, 0) 86 | 87 | //log.Println(body) 88 | r, err := c.Client.Post(url, param, c.Header, req.BodyJSON(&body)) 89 | if err != nil { 90 | log.Println(err) 91 | return "" 92 | } 93 | //因为结果为"hex"\n ,所以去掉双引号和\n 94 | lenght := len(r.Bytes()) 95 | return string(r.Bytes()[1:lenght-2]) 96 | } 97 | 98 | func (c *Client) CallPreapplyOps(body interface{}) []byte{ 99 | url := c.BaseURL + "/chains/main/blocks/head/helpers/preapply/operations" 100 | param := make(req.Param, 0) 101 | 102 | r, err := c.Client.Post(url, param, c.Header, req.BodyJSON(&body)) 103 | if err != nil { 104 | log.Println(err) 105 | return nil 106 | } 107 | 108 | return r.Bytes() 109 | } 110 | 111 | func (c *Client) CallInjectOps(body string) []byte { 112 | url := c.BaseURL + "/injection/operation" 113 | param := make(req.Param, 0) 114 | 115 | r, err := c.Client.Post(url, param, c.Header, req.BodyJSON(&body)) 116 | 117 | if err != nil { 118 | log.Println(err.Error()) 119 | return nil 120 | } 121 | 122 | return r.Bytes() 123 | } 124 | 125 | func (c *Client) CallGetbalance(addr string) []byte { 126 | url := c.BaseURL + "/chains/main/blocks/head/context/contracts/" + addr + "/balance" 127 | param := make(req.QueryParam, 0) 128 | 129 | r, err := c.Client.Get(url, param) 130 | if err != nil { 131 | log.Println(err) 132 | return nil 133 | } 134 | 135 | //因为结果为"number"\n ,所以去掉双引号和\n 136 | lenght := len(r.Bytes()) 137 | return r.Bytes()[1:lenght-2] 138 | } 139 | 140 | -------------------------------------------------------------------------------- /assets/tezos/models.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package tezos 17 | 18 | import ( 19 | "os" 20 | "strings" 21 | ) 22 | 23 | type Key struct { 24 | Address string `storm:"id"` 25 | PublicKey string 26 | PrivateKey []byte 27 | } 28 | 29 | // skipKeyFile ignores editor backups, hidden files and folders/symlinks. 30 | func skipKeyFile(fi os.FileInfo) bool { 31 | // Skip editor backups and UNIX-style hidden files. 32 | if strings.HasSuffix(fi.Name(), "~") || strings.HasPrefix(fi.Name(), ".") { 33 | return true 34 | } 35 | // Skip misc special files, directories (yes, symlinks too). 36 | if fi.IsDir() || fi.Mode()&os.ModeType != 0 { 37 | return true 38 | } 39 | return false 40 | } -------------------------------------------------------------------------------- /cmd/utils/log.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package utils 17 | 18 | import ( 19 | "fmt" 20 | "github.com/astaxie/beego/logs" 21 | "github.com/blocktree/openwallet/v2/common/file" 22 | "github.com/blocktree/openwallet/v2/log" 23 | "path/filepath" 24 | ) 25 | 26 | //SetupLog 配置日志 27 | func SetupLog(logDir, logFile string, debug bool) { 28 | 29 | //记录日志 30 | logLevel := log.LevelInformational 31 | if debug { 32 | logLevel = log.LevelDebug 33 | } 34 | 35 | if len(logDir) > 0 { 36 | file.MkdirAll(logDir) 37 | logFile := filepath.Join(logDir, logFile) 38 | logConfig := fmt.Sprintf(`{"filename":"%s","level":%d,"daily":true,"maxdays":7,"maxsize":0}`, logFile, logLevel) 39 | //log.Println(logConfig) 40 | log.SetLogger(logs.AdapterFile, logConfig) 41 | log.SetLogger(logs.AdapterConsole, logConfig) 42 | } else { 43 | log.SetLevel(logLevel) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /cmd/wmd/commands/config.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package commands 17 | 18 | /* 19 | 20 | var ( 21 | // 钱包命令 22 | CmdConfig = cli.Command{ 23 | Name: "config", 24 | Usage: "Manage wallet config", 25 | Action: configWMD, 26 | ArgsUsage: "", 27 | Category: "Application COMMANDS", 28 | Flags: []cli.Flag{ 29 | utils.SymbolFlag, 30 | utils.InitFlag, 31 | }, 32 | Description: ` 33 | Manage wallet config 34 | 35 | `, 36 | // Subcommands: []cli.Command{ 37 | // { 38 | // //查看配置文件信息 39 | // Name: "init", 40 | // Usage: "Init config flow", 41 | // Action: configWallet, 42 | // Category: "CONFIG COMMANDS", 43 | // Flags: []cli.Flag{ 44 | // utils.SymbolFlag, 45 | // }, 46 | // Description: ` 47 | // wmd config init -s ada 48 | // 49 | //Init config flow. 50 | // 51 | // `, 52 | // }, 53 | // { 54 | // //查看配置文件信息 55 | // Name: "see", 56 | // Usage: "See Wallet config info", 57 | // Action: configSee, 58 | // Category: "CONFIG COMMANDS", 59 | // Flags: []cli.Flag{ 60 | // utils.SymbolFlag, 61 | // }, 62 | // Description: ` 63 | // wmd config see -s ada 64 | // 65 | //See Wallet config info. 66 | // 67 | // `, 68 | // }, 69 | // }, 70 | } 71 | ) 72 | 73 | func configWMD(c *cli.Context) error { 74 | symbol := c.String("symbol") 75 | if len(symbol) == 0 { 76 | log.Error("Argument -s is missing") 77 | return nil 78 | } 79 | m, ok := assets.GetWMD(symbol).(assets.ConfigManager) 80 | if !ok { 81 | log.Error(symbol, " wallet manager is not register") 82 | return nil 83 | } 84 | isInit := c.Bool("init") 85 | subModule := c.Args().Get(0) 86 | 87 | if isInit { 88 | return m.SetConfigFlow(subModule) 89 | } else { 90 | return m.ShowConfigInfo(subModule) 91 | } 92 | } 93 | 94 | //configWallet 配置钱包流程 95 | func configWallet(c *cli.Context) error { 96 | symbol := c.String("symbol") 97 | if len(symbol) == 0 { 98 | log.Error("Argument -s is missing") 99 | return nil 100 | } 101 | m, ok := assets.GetWMD(symbol).(assets.WalletManager) 102 | if !ok { 103 | log.Error(symbol, " wallet manager is not register") 104 | return nil 105 | } 106 | //配置钱包 107 | err := m.InitConfigFlow() 108 | if err != nil { 109 | log.Error("unexpected error: ", err) 110 | } 111 | return err 112 | } 113 | 114 | //configSee 查看钱包配置信息 115 | func configSee(c *cli.Context) error { 116 | symbol := c.String("symbol") 117 | if len(symbol) == 0 { 118 | log.Error("Argument -s is missing") 119 | return nil 120 | } 121 | m, ok := assets.GetWMD(symbol).(assets.WalletManager) 122 | if !ok { 123 | log.Error(symbol, " wallet manager is not register") 124 | return nil 125 | } 126 | err := m.ShowConfig() 127 | if err != nil { 128 | log.Error("unexpected error: ", err) 129 | } 130 | return err 131 | } 132 | 133 | */ -------------------------------------------------------------------------------- /cmd/wmd/commands/merchant.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package commands 17 | 18 | /* 19 | 20 | var ( 21 | // 钱包命令 22 | CmdMerchant = cli.Command{ 23 | Name: "merchant", 24 | Usage: "Manage merchant node", 25 | ArgsUsage: "", 26 | Category: "Application COMMANDS", 27 | Description: ` 28 | Use merchant commands to join merchant server 29 | 30 | `, 31 | Subcommands: []cli.Command{ 32 | { 33 | //创建或查看本地通信密钥对 34 | Name: "keychain", 35 | Usage: "create or see node keychain", 36 | ArgsUsage: "", 37 | Action: getMerchantKeychain, 38 | Category: "MERCHANT COMMANDS", 39 | Flags: []cli.Flag{ 40 | utils.InitFlag, 41 | }, 42 | Description: ` 43 | wmd merchant keychain [-i] 44 | 45 | This command will show the local publicKey and merchant publicKey. 46 | 47 | `, 48 | }, 49 | { 50 | //加入并连接到商户节点 51 | Name: "join", 52 | Usage: "Join and connect merchant node", 53 | Action: joinMerchantNode, 54 | Category: "MERCHANT COMMANDS", 55 | Description: ` 56 | wmd merchant join 57 | 58 | This command will connect and join merchant node. 59 | 60 | `, 61 | }, 62 | 63 | { 64 | //配置商户 65 | Name: "config", 66 | Usage: "Start a timer to sum wallet balance", 67 | ArgsUsage: "", 68 | Action: configMerchantNode, 69 | Category: "MERCHANT COMMANDS", 70 | Flags: []cli.Flag{ 71 | utils.InitFlag, 72 | }, 73 | Description: ` 74 | wmd wallet config [i] 75 | 76 | `, 77 | }, 78 | }, 79 | } 80 | ) 81 | 82 | func getMerchantKeychain(c *cli.Context) error { 83 | 84 | var ( 85 | err error 86 | ) 87 | 88 | isInit := c.Bool("init") 89 | 90 | if isInit { 91 | err = merchant.InitMerchantKeychainFlow() 92 | } else { 93 | err = merchant.GetMerchantKeychain() 94 | } 95 | 96 | if err != nil { 97 | log.Error("unexpected error: ", err) 98 | } 99 | 100 | return err 101 | } 102 | 103 | func joinMerchantNode(c *cli.Context) error { 104 | var ( 105 | err error 106 | ) 107 | 108 | logDir := c.GlobalString("logdir") 109 | debug := c.GlobalBool("debug") 110 | utils.SetupLog(logDir, "merchant.log", debug) 111 | 112 | err = merchant.JoinMerchantNodeFlow() 113 | if err != nil { 114 | log.Error("unexpected error: ", err) 115 | } 116 | return err 117 | } 118 | 119 | func configMerchantNode(c *cli.Context) error { 120 | var ( 121 | err error 122 | ) 123 | 124 | isInit := c.Bool("init") 125 | 126 | if isInit { 127 | err = merchant.ConfigMerchantFlow() 128 | } else { 129 | err = merchant.ShowMechantConfig() 130 | } 131 | 132 | if err != nil { 133 | log.Error("unexpected error: ", err) 134 | } 135 | return err 136 | } 137 | */ -------------------------------------------------------------------------------- /cmd/wmd/commands/version.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The OpenWallet Authors 3 | * This file is part of the OpenWallet library. 4 | * 5 | * The OpenWallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The OpenWallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package commands 17 | 18 | import ( 19 | "fmt" 20 | "gopkg.in/urfave/cli.v1" 21 | ) 22 | 23 | var ( 24 | Version = "" 25 | GitRev = "" 26 | BuildTime = "" 27 | ) 28 | 29 | var ( 30 | // 钱包命令 31 | CmdVersion = cli.Command{ 32 | Name: "version", 33 | Usage: "Manage multi currency wallet", 34 | ArgsUsage: "", 35 | Action: version, 36 | Category: "VERSION COMMANDS", 37 | } 38 | ) 39 | 40 | //walletConfig 钱包配置 41 | func version(c *cli.Context) error { 42 | fmt.Printf("Version: %s\n", Version) 43 | fmt.Printf("GitRev: %s\n", GitRev) 44 | fmt.Printf("BuildTime: %s\n", BuildTime) 45 | return nil 46 | } 47 | -------------------------------------------------------------------------------- /cmd/wmd/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package main 17 | 18 | import ( 19 | "fmt" 20 | "github.com/blocktree/openwallet/v2/cmd/utils" 21 | "github.com/blocktree/openwallet/v2/cmd/wmd/commands" 22 | "gopkg.in/urfave/cli.v1" 23 | "os" 24 | "sort" 25 | ) 26 | 27 | const ( 28 | clientIdentifier = "wmd" // Client identifier to advertise over the network 29 | ) 30 | 31 | var ( 32 | // The app that holds all commands and flags. 33 | app = utils.NewApp(commands.GitRev, "the Wallet Manager Driver command line interface") 34 | ) 35 | 36 | func init() { 37 | // Initialize the CLI app and start openw 38 | app.Name = "wmd" 39 | app.Action = wmd 40 | app.HideVersion = true // we have a command to print the version 41 | app.Copyright = "Copyright 2019 The openwallet Authors" 42 | app.Version = commands.Version 43 | app.Commands = []cli.Command{ 44 | commands.CmdWallet, 45 | commands.CmdVersion, 46 | //commands.CmdNode, 47 | //commands.CmdConfig, 48 | //commands.CmdMerchant, 49 | } 50 | app.Flags = []cli.Flag{ 51 | utils.AppNameFlag, 52 | utils.LogDirFlag, 53 | utils.LogDebugFlag, 54 | } 55 | 56 | sort.Sort(cli.CommandsByName(app.Commands)) 57 | } 58 | 59 | func main() { 60 | 61 | if err := app.Run(os.Args); err != nil { 62 | fmt.Fprintln(os.Stderr, err) 63 | os.Exit(1) 64 | } 65 | } 66 | 67 | //wmd is a util to manager multi currency symbol wallet 68 | func wmd(ctx *cli.Context) error { 69 | 70 | return nil 71 | } 72 | -------------------------------------------------------------------------------- /common/bool.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | 19 | func BoolToUInt(b bool) uint64 { 20 | if b { 21 | return 1 22 | } 23 | return 0 24 | } 25 | 26 | func UIntToBool(u uint64) bool { 27 | if u == 1 { 28 | return true 29 | } 30 | return false 31 | } 32 | -------------------------------------------------------------------------------- /common/bytes.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | import "encoding/hex" 19 | 20 | // ToHex returns the hex representation of b, prefixed with '0x'. 21 | // For empty slices, the return value is "0x0". 22 | // 23 | // Deprecated: use hexutil.Encode instead. 24 | func ToHex(b []byte) string { 25 | hex := Bytes2Hex(b) 26 | if len(hex) == 0 { 27 | hex = "0" 28 | } 29 | return "0x" + hex 30 | } 31 | 32 | // ToHexArray creates a array of hex-string based on []byte 33 | func ToHexArray(b [][]byte) []string { 34 | r := make([]string, len(b)) 35 | for i := range b { 36 | r[i] = ToHex(b[i]) 37 | } 38 | return r 39 | } 40 | 41 | // FromHex returns the bytes represented by the hexadecimal string s. 42 | // s may be prefixed with "0x". 43 | func FromHex(s string) []byte { 44 | if len(s) > 1 { 45 | if s[0:2] == "0x" || s[0:2] == "0X" { 46 | s = s[2:] 47 | } 48 | } 49 | if len(s)%2 == 1 { 50 | s = "0" + s 51 | } 52 | return Hex2Bytes(s) 53 | } 54 | 55 | // CopyBytes returns an exact copy of the provided bytes. 56 | func CopyBytes(b []byte) (copiedBytes []byte) { 57 | if b == nil { 58 | return nil 59 | } 60 | copiedBytes = make([]byte, len(b)) 61 | copy(copiedBytes, b) 62 | 63 | return 64 | } 65 | 66 | // hasHexPrefix validates str begins with '0x' or '0X'. 67 | func hasHexPrefix(str string) bool { 68 | return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') 69 | } 70 | 71 | // isHexCharacter returns bool of c being a valid hexadecimal. 72 | func isHexCharacter(c byte) bool { 73 | return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F') 74 | } 75 | 76 | // isHex validates whether each byte is valid hexadecimal string. 77 | func isHex(str string) bool { 78 | if len(str)%2 != 0 { 79 | return false 80 | } 81 | for _, c := range []byte(str) { 82 | if !isHexCharacter(c) { 83 | return false 84 | } 85 | } 86 | return true 87 | } 88 | 89 | // Bytes2Hex returns the hexadecimal encoding of d. 90 | func Bytes2Hex(d []byte) string { 91 | return hex.EncodeToString(d) 92 | } 93 | 94 | // Hex2Bytes returns the bytes represented by the hexadecimal string str. 95 | func Hex2Bytes(str string) []byte { 96 | h, _ := hex.DecodeString(str) 97 | return h 98 | } 99 | 100 | // Hex2BytesFixed returns bytes of a specified fixed length flen. 101 | func Hex2BytesFixed(str string, flen int) []byte { 102 | h, _ := hex.DecodeString(str) 103 | if len(h) == flen { 104 | return h 105 | } 106 | if len(h) > flen { 107 | return h[len(h)-flen:] 108 | } 109 | hh := make([]byte, flen) 110 | copy(hh[flen-len(h):flen], h) 111 | return hh 112 | } 113 | 114 | // RightPadBytes zero-pads slice to the right up to length l. 115 | func RightPadBytes(slice []byte, l int) []byte { 116 | if l <= len(slice) { 117 | return slice 118 | } 119 | 120 | padded := make([]byte, l) 121 | copy(padded, slice) 122 | 123 | return padded 124 | } 125 | 126 | // LeftPadBytes zero-pads slice to the left up to length l. 127 | func LeftPadBytes(slice []byte, l int) []byte { 128 | if l <= len(slice) { 129 | return slice 130 | } 131 | 132 | padded := make([]byte, l) 133 | copy(padded[l-len(slice):], slice) 134 | 135 | return padded 136 | } 137 | -------------------------------------------------------------------------------- /common/check_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | import "testing" 19 | 20 | func TestIsRealNumberString(t *testing.T) { 21 | 22 | tests := []struct { 23 | text string 24 | tag string 25 | }{ 26 | { 27 | text: "-90000000", 28 | tag: "zheng shu", 29 | }, 30 | { 31 | text: "-1212", 32 | tag: "zheng shu", 33 | }, 34 | { 35 | text: "1.232", 36 | tag: "xiao shu", 37 | }, 38 | { 39 | text: "-1.232", 40 | tag: "xiao shu", 41 | }, 42 | { 43 | text: "dfsfsdfsdf", 44 | tag: "charactor", 45 | }, 46 | } 47 | 48 | for i, test := range tests { 49 | 50 | t.Logf("TestIsRealNumber[%d] = %v", i, IsRealNumberString(test.text)) 51 | 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /common/file/copy.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "strings" 8 | ) 9 | 10 | // CopyEnv describes the environment in which a copy is invoked. 11 | type CopyEnv struct { 12 | FollowSymbolicLinks bool 13 | Overwrite bool 14 | Verbose bool 15 | } 16 | 17 | func (c *CopyEnv) Copy(src, dst string) error { 18 | return nil 19 | } 20 | 21 | var std = &CopyEnv{ 22 | FollowSymbolicLinks: false, 23 | Overwrite: false, 24 | Verbose: false, 25 | } 26 | 27 | // Copy copies the file or directory from source path to destination path with 28 | // the standart copy environment. For more control create a custom copy environment. 29 | func Copy(src, dst string) error { 30 | if dst == "." { 31 | dst = filepath.Base(src) 32 | } 33 | 34 | if src == dst { 35 | return fmt.Errorf("%s and %s are identical (not copied).", src, dst) 36 | } 37 | 38 | if !Exists(src) { 39 | return fmt.Errorf("%s: no such file or directory.", src) 40 | } 41 | 42 | if Exists(dst) && IsFile(dst) { 43 | return fmt.Errorf("%s is a directory (not copied).", src) 44 | } 45 | 46 | srcBase, _ := filepath.Split(src) 47 | walks := 0 48 | 49 | // dstPath returns the rewritten destination path for the given source path 50 | dstPath := func(srcPath string) string { 51 | // some/random/long/path/example/hello.txt -> example/hello.txt 52 | srcPath = strings.TrimPrefix(srcPath, srcBase) 53 | 54 | // example/hello.txt -> destination/example/hello.txt 55 | if walks != 0 { 56 | return filepath.Join(dst, srcPath) 57 | } 58 | 59 | // hello.txt -> example/hello.txt 60 | if Exists(dst) && !IsFile(dst) { 61 | return filepath.Join(dst, filepath.Base(srcPath)) 62 | } 63 | 64 | // hello.txt -> test.txt 65 | return dst 66 | } 67 | 68 | filepath.Walk(src, func(srcPath string, file os.FileInfo, err error) error { 69 | defer func() { walks++ }() 70 | 71 | if file.IsDir() { 72 | //fmt.Printf("copy dir from '%s' to '%s'\n", srcPath, dstPath(srcPath)) 73 | os.MkdirAll(dstPath(srcPath), 0755) 74 | } else { 75 | //fmt.Printf("copy file from '%s' to '%s'\n", srcPath, dstPath(srcPath)) 76 | err = copyFile(srcPath, dstPath(srcPath)) 77 | if err != nil { 78 | fmt.Println(err) 79 | } 80 | } 81 | 82 | return nil 83 | }) 84 | 85 | return nil 86 | } 87 | -------------------------------------------------------------------------------- /common/file/copy_test.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "testing" 5 | "log" 6 | ) 7 | 8 | func TestCopyFile(t *testing.T) { 9 | Delete("/myspace/dest/wallet.txt") 10 | err := Copy("/myspace/source/text-1232323.txt", "/myspace/dest/wallet.txt") 11 | if err != nil { 12 | log.Fatal(err) 13 | } 14 | } -------------------------------------------------------------------------------- /common/file/file_test.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "io/ioutil" 5 | "os" 6 | "path/filepath" 7 | "testing" 8 | ) 9 | 10 | var ( 11 | testPath = "." 12 | testPrefix = "test_" 13 | exampleFile = "exampleFile" 14 | exampleDir = "exampleDir" 15 | ) 16 | 17 | func cleanup() { 18 | os.Remove(exampleFile) 19 | os.RemoveAll(exampleDir) 20 | } 21 | 22 | func TestCopy(t *testing.T) { 23 | defer cleanup() 24 | 25 | testDir, err := ioutil.TempDir(testPath, testPrefix) 26 | if err != nil { 27 | t.Error(err) 28 | } 29 | defer os.RemoveAll(testDir) 30 | 31 | testDir2, err := ioutil.TempDir(testPath, testPrefix) 32 | if err != nil { 33 | t.Error(err) 34 | } 35 | defer os.RemoveAll(testDir2) 36 | 37 | testFile, err := ioutil.TempFile(testDir, testPrefix) 38 | if err != nil { 39 | t.Error(err) 40 | } 41 | defer os.Remove(testFile.Name()) 42 | 43 | // test cases: 44 | // 1. file to file 45 | err = Copy(testFile.Name(), exampleFile) 46 | if err != nil { 47 | t.Errorf("1: %s\n", err) 48 | } 49 | 50 | if !Exists(exampleFile) { 51 | t.Error("1: exampleFile does not exist") 52 | } 53 | 54 | // 2. file into directory 55 | err = Copy(testFile.Name(), testDir2) 56 | if err != nil { 57 | t.Errorf("2: %s\n", err) 58 | } 59 | 60 | if !Exists(filepath.Join(testDir2, filepath.Base(testFile.Name()))) { 61 | t.Errorf("2: testFile does not exist in %s\n", testDir2) 62 | } 63 | 64 | // 3. file to an existing file should give an error 65 | err = Copy(exampleFile, exampleFile) 66 | if err == nil { 67 | t.Errorf("3: %s\n", err) 68 | } 69 | 70 | // 4. dir to file should give an error 71 | err = Copy(testDir, exampleFile) 72 | if err != nil { 73 | t.Errorf("4: %s\n", err) 74 | } 75 | 76 | // 5. dir to an existing dir is not allowed due to infinite recursive loop 77 | err = Copy(testDir, testDir) 78 | if err == nil { 79 | t.Errorf("5: %s\n", err) 80 | } 81 | 82 | // 6. dir to dir 83 | t2, err := ioutil.TempDir(testDir, testPrefix) 84 | if err != nil { 85 | t.Error(err) 86 | } 87 | defer os.RemoveAll(t2) 88 | 89 | f, err := ioutil.TempFile(t2, testPrefix) 90 | if err != nil { 91 | t.Error(err) 92 | } 93 | defer os.Remove(f.Name()) 94 | 95 | err = Copy(testDir, exampleDir) 96 | if err != nil { 97 | t.Errorf("6: %s\n", err) 98 | } 99 | 100 | // final layout should bee: 101 | // exampleDir/ 102 | // testDir/ 103 | // t2/ 104 | // f 105 | // testFile 106 | 107 | if !Exists(exampleDir) { 108 | t.Error("6: exampleDir does not exist") 109 | } 110 | 111 | if !Exists(t2) { 112 | t.Error("6: t2 does not exist") 113 | } 114 | 115 | t1 := filepath.Join(exampleDir, testDir, filepath.Base(testFile.Name())) 116 | if !Exists(t1) { 117 | t.Error("6: testfile inside exampleDir does not exist", t1) 118 | } 119 | 120 | if !Exists(filepath.Join(t2, filepath.Base(f.Name()))) { 121 | t.Error("6: f file inside exampleDir does not exist") 122 | } 123 | } 124 | 125 | func TestWriteFile(t *testing.T) { 126 | content := "Hello, xxbandy.github.io!\n" 127 | WriteFile("testfile.txt", []byte(content), true) 128 | WriteFile("testfile.txt", []byte(content), true) 129 | WriteFile("testfile.txt", []byte(content), true) 130 | } 131 | 132 | func TestDelete(t *testing.T) { 133 | file := "/myspace/workplace/go-workspace/projects/src/github.com/blocktree/openwallet/cmd/wmd/wmd-linux-amd64" 134 | flag := Delete(file) 135 | if !flag { 136 | t.Log("DeleteFile failed!") 137 | } 138 | } -------------------------------------------------------------------------------- /common/float.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | //FloatProtocal 强化float的扩展方法 19 | type FloatProtocal interface { 20 | Float32(def ...float32) float32 21 | Float64(def ...float64) float64 22 | } 23 | -------------------------------------------------------------------------------- /common/int.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | import "strconv" 19 | 20 | /***************** 数值类型转字符串 *****************/ 21 | 22 | //Int 强化int类型 23 | type Int int 24 | 25 | //IntProtocal 强化int的扩展方法 26 | type IntProtocal interface { 27 | Int(def ...int) int 28 | Int8(def ...int8) int8 29 | Int16(def ...int16) int16 30 | Int32(def ...int32) int32 31 | Int64(def ...int64) int64 32 | } 33 | 34 | // ToString int转为string类型 35 | func (v Int) String() string { 36 | string := strconv.FormatInt(int64(v), 10) 37 | return string 38 | } 39 | 40 | -------------------------------------------------------------------------------- /common/math.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | import ( 19 | "fmt" 20 | "github.com/shopspring/decimal" 21 | "math/big" 22 | "strings" 23 | ) 24 | 25 | func StringNumToBigIntWithExp(amount string, exp int32) *big.Int { 26 | vDecimal, _ := decimal.NewFromString(amount) 27 | vDecimal = vDecimal.Shift(exp) 28 | bigInt, ok := new(big.Int).SetString(vDecimal.String(), 10) 29 | if !ok { 30 | return big.NewInt(0) 31 | } 32 | return bigInt 33 | } 34 | 35 | 36 | func IntToDecimals(amount int64, decimals int32) decimal.Decimal { 37 | return decimal.New(amount, 0).Shift(-decimals) 38 | } 39 | 40 | func BigIntToDecimals(amount *big.Int, decimals int32) decimal.Decimal { 41 | if amount == nil { 42 | return decimal.Zero 43 | } 44 | return decimal.NewFromBigInt(amount, 0).Shift(-decimals) 45 | } 46 | 47 | func StringValueToBigInt(value string, base int) (*big.Int, error) { 48 | bigvalue := new(big.Int) 49 | var success bool 50 | 51 | if value == "" { 52 | value = "0" 53 | } 54 | value = strings.TrimPrefix(value, "0x") 55 | 56 | _, success = bigvalue.SetString(value, base) 57 | if !success { 58 | return big.NewInt(0), fmt.Errorf("convert value [%v] to bigint failed, check the value and base passed through", value) 59 | } 60 | return bigvalue, nil 61 | } 62 | 63 | func BytesToDecimals(bits []byte, decimals int32) decimal.Decimal { 64 | if bits == nil { 65 | return decimal.Zero 66 | } 67 | amount := new(big.Int) 68 | amount.SetBytes(bits) 69 | return decimal.NewFromBigInt(amount, 0).Shift(-decimals) 70 | } 71 | -------------------------------------------------------------------------------- /common/math_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | import ( 19 | "testing" 20 | ) 21 | 22 | 23 | func TestStringNumToBigIntWithDecimals(t *testing.T) { 24 | num := StringNumToBigIntWithExp("3.223", 8) 25 | t.Logf("num : %v\n", num) 26 | t.Logf("num int64 : %v\n", num.Int64()) 27 | newnum := BigIntToDecimals(num, 8) 28 | t.Logf("newnum : %v\n", newnum.String()) 29 | } 30 | -------------------------------------------------------------------------------- /common/slice.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | import ( 19 | "reflect" 20 | ) 21 | 22 | // Contain 判断obj是否在target中,target支持的类型arrary,slice,map 23 | func Contain(obj interface{}, target interface{}) bool { 24 | targetValue := reflect.ValueOf(target) 25 | switch reflect.TypeOf(target).Kind() { 26 | case reflect.Slice, reflect.Array: 27 | for i := 0; i < targetValue.Len(); i++ { 28 | if targetValue.Index(i).Interface() == obj { 29 | return true 30 | } 31 | } 32 | case reflect.Map: 33 | if targetValue.MapIndex(reflect.ValueOf(obj)).IsValid() { 34 | return true 35 | } 36 | } 37 | 38 | return false 39 | } 40 | -------------------------------------------------------------------------------- /common/slice_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | import ( 19 | "fmt" 20 | "testing" 21 | ) 22 | 23 | func TestContain(t *testing.T) { 24 | testMap() 25 | testArray() 26 | testSlice() 27 | } 28 | 29 | func testArray() { 30 | a := 1 31 | b := [3]int{1, 2, 3} 32 | 33 | fmt.Println(Contain(a, b)) 34 | 35 | c := "a" 36 | d := [4]string{"b", "c", "d", "a"} 37 | fmt.Println(Contain(c, d)) 38 | 39 | e := 1.1 40 | f := [4]float64{1.2, 1.3, 1.1, 1.4} 41 | fmt.Println(Contain(e, f)) 42 | 43 | g := 1 44 | h := [4]interface{}{2, 4, 6, 1} 45 | fmt.Println(Contain(g, h)) 46 | 47 | i := [4]int64{} 48 | fmt.Println(Contain(a, i)) 49 | } 50 | 51 | func testSlice() { 52 | a := 1 53 | b := []int{1, 2, 3} 54 | 55 | fmt.Println(Contain(a, b)) 56 | 57 | c := "a" 58 | d := []string{"b", "c", "d", "a"} 59 | fmt.Println(Contain(c, d)) 60 | 61 | e := 1.1 62 | f := []float64{1.2, 1.3, 1.1, 1.4} 63 | fmt.Println(Contain(e, f)) 64 | 65 | g := 1 66 | h := []interface{}{2, 4, 6, 1} 67 | fmt.Println(Contain(g, h)) 68 | 69 | i := []int64{} 70 | fmt.Println(Contain(a, i)) 71 | } 72 | 73 | func testMap() { 74 | var a = map[int]string{1: "1", 2: "2"} 75 | fmt.Println(Contain(3, a)) 76 | 77 | var b = map[string]int{"1": 1, "2": 2} 78 | fmt.Println(Contain("1", b)) 79 | 80 | var c = map[string][]int{"1": {1, 2}, "2": {2, 3}} 81 | fmt.Println(Contain("6", c)) 82 | } 83 | -------------------------------------------------------------------------------- /common/string_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | import ( 19 | "fmt" 20 | "testing" 21 | ) 22 | 23 | // 测试明文AES加密 24 | func TestAES(t *testing.T) { 25 | var ( 26 | // appkey = "2d68067484a20f1a346b3cf28a898ed7f5736f5bacf0fe60449da95efdb97ad4" 27 | appsecret = "0dd1e322907ad7f55deaa35fec2aac97cae7931454d734364bc63f3e9b9f993a" 28 | planttext = String("考几分就;辣椒粉李经理发吉林省;发;快递放假;介绍费sdfaf") 29 | ciphertext string 30 | err error 31 | ) 32 | 33 | if ciphertext, err = planttext.AES(appsecret); err != nil { 34 | fmt.Println("err =", err.Error()) 35 | } 36 | 37 | fmt.Println("ciphertext = ", ciphertext) 38 | } 39 | 40 | //测试AES密文解密 41 | func TestUnAES(t *testing.T) { 42 | 43 | var ( 44 | // appkey = "2d68067484a20f1a346b3cf28a898ed7f5736f5bacf0fe60449da95efdb97ad4" 45 | appsecret = "0dd1e322907ad7f55deaa35fec2aac97cae7931454d734364bc63f3e9b9f993a" 46 | planttext = new(String) 47 | ciphertext = "Pr5nzcrcWtoJBjx3JrmeUwgftz3tWrpM8+/9BCduLEqcZBjNslDDiqWbvI+hpXMEZNsjorj3zpX2Sbolj/gpoLUqsXHN2UZmrdDCZY2M3PM=" 48 | err error 49 | // result interface{} 50 | ) 51 | 52 | err = planttext.UnAES(ciphertext, appsecret) 53 | 54 | fmt.Println("planttext = ", planttext) 55 | if err != nil { 56 | fmt.Println("err = ", err.Error()) 57 | } 58 | 59 | } 60 | 61 | // 测试各种基本类型转为String 62 | func TestTypeToString(t *testing.T) { 63 | var ( 64 | a = int8(10) 65 | b = int32(100) 66 | c = int64(1000) 67 | d = "sdfsf" 68 | f = 100.2 69 | g = 9999 70 | h = false 71 | i = []string{"12345", "asdfg"} 72 | j = map[string]interface{}{"a": "12345", "b": "asdfg"} 73 | k = struct { 74 | Name string 75 | Age uint64 76 | }{Name: "john", Age: 90} 77 | kv = make(map[string]interface{}, 0) 78 | ) 79 | 80 | kv["a"] = a 81 | kv["b"] = b 82 | kv["c"] = c 83 | kv["d"] = d 84 | kv["f"] = f 85 | kv["g"] = g 86 | kv["h"] = h 87 | kv["i"] = i 88 | kv["j"] = j 89 | kv["k"] = k 90 | 91 | for k, v := range kv { 92 | newString := NewString(v) 93 | fmt.Println(k, ":", newString) 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /common/time.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | import ( 19 | "time" 20 | "fmt" 21 | ) 22 | 23 | func ToISO8601(t ...time.Time) string { 24 | var tt time.Time 25 | if len(t) > 0 { 26 | tt = t[0] 27 | } else { 28 | tt = time.Now().UTC() 29 | } 30 | 31 | var tz string 32 | name, offset := tt.Zone() 33 | if name == "UTC" { 34 | tz = "Z" 35 | } else { 36 | tz = fmt.Sprintf("%03d00", offset/3600) 37 | } 38 | return fmt.Sprintf("%04d-%02d-%02dT%02d-%02d-%02d.%09d%s", tt.Year(), tt.Month(), tt.Day(), tt.Hour(), tt.Minute(), tt.Second(), tt.Nanosecond(), tz) 39 | } 40 | 41 | //timeFormat 格式化时间 42 | //@param format 在go中,为2006-01-02 15:04:05 43 | func TimeFormat(format string, t ...time.Time) string { 44 | var tt time.Time 45 | if len(t) > 0 { 46 | tt = t[0] 47 | } else { 48 | tt = time.Now() 49 | } 50 | s := tt.Format(format) 51 | return s 52 | } -------------------------------------------------------------------------------- /common/time_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package common 17 | 18 | import ( 19 | "testing" 20 | "time" 21 | "fmt" 22 | ) 23 | 24 | func TestTimeToTimestamp(t *testing.T) { 25 | 26 | count := 60 27 | year := 2018 28 | month := 2 29 | 30 | for i := 0; i 12 { 37 | month = 1 38 | year++ 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /concurrent/concurrent.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The OpenWallet Authors 3 | * This file is part of the OpenWallet library. 4 | * 5 | * The OpenWallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The OpenWallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package concurrent 17 | 18 | //ProducerToConsumerRuntime 生产消费者运行模型 19 | func ProducerToConsumerRuntime(producer chan interface{}, consumer chan interface{}) { 20 | 21 | var ( 22 | values = make([]interface{}, 0) 23 | ) 24 | 25 | for { 26 | 27 | var activeWorker chan<- interface{} 28 | var activeValue interface{} 29 | 30 | //当数据队列有数据时,释放顶部,传输给消费者 31 | if len(values) > 0 { 32 | activeWorker = consumer 33 | activeValue = values[0] 34 | } 35 | 36 | select { 37 | 38 | //生成者不断生成数据,插入到数据队列尾部 39 | case pa, exist := <-producer: 40 | if !exist { 41 | return 42 | } 43 | values = append(values, pa) 44 | case activeWorker <- activeValue: 45 | values = values[1:] 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /crypto/aes_utils.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import ( 4 | "bytes" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | ) 8 | 9 | // AESEncrypt AES加密 10 | // plantText 明文 11 | // key密钥 16字节,24字节,32字节 12 | // return 密文 13 | func AESEncrypt(plantText, key []byte) ([]byte, error) { 14 | block, err := aes.NewCipher(key) //选择加密算法 15 | if err != nil { 16 | return nil, err 17 | } 18 | plantText = PKCS7Padding(plantText, block.BlockSize()) 19 | 20 | blockModel := cipher.NewCBCEncrypter(block, key[:block.BlockSize()]) 21 | 22 | ciphertext := make([]byte, len(plantText)) 23 | 24 | blockModel.CryptBlocks(ciphertext, plantText) 25 | return ciphertext, nil 26 | } 27 | 28 | // PKCS7Padding PKCS7填充 29 | // ciphertext 明文 30 | // blockSize 分组大小 31 | // return 填充后的明文 32 | func PKCS7Padding(ciphertext []byte, blockSize int) []byte { 33 | padding := blockSize - len(ciphertext)%blockSize 34 | padtext := bytes.Repeat([]byte{byte(padding)}, padding) 35 | return append(ciphertext, padtext...) 36 | } 37 | 38 | // AESDecrypt AES加密 39 | // plantText 密码 40 | // key密钥 16字节,24字节,32字节 41 | // return 明文 42 | func AESDecrypt(ciphertext, key []byte) ([]byte, error) { 43 | block, err := aes.NewCipher(key) //选择加密算法 44 | if err != nil { 45 | return nil, err 46 | } 47 | blockModel := cipher.NewCBCDecrypter(block, key[:block.BlockSize()]) 48 | plantText := make([]byte, len(ciphertext)) 49 | blockModel.CryptBlocks(plantText, ciphertext) 50 | plantText = PKCS7UnPadding(plantText, block.BlockSize()) 51 | return plantText, nil 52 | } 53 | 54 | // PKCS7UnPadding PKCS7清理填充 55 | // ciphertext 填充后的明文 56 | // blockSize 分组大小 57 | // return 恢复后的明文 58 | func PKCS7UnPadding(plantText []byte, blockSize int) []byte { 59 | length := len(plantText) 60 | unpadding := int(plantText[length-1]) 61 | if length - unpadding < 0 { 62 | return nil 63 | } 64 | return plantText[:(length - unpadding)] 65 | } 66 | 67 | /******** String扩展,获得AES加密方法 ********/ 68 | 69 | //AESProtocal String扩展,获得AES加密方法 70 | type AESProtocal interface { 71 | AES(key string) (string, error) 72 | UnAES(aesBase64string string, key string) error 73 | } 74 | -------------------------------------------------------------------------------- /crypto/crypto_utils.go: -------------------------------------------------------------------------------- 1 | package crypto 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/md5" 6 | "crypto/sha1" 7 | "crypto/sha256" 8 | "fmt" 9 | "github.com/blocktree/openwallet/v2/crypto/sha3" 10 | ) 11 | 12 | //MD5 加密 13 | func GetMD5(str string) (md5str string) { 14 | data := []byte(str) 15 | has := md5.Sum(data) 16 | md5str = fmt.Sprintf("%x", has) 17 | return 18 | } 19 | 20 | //MD5 加密 21 | func MD5(data []byte) []byte { 22 | md := md5.Sum(data) 23 | return md[:] 24 | } 25 | 26 | //SHA1 加密 27 | func SHA1(data []byte) []byte { 28 | hash := sha1.New() 29 | hash.Write(data) 30 | md := hash.Sum(nil) 31 | return md 32 | } 33 | 34 | //SHA256 加密 35 | func SHA256(data []byte) []byte { 36 | hash := sha256.New() 37 | hash.Write(data) 38 | md := hash.Sum(nil) 39 | return md 40 | } 41 | 42 | //HmacSHA1 加密 43 | func HmacSHA1(secret string, data []byte) []byte { 44 | h := hmac.New(sha1.New, []byte(secret)) 45 | h.Write(data) 46 | md := h.Sum(nil) 47 | return md 48 | } 49 | 50 | //HmacMD5 加密 51 | func HmacMD5(secret string, data []byte) []byte { 52 | h := hmac.New(md5.New, []byte(secret)) 53 | h.Write(data) 54 | md := h.Sum(nil) 55 | return md 56 | } 57 | 58 | // Keccak256 calculates and returns the Keccak256 hash of the input data. 59 | func Keccak256(data ...[]byte) []byte { 60 | d := sha3.NewKeccak256() 61 | for _, b := range data { 62 | d.Write(b) 63 | } 64 | return d.Sum(nil) 65 | } 66 | -------------------------------------------------------------------------------- /crypto/sha3/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /crypto/sha3/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /crypto/sha3/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package sha3 implements the SHA-3 fixed-output-length hash functions and 6 | // the SHAKE variable-output-length hash functions defined by FIPS-202. 7 | // 8 | // Both types of hash function use the "sponge" construction and the Keccak 9 | // permutation. For a detailed specification see http://keccak.noekeon.org/ 10 | // 11 | // 12 | // Guidance 13 | // 14 | // If you aren't sure what function you need, use SHAKE256 with at least 64 15 | // bytes of output. The SHAKE instances are faster than the SHA3 instances; 16 | // the latter have to allocate memory to conform to the hash.Hash interface. 17 | // 18 | // If you need a secret-key MAC (message authentication code), prepend the 19 | // secret key to the input, hash with SHAKE256 and read at least 32 bytes of 20 | // output. 21 | // 22 | // 23 | // Security strengths 24 | // 25 | // The SHA3-x (x equals 224, 256, 384, or 512) functions have a security 26 | // strength against preimage attacks of x bits. Since they only produce "x" 27 | // bits of output, their collision-resistance is only "x/2" bits. 28 | // 29 | // The SHAKE-256 and -128 functions have a generic security strength of 256 and 30 | // 128 bits against all attacks, provided that at least 2x bits of their output 31 | // is used. Requesting more than 64 or 32 bytes of output, respectively, does 32 | // not increase the collision-resistance of the SHAKE functions. 33 | // 34 | // 35 | // The sponge construction 36 | // 37 | // A sponge builds a pseudo-random function from a public pseudo-random 38 | // permutation, by applying the permutation to a state of "rate + capacity" 39 | // bytes, but hiding "capacity" of the bytes. 40 | // 41 | // A sponge starts out with a zero state. To hash an input using a sponge, up 42 | // to "rate" bytes of the input are XORed into the sponge's state. The sponge 43 | // is then "full" and the permutation is applied to "empty" it. This process is 44 | // repeated until all the input has been "absorbed". The input is then padded. 45 | // The digest is "squeezed" from the sponge in the same way, except that output 46 | // output is copied out instead of input being XORed in. 47 | // 48 | // A sponge is parameterized by its generic security strength, which is equal 49 | // to half its capacity; capacity + rate is equal to the permutation's width. 50 | // Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means 51 | // that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. 52 | // 53 | // 54 | // Recommendations 55 | // 56 | // The SHAKE functions are recommended for most new uses. They can produce 57 | // output of arbitrary length. SHAKE256, with an output length of at least 58 | // 64 bytes, provides 256-bit security against all attacks. The Keccak team 59 | // recommends it for most applications upgrading from SHA2-512. (NIST chose a 60 | // much stronger, but much slower, sponge instance for SHA3-512.) 61 | // 62 | // The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. 63 | // They produce output of the same length, with the same security strengths 64 | // against all attacks. This means, in particular, that SHA3-256 only has 65 | // 128-bit collision resistance, because its output length is 32 bytes. 66 | package sha3 67 | -------------------------------------------------------------------------------- /crypto/sha3/hashes.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sha3 6 | 7 | // This file provides functions for creating instances of the SHA-3 8 | // and SHAKE hash functions, as well as utility functions for hashing 9 | // bytes. 10 | 11 | import ( 12 | "hash" 13 | ) 14 | 15 | // NewKeccak256 creates a new Keccak-256 hash. 16 | func NewKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} } 17 | 18 | // NewKeccak512 creates a new Keccak-512 hash. 19 | func NewKeccak512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x01} } 20 | 21 | // New224 creates a new SHA3-224 hash. 22 | // Its generic security strength is 224 bits against preimage attacks, 23 | // and 112 bits against collision attacks. 24 | func New224() hash.Hash { return &state{rate: 144, outputLen: 28, dsbyte: 0x06} } 25 | 26 | // New256 creates a new SHA3-256 hash. 27 | // Its generic security strength is 256 bits against preimage attacks, 28 | // and 128 bits against collision attacks. 29 | func New256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x06} } 30 | 31 | // New384 creates a new SHA3-384 hash. 32 | // Its generic security strength is 384 bits against preimage attacks, 33 | // and 192 bits against collision attacks. 34 | func New384() hash.Hash { return &state{rate: 104, outputLen: 48, dsbyte: 0x06} } 35 | 36 | // New512 creates a new SHA3-512 hash. 37 | // Its generic security strength is 512 bits against preimage attacks, 38 | // and 256 bits against collision attacks. 39 | func New512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x06} } 40 | 41 | // Sum224 returns the SHA3-224 digest of the data. 42 | func Sum224(data []byte) (digest [28]byte) { 43 | h := New224() 44 | h.Write(data) 45 | h.Sum(digest[:0]) 46 | return 47 | } 48 | 49 | // Sum256 returns the SHA3-256 digest of the data. 50 | func Sum256(data []byte) (digest [32]byte) { 51 | h := New256() 52 | h.Write(data) 53 | h.Sum(digest[:0]) 54 | return 55 | } 56 | 57 | // Sum384 returns the SHA3-384 digest of the data. 58 | func Sum384(data []byte) (digest [48]byte) { 59 | h := New384() 60 | h.Write(data) 61 | h.Sum(digest[:0]) 62 | return 63 | } 64 | 65 | // Sum512 returns the SHA3-512 digest of the data. 66 | func Sum512(data []byte) (digest [64]byte) { 67 | h := New512() 68 | h.Write(data) 69 | h.Sum(digest[:0]) 70 | return 71 | } 72 | -------------------------------------------------------------------------------- /crypto/sha3/keccakf_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build amd64,!appengine,!gccgo 6 | 7 | package sha3 8 | 9 | // This function is implemented in keccakf_amd64.s. 10 | 11 | //go:noescape 12 | 13 | func keccakF1600(state *[25]uint64) 14 | -------------------------------------------------------------------------------- /crypto/sha3/register.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.4 6 | 7 | package sha3 8 | 9 | import ( 10 | "crypto" 11 | ) 12 | 13 | func init() { 14 | crypto.RegisterHash(crypto.SHA3_224, New224) 15 | crypto.RegisterHash(crypto.SHA3_256, New256) 16 | crypto.RegisterHash(crypto.SHA3_384, New384) 17 | crypto.RegisterHash(crypto.SHA3_512, New512) 18 | } 19 | -------------------------------------------------------------------------------- /crypto/sha3/shake.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sha3 6 | 7 | // This file defines the ShakeHash interface, and provides 8 | // functions for creating SHAKE instances, as well as utility 9 | // functions for hashing bytes to arbitrary-length output. 10 | 11 | import ( 12 | "io" 13 | ) 14 | 15 | // ShakeHash defines the interface to hash functions that 16 | // support arbitrary-length output. 17 | type ShakeHash interface { 18 | // Write absorbs more data into the hash's state. It panics if input is 19 | // written to it after output has been read from it. 20 | io.Writer 21 | 22 | // Read reads more output from the hash; reading affects the hash's 23 | // state. (ShakeHash.Read is thus very different from Hash.Sum) 24 | // It never returns an error. 25 | io.Reader 26 | 27 | // Clone returns a copy of the ShakeHash in its current state. 28 | Clone() ShakeHash 29 | 30 | // Reset resets the ShakeHash to its initial state. 31 | Reset() 32 | } 33 | 34 | func (d *state) Clone() ShakeHash { 35 | return d.clone() 36 | } 37 | 38 | // NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. 39 | // Its generic security strength is 128 bits against all attacks if at 40 | // least 32 bytes of its output are used. 41 | func NewShake128() ShakeHash { return &state{rate: 168, dsbyte: 0x1f} } 42 | 43 | // NewShake256 creates a new SHAKE128 variable-output-length ShakeHash. 44 | // Its generic security strength is 256 bits against all attacks if 45 | // at least 64 bytes of its output are used. 46 | func NewShake256() ShakeHash { return &state{rate: 136, dsbyte: 0x1f} } 47 | 48 | // ShakeSum128 writes an arbitrary-length digest of data into hash. 49 | func ShakeSum128(hash, data []byte) { 50 | h := NewShake128() 51 | h.Write(data) 52 | h.Read(hash) 53 | } 54 | 55 | // ShakeSum256 writes an arbitrary-length digest of data into hash. 56 | func ShakeSum256(hash, data []byte) { 57 | h := NewShake256() 58 | h.Write(data) 59 | h.Read(hash) 60 | } 61 | -------------------------------------------------------------------------------- /crypto/sha3/testdata/keccakKats.json.deflate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/blocktree/openwallet/56b96c7c049495b7b001b09aa25c1ad6fcce6d50/crypto/sha3/testdata/keccakKats.json.deflate -------------------------------------------------------------------------------- /crypto/sha3/xor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !amd64,!386,!ppc64le appengine 6 | 7 | package sha3 8 | 9 | var ( 10 | xorIn = xorInGeneric 11 | copyOut = copyOutGeneric 12 | xorInUnaligned = xorInGeneric 13 | copyOutUnaligned = copyOutGeneric 14 | ) 15 | 16 | const xorImplementationUnaligned = "generic" 17 | -------------------------------------------------------------------------------- /crypto/sha3/xor_generic.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package sha3 6 | 7 | import "encoding/binary" 8 | 9 | // xorInGeneric xors the bytes in buf into the state; it 10 | // makes no non-portable assumptions about memory layout 11 | // or alignment. 12 | func xorInGeneric(d *state, buf []byte) { 13 | n := len(buf) / 8 14 | 15 | for i := 0; i < n; i++ { 16 | a := binary.LittleEndian.Uint64(buf) 17 | d.a[i] ^= a 18 | buf = buf[8:] 19 | } 20 | } 21 | 22 | // copyOutGeneric copies ulint64s to a byte buffer. 23 | func copyOutGeneric(d *state, b []byte) { 24 | for i := 0; len(b) >= 8; i++ { 25 | binary.LittleEndian.PutUint64(b, d.a[i]) 26 | b = b[8:] 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crypto/sha3/xor_unaligned.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build amd64 386 ppc64le 6 | // +build !appengine 7 | 8 | package sha3 9 | 10 | import "unsafe" 11 | 12 | func xorInUnaligned(d *state, buf []byte) { 13 | bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0])) 14 | n := len(buf) 15 | if n >= 72 { 16 | d.a[0] ^= bw[0] 17 | d.a[1] ^= bw[1] 18 | d.a[2] ^= bw[2] 19 | d.a[3] ^= bw[3] 20 | d.a[4] ^= bw[4] 21 | d.a[5] ^= bw[5] 22 | d.a[6] ^= bw[6] 23 | d.a[7] ^= bw[7] 24 | d.a[8] ^= bw[8] 25 | } 26 | if n >= 104 { 27 | d.a[9] ^= bw[9] 28 | d.a[10] ^= bw[10] 29 | d.a[11] ^= bw[11] 30 | d.a[12] ^= bw[12] 31 | } 32 | if n >= 136 { 33 | d.a[13] ^= bw[13] 34 | d.a[14] ^= bw[14] 35 | d.a[15] ^= bw[15] 36 | d.a[16] ^= bw[16] 37 | } 38 | if n >= 144 { 39 | d.a[17] ^= bw[17] 40 | } 41 | if n >= 168 { 42 | d.a[18] ^= bw[18] 43 | d.a[19] ^= bw[19] 44 | d.a[20] ^= bw[20] 45 | } 46 | } 47 | 48 | func copyOutUnaligned(d *state, buf []byte) { 49 | ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) 50 | copy(buf, ab[:]) 51 | } 52 | 53 | var ( 54 | xorIn = xorInUnaligned 55 | copyOut = copyOutUnaligned 56 | ) 57 | 58 | const xorImplementationUnaligned = "unaligned" 59 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/blocktree/openwallet/v2 2 | 3 | go 1.13 4 | 5 | require ( 6 | docker.io/go-docker v1.0.0 7 | github.com/NebulousLabs/entropy-mnemonics v0.0.0-20181203154559-bc7e13c5ccd8 8 | github.com/asdine/storm v2.1.2+incompatible 9 | github.com/astaxie/beego v1.12.0 10 | github.com/blocktree/go-owcdrivers v1.2.0 11 | github.com/blocktree/go-owcrypt v1.1.9 12 | github.com/bndr/gotabulate v1.1.2 13 | github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b 14 | github.com/btcsuite/btcd v0.23.1 // indirect 15 | github.com/btcsuite/btcd/btcutil v1.1.0 16 | github.com/bwmarrin/snowflake v0.3.0 17 | github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 18 | github.com/couchbase/go-couchbase v0.0.0-20191217190632-b2754d72cc98 19 | github.com/docker/go-connections v0.4.0 20 | github.com/ethereum/go-ethereum v1.10.17 21 | github.com/go-redis/redis v6.15.6+incompatible 22 | github.com/go-sql-driver/mysql v1.5.0 23 | github.com/gomodule/redigo v2.0.0+incompatible 24 | github.com/gorilla/websocket v1.4.2 25 | github.com/imroc/req v0.2.4 26 | github.com/lib/pq v1.3.0 27 | github.com/mr-tron/base58 v1.1.3 28 | github.com/pborman/uuid v1.2.0 29 | github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 30 | github.com/pkg/errors v0.9.1 31 | github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect 32 | github.com/shopspring/decimal v0.0.0-20200105231215-408a2507e114 33 | github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92 34 | github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec 35 | github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271 36 | github.com/tidwall/gjson v1.9.3 37 | github.com/tyler-smith/go-bip39 v1.0.2 38 | go.etcd.io/bbolt v1.3.3 39 | golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 40 | gopkg.in/urfave/cli.v1 v1.20.0 41 | ) 42 | -------------------------------------------------------------------------------- /hdkeystore/hdkey_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package hdkeystore 17 | 18 | import ( 19 | "github.com/blocktree/go-owcrypt" 20 | "testing" 21 | "encoding/hex" 22 | ) 23 | 24 | func TestGenerateSeed(t *testing.T) { 25 | 26 | for i:= 0; i<30;i++ { 27 | seed, err := GenerateSeed(32) 28 | if err != nil { 29 | t.Fatalf("GenerateSeed failed unexpected error: %v",err) 30 | return 31 | } 32 | 33 | key, err := NewHDKey(seed, "hello", OpenwCoinTypePath) 34 | if err != nil { 35 | t.Fatalf("GenerateSeed failed unexpected error: %v", err) 36 | } 37 | 38 | t.Logf("[%d] Seed = %s", i, hex.EncodeToString(seed)) 39 | //t.Logf("[%d] Mnemonic = %s", i, key.Mnemonic()) 40 | t.Logf("[%d] KeyID = %s", i, key.KeyID) 41 | } 42 | } 43 | 44 | func TestNewHDKey(t *testing.T) { 45 | 46 | tests := []struct { 47 | accountId string 48 | seed string 49 | startPath string 50 | }{ 51 | { 52 | accountId: "hello", 53 | seed: "4b68b20a5d3ac671a61e6e94b4de309530a12439b7c3ee548d20966674696656", 54 | startPath: "m/44'/88", 55 | }, 56 | { 57 | accountId: "hello2", 58 | seed: "dfac3098fd7c3cd9b9cdf44e3e1ae912e3d2ce05795a857a53ebff6111b1580b", 59 | startPath: "m/44'/88'", 60 | }, 61 | } 62 | 63 | for i, test := range tests { 64 | seed, _ := hex.DecodeString(test.seed) 65 | key, err := NewHDKey(seed, "hello", test.startPath) 66 | if err != nil { 67 | t.Fatalf("NewHDKey failed unexpected error: %v", err) 68 | } 69 | //t.Logf("Key[%d] Mnemonic = %s", i, key.Mnemonic()) 70 | t.Logf("Key[%d] address = %s", i, key.KeyID) 71 | t.Logf("Key[%d] seed = %s", i, hex.EncodeToString(key.Seed())) 72 | } 73 | } 74 | 75 | func TestHDKey_DerivedKeyWithPath(t *testing.T) { 76 | seed, _ := GenerateSeed(32) 77 | key, _ := NewHDKey(seed, "hello", OpenwCoinTypePath) 78 | childKey, err := key.DerivedKeyWithPath("m/44'/88'/1581919647/0", owcrypt.ECC_CURVE_ED25519_NORMAL) 79 | if err != nil { 80 | t.Fatalf("DerivedKeyWithPath failed unexpected error: %v", err) 81 | return 82 | } 83 | t.Logf("child key: %s", hex.EncodeToString(childKey.GetPublicKeyBytes())) 84 | } -------------------------------------------------------------------------------- /hdkeystore/hdkeystore_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package hdkeystore 17 | 18 | import ( 19 | "testing" 20 | "path/filepath" 21 | ) 22 | 23 | 24 | func TestStoreHDKey(t *testing.T) { 25 | path := filepath.Join(".", "keys") 26 | _, rootId, err := StoreHDKey(path, "sogosdfo", "", StandardScryptN, StandardScryptP) 27 | if err != nil { 28 | t.Errorf("StoreHDKey failed unexpected error: %v", err) 29 | } else { 30 | t.Logf("StoreHDKey root id = %s", rootId) 31 | } 32 | } 33 | 34 | func TestGetKey(t *testing.T) { 35 | path := filepath.Join(".", "keys") 36 | ks := &HDKeystore{path, StandardScryptN, StandardScryptP} 37 | 38 | key, err := ks.GetKey("WAeAP5ggYYZ1euSJqURNEoGBRP6ucfPq2g", 39 | "sogosdfo-WAeAP5ggYYZ1euSJqURNEoGBRP6ucfPq2g.key", 40 | "") 41 | 42 | if err != nil { 43 | t.Errorf("GetKey failed unexpected error: %v\n", err) 44 | } else { 45 | t.Logf("GetKey root id = %s", key.KeyID) 46 | } 47 | } -------------------------------------------------------------------------------- /log/log.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package log 17 | 18 | import ( 19 | "strings" 20 | ) 21 | 22 | // Log levels to control the logging output. 23 | const ( 24 | LevelEmergency = iota 25 | LevelAlert 26 | LevelCritical 27 | LevelError 28 | LevelWarning 29 | LevelNotice 30 | LevelInformational 31 | LevelDebug 32 | ) 33 | 34 | // BeeLogger references the used application logger. 35 | var Std = newLogger("") 36 | 37 | // SetLevel sets the global log level used by the simple logger. 38 | func SetLevel(l int) { 39 | Std.SetLevel(l) 40 | } 41 | 42 | // SetLogFuncCall set the CallDepth, default is 3 43 | func SetLogFuncCall(b bool) { 44 | Std.EnableFuncCallDepth(b) 45 | Std.SetLogFuncCallDepth(4) 46 | } 47 | 48 | // SetLogger sets a new logger. 49 | func SetLogger(adaptername string, config string) error { 50 | return Std.SetLogger(adaptername, config) 51 | } 52 | 53 | // Emergency logs a message at emergency level. 54 | func Emergency(v ...interface{}) { 55 | Std.Emergency(generateFmtStr(len(v)), v...) 56 | } 57 | 58 | // Alert logs a message at alert level. 59 | func Alert(v ...interface{}) { 60 | Std.Alert(generateFmtStr(len(v)), v...) 61 | } 62 | 63 | // Critical logs a message at critical level. 64 | func Critical(v ...interface{}) { 65 | Std.Critical(generateFmtStr(len(v)), v...) 66 | } 67 | 68 | // format & Error logs a message at error level. 69 | func Errorf(format string, v ...interface{}) { 70 | Std.Error(format, v...) 71 | } 72 | 73 | // Error logs a message at error level. 74 | func Error(v ...interface{}) { 75 | Std.Error(generateFmtStr(len(v)), v...) 76 | } 77 | 78 | // format & Warning logs a message at warning level. 79 | func Warningf(format string, v ...interface{}) { 80 | Std.Warning(format, v...) 81 | } 82 | 83 | // Warning logs a message at warning level. 84 | func Warning(v ...interface{}) { 85 | Std.Warning(generateFmtStr(len(v)), v...) 86 | } 87 | 88 | // Warn compatibility alias for Warning() 89 | func Warn(v ...interface{}) { 90 | Std.Warn(generateFmtStr(len(v)), v...) 91 | } 92 | 93 | // Notice logs a message at notice level. 94 | func Notice(v ...interface{}) { 95 | Std.Notice(generateFmtStr(len(v)), v...) 96 | } 97 | 98 | // Informational logs a message at info level. 99 | func Informational(v ...interface{}) { 100 | Std.Informational(generateFmtStr(len(v)), v...) 101 | } 102 | 103 | func Infof(format string, v ...interface{}) { 104 | Std.Info(format, v...) 105 | } 106 | 107 | // Info compatibility alias for Warning() 108 | func Info(v ...interface{}) { 109 | Std.Info(generateFmtStr(len(v)), v...) 110 | } 111 | 112 | // Format & debug logs a message at debug level. 113 | func Debugf(format string, v ...interface{}) { 114 | Std.Debug(format, v...) 115 | } 116 | 117 | // Debug logs a message at debug level. 118 | func Debug(v ...interface{}) { 119 | Std.Debug(generateFmtStr(len(v)), v...) 120 | } 121 | 122 | // Trace logs a message at trace level. 123 | // compatibility alias for Warning() 124 | func Trace(v ...interface{}) { 125 | Std.Trace(generateFmtStr(len(v)), v...) 126 | } 127 | 128 | func generateFmtStr(n int) string { 129 | return strings.Repeat("%v ", n) 130 | } 131 | -------------------------------------------------------------------------------- /log/log_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package log 17 | 18 | import ( 19 | "github.com/astaxie/beego/logs" 20 | "testing" 21 | ) 22 | 23 | func TestInfo(t *testing.T) { 24 | Debug("hello","world") 25 | } 26 | 27 | func TestCustomLogger(t *testing.T) { 28 | l := logs.GetLogger("BTC") 29 | l.Println("hello", "world") 30 | } 31 | 32 | func TestOWLogger(t *testing.T) { 33 | l := NewOWLogger("BTC") 34 | l.Info("hello", "world") 35 | } -------------------------------------------------------------------------------- /log/logger.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package log 17 | 18 | import ( 19 | "fmt" 20 | "github.com/astaxie/beego/logs" 21 | ) 22 | 23 | type logger struct { 24 | *logs.BeeLogger 25 | prefix string 26 | } 27 | 28 | func newLogger(prefix string) *logger { 29 | l := logger{} 30 | if len(prefix) > 0 { 31 | l.prefix = fmt.Sprintf("[%s] ", prefix) 32 | } 33 | l.BeeLogger = logs.NewLogger() 34 | return &l 35 | } 36 | 37 | // SetPrefix 38 | func (bl *logger)SetPrefix(prefix string) { 39 | if len(prefix) > 0 { 40 | bl.prefix = fmt.Sprintf("[%s] ", prefix) 41 | } 42 | } 43 | 44 | // Emergency Log EMERGENCY level message. 45 | func (bl *logger) Emergency(format string, v ...interface{}) { 46 | bl.BeeLogger.Emergency(bl.prefix + format, v...) 47 | } 48 | 49 | // Alert Log ALERT level message. 50 | func (bl *logger) Alert(format string, v ...interface{}) { 51 | bl.BeeLogger.Alert(bl.prefix + format, v...) 52 | } 53 | 54 | // Critical Log CRITICAL level message. 55 | func (bl *logger) Critical(format string, v ...interface{}) { 56 | bl.BeeLogger.Critical(bl.prefix + format, v...) 57 | } 58 | 59 | // Error Log ERROR level message. 60 | func (bl *logger) Error(format string, v ...interface{}) { 61 | bl.BeeLogger.Error(bl.prefix + format, v...) 62 | } 63 | 64 | // Warning Log WARNING level message. 65 | func (bl *logger) Warning(format string, v ...interface{}) { 66 | bl.BeeLogger.Warning(bl.prefix + format, v...) 67 | } 68 | 69 | // Notice Log NOTICE level message. 70 | func (bl *logger) Notice(format string, v ...interface{}) { 71 | bl.BeeLogger.Notice(bl.prefix + format, v...) 72 | } 73 | 74 | // Informational Log INFORMATIONAL level message. 75 | func (bl *logger) Informational(format string, v ...interface{}) { 76 | bl.BeeLogger.Informational(bl.prefix + format, v...) 77 | } 78 | 79 | // Debug Log DEBUG level message. 80 | func (bl *logger) Debug(format string, v ...interface{}) { 81 | bl.BeeLogger.Debug(bl.prefix + format, v...) 82 | } 83 | 84 | // Warn Log WARN level message. 85 | // compatibility alias for Warning() 86 | func (bl *logger) Warn(format string, v ...interface{}) { 87 | bl.BeeLogger.Warn(bl.prefix + format, v...) 88 | } 89 | 90 | // Info Log INFO level message. 91 | // compatibility alias for Informational() 92 | func (bl *logger) Info(format string, v ...interface{}) { 93 | bl.BeeLogger.Info(bl.prefix + format, v...) 94 | } 95 | 96 | // Trace Log TRACE level message. 97 | // compatibility alias for Debug() 98 | func (bl *logger) Trace(format string, v ...interface{}) { 99 | bl.BeeLogger.Trace(bl.prefix + format, v...) 100 | } 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /log/owlogger_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package log 17 | 18 | import ( 19 | "fmt" 20 | "github.com/astaxie/beego/logs" 21 | "github.com/blocktree/openwallet/v2/common/file" 22 | "path/filepath" 23 | "sync" 24 | "testing" 25 | "time" 26 | ) 27 | 28 | //SetupLog 配置日志 29 | func getNewLogger(prefix string) *OWLogger { 30 | l := NewOWLogger(prefix) 31 | logDir := filepath.Join("logs") 32 | //记录日志 33 | file.MkdirAll(logDir) 34 | logFile := filepath.Join("logs", "test.log") 35 | logConfig := fmt.Sprintf(`{"filename":"%s"}`, logFile) 36 | //log.Println(logConfig) 37 | l.SetLogger(logs.AdapterFile, logConfig) 38 | l.SetLogger(logs.AdapterConsole, logConfig) 39 | return l 40 | } 41 | 42 | func TestMultiLogger(t *testing.T) { 43 | log_btc := getNewLogger("BTC") 44 | log_ltc := getNewLogger("LTC") 45 | log_eth := getNewLogger("ETH") 46 | log_qtum := getNewLogger("QTUM") 47 | log_nas := getNewLogger("NAS") 48 | 49 | var wait sync.WaitGroup 50 | wait.Add(1) 51 | go func() { 52 | 53 | for i := 0; i < 10000; i++ { 54 | log_btc.Info("BTC log out:", i) 55 | time.Sleep(800) 56 | } 57 | wait.Done() 58 | }() 59 | 60 | wait.Add(1) 61 | go func() { 62 | 63 | for i := 0; i < 10000; i++ { 64 | log_ltc.Info("LTC log out:", i) 65 | time.Sleep(800) 66 | } 67 | wait.Done() 68 | }() 69 | 70 | wait.Add(1) 71 | go func() { 72 | 73 | for i := 0; i < 10000; i++ { 74 | log_eth.Info("ETH log out:", i) 75 | time.Sleep(800) 76 | } 77 | wait.Done() 78 | }() 79 | 80 | wait.Add(1) 81 | go func() { 82 | 83 | for i := 0; i < 10000; i++ { 84 | log_qtum.Info("QTUM log out:", i) 85 | time.Sleep(800) 86 | } 87 | wait.Done() 88 | }() 89 | 90 | wait.Add(1) 91 | go func() { 92 | 93 | for i := 0; i < 10000; i++ { 94 | log_nas.Info("NAS log out:", i) 95 | time.Sleep(800) 96 | } 97 | wait.Done() 98 | }() 99 | wait.Wait() 100 | } 101 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | 5 | //添加eth进入资产路由中 6 | //eth := &assets.EthereumAssets{} 7 | //openwallet.Router(eth.Name(), eth) 8 | // 9 | ////运行应用 10 | //openwallet.Run() 11 | 12 | } 13 | -------------------------------------------------------------------------------- /openw/README.md: -------------------------------------------------------------------------------- 1 | # openw 2 | 3 | openw包实现了一个单机版的钱包管理模型。目前用于给实现AssetsAapter协议的区块链资产适配器做功能测试。 4 | 后续会做一个可视化的钱包管理系统,专门用于区块链资产适配器的测试。 -------------------------------------------------------------------------------- /openw/address_batch_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openw 17 | 18 | import ( 19 | "testing" 20 | ) 21 | 22 | func TestBatchCreateAddressByAccount(t *testing.T) { 23 | //account := openwallet.AssetsAccount{ 24 | // AccountID: "Aa7Chh2MdaGDejHdCJZAaX7AwvGNmMEMry2kZZTq114a", 25 | // Symbol: "LTC", 26 | // PublicKey: "owpubeyoV6FsNaAN9wxUDsBAXyKr4EVt3ib6R1CRLpGJ7qUdGUgiwB6tLbUATvFYDm2JGTaB6i7PkeXBAxzo5RkNXmx64KE9vFN4qPtbK7ywZTd9unM2C1", 27 | // OwnerKeys: []string{"owpubeyoV6FsNaAN9wxUDsBAXyKr4EVt3ib6R1CRLpGJ7qUdGUgiwB6tLbUATvFYDm2JGTaB6i7PkeXBAxzo5RkNXmx64KE9vFN4qPtbK7ywZTd9unM2C1"}, 28 | // HDPath: "m/44'/88'/1'", 29 | // AddressIndex: 0, 30 | // Index: 1, 31 | //} 32 | //wm := litecoin.NewWalletManager() 33 | //decoder := wm.Decoder 34 | // 35 | //addrArr, err := openwallet.BatchCreateAddressByAccount(&account, decoder, 5000, 20) 36 | //if err != nil { 37 | // t.Errorf("error: %v", err) 38 | // return 39 | //} 40 | //addrs := make([]string, 0) 41 | //for _, a := range addrArr { 42 | // //t.Logf("address[%d]: %s", a.Index, a.Address) 43 | // addrs = append(addrs, a.Address) 44 | //} 45 | //log.Infof("create address") 46 | //j, err := json.Marshal(addrs) 47 | //if err != nil { 48 | // t.Errorf("json.Marshal: %v", err) 49 | // return 50 | //} 51 | //log.Infof("json.Marshal") 52 | //enc, err := crypto.AESEncrypt(j, crypto.SHA256([]byte("1234"))) 53 | //if err != nil { 54 | // t.Errorf("crypto.AESEncrypt: %v", err) 55 | // return 56 | //} 57 | //log.Infof("AESEncrypt") 58 | //encB58 := base64.StdEncoding.EncodeToString(enc) 59 | //log.Infof("base58.Encode: %s", encB58) 60 | //decB58, _ := base64.StdEncoding.DecodeString(encB58) 61 | //log.Infof("base58.Decode") 62 | //dec, err := crypto.AESDecrypt(decB58, crypto.SHA256([]byte("1234"))) 63 | //if err != nil { 64 | // t.Errorf("crypto.AESEncrypt: %v", err) 65 | // return 66 | //} 67 | //log.Infof("AESDecrypt") 68 | //log.Infof("dec: %s", string(dec)) 69 | } 70 | -------------------------------------------------------------------------------- /openw/app_wrapper.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The OpenWallet Authors 3 | * This file is part of the OpenWallet library. 4 | * 5 | * The OpenWallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The OpenWallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openw 17 | 18 | import ( 19 | "github.com/asdine/storm" 20 | "github.com/blocktree/openwallet/v2/openwallet" 21 | ) 22 | 23 | type AppID string 24 | 25 | //AppWrapper 应用装器,扩展应用功能 26 | type AppWrapper struct { 27 | *Wrapper 28 | appID string 29 | } 30 | 31 | func NewAppWrapper(args ...interface{}) *AppWrapper { 32 | 33 | wrapper := NewWrapper(args...) 34 | 35 | appWrapper := AppWrapper{Wrapper: wrapper} 36 | 37 | for _, arg := range args { 38 | switch obj := arg.(type) { 39 | case AppID: 40 | appWrapper.appID = string(obj) 41 | case *Wrapper: 42 | appWrapper.Wrapper = obj 43 | } 44 | } 45 | 46 | return &appWrapper 47 | } 48 | 49 | // GetWalletInfo 50 | func (wrapper *AppWrapper) GetWalletInfo(walletID string) (*openwallet.Wallet, error) { 51 | 52 | //打开数据库 53 | db, err := wrapper.OpenStormDB() 54 | if err != nil { 55 | return nil, err 56 | } 57 | defer wrapper.CloseDB() 58 | 59 | var wallet openwallet.Wallet 60 | err = db.One("WalletID", walletID, &wallet) 61 | if err != nil { 62 | return nil, err 63 | } 64 | 65 | return &wallet, nil 66 | } 67 | 68 | // GetWalletList 69 | func (wrapper *AppWrapper) GetWalletList(offset, limit int) ([]*openwallet.Wallet, error) { 70 | 71 | //打开数据库 72 | db, err := wrapper.OpenStormDB() 73 | if err != nil { 74 | return nil, err 75 | } 76 | defer wrapper.CloseDB() 77 | 78 | var wallets []*openwallet.Wallet 79 | err = db.All(&wallets, storm.Limit(limit), storm.Skip(offset)) 80 | if err != nil { 81 | return nil, err 82 | } 83 | 84 | return wallets, nil 85 | } 86 | -------------------------------------------------------------------------------- /openw/assets_manager.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openw 17 | 18 | import ( 19 | "fmt" 20 | "github.com/astaxie/beego/config" 21 | "github.com/blocktree/openwallet/v2/log" 22 | "github.com/blocktree/openwallet/v2/openwallet" 23 | "strings" 24 | ) 25 | 26 | //type AssetsManager interface { 27 | // openwallet.AssetsAdapter 28 | // 29 | // //ImportWatchOnlyAddress 导入观测地址 30 | // ImportWatchOnlyAddress(address ...*openwallet.Address) error 31 | // 32 | // //GetAddressWithBalance 获取多个地址余额,使用查账户和单地址 33 | // GetAddressWithBalance(address ...*openwallet.Address) error 34 | //} 35 | 36 | //注册钱包管理工具 37 | func initAssetAdapter() { 38 | //注册钱包管理工具 39 | log.Notice("Wallet Manager Load Successfully.") 40 | //RegAssets(qtum.Symbol, qtum.NewWalletManager()) 41 | //RegAssets(nebulasio.Symbol, nebulasio.NewWalletManager()) 42 | //RegAssets(ontology.Symbol, ontology.NewWalletManager()) 43 | //RegAssets(virtualeconomy.Symbol, virtualeconomy.NewWalletManager()) 44 | //RegAssets(eosio.Symbol, eosio.NewWalletManager()) 45 | } 46 | 47 | //区块链适配器注册组 48 | var assetsAdapterManagers = make(map[string]interface{}) 49 | 50 | // RegAssets 注册资产 51 | // @param name 资产别名 52 | // @param manager 资产适配器或管理器 53 | // @param config 加载配置 54 | // 资产适配器实现了openwallet.AssetsConfig,可以传入配置接口完成预加载配置 55 | // usage: 56 | // RegAssets(cardano.Symbol, &cardano.WalletManager{}, c) 57 | // RegAssets(bytom.Symbol, &bytom.WalletManager{}, c) 58 | func RegAssets(name string, manager interface{}, config ...config.Configer) { 59 | name = strings.ToUpper(name) 60 | if manager == nil { 61 | panic("assets: Register adapter is nil") 62 | } 63 | if _, ok := assetsAdapterManagers[name]; ok { 64 | log.Error("assets: Register called twice for adapter ", name) 65 | return 66 | } 67 | 68 | assetsAdapterManagers[name] = manager 69 | 70 | //如果有配置则加载所有配置 71 | if ac, ok := manager.(openwallet.AssetsConfig); ok && config != nil { 72 | for _, c := range config { 73 | ac.LoadAssetsConfig(c) 74 | } 75 | } 76 | } 77 | 78 | // GetAssets 根据币种类型获取已注册的管理者 79 | func GetAssets(symbol string) interface{} { 80 | symbol = strings.ToUpper(symbol) 81 | manager, ok := assetsAdapterManagers[symbol] 82 | if !ok { 83 | return nil 84 | } 85 | return manager 86 | } 87 | 88 | // GetSymbolInfo 获取资产的币种信息 89 | func GetSymbolInfo(symbol string) (openwallet.SymbolInfo, error) { 90 | adapter := GetAssets(symbol) 91 | if adapter == nil { 92 | return nil, fmt.Errorf("assets: %s is not support", symbol) 93 | } 94 | 95 | manager, ok := adapter.(openwallet.SymbolInfo) 96 | if !ok { 97 | return nil, fmt.Errorf("assets: %s is not support", symbol) 98 | } 99 | 100 | return manager, nil 101 | } 102 | 103 | // GetAssetsAdapter 获取资产控制器 104 | func GetAssetsAdapter(symbol string) (openwallet.AssetsAdapter, error) { 105 | 106 | adapter := GetAssets(symbol) 107 | if adapter == nil { 108 | return nil, fmt.Errorf("assets: %s is not support", symbol) 109 | } 110 | 111 | manager, ok := adapter.(openwallet.AssetsAdapter) 112 | if !ok { 113 | return nil, fmt.Errorf("assets: %s is not support", symbol) 114 | } 115 | 116 | return manager, nil 117 | } 118 | -------------------------------------------------------------------------------- /openw/block_manager.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openw 17 | 18 | import ( 19 | "fmt" 20 | ) 21 | 22 | //AddAddressForBlockScan 添加订阅地址 23 | func (wm *WalletManager) AddAddressForBlockScan(address, sourceKey string) error { 24 | wm.mu.Lock() 25 | defer wm.mu.Unlock() 26 | wm.AddressInScanning[address] = sourceKey 27 | return nil 28 | //if _, exist := wm.WalletInScanning[sourceKey]; exist { 29 | // return 30 | //} 31 | //wm.WalletInScanning[sourceKey] = wrapper 32 | } 33 | 34 | //IsExistAddressForBlockScan 指定地址是否已登记扫描 35 | func (wm *WalletManager) IsExistAddressForBlockScan(address string) bool { 36 | wm.mu.RLock() 37 | defer wm.mu.RUnlock() 38 | 39 | _, exist := wm.AddressInScanning[address] 40 | return exist 41 | } 42 | 43 | //ClearAddressForBlockScan 清理订阅扫描的内容 44 | func (wm *WalletManager) ClearAddressForBlockScan() error { 45 | wm.mu.Lock() 46 | defer wm.mu.Unlock() 47 | //wm.WalletInScanning = nil 48 | wm.AddressInScanning = nil 49 | wm.AddressInScanning = make(map[string]string) 50 | //wm.WalletInScanning = make(map[string]*WalletWrapper) 51 | return nil 52 | } 53 | 54 | //GetSourceKeyByAddressForBlockScan 获取地址对应的数据源标识 55 | func (wm *WalletManager) GetSourceKeyByAddressForBlockScan(address string) (string, bool) { 56 | wm.mu.RLock() 57 | defer wm.mu.RUnlock() 58 | 59 | sourceKey, ok := wm.AddressInScanning[address] 60 | return sourceKey, ok 61 | } 62 | 63 | func (wm *WalletManager) RescanBlockHeight(symbol string, startHeight uint64, endHeight uint64) error { 64 | 65 | assetsMgr, err := GetAssetsAdapter(symbol) 66 | if err != nil { 67 | return err 68 | } 69 | 70 | scanner := assetsMgr.GetBlockScanner() 71 | 72 | if scanner == nil { 73 | return fmt.Errorf("%s is not support block scan", symbol) 74 | } 75 | 76 | if startHeight <= endHeight { 77 | for i := startHeight; i <= endHeight; i++ { 78 | err := scanner.ScanBlock(i) 79 | if err != nil { 80 | continue 81 | } 82 | } 83 | } else { 84 | return fmt.Errorf("start block height: %d is greater than end block height: %d", startHeight, endHeight) 85 | } 86 | 87 | return nil 88 | } 89 | 90 | //SetRescanBlockHeight 重置区块高度起扫描 91 | func (wm *WalletManager) SetRescanBlockHeight(symbol string, height uint64) error { 92 | 93 | assetsMgr, err := GetAssetsAdapter(symbol) 94 | if err != nil { 95 | return err 96 | } 97 | 98 | scanner := assetsMgr.GetBlockScanner() 99 | 100 | if scanner == nil { 101 | return fmt.Errorf("%s is not support block scan", symbol) 102 | } 103 | 104 | err = scanner.SetRescanBlockHeight(height) 105 | if err != nil { 106 | return err 107 | } 108 | 109 | return nil 110 | } 111 | 112 | //GetNewBlockHeight 获取区块高度,(最新高度,已扫描高度) 113 | func (wm *WalletManager) GetNewBlockHeight(symbol string) (uint64, uint64, error) { 114 | 115 | assetsMgr, err := GetAssetsAdapter(symbol) 116 | if err != nil { 117 | return 0, 0, err 118 | } 119 | 120 | scanner := assetsMgr.GetBlockScanner() 121 | 122 | if scanner == nil { 123 | return 0, 0, fmt.Errorf("%s is not support block scan", symbol) 124 | } 125 | 126 | header, err := scanner.GetCurrentBlockHeader() 127 | if err != nil { 128 | return 0, 0, err 129 | } 130 | 131 | scannedHeight := scanner.GetScannedBlockHeight() 132 | 133 | return header.Height, scannedHeight, nil 134 | } 135 | -------------------------------------------------------------------------------- /openw/config.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openw 17 | 18 | import "path/filepath" 19 | 20 | var ( 21 | defaultDataDir = filepath.Join(".", "openw_data") 22 | ) 23 | 24 | type Config struct { 25 | KeyDir string //钥匙备份路径 26 | DBPath string //本地数据库文件路径 27 | BackupDir string //备份路径 28 | SupportAssets []string //支持的资产类型 29 | EnableBlockScan bool 30 | ConfigDir string 31 | } 32 | 33 | func NewConfig() *Config { 34 | 35 | c := Config{} 36 | 37 | //钥匙备份路径 38 | c.KeyDir = filepath.Join(defaultDataDir, "key") 39 | //本地数据库文件路径 40 | c.DBPath = filepath.Join(defaultDataDir, "db") 41 | //备份路径 42 | c.BackupDir = filepath.Join(defaultDataDir, "backup") 43 | //支持资产 44 | c.SupportAssets = []string{"BTC", "ETH", "QTUM", "NAS", "TRX"} 45 | //开启区块扫描 46 | c.EnableBlockScan = true 47 | 48 | return &c 49 | } 50 | 51 | //loadConfig 加载配置文件 52 | //@param path 配置文件路径 53 | func loadConfig(path string) *Config { 54 | return nil 55 | } 56 | -------------------------------------------------------------------------------- /openw/database.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The OpenWallet Authors 3 | * This file is part of the OpenWallet library. 4 | * 5 | * The OpenWallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The OpenWallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openw 17 | 18 | import ( 19 | "github.com/asdine/storm" 20 | "fmt" 21 | ) 22 | 23 | type StormDB struct { 24 | *storm.DB 25 | FileName string 26 | Opened bool 27 | } 28 | 29 | //OpenStormDB 30 | func OpenStormDB(filename string, stormOptions ...func(*storm.Options) error) (*StormDB, error) { 31 | 32 | db, err := storm.Open(filename, stormOptions...) 33 | //fmt.Println("open app db") 34 | if err != nil { 35 | return nil, fmt.Errorf("can not open dbfile: '%s', unexpected error: %v", filename, err) 36 | } 37 | 38 | // Check the metadata. 39 | stormDB := &StormDB{ 40 | FileName: filename, 41 | DB: db, 42 | Opened: true, 43 | } 44 | 45 | return stormDB, nil 46 | } 47 | 48 | // Close closes the database. 49 | func (db *StormDB) Close() error { 50 | err := db.DB.Close() 51 | if err != nil { 52 | return err 53 | } 54 | db.Opened = false 55 | return nil 56 | } 57 | 58 | -------------------------------------------------------------------------------- /openw/subscribe.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openw 17 | 18 | import ( 19 | "github.com/blocktree/openwallet/v2/log" 20 | "github.com/blocktree/openwallet/v2/openwallet" 21 | ) 22 | 23 | //blockScanNotify 区块扫描结果通知 24 | func (wm *WalletManager) BlockScanNotify(header *openwallet.BlockHeader) error { 25 | //log.Debug("NewBlock:", header) 26 | if header.Fork { 27 | 28 | //加载已存在所有app 29 | appIDs, err := wm.loadAllAppIDs() 30 | if err != nil { 31 | return err 32 | } 33 | 34 | //分叉的区块,删除提出记录 35 | for _, appID := range appIDs { 36 | 37 | wrapper, err := wm.NewWalletWrapper(appID, "") 38 | if err != nil { 39 | return err 40 | } 41 | 42 | txWrapper := NewTransactionWrapper(wrapper) 43 | err = txWrapper.DeleteBlockDataByHeight(header.Height) 44 | if err != nil { 45 | return err 46 | } 47 | 48 | } 49 | return nil 50 | } 51 | 52 | //推送数据 53 | for o, _ := range wm.observers { 54 | o.BlockScanNotify(header) 55 | } 56 | 57 | //TODO:定时删除过时的记录,保证数据库不会无限增加 58 | //可以由配置,自定义删除超过例如1000个块之前的记录 59 | 60 | return nil 61 | } 62 | 63 | //BlockExtractDataNotify 区块提取结果通知 64 | func (wm *WalletManager) BlockExtractDataNotify(sourceKey string, data *openwallet.TxExtractData) error { 65 | 66 | //保存提取出来的数据 67 | appID, accountID := wm.decodeSourceKey(sourceKey) 68 | 69 | log.Debug("NewBlockExtractData:", appID, accountID) 70 | 71 | wrapper, err := wm.NewWalletWrapper(appID, "") 72 | if err != nil { 73 | return err 74 | } 75 | 76 | txWrapper := NewTransactionWrapper(wrapper) 77 | err = txWrapper.SaveBlockExtractData(accountID, data) 78 | if err != nil { 79 | return err 80 | } 81 | 82 | //更新账户余额 83 | //err = wm.RefreshAssetsAccountBalance(appID, accountID) 84 | //if err != nil { 85 | // log.Error("RefreshAssetsAccountBalance error:", err) 86 | //} 87 | 88 | account, err := wrapper.GetAssetsAccountInfo(accountID) 89 | if err != nil { 90 | return err 91 | } 92 | 93 | for o, _ := range wm.observers { 94 | o.BlockTxExtractDataNotify(account, data) 95 | } 96 | 97 | return nil 98 | } 99 | 100 | //BlockExtractSmartContractDataNotify 区块提取智能合约交易结果通知 101 | //@param sourceKey: 为contractID 102 | //@param data: 合约交易回执 103 | //@required 104 | func (wm *WalletManager) BlockExtractSmartContractDataNotify(sourceKey string, data *openwallet.SmartContractReceipt) error { 105 | return nil 106 | } 107 | 108 | //DeleteRechargesByHeight 删除某区块高度的充值记录 109 | func (wm *WalletManager) DeleteRechargesByHeight(height uint64) error { 110 | 111 | //加载已存在所有app 112 | appIDs, err := wm.loadAllAppIDs() 113 | if err != nil { 114 | return err 115 | } 116 | 117 | for _, appID := range appIDs { 118 | 119 | wrapper, err := wm.NewWalletWrapper(appID, "") 120 | if err != nil { 121 | return err 122 | } 123 | 124 | txWrapper := NewTransactionWrapper(wrapper) 125 | err = txWrapper.DeleteBlockDataByHeight(height) 126 | if err != nil { 127 | return err 128 | } 129 | 130 | } 131 | 132 | return nil 133 | } 134 | -------------------------------------------------------------------------------- /openw/wallet_manager.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openw 17 | 18 | import ( 19 | "fmt" 20 | "github.com/blocktree/openwallet/v2/hdkeystore" 21 | "github.com/blocktree/openwallet/v2/log" 22 | "github.com/blocktree/openwallet/v2/openwallet" 23 | ) 24 | 25 | // CreateWallet 创建钱包 26 | func (wm *WalletManager) CreateWallet(appID string, wallet *openwallet.Wallet) (*openwallet.Wallet, *hdkeystore.HDKey, error) { 27 | 28 | var ( 29 | key *hdkeystore.HDKey 30 | ) 31 | //打开数据库 32 | db, err := wm.OpenDB(appID) 33 | if err != nil { 34 | return nil, nil, err 35 | } 36 | 37 | //托管密钥 38 | wallet.AppID = appID 39 | if wallet.IsTrust { 40 | 41 | if len(wallet.Password) == 0 { 42 | return nil, nil, fmt.Errorf("password is empty") 43 | } 44 | 45 | //生成keystore 46 | _key, filePath, err := hdkeystore.StoreHDKey(wm.cfg.KeyDir, wallet.Alias, wallet.Password, hdkeystore.StandardScryptN, hdkeystore.StandardScryptP) 47 | if err != nil { 48 | return nil, nil, err 49 | } 50 | wallet.Password = "" //clear password to save 51 | wallet.KeyFile = filePath 52 | wallet.WalletID = _key.KeyID 53 | wallet.RootPath = _key.RootPath 54 | key = _key 55 | } 56 | 57 | if len(wallet.WalletID) == 0 { 58 | return nil, nil, fmt.Errorf("walletID is empty") 59 | } 60 | 61 | //数据路径 62 | wallet.DBFile = db.FileName 63 | 64 | //保存钱包到本地应用数据库 65 | err = db.Save(wallet) 66 | if err != nil { 67 | return nil, nil, err 68 | } 69 | 70 | log.Debug("new wallet create success:", wallet.WalletID) 71 | 72 | return wallet, key, nil 73 | } 74 | 75 | // GetWalletInfo 76 | func (wm *WalletManager) GetWalletInfo(appID string, walletID string) (*openwallet.Wallet, error) { 77 | 78 | wrapper, err := wm.NewWalletWrapper(appID, "") 79 | if err != nil { 80 | return nil, err 81 | } 82 | return wrapper.GetWalletInfo(walletID) 83 | } 84 | 85 | // GetWalletList 86 | func (wm *WalletManager) GetWalletList(appID string, offset, limit int) ([]*openwallet.Wallet, error) { 87 | 88 | wrapper, err := wm.NewWalletWrapper(appID, "") 89 | if err != nil { 90 | return nil, err 91 | } 92 | return wrapper.GetWalletList(offset, limit) 93 | 94 | //打开数据库 95 | //db, err := wm.OpenDB(appID) 96 | //if err != nil { 97 | // return nil, err 98 | //} 99 | // 100 | //var wallets []*openwallet.Wallet 101 | //err = db.All(&wallets, storm.Limit(limit), storm.Skip(offset)) 102 | //if err != nil { 103 | // return nil, err 104 | //} 105 | // 106 | //return wallets, nil 107 | } 108 | -------------------------------------------------------------------------------- /openw/wrapper.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The OpenWallet Authors 3 | * This file is part of the OpenWallet library. 4 | * 5 | * The OpenWallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The OpenWallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openw 17 | 18 | import ( 19 | "github.com/blocktree/openwallet/v2/openwallet" 20 | "sync" 21 | "time" 22 | 23 | "github.com/asdine/storm" 24 | bolt "go.etcd.io/bbolt" 25 | ) 26 | 27 | type WrapperSourceFile string 28 | 29 | // Wrapper 基于OpenWallet钱包体系模型,专门处理钱包的持久化问题,关系数据查询 30 | type Wrapper struct { 31 | openwallet.WalletDAIBase 32 | sourceDB *StormDB //存储钱包相关数据的数据库,目前使用boltdb作为持久方案 33 | mu sync.RWMutex //锁 34 | isExternalDB bool //是否外部加载的数据库,非内部打开,内部打开需要关闭 35 | sourceFile string //钱包数据库文件路径,用于内部打开 36 | } 37 | 38 | func NewWrapper(args ...interface{}) *Wrapper { 39 | 40 | wrapper := Wrapper{} 41 | 42 | for _, arg := range args { 43 | switch obj := arg.(type) { 44 | case *StormDB: 45 | if obj != nil { 46 | //if !obj.Opened { 47 | // return nil, fmt.Errorf("wallet db is close") 48 | //} 49 | 50 | wrapper.isExternalDB = true 51 | wrapper.sourceDB = obj 52 | } 53 | case WrapperSourceFile: 54 | wrapper.sourceFile = string(obj) 55 | } 56 | } 57 | 58 | return &wrapper 59 | } 60 | 61 | //OpenStormDB 打开数据库 62 | func (wrapper *Wrapper) OpenStormDB() (*StormDB, error) { 63 | 64 | var ( 65 | db *StormDB 66 | err error 67 | ) 68 | 69 | if wrapper.sourceDB != nil && wrapper.sourceDB.Opened { 70 | return wrapper.sourceDB, nil 71 | } 72 | 73 | //保证数据库文件并发下不被同时打开 74 | wrapper.mu.Lock() 75 | defer wrapper.mu.Unlock() 76 | 77 | //解锁进入后,再次确认是否已经存在 78 | if wrapper.sourceDB != nil && wrapper.sourceDB.Opened { 79 | return wrapper.sourceDB, nil 80 | } 81 | 82 | //log.Debugf("sourceFile :%v", wrapper.sourceFile) 83 | db, err = OpenStormDB( 84 | wrapper.sourceFile, 85 | storm.BoltOptions(0600, &bolt.Options{Timeout: 3 * time.Second}), 86 | ) 87 | 88 | if err != nil { 89 | return nil, err 90 | } 91 | 92 | wrapper.isExternalDB = false 93 | wrapper.sourceDB = db 94 | 95 | return db, nil 96 | } 97 | 98 | //SetStormDB 设置钱包的应用数据库 99 | func (wrapper *Wrapper) SetExternalDB(db *StormDB) error { 100 | 101 | //关闭之前的数据库 102 | wrapper.CloseDB() 103 | 104 | //保证数据库文件并发下不被同时打开 105 | wrapper.mu.Lock() 106 | defer wrapper.mu.Unlock() 107 | 108 | wrapper.sourceDB = db 109 | wrapper.isExternalDB = true 110 | 111 | return nil 112 | } 113 | 114 | //CloseDB 关闭数据库 115 | func (wrapper *Wrapper) CloseDB() { 116 | // 如果是外部引入的数据库不进行关闭,因为这样会外部无法再操作同一个数据库实力 117 | if wrapper.isExternalDB == false { 118 | if wrapper.sourceDB != nil && wrapper.sourceDB.Opened { 119 | wrapper.sourceDB.Close() 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /openwallet/accounts.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | import ( 19 | "encoding/hex" 20 | "github.com/blocktree/go-owcdrivers/owkeychain" 21 | "github.com/blocktree/openwallet/v2/crypto" 22 | "github.com/btcsuite/btcd/btcutil/hdkeychain" 23 | ) 24 | 25 | var ( 26 | //ID首字节的标识 27 | AccountIDVer = []byte{0x09} 28 | ) 29 | 30 | //解锁的密钥 31 | type unlocked struct { 32 | Key *hdkeychain.ExtendedKey 33 | abort chan struct{} 34 | } 35 | 36 | //AccountOwner 账户拥有者接口 37 | type AccountOwner interface { 38 | } 39 | 40 | //AssetsAccount 千张包资产账户 41 | type AssetsAccount struct { 42 | WalletID string `json:"walletID"` //钱包ID 43 | Alias string `json:"alias"` //别名 44 | AccountID string `json:"accountID" storm:"id"` //账户ID,合成地址 45 | Index uint64 `json:"index"` //账户ID,索引位 46 | HDPath string `json:"hdPath"` //衍生路径 47 | PublicKey string `json:"publicKey"` //主公钥 48 | OwnerKeys []string `json:"ownerKeys"` //公钥数组,大于1为多签 49 | //Owners map[string]AccountOwner //拥有者列表, 账户公钥: 拥有者 50 | ContractAddress string `json:"contractAddress"` //多签合约地址 51 | Required uint64 `json:"required"` //必要签名数 52 | Symbol string `json:"symbol"` //资产币种类别 53 | AddressIndex int `json:"addressIndex"` 54 | Balance string `json:"balance"` 55 | IsTrust bool `json:"isTrust"` //是否托管密钥 56 | ExtParam string `json:"extParam"` //扩展参数,用于调用智能合约,json结构 57 | ModelType uint64 `json:"modelType"` //模型类别, 1: utxo模型(BTC), 2: account模型(ETH),3: 账户别名模型(EOS) 58 | 59 | core interface{} //核心账户指针 60 | } 61 | 62 | func NewMultiSigAccount(wallets []*Wallet, required uint, creator *Wallet) (*AssetsAccount, error) { 63 | 64 | return nil, nil 65 | } 66 | 67 | //NewUserAccount 创建账户 68 | func NewUserAccount() *AssetsAccount { 69 | account := &AssetsAccount{} 70 | return account 71 | } 72 | 73 | func (a *AssetsAccount) GetOwners() []AccountOwner { 74 | return nil 75 | } 76 | 77 | //GetAccountID 计算AccountID 78 | func (a *AssetsAccount) GetAccountID() string { 79 | 80 | if len(a.AccountID) > 0 { 81 | return a.AccountID 82 | } 83 | 84 | a.AccountID = GenAccountID(a.PublicKey) 85 | 86 | return a.AccountID 87 | } 88 | 89 | //GenAccountID 计算publicKey的AccountID 90 | //publickey为OW编码后 91 | func GenAccountID(publicKey string) string { 92 | 93 | pub, err := owkeychain.OWDecode(publicKey) 94 | if err != nil { 95 | return "" 96 | } 97 | 98 | return genAccountID(pub.GetPublicKeyBytes()) 99 | } 100 | 101 | //GenAccountIDByHex 计算publicKey的AccountID 102 | //publickey为HEX传 103 | func GenAccountIDByHex(publicKeyHex string) string { 104 | 105 | pub, err := hex.DecodeString(publicKeyHex) 106 | if err != nil { 107 | return "" 108 | } 109 | return genAccountID(pub) 110 | } 111 | 112 | func genAccountID(pub []byte) string { 113 | //seed Keccak256 两次得到keyID 114 | hash := crypto.Keccak256(pub) 115 | hash = crypto.Keccak256(hash) 116 | accountID := owkeychain.Encode(hash, owkeychain.BitcoinAlphabet) 117 | return accountID 118 | } 119 | -------------------------------------------------------------------------------- /openwallet/app.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | const ( 19 | defaultAppName = "openw" 20 | ) 21 | 22 | // App 23 | type App struct { 24 | AppID string `json:"appID"` 25 | AppName string `json:"appID"` 26 | } 27 | -------------------------------------------------------------------------------- /openwallet/assets.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | import ( 19 | "github.com/blocktree/openwallet/v2/log" 20 | ) 21 | 22 | //Coin 币种信息 23 | type Coin struct { 24 | Symbol string `json:"symbol"` 25 | IsContract bool `json:"isContract"` 26 | ContractID string `json:"contractID"` 27 | Contract SmartContract `json:"contract"` 28 | } 29 | 30 | // AssetsAdapter 资产适配器接口 31 | // 适配OpenWallet钱包体系的抽象接口 32 | type AssetsAdapter interface { 33 | 34 | //币种信息 35 | //@required 36 | SymbolInfo 37 | 38 | //配置 39 | //@required 40 | AssetsConfig 41 | 42 | //GetAddressDecodeV2 地址解析器V2 43 | //如果实现了AddressDecoderV2,就无需实现AddressDecoder 44 | //@required 45 | GetAddressDecoderV2() AddressDecoderV2 46 | 47 | //GetAddressDecode 地址解析器 48 | //如果实现了AddressDecoderV2,就无需实现AddressDecoder 49 | //@required 50 | GetAddressDecode() AddressDecoder 51 | 52 | //GetTransactionDecoder 交易单解析器 53 | //@required 54 | GetTransactionDecoder() TransactionDecoder 55 | 56 | //GetBlockScanner 获取区块链扫描器 57 | //@required 58 | GetBlockScanner() BlockScanner 59 | 60 | //GetSmartContractDecoder 获取智能合约解析器 61 | //@optional 62 | GetSmartContractDecoder() SmartContractDecoder 63 | 64 | //GetAssetsLogger 获取资产日志工具 65 | //@optional 66 | GetAssetsLogger() *log.OWLogger 67 | 68 | //GetJsonRPCEndpoint 获取全节点服务的JSON-RPC客户端 69 | //@optional 70 | GetJsonRPCEndpoint() JsonRPCEndpoint 71 | 72 | //GetNFTContractDecoder 获取NFT智能合约解析器 73 | //@optional 74 | GetNFTContractDecoder() NFTContractDecoder 75 | } 76 | 77 | type AssetsAdapterBase struct { 78 | SymbolInfoBase 79 | AssetsConfigBase 80 | } 81 | 82 | //GetAddressDecode 地址解析器 83 | func (a *AssetsAdapterBase) InitAssetsAdapter() error { 84 | return nil 85 | } 86 | 87 | //GetAddressDecode 地址解析器 88 | //如果实现了AddressDecoderV2,就无需实现AddressDecoder 89 | func (a *AssetsAdapterBase) GetAddressDecode() AddressDecoder { 90 | return nil 91 | } 92 | 93 | //GetAddressDecode 地址解析器 94 | //如果实现了AddressDecoderV2,就无需实现AddressDecoder 95 | func (a *AssetsAdapterBase) GetAddressDecoderV2() AddressDecoderV2 { 96 | return nil 97 | } 98 | 99 | //GetTransactionDecoder 交易单解析器 100 | func (a *AssetsAdapterBase) GetTransactionDecoder() TransactionDecoder { 101 | return nil 102 | } 103 | 104 | //GetBlockScanner 获取区块链扫描器 105 | func (a *AssetsAdapterBase) GetBlockScanner() BlockScanner { 106 | return nil 107 | } 108 | 109 | //GetBlockScanner 获取智能合约解析器 110 | func (a *AssetsAdapterBase) GetSmartContractDecoder() SmartContractDecoder { 111 | return nil 112 | } 113 | 114 | //GetAssetsLogger 获取资产账户日志工具 115 | func (a *AssetsAdapterBase) GetAssetsLogger() *log.OWLogger { 116 | return nil 117 | } 118 | 119 | //GetJsonRPCEndpoint 获取全节点服务的JSON-RPC客户端 120 | //@optional 121 | func (a *AssetsAdapterBase) GetJsonRPCEndpoint() JsonRPCEndpoint { 122 | return nil 123 | } 124 | 125 | //GetNFTContractDecoder 获取NFT智能合约解析器 126 | //@optional 127 | func (a *AssetsAdapterBase) GetNFTContractDecoder() NFTContractDecoder { 128 | return nil 129 | } 130 | -------------------------------------------------------------------------------- /openwallet/balance.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | type Balance struct { 19 | Symbol string 20 | AccountID string 21 | Address string 22 | ConfirmBalance string 23 | UnconfirmBalance string 24 | Balance string 25 | } 26 | 27 | type TokenBalance struct { 28 | Contract *SmartContract 29 | Balance *Balance 30 | } 31 | -------------------------------------------------------------------------------- /openwallet/cache.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | import "time" 19 | 20 | // CacheEntry Cache Entry 21 | type CacheEntry struct { 22 | Key string 23 | Value interface{} 24 | Expiration int64 25 | } 26 | 27 | // ICacheManager Cache Manager Interface 28 | type ICacheManager interface { 29 | Add(key string, value interface{}, duration time.Duration) error 30 | Get(key string) (interface{}, bool) 31 | GetCacheEntry(key string) (*CacheEntry, bool) 32 | Remove(key string) (interface{}, bool) 33 | Contains(key string) bool 34 | Clear() 35 | } 36 | -------------------------------------------------------------------------------- /openwallet/config.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | import "github.com/astaxie/beego/config" 19 | 20 | //AssetsConfig 用于给AssetsAdapter调用者初始化、加载外部配置的接口 21 | type AssetsConfig interface { 22 | 23 | //LoadExternalConfig 加载外部配置 24 | LoadAssetsConfig(c config.Configer) error 25 | 26 | //InitDefaultConfig 初始化默认配置 27 | InitAssetsConfig() (config.Configer, error) 28 | } 29 | 30 | type AssetsConfigBase struct{} 31 | 32 | //LoadAssetsConfig 加载外部配置 33 | func (as *AssetsConfigBase) LoadAssetsConfig(c config.Configer) error { 34 | return nil 35 | } 36 | 37 | //InitAssetsConfig 初始化默认配置 38 | func (as *AssetsConfigBase) InitAssetsConfig() (config.Configer, error) { 39 | return nil, nil 40 | } 41 | -------------------------------------------------------------------------------- /openwallet/constants.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | //钱包类型 19 | type WalletType = uint 20 | 21 | const ( 22 | WalletTypeSingle = 0 23 | WalletTypeMulti = 1 24 | ) 25 | 26 | const ( 27 | 28 | /// 私钥字节长度 29 | PrivateKeyLength = 32 30 | 31 | /// 公钥字节长度(压缩) 32 | PublicKeyLengthCompressed = 33 33 | 34 | /// 公钥字节长度(未压缩) 35 | PublicKeyLengthUncompressed = 65 36 | 37 | ) 38 | 39 | 40 | -------------------------------------------------------------------------------- /openwallet/contract_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | import ( 19 | "strings" 20 | "testing" 21 | ) 22 | 23 | func TestGenContractID(t *testing.T) { 24 | address := "" 25 | address = strings.ToLower(address) 26 | t.Logf("lower addr 1: %v", address) 27 | symbol := "MATIC" 28 | ID := GenContractID(symbol, address) 29 | t.Logf("ID 1: %v", ID) 30 | ID = GenContractID(symbol, address) 31 | t.Logf("ID 2: %v", ID) 32 | } 33 | -------------------------------------------------------------------------------- /openwallet/directory.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | import ( 19 | "path/filepath" 20 | "strings" 21 | ) 22 | 23 | //GetDataDir 钱包数据目录 24 | func GetDataDir(symbol string) string { 25 | return filepath.Join("data", strings.ToLower(symbol)) 26 | } 27 | 28 | //GetKeyDir 密钥目录 29 | func GetKeyDir(symbol string) string { 30 | return filepath.Join(GetDataDir(symbol), "key") 31 | } 32 | 33 | //GetDBDir 钱包数据库目录 34 | func GetDBDir(symbol string) string { 35 | return filepath.Join(GetDataDir(symbol), "db") 36 | } 37 | 38 | //GetBackupDir 钱包备份目录 39 | func GetBackupDir(symbol string) string { 40 | return filepath.Join(GetDataDir(symbol), "backup") 41 | } 42 | 43 | //GetExportAddressDir 导出地址目录 44 | func GetExportAddressDir(symbol string) string { 45 | return filepath.Join(GetDataDir(symbol), "address") 46 | } -------------------------------------------------------------------------------- /openwallet/docs/README.md: -------------------------------------------------------------------------------- 1 | # openwallet document 2 | 3 | openwallet包定义了规范化的钱包体系模型和协议。 4 | 5 | - [区块链资产适配器开发教程](./assets.md)。 6 | - [钱包管理模型开发教程](./wallet.md)。 -------------------------------------------------------------------------------- /openwallet/docs/assets.md: -------------------------------------------------------------------------------- 1 | # AssetsAdapter 2 | 3 | AssetsAdapter是区块链资产适配器接口。开发者可以创建独立的项目进行实现,例如:bitcoin-adapter。 4 | 我们的开发经验总结出,适配区块链资产需要支持以下,则实现以下接口: 5 | 6 | - 币种信息。关键信息有"标识符"symbol(用于作为关键字映射适配器),"小数位精度"Decimal,"ECC曲线类型"CurveType。 7 | - 适配器配置。每个资产适配器的配置存在差异,适配器实现加载配置,外部程序传入配置接口。 8 | - 地址解析器。不同区块链存在地址编码不同的情况,资产适配器提供地址解析器工具,给应用去处理地址解析问题。 9 | - 交易单解析器。提供标准的交易流程:创建交易单,签名交易单,验证交易单,广播交易单。资产适配器各自实现其交易协议。 10 | - [区块链扫描器](./blockscanner.md)。提供标准的区块扫描器,调用设置观测者,可接受区块扫描提取结果。资产适配器各自实现区块提取算法。 11 | - 智能合约解析器。用于区块链智能合约方面的扩展,目前支持获取Token余额。 12 | - 日志工具。每个适配包独立的日志管理,方便上层应用控制。 13 | 14 | 代码接口如下: 15 | 16 | ```go 17 | 18 | // AssetsAdapter 资产适配器接口 19 | // 适配OpenWallet钱包体系的抽象接口 20 | type AssetsAdapter interface { 21 | 22 | //币种信息 23 | //@required 24 | SymbolInfo 25 | 26 | //配置 27 | //@required 28 | AssetsConfig 29 | 30 | //GetAddressDecode 地址解析器 31 | //@required 32 | GetAddressDecode() AddressDecoder 33 | 34 | //GetTransactionDecoder 交易单解析器 35 | //@required 36 | GetTransactionDecoder() TransactionDecoder 37 | 38 | //GetBlockScanner 获取区块链扫描器 39 | //@required 40 | GetBlockScanner() BlockScanner 41 | 42 | //GetSmartContractDecoder 获取智能合约解析器 43 | //@optional 44 | GetSmartContractDecoder() SmartContractDecoder 45 | 46 | //GetAssetsLogger 获取资产日志工具 47 | //@optional 48 | GetAssetsLogger() *log.OWLogger 49 | } 50 | 51 | 52 | ``` 53 | 54 | ## 已完成区块链资产适配器 55 | 56 | - [bitcoin-adapter](https://github.com/blocktree/bitcoin-adapter) 57 | - [litcoin-adapter](https://github.com/blocktree/litcoin-adapter) 58 | - [ethereum-adapter](https://github.com/blocktree/ethereum-adapter) 59 | - [tron-adapter](https://github.com/blocktree/tron-adapter) 60 | - more... -------------------------------------------------------------------------------- /openwallet/docs/blockscanner.md: -------------------------------------------------------------------------------- 1 | # BlockScanner 2 | 3 | 区块扫描器接口,由资产适配包实现区块扫描方法,通知已openwallet钱包体系设计的数据到应用层。 4 | 5 | ## 区块链交易单模型 6 | 7 | 几乎所有的区块链交易单结构,或采用utxo模型,或采用account模型。(DAG有向无环图未研究) 8 | 9 | ### UTXO模型 10 | 11 | 这类模型的区块链不能直接查询到余额的,每笔交易单都以多个输入(vins)和多个输出(vouts)组成。 12 | 输入合计数量必须大于或等于输出合计数量。矿工费 = 总输入 - 总输出。 13 | 每次构建新交易单,总是依赖地址未使用过的输出,我们称为unspent transaction output(utxo)。 14 | 所以要知道地址的余额,就是累计地址所有的utxo中的数量。 15 | 16 | 大部分区块链采用这种模型的:bitcoin系,bytom,qtum等等。 17 | 18 | ### account模型 19 | 20 | 采用这类模型的,可以直接在区块链中查到地址的余额。与utxo模型不同是,交易单只能有一对输入输出。 21 | 22 | 采用这种模型的:ethereum,nas等等。 23 | 24 | ## 区块扫描器使用流程 25 | 26 | - 获取某个适配的区块扫描器接口。 27 | - 通过调用SetBlockScanAddressFunc(scanAddressFunc BlockScanAddressFunc)方法,设置区块扫描器,查找地址算法。 28 | - 通过AddObserver(obj BlockScanNotificationObject)添加监听者。 29 | - 调用者实现BlockScanAddressFunc方法,返回传入的地址是否存在,及地址关联的sourceKey值。 30 | - BlockScanNotificationObject要实现接收数据的接口方法,并保存。 31 | - 执行Run()启动扫描器运行。 32 | 33 | ## 区块扫描任务实现 34 | 35 | - 区块任务会放在定时器中定时执行,定时间隔要少于出块时间,不然永远都扫不到链的最大高度。 36 | - 扫描器以本地已扫高度为开始,先一直扫描到最大高度,再扫描内存池交易,最后扫描失败记录,结束一次任务。 37 | - 每完成一个区块扫描,通知观察者新的区块头数据,并使用本地数据库文件记录区块头数据。 38 | - 每次任务都会查找是否有新区块可扫。 39 | - 如果扫描到新区块时,发现就上一区块分叉,则回退扫描,并通知观察者有区块分叉,直到没有分叉的区块为止。 40 | 41 | ## 区块中的交易单提取实现 42 | 43 | - 由于区块中的交易单数组是否互相独立的,为了提高效率,我们可以采用生产消费者并发模型,并行提取多张交易单的数据。 44 | - openwallet钱包体系,以资产账户作为基本操作单位。一个账户可能有多个地址,所以存在多个地址指向相同的sourceKey。sourceKey作为索引收集一张交易单中与地址相关的提取结果。 45 | - 提取结果最终以N个TxInput,M个TxOutPut,1个Transaction,通知给BlockScanNotificationObject观察者。 46 | 47 | ## BlockScanNotificationObject接口说明 48 | 49 | 实现BlockScanNotificationObject接口。 50 | 51 | - BlockScanNotify获取新区块。 52 | - BlockExtractDataNotify交易单提取结果 53 | 54 | ```go 55 | 56 | //BlockScanNotify 新区块扫描完成通知 57 | BlockScanNotify(header *BlockHeader) error 58 | 59 | //BlockExtractDataNotify 区块提取结果通知 60 | BlockExtractDataNotify(sourceKey string, data *TxExtractData) error 61 | 62 | ``` 63 | 64 | ### TxExtractData 65 | 66 | blockscanner会从每笔交易单中,根据订阅地址提取出来,并以地址绑定的sourceKey汇集在一个提取结果中。 67 | sourceKey其实就是账户的唯一标识符。 68 | 69 | - []*TxInput,utxo模型的可以有多个输入,account模型只有1个。 70 | - []*TxOutPut,utxo模型的可以有多个输出,account模型只有1个。 71 | - *Transaction,openwallet的钱包模型是以账户为单位的,账户存在多个地址可能,所以账户在该交易单的转账数量是以[]*TxOutPut的总数量 - []*TxInput的总数量计算出来。 72 | 73 | ### account模型类区块扫描注意事项 74 | 75 | - 手续费是记录在交易单上,为了给上层应用计算完整,需要为手续费建1个TxInput。 76 | - 智能合约类的交易单存在失败状态。失败状态下,只扣了手续费,而from和to就不需要建TxOutPut,TxInput。 77 | - 扫描合约转账。要提取2张交易单,1张是代币的转账,1张是主链币消耗手续费单。 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /openwallet/docs/wallet.md: -------------------------------------------------------------------------------- 1 | # 钱包管理模型开发 2 | 3 | 钱包与资产账户是一对多的关系,资产账户与地址是一对多的关系。 4 | openw包实现了一个单机版的钱包管理模型。其集成了AssetsAdapter接口,可用于测试整个区块链资产适配器的功能。 5 | 钱包管理系统开发者可参考openw包,基于openwallet框架实现自己的钱包管理系统。 6 | 7 | ## WalletDAI实现 8 | 9 | WalletDAI是钱包数据访问接口。该接口由钱包管理系统实现,这样AssetsAdapter便可通过该接口查询钱包相关数据,主要完成交易单构建工作。 10 | 11 | 如下接口定义: 12 | 13 | ```go 14 | 15 | 16 | //WalletDAI 钱包数据访问接口 17 | type WalletDAI interface { 18 | //获取当前钱包 19 | GetWallet() *Wallet 20 | //根据walletID查询钱包 21 | GetWalletByID(walletID string) (*Wallet, error) 22 | 23 | //获取单个资产账户 24 | GetAssetsAccountInfo(accountID string) (*AssetsAccount, error) 25 | //查询资产账户列表 26 | GetAssetsAccountList(offset, limit int, cols ...interface{}) ([]*AssetsAccount, error) 27 | //根据地址查询资产账户 28 | GetAssetsAccountByAddress(address string) (*AssetsAccount, error) 29 | 30 | //获取单个地址 31 | GetAddress(address string) (*Address, error) 32 | //查询地址列表 33 | GetAddressList(offset, limit int, cols ...interface{}) ([]*Address, error) 34 | //设置地址的扩展字段 35 | SetAddressExtParam(address string, key string, val interface{}) error 36 | //获取地址的扩展字段 37 | GetAddressExtParam(address string, key string) (interface{}, error) 38 | 39 | //解锁钱包,指定时间内免密 40 | UnlockWallet(password string, time time.Duration) error 41 | //获取钱包HDKey 42 | HDKey(password ...string) (*hdkeystore.HDKey, error) 43 | } 44 | 45 | ``` -------------------------------------------------------------------------------- /openwallet/endpoint.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The OpenWallet Authors 3 | * This file is part of the OpenWallet library. 4 | * 5 | * The OpenWallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The OpenWallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | import "fmt" 19 | 20 | // JsonRPCEndpoint 全节点服务的JSON-RPC接口 21 | type JsonRPCEndpoint interface { 22 | 23 | //SendRPCRequest 发起JSON-RPC请求 24 | //@optional 25 | SendRPCRequest(method string, request interface{}) ([]byte, error) 26 | 27 | //SupportJsonRPCEndpoint 是否开放客户端直接调用全节点的JSON-RPC方法 28 | //@optional 29 | SupportJsonRPCEndpoint() bool 30 | } 31 | 32 | type JsonRPCEndpointBase int 33 | 34 | //SendRPCRequest 发起JSON-RPC请求 35 | //@optional 36 | func (base *JsonRPCEndpointBase) SendRPCRequest(method string, request interface{}) ([]byte, error) { 37 | return nil, fmt.Errorf("SendRPCRequest is not implemented") 38 | } 39 | 40 | //SupportJsonRPCEndpoint 是否开放客户端直接调用全节点的JSON-RPC方法 41 | //@optional 42 | func (base *JsonRPCEndpointBase) SupportJsonRPCEndpoint() bool { 43 | return false 44 | } 45 | -------------------------------------------------------------------------------- /openwallet/error_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The OpenWallet Authors 3 | * This file is part of the OpenWallet library. 4 | * 5 | * The OpenWallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The OpenWallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | import ( 19 | "encoding/json" 20 | "fmt" 21 | "github.com/blocktree/openwallet/v2/log" 22 | "testing" 23 | ) 24 | 25 | func TestConvertError(t *testing.T) { 26 | err := Errorf(ErrAccountNotAddress, "[%s] have not addresses", "zzz") 27 | log.Infof("err: %v", err) 28 | owerr := ConvertError(err) 29 | log.Infof("owerr: %v", owerr) 30 | jerr, _ := json.Marshal(owerr) 31 | log.Infof("jerr: %v", string(jerr)) 32 | 33 | err2 := fmt.Errorf("[%s] have not addresses", "zzz") 34 | log.Infof("err2: %v", err2) 35 | owerr2 := ConvertError(err2) 36 | log.Infof("owerr2: %v", owerr2) 37 | jerr2, _ := json.Marshal(owerr2) 38 | log.Infof("jerr2: %v", string(jerr2)) 39 | } 40 | -------------------------------------------------------------------------------- /openwallet/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | import ( 19 | "encoding/json" 20 | "fmt" 21 | ) 22 | 23 | const ( 24 | /* 交易类别 */ 25 | ErrInsufficientBalanceOfAccount = 2001 //账户余额不足 26 | ErrInsufficientBalanceOfAddress = 2002 //地址余额不足 27 | ErrInsufficientFees = 2003 //手续费不足 28 | ErrDustLimit = 2004 //限制粉尘攻击 29 | ErrCreateRawTransactionFailed = 2005 //创建原始交易单失败 30 | ErrSignRawTransactionFailed = 2006 //签名原始交易单失败 31 | ErrVerifyRawTransactionFailed = 2007 //验证原始交易单失败 32 | ErrSubmitRawTransactionFailed = 2008 //广播原始交易单失败 33 | ErrInsufficientTokenBalanceOfAddress = 2009 //地址代币余额不足 34 | 35 | /* 账户类别 */ 36 | ErrAccountNotFound = 3001 //账户不存在 37 | ErrAddressNotFound = 3002 //地址不存在 38 | ErrContractNotFound = 3003 //合约不存在 39 | ErrAdressEncodeFailed = 3004 //地址编码失败 40 | ErrAdressDecodeFailed = 3006 //地址解码失败 41 | ErrNonceInvaild = 3007 //Nonce不正确 42 | ErrAccountNotAddress = 3008 //账户没有地址 43 | 44 | /* 网络类型 */ 45 | ErrCallFullNodeAPIFailed = 4001 //全节点API无法访问 46 | ErrNetworkRequestFailed = 4002 //网络请求失败 47 | 48 | /* 智能合约类 */ 49 | ErrContractCallMsgInvalid = 5001 //合约调用参数无效 50 | ErrCreateRawSmartContractTransactionFailed = 5002 //创建原始合约交易单失败 51 | ErrSubmitRawSmartContractTransactionFailed = 5003 //广播原始合约交易单失败 52 | 53 | /* 其他 */ 54 | ErrUnknownException = 9001 //未知异常情况 55 | ErrSystemException = 9002 //系统程序异常情况 56 | ) 57 | 58 | type Error struct { 59 | code uint64 60 | err string 61 | } 62 | 63 | // Error 错误信息 64 | func (err *Error) Error() string { 65 | return fmt.Sprintf("[%d]%s", err.code, err.err) 66 | } 67 | 68 | // Code 错误编号 69 | func (err *Error) Code() uint64 { 70 | return err.code 71 | } 72 | 73 | //ConvertError error转OWError 74 | func ConvertError(err error) *Error { 75 | 76 | if err == nil { 77 | return nil 78 | } 79 | 80 | owErr, ok := err.(*Error) 81 | if !ok { 82 | return &Error{code: ErrUnknownException, err: err.Error()} 83 | } 84 | return owErr 85 | } 86 | 87 | //Errorf 生成OWError 88 | func Errorf(code uint64, format string, a ...interface{}) *Error { 89 | err := &Error{ 90 | code: code, 91 | err: fmt.Sprintf(format, a...), 92 | } 93 | return err 94 | } 95 | 96 | //NewError 生成OWError 97 | func NewError(code uint64, text string) *Error { 98 | err := &Error{ 99 | code: code, 100 | err: text, 101 | } 102 | return err 103 | } 104 | 105 | // Json 错误信息JSON输出 106 | func (err *Error) MarshalJSON() ([]byte, error) { 107 | obj := map[string]interface{}{ 108 | "code": err.code, 109 | "msg": err.err, 110 | } 111 | return json.Marshal(obj) 112 | } 113 | 114 | func (err *Error) UnmarshalJSON(b []byte) error { 115 | var obj map[string]interface{} 116 | e := json.Unmarshal(b, &obj) 117 | if e != nil { 118 | return e 119 | } 120 | 121 | err.err = obj["msg"].(string) 122 | err.code = obj["code"].(uint64) 123 | 124 | return nil 125 | } 126 | -------------------------------------------------------------------------------- /openwallet/openwallet.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | const ( 19 | // VERSION represent openw web framework version. 20 | VERSION = "1.0.0" 21 | // DEV is for develop 22 | DEV = "dev" 23 | // PROD is for production 24 | PROD = "prod" 25 | ) 26 | 27 | //hook function to run 28 | type hookfunc func() error 29 | 30 | var ( 31 | hooks = make([]hookfunc, 0) //hook function slice to store the hookfunc 32 | ) 33 | 34 | -------------------------------------------------------------------------------- /openwallet/signer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The OpenWallet Authors 3 | * This file is part of the OpenWallet library. 4 | * 5 | * The OpenWallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The OpenWallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | import "fmt" 19 | 20 | //TransactionSigner 交易签署器 21 | type TransactionSigner interface { 22 | 23 | // SignTransactionHash 交易哈希签名算法 24 | // required 25 | SignTransactionHash(msg []byte, privateKey []byte, eccType uint32) ([]byte, error) 26 | } 27 | 28 | type TransactionSignerBase struct { 29 | 30 | 31 | } 32 | 33 | // SignTransactionHash 交易哈希签名算法 34 | // required 35 | func (singer *TransactionSignerBase) SignTransactionHash(msg []byte, privateKey []byte, eccType uint32) ([]byte, error) { 36 | return nil, fmt.Errorf("SignTransactionHash not implement") 37 | } -------------------------------------------------------------------------------- /openwallet/symbol.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | // 余额模型类别 19 | type BalanceModelType uint32 20 | 21 | const ( 22 | BalanceModelTypeAddress BalanceModelType = 0 //以地址记录余额 23 | BalanceModelTypeAccount BalanceModelType = 1 //以账户记录余额 24 | ) 25 | 26 | type SymbolInfo interface { 27 | 28 | //CurveType 曲线类型 29 | CurveType() uint32 30 | 31 | //FullName 币种全名 32 | FullName() string 33 | 34 | //Symbol 币种标识 35 | Symbol() string 36 | 37 | //Decimal 小数位精度 38 | Decimal() int32 39 | 40 | //BalanceModelType 余额模型类别 41 | BalanceModelType() BalanceModelType 42 | } 43 | 44 | type SymbolInfoBase struct { 45 | } 46 | 47 | //CurveType 曲线类型 48 | func (s *SymbolInfoBase) CurveType() uint32 { 49 | return 0 50 | } 51 | 52 | //FullName 币种全名 53 | func (s *SymbolInfoBase) FullName() string { 54 | return "" 55 | } 56 | 57 | //Symbol 币种标识 58 | func (s *SymbolInfoBase) Symbol() string { 59 | return "" 60 | } 61 | 62 | //Decimal 小数位精度 63 | func (s *SymbolInfoBase) Decimal() int32 { 64 | return 0 65 | } 66 | 67 | //BalanceModelType 余额模型类别 68 | func (s *SymbolInfoBase) BalanceModelType() BalanceModelType { 69 | return BalanceModelTypeAddress 70 | } 71 | -------------------------------------------------------------------------------- /openwallet/type.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | //公钥 19 | type PublicKey []byte 20 | 21 | //字节流 22 | type Bytes []byte 23 | 24 | 25 | func BytesToPublicKey(b []byte) PublicKey { 26 | var pk PublicKey 27 | copy(pk, b) 28 | return pk 29 | } 30 | 31 | 32 | -------------------------------------------------------------------------------- /openwallet/wallet_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package openwallet 17 | 18 | import ( 19 | "testing" 20 | "log" 21 | ) 22 | 23 | func TestNewWallet(t *testing.T) { 24 | wallet := NewWallet("W4ruoAyS5HdBMrEeeHQTBxo4XtaAixheXQ", "btc") 25 | if wallet == nil { 26 | log.Printf("NewWallet unexpected error: ") 27 | } 28 | log.Printf("wallet: %v", wallet) 29 | } 30 | -------------------------------------------------------------------------------- /owtp/auth_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package owtp 17 | 18 | import ( 19 | "crypto/hmac" 20 | "crypto/sha256" 21 | "encoding/hex" 22 | "github.com/blocktree/openwallet/v2/common" 23 | "github.com/blocktree/openwallet/v2/log" 24 | "github.com/mr-tron/base58/base58" 25 | "testing" 26 | ) 27 | 28 | func TestRandomPrivateKey(t *testing.T) { 29 | key := RandomPrivateKey() 30 | t.Logf("key: %v", key) 31 | } 32 | 33 | func TestNewOWTPAuthWithCertificate(t *testing.T) { 34 | 35 | key := RandomPrivateKey() 36 | t.Logf("key: %v", key) 37 | 38 | cert, err := NewCertificate(key, "") 39 | if err != nil { 40 | t.Errorf("Dial failed unexpected error: %v", err) 41 | return 42 | } 43 | //t.Logf("cert: %v", cert) 44 | auth, err := NewOWTPAuthWithCertificate(cert, false) 45 | if err != nil { 46 | t.Errorf("Dial failed unexpected error: %v", err) 47 | return 48 | } 49 | //t.Logf("localPublicKey: %v", auth.localPublicKey) 50 | t.Logf("nodeID: %v", auth.LocalPID()) 51 | t.Logf("auth header: %v", auth.HTTPAuthHeader()) 52 | } 53 | 54 | func TestCertificate(t *testing.T) { 55 | cert, err := NewCertificate("CKv1vLjKGCp9uSGhLmXFgn2TLRdvEiiqRCfvmW6qwWJQ", "") 56 | if err != nil { 57 | t.Errorf("Dial failed unexpected error: %v", err) 58 | return 59 | } 60 | t.Logf("nodeID: %v", cert.ID()) 61 | } 62 | 63 | func TestBase58(t *testing.T) { 64 | encode := "6f1yErtapWhSGwQmXQUeM7dTnaGgQb2m8hv13hXYsPW6q5EvkZXWdPa3HjYo4yYV6YocGZerwth6qyNdAaT9MrV7B2wJZeugTn5CrvbuWC4cqQkKXWWhXa76LNfK8fDcDjhJvKMeGEce2R2j2fadQHXyH5QbSieWUuhxMUUi8dRY7wP" 65 | pub, _ := base58.Decode(encode) 66 | log.Info("pub decode:", hex.EncodeToString(pub)) 67 | 68 | pubbs, _ := hex.DecodeString("038EA1AF7C58F2FC1BF1BF7C04075513D9B6FFF4517D84F53B2D04E179D1054810F4C27C24AB9A54F962E2892A067B4E83BEF7C53A145C2EDC6BFB83852EDD77") 69 | 70 | log.Info("pub encode:", base58.Encode(pubbs)) 71 | } 72 | 73 | func TestEncryptData(t *testing.T) { 74 | nonce := 1181076977457565696 75 | log.Infof("nonce: %d", nonce) 76 | b58 := "CKv1vLjKGCp9uSGhLmXFgn2TLRdvEiiqRCfvmW6qwWJQ" 77 | key, _ := base58.Decode(b58) 78 | log.Infof("key: %s", hex.EncodeToString(key)) 79 | //把nonce作为salt 80 | nonceBit := []byte(common.NewString(nonce).String()) 81 | h := hmac.New(sha256.New, nonceBit) 82 | h.Write(key) 83 | md := h.Sum(nil) 84 | newkey := md 85 | log.Infof("key: %s", hex.EncodeToString(newkey)) 86 | } 87 | -------------------------------------------------------------------------------- /owtp/http_listener.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package owtp 17 | 18 | import ( 19 | "fmt" 20 | "net" 21 | "net/http" 22 | 23 | "github.com/blocktree/openwallet/v2/log" 24 | "github.com/pkg/errors" 25 | ) 26 | 27 | // owtp监听器 28 | type httpListener struct { 29 | net.Listener 30 | handler PeerHandler 31 | laddr string 32 | peerstore Peerstore //节点存储器 33 | enableSignature bool 34 | } 35 | 36 | // serve 监听服务 37 | func (l *httpListener) serve() error { 38 | 39 | if l.Listener == nil { 40 | return errors.New("listener is not setup.") 41 | } 42 | 43 | http.Serve(l.Listener, l) 44 | 45 | return nil 46 | } 47 | 48 | // ServeHTTP 实现HTTP服务监听 49 | func (l *httpListener) ServeHTTP(w http.ResponseWriter, r *http.Request) { 50 | 51 | //建立节点 52 | peer, err := NewHTTPClientWithHeader(w, r, l.handler, l.enableSignature) 53 | if err != nil { 54 | log.Error("NewClient unexpected error:", err) 55 | //http.Error(w, "authorization not passed", 400) 56 | HttpError(w, r, err.Error(), http.StatusOK) 57 | return 58 | } 59 | 60 | //HTTP是短连接,接收到数据,节点马上处理,无需像websocket那样管理连接 61 | err = peer.HandleRequest() 62 | if err != nil { 63 | //log.Error("HandleRequest unexpected error:", err) 64 | HttpError(w, r, err.Error(), http.StatusOK) 65 | return 66 | } 67 | } 68 | 69 | // HttpError 错误 70 | func HttpError(w http.ResponseWriter, r *http.Request, error string, code int) { 71 | w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin")) 72 | w.Header().Set("Access-Control-Allow-Headers", "*") 73 | w.WriteHeader(code) 74 | fmt.Fprintln(w, error) 75 | } 76 | 77 | // Accept 接收新节点链接,线程阻塞 78 | func (l *httpListener) Accept() (Peer, error) { 79 | return nil, fmt.Errorf("http do not implement") 80 | } 81 | 82 | // ListenAddr 创建OWTP协议通信监听 83 | func HttpListenAddr(addr string, enableSignature bool, handler PeerHandler) (*httpListener, error) { 84 | l, err := net.Listen("tcp", addr) 85 | if err != nil { 86 | return nil, err 87 | } 88 | listener := httpListener{ 89 | Listener: l, 90 | laddr: addr, 91 | handler: handler, 92 | enableSignature: enableSignature, 93 | } 94 | 95 | go listener.serve() 96 | 97 | return &listener, nil 98 | } 99 | -------------------------------------------------------------------------------- /owtp/mq_client_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package owtp 17 | 18 | import ( 19 | "encoding/json" 20 | "testing" 21 | "time" 22 | ) 23 | 24 | var ( 25 | mqtestUrl = "amqp://aielves:aielves12301230@39.108.64.191:36672/" 26 | ) 27 | 28 | func init() { 29 | 30 | } 31 | 32 | func TestMQDial(t *testing.T) { 33 | 34 | client, err := MQDial("hello", mqtestUrl, nil) 35 | if err != nil { 36 | t.Errorf("Dial failed unexpected error: %v", err) 37 | return 38 | } 39 | defer client.close() 40 | 41 | client.openPipe() 42 | } 43 | 44 | func TestMQEncodeDataPacket(t *testing.T) { 45 | 46 | //封装数据包 47 | packet := DataPacket{ 48 | Method: "subscribe", 49 | Req: WSRequest, 50 | Nonce: 1, 51 | Timestamp: time.Now().Unix(), 52 | Data: map[string]interface{}{ 53 | "sss": "sdfsdf", 54 | }, 55 | } 56 | 57 | respBytes, err := json.Marshal(packet) 58 | if err != nil { 59 | t.Errorf("Dial failed unexpected error: %v", err) 60 | return 61 | } 62 | t.Logf("Send: %s \n", string(respBytes)) 63 | 64 | } 65 | -------------------------------------------------------------------------------- /owtp/mq_data.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package owtp 17 | 18 | 19 | type MqAddr struct { 20 | NetWork string 21 | } 22 | 23 | func (m *MqAddr)Network() string { 24 | return m.NetWork 25 | } 26 | 27 | func (m *MqAddr)String() string { 28 | return m.NetWork 29 | } -------------------------------------------------------------------------------- /owtp/multi_connect_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package owtp 17 | 18 | import ( 19 | "fmt" 20 | "github.com/blocktree/openwallet/v2/log" 21 | "sync" 22 | "testing" 23 | ) 24 | 25 | var ( 26 | multiConnectHost *OWTPNode 27 | multiConnectHTTPURL = "127.0.0.1:8422" 28 | multiConnectWSURL = "127.0.0.1:8423" 29 | multiConnectPrv = "FSomdQBZYzgu9YYuuSr3qXd8sP1sgQyk4rhLFo6gyi32" 30 | multiConnectHostNodeID = "54dZTdotBmE9geGJmJcj7Qzm6fzNrEUJ2NcDwZYp2QEp" 31 | ) 32 | 33 | func TestMultiConnectHostRun(t *testing.T) { 34 | 35 | var ( 36 | endRunning = make(chan bool, 1) 37 | ) 38 | 39 | cert, _ := NewCertificate(multiConnectPrv) 40 | multiConnectHost = NewNode(NodeConfig{Cert: cert}) 41 | //httpHost.SetPeerstore(globalSessions) 42 | fmt.Printf("nodeID = %s \n", multiConnectHost.NodeID()) 43 | 44 | //config["enableSignature"] = "1" 45 | multiConnectHost.HandleFunc("getInfo", getInfo) 46 | multiConnectHost.HandlePrepareFunc(func(ctx *Context) { 47 | log.Notice("prepare") 48 | log.Infof("peer[%+v] config", ctx.Peer.ConnectConfig()) 49 | }) 50 | multiConnectHost.HandleFinishFunc(func(ctx *Context) { 51 | log.Notice("finish") 52 | }) 53 | 54 | //listen HTTP 55 | multiConnectHost.Listen( 56 | ConnectConfig{ 57 | Address: multiConnectHTTPURL, 58 | ConnectType: HTTP, 59 | }) 60 | 61 | //listen websocket 62 | multiConnectHost.Listen( 63 | ConnectConfig{ 64 | Address: multiConnectWSURL, 65 | ConnectType: Websocket, 66 | }) 67 | 68 | multiConnectHost.SetOpenHandler(func(n *OWTPNode, peer PeerInfo) { 69 | log.Infof("peer[%s] connected", peer.ID) 70 | log.Infof("peer[%+v] config", peer.Config) 71 | //n.ClosePeer(peer.ID) 72 | }) 73 | 74 | <-endRunning 75 | } 76 | 77 | func TestMultiConnectClientCall(t *testing.T) { 78 | var wait sync.WaitGroup 79 | 80 | for i := 0; i < 2; i++ { 81 | wait.Add(1) 82 | 83 | go func(k int) { 84 | var connectType, addr string 85 | if k%2 == 0 { 86 | connectType = HTTP 87 | addr = multiConnectHTTPURL 88 | } else { 89 | connectType = Websocket 90 | addr = multiConnectWSURL 91 | } 92 | 93 | client := RandomOWTPNode() 94 | client.HandleFunc("getInfo", getInfo) 95 | _, err := client.Connect(multiConnectHostNodeID, ConnectConfig{ 96 | Address: addr, 97 | ConnectType: connectType, 98 | }) 99 | 100 | if err != nil { 101 | log.Errorf("Connect unexcepted error: %v", err) 102 | return 103 | } 104 | 105 | err = client.KeyAgreement(multiConnectHostNodeID, "aes") 106 | if err != nil { 107 | log.Errorf("KeyAgreement unexcepted error: %v", err) 108 | return 109 | } 110 | 111 | params := map[string]interface{}{ 112 | "name": "chance", 113 | "age": 18, 114 | } 115 | 116 | err = client.Call(multiConnectHostNodeID, "getInfo", params, true, func(resp Response) { 117 | 118 | result := resp.JsonData() 119 | symbols := result.Get("symbols") 120 | fmt.Printf("symbols: %v\n", symbols) 121 | }) 122 | 123 | if err != nil { 124 | log.Errorf("unexcepted error: %v", err) 125 | return 126 | } 127 | 128 | wait.Done() 129 | }(i) 130 | } 131 | wait.Wait() 132 | } 133 | -------------------------------------------------------------------------------- /owtp/mux_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package owtp 17 | 18 | import ( 19 | "testing" 20 | "time" 21 | ) 22 | 23 | func TestRequestReplayAttack(t *testing.T) { 24 | 25 | var ( 26 | err error 27 | status uint64 28 | msg string 29 | ) 30 | 31 | mux := NewServeMux(120) 32 | mux.requestNonceLimit = 3 * time.Second 33 | 34 | status, msg = mux.checkNonceReplayReason("1", 1) 35 | 36 | t.Logf("status = %d, msg = %s", status, msg) 37 | 38 | peer := &HTTPClient{ 39 | pid: "1", 40 | } 41 | 42 | err = mux.AddRequest(peer, 1, time.Now().Unix(), "h", nil, nil, false) 43 | if err != nil { 44 | t.Errorf("RequestReplayAttack failed unexpected error: %v", err) 45 | return 46 | } 47 | 48 | status, msg = mux.checkNonceReplayReason("1", 1) 49 | t.Logf("status = %d, msg = %s", status, msg) 50 | 51 | time.Sleep(5 * time.Second) 52 | 53 | status, msg = mux.checkNonceReplayReason("1", 1) 54 | t.Logf("status = %d, msg = %s", status, msg) 55 | } 56 | -------------------------------------------------------------------------------- /owtp/session_store_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package owtp 17 | 18 | import ( 19 | "encoding/json" 20 | "fmt" 21 | "github.com/blocktree/openwallet/v2/session" 22 | "testing" 23 | ) 24 | 25 | func TestMem(t *testing.T) { 26 | config := `{"gclifetime":10}` 27 | conf := new(session.ManagerConfig) 28 | if err := json.Unmarshal([]byte(config), conf); err != nil { 29 | t.Fatal("json decode error", err) 30 | } 31 | globalSessions, _ := NewSessionManager("memory", conf) 32 | go globalSessions.GC() 33 | 34 | err := globalSessions.Put("123456", "username", "owtp") 35 | if err != nil { 36 | t.Fatal("set error,", err) 37 | } 38 | username := globalSessions.Get("123456", "username") 39 | if username != "owtp" { 40 | t.Fatal("get username error") 41 | } 42 | 43 | err = globalSessions.Put("qwer", "username", "good") 44 | if err != nil { 45 | t.Fatal("set error,", err) 46 | } 47 | username2 := globalSessions.Get("qwer", "username") 48 | if username2 != "good" { 49 | t.Fatal("get username error") 50 | } 51 | 52 | fmt.Printf("username = %s \n", username) 53 | fmt.Printf("username2 = %s \n", username2) 54 | } 55 | -------------------------------------------------------------------------------- /session/sess_cookie_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package session 16 | 17 | import ( 18 | "encoding/json" 19 | "net/http" 20 | "net/http/httptest" 21 | "strings" 22 | "testing" 23 | ) 24 | 25 | func TestCookie(t *testing.T) { 26 | config := `{"cookieName":"gosessionid","enableSetCookie":false,"gclifetime":3600,"ProviderConfig":"{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}"}` 27 | conf := new(ManagerConfig) 28 | if err := json.Unmarshal([]byte(config), conf); err != nil { 29 | t.Fatal("json decode error", err) 30 | } 31 | globalSessions, err := NewManager("cookie", conf) 32 | if err != nil { 33 | t.Fatal("init cookie session err", err) 34 | } 35 | r, _ := http.NewRequest("GET", "/", nil) 36 | w := httptest.NewRecorder() 37 | sess, err := globalSessions.SessionStart(w, r) 38 | if err != nil { 39 | t.Fatal("set error,", err) 40 | } 41 | err = sess.Set("username", "astaxie") 42 | if err != nil { 43 | t.Fatal("set error,", err) 44 | } 45 | if username := sess.Get("username"); username != "astaxie" { 46 | t.Fatal("get username error") 47 | } 48 | sess.SessionRelease(w) 49 | if cookiestr := w.Header().Get("Set-Cookie"); cookiestr == "" { 50 | t.Fatal("setcookie error") 51 | } else { 52 | parts := strings.Split(strings.TrimSpace(cookiestr), ";") 53 | for k, v := range parts { 54 | nameval := strings.Split(v, "=") 55 | if k == 0 && nameval[0] != "gosessionid" { 56 | t.Fatal("error") 57 | } 58 | } 59 | } 60 | } 61 | 62 | func TestDestorySessionCookie(t *testing.T) { 63 | config := `{"cookieName":"gosessionid","enableSetCookie":true,"gclifetime":3600,"ProviderConfig":"{\"cookieName\":\"gosessionid\",\"securityKey\":\"beegocookiehashkey\"}"}` 64 | conf := new(ManagerConfig) 65 | if err := json.Unmarshal([]byte(config), conf); err != nil { 66 | t.Fatal("json decode error", err) 67 | } 68 | globalSessions, err := NewManager("cookie", conf) 69 | if err != nil { 70 | t.Fatal("init cookie session err", err) 71 | } 72 | 73 | r, _ := http.NewRequest("GET", "/", nil) 74 | w := httptest.NewRecorder() 75 | session, err := globalSessions.SessionStart(w, r) 76 | if err != nil { 77 | t.Fatal("session start err,", err) 78 | } 79 | 80 | // request again ,will get same sesssion id . 81 | r1, _ := http.NewRequest("GET", "/", nil) 82 | r1.Header.Set("Cookie", w.Header().Get("Set-Cookie")) 83 | w = httptest.NewRecorder() 84 | newSession, err := globalSessions.SessionStart(w, r1) 85 | if err != nil { 86 | t.Fatal("session start err,", err) 87 | } 88 | if newSession.SessionID() != session.SessionID() { 89 | t.Fatal("get cookie session id is not the same again.") 90 | } 91 | 92 | // After destroy session , will get a new session id . 93 | globalSessions.SessionDestroy(w, r1) 94 | r2, _ := http.NewRequest("GET", "/", nil) 95 | r2.Header.Set("Cookie", w.Header().Get("Set-Cookie")) 96 | 97 | w = httptest.NewRecorder() 98 | newSession, err = globalSessions.SessionStart(w, r2) 99 | if err != nil { 100 | t.Fatal("session start error") 101 | } 102 | if newSession.SessionID() == session.SessionID() { 103 | t.Fatal("after destroy session and reqeust again ,get cookie session id is same.") 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /session/sess_mem_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 beego Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package session 16 | 17 | import ( 18 | "encoding/json" 19 | "net/http" 20 | "net/http/httptest" 21 | "strings" 22 | "testing" 23 | ) 24 | 25 | func TestMem(t *testing.T) { 26 | config := `{"cookieName":"gosessionid","gclifetime":10, "enableSetCookie":true}` 27 | conf := new(ManagerConfig) 28 | if err := json.Unmarshal([]byte(config), conf); err != nil { 29 | t.Fatal("json decode error", err) 30 | } 31 | globalSessions, _ := NewManager("memory", conf) 32 | go globalSessions.GC() 33 | r, _ := http.NewRequest("GET", "/", nil) 34 | w := httptest.NewRecorder() 35 | sess, err := globalSessions.SessionStart(w, r) 36 | if err != nil { 37 | t.Fatal("set error,", err) 38 | } 39 | defer sess.SessionRelease(w) 40 | 41 | err = sess.Set("username", "astaxie") 42 | if err != nil { 43 | t.Fatal("set error,", err) 44 | } 45 | if username := sess.Get("username"); username != "astaxie" { 46 | t.Fatal("get username error") 47 | } 48 | if cookiestr := w.Header().Get("Set-Cookie"); cookiestr == "" { 49 | t.Fatal("setcookie error") 50 | } else { 51 | parts := strings.Split(strings.TrimSpace(cookiestr), ";") 52 | for k, v := range parts { 53 | nameval := strings.Split(v, "=") 54 | if k == 0 && nameval[0] != "gosessionid" { 55 | t.Fatal("error") 56 | } 57 | } 58 | } 59 | } 60 | 61 | type Student struct { 62 | Name string 63 | Age int 64 | } 65 | 66 | func TestFile(t *testing.T) { 67 | config := `{"cookieName":"gosessionid","gclifetime":10, "enableSetCookie":true}` 68 | conf := new(ManagerConfig) 69 | if err := json.Unmarshal([]byte(config), conf); err != nil { 70 | t.Fatal("json decode error", err) 71 | } 72 | globalSessions, _ := NewManager("file", conf) 73 | go globalSessions.GC() 74 | r, _ := http.NewRequest("GET", "/", nil) 75 | w := httptest.NewRecorder() 76 | sess, err := globalSessions.SessionStart(w, r) 77 | if err != nil { 78 | t.Fatal("set error,", err) 79 | } 80 | defer sess.SessionRelease(w) 81 | 82 | s := &Student{Name:"jame", Age:18} 83 | err = sess.Set("student", s) 84 | if err != nil { 85 | t.Fatal("set error,", err) 86 | } 87 | 88 | value := sess.Get("student") 89 | if student, ok := value.(*Student); ok { 90 | t.Logf("student: %+v", student) 91 | } 92 | 93 | if cookiestr := w.Header().Get("Set-Cookie"); cookiestr == "" { 94 | t.Fatal("setcookie error") 95 | } else { 96 | parts := strings.Split(strings.TrimSpace(cookiestr), ";") 97 | for k, v := range parts { 98 | nameval := strings.Split(v, "=") 99 | if k == 0 && nameval[0] != "gosessionid" { 100 | t.Fatal("error") 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /timer/task_timer.go: -------------------------------------------------------------------------------- 1 | package timer 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type TaskTimer struct { 8 | f func() //传入方法 9 | timer *time.Ticker //定时器 10 | stop bool //停止标记 11 | pause bool //暂停标记 12 | duration time.Duration 13 | } 14 | 15 | //新建定时器 16 | func NewTask(duration time.Duration, function func()) *TaskTimer { 17 | t := &TaskTimer{ 18 | //timer: time.NewTicker(duration), 19 | f: function, 20 | stop: false, 21 | pause: false, 22 | duration: duration, 23 | } 24 | return t 25 | } 26 | 27 | //启动定时器 28 | func (t *TaskTimer) Start() { 29 | t.stop = false 30 | t.pause = false 31 | 32 | if t.timer != nil { 33 | t.timer.Stop() 34 | t.timer = nil 35 | } 36 | 37 | t.timer = time.NewTicker(t.duration) 38 | 39 | go func(innerT *TaskTimer) { 40 | defer func() { 41 | innerT.timer.Stop() 42 | innerT.timer = nil 43 | }() 44 | for { 45 | select { 46 | case <-innerT.timer.C: 47 | if innerT.stop { 48 | return 49 | } 50 | if innerT.pause { 51 | continue 52 | } 53 | innerT.f() //执行我们想要的操作 54 | } 55 | } 56 | }(t) 57 | } 58 | 59 | //停止定时器 60 | func (t *TaskTimer) Stop() { 61 | t.stop = true 62 | } 63 | 64 | //暂停定时器 65 | func (t *TaskTimer) Pause() { 66 | t.pause = true 67 | } 68 | 69 | //继续定时器 70 | func (t *TaskTimer) Restart() { 71 | t.pause = false 72 | } 73 | 74 | func (t *TaskTimer) Running() bool { 75 | if t.stop || t.pause { 76 | return false 77 | } else { 78 | return true 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /timer/task_timer_test.go: -------------------------------------------------------------------------------- 1 | package timer 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | 10 | func now() { 11 | fmt.Println(time.Now().Format("2006-01-02 15:04:05:000")) 12 | } 13 | 14 | func TestTimer(t *testing.T) { 15 | timer := NewTask(time.Second*1, now) 16 | timer1 := NewTask(time.Second*2, now) 17 | timer.Start() 18 | timer1.Start() 19 | 20 | time.Sleep(time.Second * 10) 21 | 22 | timer.Pause() 23 | time.Sleep(time.Second * 5) 24 | timer.Restart() 25 | time.Sleep(time.Second * 5) 26 | timer.Stop() 27 | 28 | } 29 | -------------------------------------------------------------------------------- /walletnode/config_init.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package walletnode 17 | 18 | import ( 19 | "errors" 20 | 21 | "github.com/blocktree/openwallet/v2/common/file" 22 | // "github.com/pkg/errors" 23 | "path/filepath" 24 | s "strings" 25 | ) 26 | 27 | // Init and create .ini file automatically 28 | func initConfig(symbol string) error { 29 | configFilePath, _ := filepath.Abs("conf") 30 | configFileName := s.ToUpper(symbol) + ".ini" 31 | 32 | absFile := filepath.Join(configFilePath, configFileName) 33 | if !file.Exists(absFile) { 34 | if file.MkdirAll(configFilePath) != true { 35 | return errors.New("initConfig: MkdirAll failed") 36 | } 37 | if file.WriteFile(absFile, []byte(WNConfig.defaultConfig), false) != true { 38 | return errors.New("initConfig: WriteFile failed") 39 | } 40 | } 41 | return nil 42 | } 43 | 44 | // //读取配置 45 | // absFile := filepath.Join(wc.configFilePath, wc.configFileName) 46 | // if !file.Exists(absFile) { 47 | // file.MkdirAll(wc.configFilePath) 48 | // file.WriteFile(absFile, []byte(wc.defaultConfig), false) 49 | // } 50 | -------------------------------------------------------------------------------- /walletnode/config_init_test.go: -------------------------------------------------------------------------------- 1 | package walletnode 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestInitConfig(t *testing.T) { 9 | if err := initConfig("bopo"); err != nil { 10 | t.Errorf("\tTestInitConfig: %+v\n", err) 11 | } else { 12 | fmt.Println("\tTestInitConfig: Success!") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /walletnode/config_load.go: -------------------------------------------------------------------------------- 1 | package walletnode 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "path/filepath" 7 | s "strings" 8 | 9 | bconfig "github.com/astaxie/beego/config" 10 | ) 11 | 12 | // Load settings for global from local conf/.ini 13 | // 14 | // - will change Global VAR: WNConfig 15 | func loadConfig(symbol string) error { 16 | 17 | var c bconfig.Configer 18 | 19 | configFilePath, _ := filepath.Abs("conf") 20 | configFileName := s.ToUpper(symbol) + ".ini" 21 | absFile := filepath.Join(configFilePath, configFileName) 22 | 23 | c, err := bconfig.NewConfig("ini", absFile) 24 | if err != nil { 25 | log.Println(err) 26 | return fmt.Errorf("Load config failed: %s", err) 27 | } 28 | 29 | WNConfig.RPCUser = c.String("rpcUser") 30 | WNConfig.RPCPassword = c.String("rpcPassword") 31 | WNConfig.isTestNet = c.String("isTestNet") 32 | 33 | WNConfig.walletnodePrefix = c.String("walletnode::Prefix") 34 | WNConfig.walletnodeServerType = c.String("walletnode::ServerType") 35 | WNConfig.walletnodeServerAddr = c.String("walletnode::ServerAddr") 36 | WNConfig.walletnodeServerPort = c.String("walletnode::ServerPort") 37 | WNConfig.walletnodeStartNodeCMD = c.String("walletnode::StartNodeCMD") 38 | WNConfig.walletnodeStopNodeCMD = c.String("walletnode::StopNodeCMD") 39 | WNConfig.walletnodeMainNetDataPath = c.String("walletnode::mainNetDataPath") 40 | WNConfig.walletnodeTestNetDataPath = c.String("walletnode::testNetDataPath") 41 | WNConfig.walletnodeIsEncrypted = c.String("walletnode::isEncrypted") 42 | // WNConfig.walletnodeServerSocket = c.String("walletnode::WalletnodeServerSocket") 43 | 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /walletnode/config_load_test.go: -------------------------------------------------------------------------------- 1 | package walletnode 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLoadConfig(t *testing.T) { 8 | if err := loadConfig("bopo"); err != nil { 9 | t.Errorf("TestLoadConfig: %+v\n", err) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /walletnode/config_update.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package walletnode 17 | 18 | import ( 19 | "fmt" 20 | "path/filepath" 21 | s "strings" 22 | 23 | bconfig "github.com/astaxie/beego/config" 24 | "github.com/pkg/errors" 25 | ) 26 | 27 | // Update .ini file 28 | func updateConfig(symbol string) error { 29 | if WNConfig == nil { 30 | return errors.New("getDockerClient: WalletnodeConfig does not initialized") 31 | } 32 | 33 | configFilePath, _ := filepath.Abs("conf") 34 | configFileName := s.ToUpper(symbol) + ".ini" 35 | absFile := filepath.Join(configFilePath, configFileName) 36 | 37 | c, err := bconfig.NewConfig("ini", absFile) 38 | if err != nil { 39 | return fmt.Errorf("Load Config Failed: %s", err) 40 | } 41 | 42 | err = c.Set("isTestNet", WNConfig.isTestNet) 43 | err = c.Set("rpcuser", WNConfig.RPCUser) 44 | err = c.Set("rpcpassword", WNConfig.RPCPassword) 45 | err = c.Set("WalletURL", WNConfig.WalletURL) 46 | 47 | err = c.Set("walletnode::ServerType", WNConfig.walletnodeServerType) 48 | err = c.Set("walletnode::ServerAddr", WNConfig.walletnodeServerAddr) 49 | err = c.Set("walletnode::ServerPort", WNConfig.walletnodeServerPort) 50 | // err = c.Set("walletnode::ServerSocket", WNConfig.walletnodeServerSocket) 51 | err = c.Set("walletnode::StartNodeCMD", WNConfig.walletnodeStartNodeCMD) 52 | err = c.Set("walletnode::StopNodeCMD", WNConfig.walletnodeStopNodeCMD) 53 | err = c.Set("walletnode::MainnetDataPath", WNConfig.walletnodeMainNetDataPath) 54 | err = c.Set("walletnode::TestnetDataPath", WNConfig.walletnodeTestNetDataPath) 55 | err = c.Set("walletnode::IsEncrypted", WNConfig.walletnodeIsEncrypted) 56 | 57 | if err := c.SaveConfigFile(absFile); err != nil { 58 | return err 59 | } 60 | 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /walletnode/config_update_test.go: -------------------------------------------------------------------------------- 1 | package walletnode 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestUpdateConfig(t *testing.T) { 8 | if err := loadConfig("bopo"); err != nil { 9 | t.Errorf("\tTestUpdateConfig: %+v\n", err) 10 | } 11 | 12 | if err := updateConfig("bopo"); err != nil { 13 | t.Errorf("\tTestUpdateConfig: %+v\n", err) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /walletnode/manager.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package walletnode 17 | 18 | import ( 19 | "errors" 20 | "fmt" 21 | "log" 22 | s "strings" 23 | 24 | docker "docker.io/go-docker" 25 | ) 26 | 27 | var ( 28 | Symbol string // Current fullnode wallet's symbol 29 | FullnodeContainerConfigs map[string]*FullnodeContainerConfig // All configs of fullnode wallet for Docker 30 | WNConfig *WalletnodeConfig 31 | ) 32 | 33 | type WalletnodeManager struct{} 34 | 35 | // Get docker client 36 | func getDockerClient(symbol string) (c *docker.Client, err error) { 37 | 38 | symbol = s.ToLower(symbol) 39 | 40 | if WNConfig == nil { 41 | return nil, errors.New("getDockerClient: WalletnodeConfig does not initialized") 42 | } 43 | 44 | // Init docker client 45 | //walletnodeServerType 46 | if WNConfig.walletnodeServerType == "docker" { 47 | 48 | if WNConfig.walletnodeServerAddr == "127.0.0.1" || WNConfig.walletnodeServerAddr == "localhost" { 49 | c, err = docker.NewEnvClient() 50 | } else { 51 | host := fmt.Sprintf("tcp://%s:%s", WNConfig.walletnodeServerAddr, WNConfig.walletnodeServerPort) 52 | c, err = docker.NewClient(host, "v1.37", nil, map[string]string{}) 53 | } 54 | } 55 | 56 | if err != nil { 57 | log.Println(err) 58 | return nil, err 59 | } 60 | 61 | return c, err 62 | } 63 | 64 | // Private function, generate container name by and 65 | func getCName(symbol string) (string, error) { 66 | if WNConfig == nil { 67 | return "", errors.New("getCName: WalletnodeConfig does not initialized") 68 | } 69 | 70 | // Within testnet, use "_testnet" as container name 71 | if WNConfig.isTestNet == "true" { 72 | return s.ToLower(symbol) + "_t", nil 73 | } 74 | 75 | return s.ToLower(symbol), nil 76 | } 77 | -------------------------------------------------------------------------------- /walletnode/manager_copy_test.go: -------------------------------------------------------------------------------- 1 | package walletnode 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | var ( 8 | src string 9 | dst string 10 | ) 11 | 12 | func TestCopyFromContainer(t *testing.T) { 13 | 14 | src = "/usr/local/paicode/data/wallet.dat" 15 | dst = "./bk/wallet.dat" 16 | 17 | wn := WalletnodeManager{} 18 | if err := wn.CopyFromContainer("bopo", src, dst); err != nil { 19 | t.Errorf("Error: %v\n", err) 20 | } 21 | 22 | } 23 | 24 | func TestCopyToContainer(t *testing.T) { 25 | 26 | src = "./conf/BOPO.ini" 27 | dst = "/tmp" 28 | 29 | wn := WalletnodeManager{} 30 | if err := wn.CopyToContainer("bopo", src, dst); err != nil { 31 | t.Errorf("Error: %v\n", err) 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /walletnode/manager_logs.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package walletnode 17 | 18 | import ( 19 | "errors" 20 | "fmt" 21 | "strings" 22 | 23 | // "docker.io/go-docker/api" 24 | 25 | sh "github.com/codeskyblue/go-sh" 26 | ) 27 | 28 | // LogsWalletnode watch logs now 29 | func (w *WalletnodeManager) LogsWalletnode(symbol string) error { 30 | 31 | if err := loadConfig(symbol); err != nil { 32 | return err 33 | } 34 | 35 | cName, err := getCName(symbol) // container name 36 | if err != nil { 37 | return err 38 | } 39 | 40 | cnf := getFullnodeConfig(symbol) 41 | if cnf == nil { 42 | return errors.New("Wallet fullnode configs can not found") 43 | } 44 | 45 | logfile := cnf.getLogFile() 46 | if logfile == "" { 47 | return errors.New("Logfile no found") 48 | } 49 | 50 | host := "" 51 | if WNConfig.walletnodeServerType == "docker" { 52 | host = fmt.Sprintf("-H %s:%s", WNConfig.walletnodeServerAddr, WNConfig.walletnodeServerPort) 53 | } 54 | 55 | cmd := fmt.Sprintf("docker %s exec %s tail -f /data/%s", host, cName, logfile) 56 | cmds := strings.Split(cmd, " ") 57 | session := sh.Command(cmds[0], cmds[1:]) 58 | return session.Run() 59 | } 60 | -------------------------------------------------------------------------------- /walletnode/manager_remove.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package walletnode 17 | 18 | import ( 19 | "context" 20 | // "docker.io/go-docker/api" 21 | 22 | "docker.io/go-docker/api/types" 23 | ) 24 | 25 | // RemoveWalletnode remove walletnode 26 | func (w *WalletnodeManager) RemoveWalletnode(symbol string) error { 27 | 28 | if err := loadConfig(symbol); err != nil { 29 | return err 30 | } 31 | 32 | // Init docker client 33 | c, err := getDockerClient(symbol) 34 | if err != nil { 35 | return err 36 | } 37 | // Action within client 38 | cName, err := getCName(symbol) // container name 39 | if err != nil { 40 | return err 41 | } 42 | err = c.ContainerRemove(context.Background(), cName, types.ContainerRemoveOptions{}) 43 | if err == nil { 44 | return err 45 | } 46 | return nil 47 | } 48 | -------------------------------------------------------------------------------- /walletnode/manager_restart.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package walletnode 17 | 18 | import ( 19 | "errors" 20 | ) 21 | 22 | // RestartWalletnode restart walletnode 23 | func (w *WalletnodeManager) RestartWalletnode(symbol string) error { 24 | 25 | return errors.New("Function closed! Use stop/start, please") 26 | 27 | // if err := loadConfig(symbol); err != nil { 28 | // return err 29 | // } 30 | 31 | // // Init docker client 32 | // c, err := getDockerClient(symbol) 33 | // if err != nil { 34 | // return err 35 | // } 36 | // // Action within client 37 | // cName, err := getCName(symbol) // container name 38 | // if err != nil { 39 | // return err 40 | // } 41 | // err = c.ContainerRestart(context.Background(), cName, nil) 42 | // if err != nil { 43 | // return err 44 | // } 45 | // return nil 46 | } 47 | -------------------------------------------------------------------------------- /walletnode/manager_start.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package walletnode 17 | 18 | import ( 19 | "context" 20 | "errors" 21 | "fmt" 22 | "log" 23 | "time" 24 | 25 | "docker.io/go-docker/api/types" 26 | ) 27 | 28 | // StartWalletnode start walletnode 29 | func (w *WalletnodeManager) StartWalletnode(symbol string) error { 30 | 31 | if err := loadConfig(symbol); err != nil { 32 | return err 33 | } 34 | 35 | // Init docker client 36 | c, err := getDockerClient(symbol) 37 | if err != nil { 38 | return err 39 | } 40 | 41 | cName, err := getCName(symbol) // container name 42 | if err != nil { 43 | return err 44 | } 45 | 46 | cnf := getFullnodeConfig(symbol) 47 | if cnf == nil { 48 | // Config not exist! 49 | err := errors.New("Wallet fullnode config no found") 50 | log.Println(err) 51 | return err 52 | } 53 | 54 | // Action within client 55 | if err := c.ContainerStart(context.Background(), cName, types.ContainerStartOptions{}); err != nil { 56 | return err 57 | } 58 | 59 | // Encrypt wallet fullnode if required 60 | // 61 | // Workflow: 62 | // 1. Encrypt 63 | // 2. Start container 64 | if cnf.isEncrypted() && WNConfig.walletnodeIsEncrypted != "true" { 65 | fmt.Println("\nAttention! Wallet fullnode will be encrypted by default password same with habitus ...") 66 | 67 | time.Sleep(time.Second * 10) 68 | 69 | res, err := c.ContainerExecCreate(context.Background(), cName, types.ExecConfig{Cmd: cnf.ENCRYPT}) 70 | if err != nil { 71 | log.Println(err) 72 | return err 73 | } 74 | 75 | if err := c.ContainerExecStart(context.Background(), res.ID, types.ExecStartCheck{}); err != nil { 76 | log.Println(err) 77 | return err 78 | } 79 | 80 | // update .ini to set isencrypted=true 81 | WNConfig.walletnodeIsEncrypted = "true" 82 | if updateConfig(symbol); err != nil { 83 | log.Println(err) 84 | return err 85 | } 86 | 87 | time.Sleep(time.Second * 3) 88 | 89 | if err := c.ContainerStart(context.Background(), cName, types.ContainerStartOptions{}); err != nil { 90 | return err 91 | } 92 | 93 | fmt.Printf("\t Encrypt success!\n\n") 94 | } 95 | 96 | return nil 97 | } 98 | -------------------------------------------------------------------------------- /walletnode/manager_status.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package walletnode 17 | 18 | import ( 19 | "context" 20 | ) 21 | 22 | // GetWalletnodeStatus get walletnode status 23 | func (w *WalletnodeManager) GetWalletnodeStatus(symbol string) (status string, err error) { 24 | 25 | if err := loadConfig(symbol); err != nil { 26 | return "", err 27 | } 28 | 29 | // Init docker client 30 | c, err := getDockerClient(symbol) 31 | if err != nil { 32 | return "", err 33 | } 34 | 35 | // Instantize parameters 36 | cname, err := getCName(symbol) // container name 37 | if err != nil { 38 | return "", err 39 | } 40 | 41 | // Action within client 42 | res, err := c.ContainerInspect(context.Background(), cname) 43 | if err != nil { 44 | return "", err 45 | } 46 | 47 | // Get results 48 | status = res.State.Status 49 | return status, nil 50 | } 51 | -------------------------------------------------------------------------------- /walletnode/manager_stop.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package walletnode 17 | 18 | import ( 19 | "context" 20 | "errors" 21 | "fmt" 22 | "log" 23 | "time" 24 | 25 | "docker.io/go-docker/api/types" 26 | ) 27 | 28 | // StopWalletnode stop walletnode 29 | func (w *WalletnodeManager) StopWalletnode(symbol string) error { 30 | 31 | if err := loadConfig(symbol); err != nil { 32 | return err 33 | } 34 | 35 | // Init docker client 36 | c, err := getDockerClient(symbol) 37 | if err != nil { 38 | return err 39 | } 40 | 41 | cName, err := getCName(symbol) // container name 42 | if err != nil { 43 | return err 44 | } 45 | 46 | cnf := getFullnodeConfig(symbol) 47 | if cnf == nil { 48 | return errors.New("Fullnode config no found") 49 | } 50 | 51 | if cnf.STOPCMD == nil { 52 | fmt.Printf("\n> Stop container by Docker signal(Docker Signal)... \n\n") 53 | 54 | d := time.Duration(3000) 55 | err = c.ContainerStop(context.Background(), cName, &d) 56 | if err != nil { 57 | return err 58 | } 59 | 60 | time.Sleep(time.Second * 3) 61 | 62 | } else { 63 | fmt.Printf("\n> Stop container by Command from Service(Stop Command)... \n\n") 64 | 65 | exec := types.ExecConfig{Cmd: cnf.STOPCMD, AttachStderr: true, AttachStdin: true, AttachStdout: true} 66 | if res, err := c.ContainerExecCreate(context.Background(), cName, exec); err != nil { 67 | log.Println(err) 68 | return err 69 | } else { 70 | if err := c.ContainerExecStart(context.Background(), res.ID, types.ExecStartCheck{}); err != nil { 71 | log.Println(err) 72 | return err 73 | } 74 | 75 | time.Sleep(time.Second * 16) 76 | } 77 | } 78 | 79 | if status, err := w.GetWalletnodeStatus(symbol); err != nil { 80 | log.Println(err) 81 | } else { 82 | fmt.Printf("\nStop container finished, check current container status: %s\n", status) 83 | if status == "running" { 84 | fmt.Printf("\n!!!May wait for more seconds, and please check returns to confirm finally!\n\n") 85 | } 86 | } 87 | 88 | return nil 89 | } 90 | -------------------------------------------------------------------------------- /walletnode/manager_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package walletnode 17 | 18 | import ( 19 | "testing" 20 | ) 21 | 22 | var ( // Usecase Data 23 | symbols = []string{"btc", "bch", "eth", "sc"} 24 | ) 25 | 26 | func TestCreate(t *testing.T) { 27 | // if err := nil; err != nil { 28 | // t.Errorf("GetBlockChainInfo failed unexpected error: %v\n", err) 29 | // } else { 30 | // t.Logf("GetBlockChainInfo info: %v\n", b) 31 | // } 32 | } 33 | 34 | func TestGet(t *testing.T) { 35 | } 36 | 37 | func TestStart(t *testing.T) { 38 | } 39 | 40 | func TestStop(t *testing.T) { 41 | } 42 | 43 | func TestRestart(t *testing.T) { 44 | } 45 | 46 | func TestRemove(t *testing.T) { 47 | } 48 | -------------------------------------------------------------------------------- /wmd/README.md: -------------------------------------------------------------------------------- 1 | # wmd 2 | 3 | ## Build development environment 4 | 5 | The requirements to build openwallet are: 6 | 7 | - Golang version 1.12 or later 8 | - xgo (Go CGO cross compiler) 9 | - Properly configured Go language environment 10 | - Golang supported operating system 11 | 12 | ## 源码编译跨平台工具 13 | 14 | ### 安装xgo(支持跨平台编译C代码) 15 | 16 | [官方github(目前还不支持go module)](https://github.com/karalabe/xgo) 17 | [支持go module的xgo fork](https://github.com/gythialy/xgo) 18 | 19 | xgo的使用依赖docker。并且把要跨平台编译的项目文件加入到File sharing。 20 | 21 | ```shell 22 | 23 | # 官方的目前还不支持go module编译,所以我们用了别人改造后能够给支持的fork版 24 | $ go get -u github.com/gythialy/xgo 25 | ... 26 | $ xgo -h 27 | ... 28 | 29 | ``` 30 | 31 | ## wmd--多币种钱包维护工具(Deprecated, please use go-openw-cli) 32 | 33 | ### 特点 34 | 35 | wmd为了实现对多币种的钱包操作,规范了以下接口: 36 | 37 | - 初始币种配置流程。 38 | - 创建币种钱包流程。 39 | - 批量币种钱包地址流程。 40 | - 备份钱包流程。 41 | - 启动定时器汇总钱包流程。 42 | 43 | ### 编译wmd工具 44 | 45 | ```shell 46 | 47 | # 本地系统编译 48 | $ make clean build 49 | 50 | # 跨平台编译wmd,更多可选平台可修改Makefile的$TARGETS变量 51 | $ make clean wmd 52 | 53 | ``` 54 | 55 | ### wmd工具使用 56 | 57 | wmd是一款多币种钱包维护工具。你只需要在服务器安装某币种的官方全节点钱包,并且wmd已经支持的币种。 58 | 你就可以使用wmd的规范的命令完成钱包维护工作。 59 | 60 | #### 钱包相关 61 | 62 | ```shell 63 | 64 | # 查看./conf/[symbol].ini文件中与钱包相关的配置信息 65 | $ ./wmd wallet config -s [symbol] 66 | 67 | # 执行重新初始化钱包配置 68 | $ ./wmd wallet config -s [symbol] -i 69 | 70 | # 创建钱包,成功后,文件保存在./data/[symbol]/key/ 71 | $ ./wmd wallet new -s [symbol] 72 | 73 | # 备份钱包私钥和账户相关文件,文件保存在./data/[symbol]/key/backup/ 74 | $ ./wmd wallet backup -s [symbol] 75 | 76 | # 执行恢复钱包,提供钱包的备份文件 77 | $ ./wmd wallet restore -s [symbol] 78 | 79 | # 执行批量创建地址命令,文件保存在./conf/[symbol]/address/ 80 | $ ./wmd wallet batchaddr -s [symbol] 81 | 82 | # 启动批量汇总监听器 83 | $ ./wmd wallet startsum -s [symbol] 84 | 85 | # 查询钱包列表 86 | $ ./wmd wallet list -s [symbol] 87 | 88 | # 发起转行交易 89 | $ ./wmd wallet transfer -s [symbol] 90 | 91 | ``` -------------------------------------------------------------------------------- /wmd/assets.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 The openwallet Authors 3 | * This file is part of the openwallet library. 4 | * 5 | * The openwallet library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The openwallet library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | */ 15 | 16 | package wmd 17 | 18 | import ( 19 | "github.com/blocktree/openwallet/v2/assets" 20 | "github.com/blocktree/openwallet/v2/assets/bytom" 21 | "github.com/blocktree/openwallet/v2/assets/cardano" 22 | "github.com/blocktree/openwallet/v2/assets/decred" 23 | "github.com/blocktree/openwallet/v2/assets/hypercash" 24 | "github.com/blocktree/openwallet/v2/assets/icon" 25 | "github.com/blocktree/openwallet/v2/assets/luxapla" 26 | "github.com/blocktree/openwallet/v2/assets/obyte" 27 | "github.com/blocktree/openwallet/v2/assets/sia" 28 | "github.com/blocktree/openwallet/v2/assets/tezos" 29 | "github.com/blocktree/openwallet/v2/log" 30 | ) 31 | 32 | //WalletManagerInterface 钱包管理器 33 | type WalletManagerInterface interface { 34 | //初始化配置流程 35 | InitConfigFlow() error 36 | //查看配置信息 37 | ShowConfig() error 38 | //创建钱包流程 39 | CreateWalletFlow() error 40 | //创建地址流程 41 | CreateAddressFlow() error 42 | //汇总钱包流程 43 | SummaryFollow() error 44 | //备份钱包流程 45 | BackupWalletFlow() error 46 | //查看钱包列表,显示信息 47 | GetWalletList() error 48 | //发送交易 49 | TransferFlow() error 50 | //恢复钱包 51 | RestoreWalletFlow() error 52 | } 53 | 54 | // 节点管理接口 55 | type NodeManagerInterface interface { 56 | // GetNodeStatus 节点状态 57 | GetNodeStatus(string) error 58 | // StartNodeFlow 创建节点 59 | CreateNodeFlow(string) error 60 | // StartNodeFlow 开启节点 61 | StartNodeFlow(string) error 62 | // StopNodeFlow 关闭节点 63 | StopNodeFlow(string) error 64 | // RestartNodeFlow 重启节点 65 | RestartNodeFlow(string) error 66 | // RemoveNodeFlow 移除节点 67 | RemoveNodeFlow(string) error 68 | // LogsNodeFlow 日志 69 | LogsNodeFlow(string) error 70 | 71 | // //LoginNode 登陆节点 72 | // LoginNode() error 73 | // //ShowNodeInfo 显示节点信息 74 | // ShowNodeInfo() error 75 | } 76 | 77 | // 配置管理接口 78 | //type ConfigManagerInterfac interface { 79 | // //SetConfigFlow 初始化配置流程 80 | // SetConfigFlow(subCmd string) error 81 | // //ShowConfigInfo 查看配置信息 82 | // ShowConfigInfo(subCmd string) error 83 | //} 84 | 85 | //注册钱包管理工具 86 | func init() { 87 | //注册钱包管理工具 88 | log.Notice("Wallet Manager Driver Load Successfully.") 89 | assets.RegAssets(cardano.Symbol, cardano.NewWalletManager()) 90 | assets.RegAssets(bytom.Symbol, &bytom.WalletManager{}) 91 | assets.RegAssets(sia.Symbol, &sia.WalletManager{}) 92 | assets.RegAssets(hypercash.Symbol, hypercash.NewWalletManager()) 93 | //assets.RegAssets(iota.Symbol, &iota.WalletManager{}) 94 | assets.RegAssets(tezos.Symbol, tezos.NewWalletManager()) 95 | assets.RegAssets(decred.Symbol, decred.NewWalletManager()) 96 | assets.RegAssets(icon.Symbol, icon.NewWalletManager()) 97 | assets.RegAssets(obyte.Symbol, obyte.NewWalletManager()) 98 | assets.RegAssets(luxapla.Symbol, luxapla.NewWalletManager()) 99 | } 100 | --------------------------------------------------------------------------------