hi, I’m using ipfs to implemen a small cli tool. The code is mainly depends on example code. And my code is
package main
import (
"context"
"fmt"
"log"
"os"
"path/filepath"
"sync"
config "github.com/ipfs/go-ipfs-config"
ipfsfiles "github.com/ipfs/go-ipfs-files"
icore "github.com/ipfs/interface-go-ipfs-core"
path "github.com/ipfs/interface-go-ipfs-core/path"
peer "github.com/libp2p/go-libp2p-peer"
peerstore "github.com/libp2p/go-libp2p-peerstore"
ma "github.com/multiformats/go-multiaddr"
"github.com/abiosoft/ishell"
"github.com/ipfs/go-ipfs/core"
"github.com/ipfs/go-ipfs/core/coreapi"
"github.com/ipfs/go-ipfs/core/node/libp2p"
"github.com/ipfs/go-ipfs/plugin/loader"
"github.com/ipfs/go-ipfs/repo/fsrepo"
)
func setupPlugins(externalPluginsPath string) error {
// Load any external plugins if available on externalPluginsPath
plugins, err := loader.NewPluginLoader(filepath.Join(externalPluginsPath, "plugins"))
if err != nil {
return fmt.Errorf("error loading plugins: %s", err)
}
// Load preloaded and external plugins
if err := plugins.Initialize(); err != nil {
return fmt.Errorf("error initializing plugins: %s", err)
}
if err := plugins.Inject(); err != nil {
return fmt.Errorf("error initializing plugins: %s", err)
}
return nil
}
// Creates an IPFS node and returns its coreAPI
func createNode(ctx context.Context, repoPath string) (*core.IpfsNode, error) {
// Open the repo
repo, err := fsrepo.Open(repoPath)
if err != nil {
fmt.Println(err)
return nil, err
}
// Construct the node
nodeOptions := &core.BuildCfg{
Online: true,
Routing: libp2p.DHTOption, // This option sets the node to be a full DHT node (both fetching and storing DHT Records)
// Routing: libp2p.DHTClientOption, // This option sets the node to be a client DHT node (only fetching records)
Repo: repo,
}
return core.NewNode(ctx, nodeOptions)
}
func spawnDefault(ctx context.Context) (*core.IpfsNode, error) {
defaultPath, err := config.PathRoot()
fmt.Println(defaultPath)
if err != nil {
fmt.Println("in spawn", err)
return nil, err
}
if err := setupPlugins(defaultPath); err != nil {
return nil, err
}
return createNode(ctx, defaultPath)
}
func connectToPeers(ctx context.Context, ipfs icore.CoreAPI, peers []string) error {
var wg sync.WaitGroup
peerInfos := make(map[peer.ID]*peerstore.PeerInfo, len(peers))
for _, addrStr := range peers {
addr, err := ma.NewMultiaddr(addrStr)
if err != nil {
return err
}
pii, err := peerstore.InfoFromP2pAddr(addr)
if err != nil {
return err
}
pi, ok := peerInfos[pii.ID]
if !ok {
pi = &peerstore.PeerInfo{ID: pii.ID}
peerInfos[pi.ID] = pi
}
pi.Addrs = append(pi.Addrs, pii.Addrs...)
}
wg.Add(len(peerInfos))
for _, peerInfo := range peerInfos {
go func(peerInfo *peerstore.PeerInfo) {
defer wg.Done()
err := ipfs.Swarm().Connect(ctx, *peerInfo)
if err != nil {
log.Printf("failed to connect to %s: %s", peerInfo.ID, err)
}
}(peerInfo)
}
wg.Wait()
return nil
}
func getUnixfsFile(path string) (ipfsfiles.File, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
st, err := file.Stat()
if err != nil {
return nil, err
}
f, err := ipfsfiles.NewReaderPathFile(path, file, st)
if err != nil {
return nil, err
}
return f, nil
}
func getUnixfsNode(path string) (ipfsfiles.Node, error) {
st, err := os.Stat(path)
if err != nil {
return nil, err
}
f, err := ipfsfiles.NewSerialFile(path, false, st)
if err != nil {
return nil, err
}
return f, nil
}
func main() {
bootstrapNodes := []string{
// IPFS Bootstrapper nodes.
"/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
"/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
// IPFS Cluster Pinning nodes
"/ip4/138.201.67.219/tcp/4001/p2p/QmUd6zHcbkbcs7SMxwLs48qZVX3vpcM8errYS7xEczwRMA",
"/ip4/138.201.67.220/tcp/4001/p2p/QmNSYxZAiJHeLdkBg38roksAR9So7Y5eojks1yjEcUtZ7i",
"/ip4/138.201.68.74/tcp/4001/p2p/QmdnXwLrC8p1ueiq2Qya8joNvk3TVVDAut7PrikmZwubtR",
"/ip4/94.130.135.167/tcp/4001/p2p/QmUEMvxS2e7iDrereVYc5SWPauXPyNwxcy9BXZrC1QTcHE",
"/ip4/192.168.31.125/tcp/4001/ipfs/QmcgLqX5dvAjp9PjtkRqj2mDoVKeokHd2QEJ9cnUHMRw7f",
"ipfs/QmdCAWG4bniPnqsusiX4UbX7vjSBzfnzX4Uj1eLubW2XKK",
}
fmt.Println("Starting IPFS")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
node, err := spawnDefault(ctx)
if err != nil {
fmt.Println("Cann't create node")
}
ipfs, err := coreapi.NewCoreAPI(node)
if err != nil {
fmt.Println("No IPFS repo on default path")
}
go connectToPeers(ctx, ipfs, bootstrapNodes)
fmt.Println("IPFS running")
shell := ishell.New()
shell.AddCmd(&ishell.Cmd{
Name: "add",
Help: "add file to current node",
Func: func(c *ishell.Context) {
fileName := c.Args[0]
filePath := "./" + fileName
file, err := getUnixfsNode(filePath)
if err != nil {
fmt.Errorf("Could not get File: %s", err)
}
cidFile, err := ipfs.Unixfs().Add(ctx, file)
if err != nil {
fmt.Errorf("Could not add File: %s", err)
}
fmt.Printf("Added file with HASH: %s\n", cidFile.String())
},
})
shell.AddCmd(&ishell.Cmd{
Name: "get",
Help: "get a fiile or directory from ipfs",
Func: func(c *ishell.Context) {
fileHash := c.Args[0]
filePath := "./" + fileHash
cidFile := path.New("/ipfs/" + fileHash)
fileNode, err := ipfs.Unixfs().Get(ctx, cidFile)
if err != nil {
fmt.Errorf("Could not get file with Hash: %s", err)
}
err = ipfsfiles.WriteTo(fileNode, filePath)
if err != nil {
fmt.Errorf("Could not write out file: %s", err)
}
},
})
shell.Run()
}
And my problem is:
- When I build the project, error occurs as follows:
# github.com/ipfs/go-ipfs/core/bootstrap ../../pkg/mod/github.com/ipfs/go-ipfs@v0.4.23/core/bootstrap/bootstrap.go:220:14: undefined: config.BootstrapPeer # github.com/ipfs/go-ipfs/repo/fsrepo ../../pkg/mod/github.com/ipfs/go-ipfs@v0.4.23/repo/fsrepo/datastores.go:247:20: cannot use measure.New(c.prefix, child) (type *measure.measure) as type repo.Datastore in return argument: *measure.measure does not implement repo.Datastore (missing Sync method) ../../pkg/mod/github.com/ipfs/go-ipfs@v0.4.23/repo/fsrepo/fsrepo.go:432:7: cannot use measure.New(prefix, r.ds) (type *measure.measure) as type repo.Datastore in assignment: *measure.measure does not implement repo.Datastore (missing Sync method) # github.com/ipfs/go-ds-flatfs ../../pkg/mod/github.com/ipfs/go-ds-flatfs@v0.0.2/flatfs.go:91:5: cannot use (*Datastore)(nil) (type *Datastore) as type datastore.Datastore in assignment: *Datastore does not implement datastore.Datastore (missing Sync method)
It seems that I got some package errors, I don’t know where I got wrong.
2. But if I move source file to the $GOPATH/src/github.com/ipfs/go-ipfs/docs/examples/test/, and run cmmmand go build main.go
, executable file shows up and it works well.
I don’t konw how to solve ths problem, can anybody helps me. Thanks a lot. Ask questions if my presentation isn’t clear.
Other informations:
OS: 4.19.108-1-MANJARO
golang version:go version go1.14 linux/amd64
ipfs package version:go-ipfs@v0.4.23