Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion tests/e2e/banff/suites.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ var _ = ginkgo.Describe("[Banff]", func() {
// 5-second is enough to fetch initial UTXOs for test cluster in "primary.NewWallet"
ctx, cancel := context.WithTimeout(context.Background(), e2e.DefaultWalletCreationTimeout)
var err error
wallet, err = primary.NewWalletFromURI(ctx, walletURI, kc)
wallet, err = primary.MakeWallet(ctx, &primary.WalletConfig{
URI: walletURI,
Keychain: kc,
})
cancel()
gomega.Expect(err).Should(gomega.BeNil())

Expand Down
5 changes: 4 additions & 1 deletion tests/e2e/p/permissionless_subnets.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ var _ = e2e.DescribePChain("[Permissionless Subnets]", func() {
ginkgo.By("setup wallet", func() {
var err error
ctx, cancel := context.WithTimeout(context.Background(), e2e.DefaultTimeout)
baseWallet, err = primary.NewWalletFromURI(ctx, nodeURI, keyChain)
baseWallet, err = primary.MakeWallet(ctx, &primary.WalletConfig{
URI: nodeURI,
Keychain: keyChain,
})
cancel()
gomega.Expect(err).Should(gomega.BeNil())
})
Expand Down
5 changes: 4 additions & 1 deletion tests/e2e/p/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ var _ = e2e.DescribePChain("[Workflow]", func() {

tests.Outf("{{blue}} setting up wallet {{/}}\n")
ctx, cancel := context.WithTimeout(context.Background(), e2e.DefaultWalletCreationTimeout)
baseWallet, err := primary.NewWalletFromURI(ctx, nodeURI, keyChain)
baseWallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{
URI: nodeURI,
Keychain: keyChain,
})
cancel()
gomega.Expect(err).Should(gomega.BeNil())

Expand Down
7 changes: 5 additions & 2 deletions tests/e2e/x/transfer/virtuous.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,12 @@ var _ = e2e.DescribeXChainSerial("[Virtuous Transfer Tx AVAX]", func() {
ginkgo.By("setting up a base wallet", func() {
walletURI := e2e.Env.GetRandomNodeURI()

// 5-second is enough to fetch initial UTXOs for test cluster in "primary.NewWallet"
// 5-second is enough to fetch initial UTXOs for test cluster in "primary.MakeWallet"
ctx, cancel := context.WithTimeout(context.Background(), e2e.DefaultWalletCreationTimeout)
baseWallet, err = primary.NewWalletFromURI(ctx, walletURI, keyChain)
baseWallet, err = primary.MakeWallet(ctx, &primary.WalletConfig{
URI: walletURI,
Keychain: keyChain,
})
cancel()
gomega.Expect(err).Should(gomega.BeNil())
})
Expand Down
9 changes: 6 additions & 3 deletions wallet/subnet/primary/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ func ExampleWallet() {
ctx := context.Background()
kc := secp256k1fx.NewKeychain(genesis.EWOQKey)

// NewWalletFromURI fetches the available UTXOs owned by [kc] on the network
// that [LocalAPIURI] is hosting.
// MakeWallet fetches the available UTXOs owned by [kc] on the network that
// [LocalAPIURI] is hosting.
walletSyncStartTime := time.Now()
wallet, err := NewWalletFromURI(ctx, LocalAPIURI, kc)
wallet, err := MakeWallet(ctx, &WalletConfig{
URI: LocalAPIURI,
Keychain: kc,
})
if err != nil {
log.Fatalf("failed to initialize wallet with: %s\n", err)
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/ava-labs/avalanchego/api/info"
"github.com/ava-labs/avalanchego/genesis"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/avalanchego/utils/units"
"github.com/ava-labs/avalanchego/vms/platformvm/txs"
"github.com/ava-labs/avalanchego/vms/secp256k1fx"
Expand Down Expand Up @@ -41,10 +42,14 @@ func main() {
}
log.Printf("fetched node ID %s in %s\n", nodeID, time.Since(nodeInfoStartTime))

// NewWalletWithTxs fetches the available UTXOs owned by [kc] on the network
// that [uri] is hosting and registers [subnetID].
// MakeWallet fetches the available UTXOs owned by [kc] on the network that
// [uri] is hosting and registers [subnetID].
walletSyncStartTime := time.Now()
wallet, err := primary.NewWalletWithTxs(ctx, uri, kc, subnetID)
wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{
URI: uri,
Keychain: kc,
PChainTxsToFetch: set.Of(subnetID),
})
if err != nil {
log.Fatalf("failed to initialize wallet: %s\n", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,13 @@ func main() {
}
log.Printf("fetched node ID %s in %s\n", nodeID, time.Since(nodeInfoStartTime))

// NewWalletFromURI fetches the available UTXOs owned by [kc] on the network
// that [uri] is hosting.
// MakeWallet fetches the available UTXOs owned by [kc] on the network that
// [uri] is hosting.
walletSyncStartTime := time.Now()
wallet, err := primary.NewWalletFromURI(ctx, uri, kc)
wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{
URI: uri,
Keychain: kc,
})
if err != nil {
log.Fatalf("failed to initialize wallet: %s\n", err)
}
Expand Down
9 changes: 6 additions & 3 deletions wallet/subnet/primary/examples/create-asset/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ func main() {

ctx := context.Background()

// NewWalletFromURI fetches the available UTXOs owned by [kc] on the network
// that [uri] is hosting.
// MakeWallet fetches the available UTXOs owned by [kc] on the network that
// [uri] is hosting.
walletSyncStartTime := time.Now()
wallet, err := primary.NewWalletFromURI(ctx, uri, kc)
wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{
URI: uri,
Keychain: kc,
})
if err != nil {
log.Fatalf("failed to initialize wallet: %s\n", err)
}
Expand Down
11 changes: 8 additions & 3 deletions wallet/subnet/primary/examples/create-chain/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/ava-labs/avalanchego/genesis"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/avalanchego/vms/secp256k1fx"
"github.com/ava-labs/avalanchego/wallet/subnet/primary"
)
Expand All @@ -36,10 +37,14 @@ func main() {

ctx := context.Background()

// NewWalletWithTxs fetches the available UTXOs owned by [kc] on the network
// that [uri] is hosting and registers [subnetID].
// MakeWallet fetches the available UTXOs owned by [kc] on the network that
// [uri] is hosting and registers [subnetID].
walletSyncStartTime := time.Now()
wallet, err := primary.NewWalletWithTxs(ctx, uri, kc, subnetID)
wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{
URI: uri,
Keychain: kc,
PChainTxsToFetch: set.Of(subnetID),
})
if err != nil {
log.Fatalf("failed to initialize wallet: %s\n", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ func main() {

ctx := context.Background()

// NewWalletFromURI fetches the available UTXOs owned by [kc] on the network
// that [uri] is hosting.
// MakeWallet fetches the available UTXOs owned by [kc] on the network that
// [uri] is hosting.
walletSyncStartTime := time.Now()
wallet, err := primary.NewWalletFromURI(ctx, uri, kc)
wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{
URI: uri,
Keychain: kc,
})
if err != nil {
log.Fatalf("failed to initialize wallet: %s\n", err)
}
Expand Down
9 changes: 6 additions & 3 deletions wallet/subnet/primary/examples/create-subnet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@ func main() {

ctx := context.Background()

// NewWalletFromURI fetches the available UTXOs owned by [kc] on the network
// that [uri] is hosting.
// MakeWallet fetches the available UTXOs owned by [kc] on the network that
// [uri] is hosting.
walletSyncStartTime := time.Now()
wallet, err := primary.NewWalletFromURI(ctx, uri, kc)
wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{
URI: uri,
Keychain: kc,
})
if err != nil {
log.Fatalf("failed to initialize wallet: %s\n", err)
}
Expand Down
11 changes: 8 additions & 3 deletions wallet/subnet/primary/examples/remove-subnet-validator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/ava-labs/avalanchego/genesis"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/avalanchego/vms/secp256k1fx"
"github.com/ava-labs/avalanchego/wallet/subnet/primary"
)
Expand All @@ -33,10 +34,14 @@ func main() {

ctx := context.Background()

// NewWalletWithTxs fetches the available UTXOs owned by [kc] on the network
// that [uri] is hosting and registers [subnetID].
// MakeWallet fetches the available UTXOs owned by [kc] on the network that
// [uri] is hosting and registers [subnetID].
walletSyncStartTime := time.Now()
wallet, err := primary.NewWalletWithTxs(ctx, uri, kc, subnetID)
wallet, err := primary.MakeWallet(ctx, &primary.WalletConfig{
URI: uri,
Keychain: kc,
PChainTxsToFetch: set.Of(subnetID),
})
if err != nil {
log.Fatalf("failed to initialize wallet: %s\n", err)
}
Expand Down
121 changes: 54 additions & 67 deletions wallet/subnet/primary/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/avalanchego/utils/crypto/keychain"
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/avalanchego/vms/avm"
"github.com/ava-labs/avalanchego/vms/platformvm"
"github.com/ava-labs/avalanchego/vms/platformvm/txs"
Expand Down Expand Up @@ -38,98 +39,84 @@ func (w *wallet) X() x.Wallet {
return w.x
}

// NewWalletFromURI returns a wallet that supports issuing transactions to the
// chains living in the primary network to a provided [uri].
// Creates a new default wallet
func NewWallet(p p.Wallet, x x.Wallet) Wallet {
return &wallet{
p: p,
x: x,
}
}

// Creates a Wallet with the given set of options
func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet {
return NewWallet(
p.NewWalletWithOptions(w.P(), options...),
x.NewWalletWithOptions(w.X(), options...),
)
}

type WalletConfig struct {
// Base URI to use for all node requests.
URI string // required
// Keys to use for signing all transactions.
Keychain keychain.Keychain // required
// Set of P-chain transactions that the wallet should know about to be able
// to generate transactions.
PChainTxs map[ids.ID]*txs.Tx // optional
// Set of P-chain transactions that the wallet should fetch to be able to
// generate transactions.
PChainTxsToFetch set.Set[ids.ID] // optional
}

// MakeWallet returns a wallet that supports issuing transactions to the chains
// living in the primary network.
//
// On creation, the wallet attaches to the provided [uri] and fetches all UTXOs
// that reference any of the keys contained in [kc]. If the UTXOs are modified
// through an external issuance process, such as another instance of the wallet,
// the UTXOs may become out of sync.
// On creation, the wallet attaches to the provided uri and fetches all UTXOs
// that reference any of the provided keys. If the UTXOs are modified through an
// external issuance process, such as another instance of the wallet, the UTXOs
// may become out of sync. The wallet will also fetch all requested P-chain
// transactions.
//
// The wallet manages all UTXOs locally, and performs all tx signing locally.
func NewWalletFromURI(ctx context.Context, uri string, kc keychain.Keychain) (Wallet, error) {
pCTX, xCTX, utxos, err := FetchState(ctx, uri, kc.Addresses())
// The wallet manages all state locally, and performs all tx signing locally.
func MakeWallet(ctx context.Context, config *WalletConfig) (Wallet, error) {
addrs := config.Keychain.Addresses()
pCTX, xCTX, utxos, err := FetchState(ctx, config.URI, addrs)
if err != nil {
return nil, err
}
return NewWalletWithState(uri, pCTX, xCTX, utxos, kc), nil
}

// Creates a wallet with pre-loaded/cached P-chain transactions.
func NewWalletWithTxs(ctx context.Context, uri string, kc keychain.Keychain, preloadTXs ...ids.ID) (Wallet, error) {
pCTX, xCTX, utxos, err := FetchState(ctx, uri, kc.Addresses())
if err != nil {
return nil, err
pChainTxs := config.PChainTxs
if pChainTxs == nil {
pChainTxs = make(map[ids.ID]*txs.Tx)
}
pTXs := make(map[ids.ID]*txs.Tx)
pClient := platformvm.NewClient(uri)
for _, id := range preloadTXs {
txBytes, err := pClient.GetTx(ctx, id)

pClient := platformvm.NewClient(config.URI)
for txID := range config.PChainTxsToFetch {
txBytes, err := pClient.GetTx(ctx, txID)
if err != nil {
return nil, err
}
tx, err := txs.Parse(txs.Codec, txBytes)
if err != nil {
return nil, err
}
pTXs[id] = tx
pChainTxs[txID] = tx
}
return NewWalletWithTxsAndState(uri, pCTX, xCTX, utxos, kc, pTXs), nil
}

// Creates a wallet with pre-loaded/cached P-chain transactions and state.
func NewWalletWithTxsAndState(
uri string,
pCTX p.Context,
xCTX x.Context,
utxos UTXOs,
kc keychain.Keychain,
pTXs map[ids.ID]*txs.Tx,
) Wallet {
addrs := kc.Addresses()
pUTXOs := NewChainUTXOs(constants.PlatformChainID, utxos)
pBackend := p.NewBackend(pCTX, pUTXOs, pTXs)
pBackend := p.NewBackend(pCTX, pUTXOs, pChainTxs)
pBuilder := p.NewBuilder(addrs, pBackend)
pSigner := p.NewSigner(kc, pBackend)
pClient := platformvm.NewClient(uri)
pSigner := p.NewSigner(config.Keychain, pBackend)

xChainID := xCTX.BlockchainID()
xUTXOs := NewChainUTXOs(xChainID, utxos)
xBackend := x.NewBackend(xCTX, xUTXOs)
xBuilder := x.NewBuilder(addrs, xBackend)
xSigner := x.NewSigner(kc, xBackend)
xClient := avm.NewClient(uri, "X")
xSigner := x.NewSigner(config.Keychain, xBackend)
xClient := avm.NewClient(config.URI, "X")

return NewWallet(
p.NewWallet(pBuilder, pSigner, pClient, pBackend),
x.NewWallet(xBuilder, xSigner, xClient, xBackend),
)
}

// Creates a wallet with pre-fetched state.
func NewWalletWithState(
uri string,
pCTX p.Context,
xCTX x.Context,
utxos UTXOs,
kc keychain.Keychain,
) Wallet {
pTXs := make(map[ids.ID]*txs.Tx)
return NewWalletWithTxsAndState(uri, pCTX, xCTX, utxos, kc, pTXs)
}

// Creates a Wallet with the given set of options
func NewWalletWithOptions(w Wallet, options ...common.Option) Wallet {
return NewWallet(
p.NewWalletWithOptions(w.P(), options...),
x.NewWalletWithOptions(w.X(), options...),
)
}

// Creates a new default wallet
func NewWallet(p p.Wallet, x x.Wallet) Wallet {
return &wallet{
p: p,
x: x,
}
), nil
}