From db61bba5a7188570438d83b216a9ed9db31faeaa Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Wed, 1 Nov 2023 14:22:29 +0800 Subject: [PATCH] Create implicit accout with funds from inx-faucet --- accountwallet/commands.go | 4 +- accountwallet/config.go | 1 - accountwallet/faucet.go | 117 +++++++++----------------------------- accountwallet/wallet.go | 4 +- main.go | 2 +- models/connector.go | 4 +- parse.go | 4 +- 7 files changed, 36 insertions(+), 100 deletions(-) diff --git a/accountwallet/commands.go b/accountwallet/commands.go index 62129d2..99e4bd9 100644 --- a/accountwallet/commands.go +++ b/accountwallet/commands.go @@ -25,7 +25,7 @@ func (a *AccountWallet) createAccountImplicitly(params *CreateAccountParams) (io // An implicit account has an implicitly defined Block Issuer Key, corresponding to the address itself. // Thus, implicit accounts can issue blocks by signing them with the private key corresponding to the public key // from which the Implicit Account Creation Address was derived. - implicitAccountOutput, privateKey, err := a.getFunds(params.Amount, iotago.AddressImplicitAccountCreation) + implicitAccountOutput, privateKey, err := a.getFunds(iotago.AddressImplicitAccountCreation) if err != nil { return iotago.EmptyAccountID, ierrors.Wrap(err, "Failed to create account") } @@ -66,7 +66,7 @@ func (a *AccountWallet) transitionImplicitAccount( AccountID(iotago.AccountIDFromOutputID(implicitAccountOutput.OutputID)). BlockIssuer(blockIssuerKeys, iotago.MaxSlotIndex).MustBuild() - log.Infof("Created account %s with %d tokens\n", accountOutput.AccountID.ToHex(), params.Amount) + log.Infof("Created account %s with %d tokens\n", accountOutput.AccountID.ToHex()) txBuilder := a.createTransactionBuilder(implicitAccountOutput, implicitAccAddr, accountOutput) // TODO get congestionResponse from API diff --git a/accountwallet/config.go b/accountwallet/config.go index fbf0e87..685f4aa 100644 --- a/accountwallet/config.go +++ b/accountwallet/config.go @@ -137,7 +137,6 @@ type AccountSubcommands interface { type CreateAccountParams struct { Alias string - Amount uint64 NoBIF bool Implicit bool Transition bool diff --git a/accountwallet/faucet.go b/accountwallet/faucet.go index 10b7cd3..743bd66 100644 --- a/accountwallet/faucet.go +++ b/accountwallet/faucet.go @@ -8,7 +8,6 @@ import ( "github.com/mr-tron/base58" "github.com/iotaledger/evil-tools/models" - "github.com/iotaledger/hive.go/core/safemath" "github.com/iotaledger/hive.go/ierrors" "github.com/iotaledger/hive.go/lo" "github.com/iotaledger/iota-core/pkg/blockhandler" @@ -39,32 +38,47 @@ func (a *AccountWallet) RequestBlockBuiltData(clt *nodeclient.Client, issuerID i return congestionResp, issuerResp, version, nil } -func (a *AccountWallet) RequestFaucetFunds(clt models.Client, receiveAddr iotago.Address, amount iotago.BaseToken) (*models.Output, error) { - congestionResp, issuerResp, version, err := a.RequestBlockBuiltData(clt.Client(), a.faucet.account.ID()) +func (a *AccountWallet) RequestFaucetFunds(clt models.Client, receiveAddr iotago.Address) (*models.Output, error) { + //nolint:all,forcetypassert + err := clt.RequestFaucetFunds(receiveAddr) if err != nil { - return nil, ierrors.Wrapf(err, "failed to get block built data for issuer %s", a.faucet.account.ID().ToHex()) + return nil, ierrors.Wrap(err, "failed to request funds from faucet") } - signedTx, err := a.faucet.prepareFaucetRequest(receiveAddr, amount, congestionResp.ReferenceManaCost) + indexer, err := clt.Indexer() if err != nil { - log.Errorf("failed to prepare faucet request: %s", err) - - return nil, err + return nil, ierrors.Wrap(err, "failed to get indexer client") } - _, err = a.PostWithBlock(clt, signedTx, a.faucet.account, congestionResp, issuerResp, version) + addrBech := receiveAddr.Bech32(clt.CommittedAPI().ProtocolParameters().Bech32HRP()) + + time.Sleep(10 * time.Second) + + res, err := indexer.Outputs(context.Background(), &apimodels.BasicOutputsQuery{ + AddressBech32: addrBech, + }) if err != nil { - log.Errorf("failed to create block: %s", err) + return nil, ierrors.Wrap(err, "indexer request failed in request faucet funds") + } + + var outputStruct iotago.Output + var outputID iotago.OutputID + for res.Next() { + unspents, err := res.Outputs(context.TODO()) + if err != nil { + return nil, ierrors.Wrap(err, "failed to get faucet unspent outputs") + } - return nil, err + outputStruct = unspents[0] + outputID = lo.Return1(res.Response.Items.OutputIDs())[0] } return &models.Output{ - OutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(signedTx.Transaction.ID()), 0), + OutputID: outputID, Address: receiveAddr, AddressIndex: 0, - Balance: signedTx.Transaction.Outputs[0].BaseTokenAmount(), - OutputStruct: signedTx.Transaction.Outputs[0], + Balance: outputStruct.BaseTokenAmount(), + OutputStruct: outputStruct, }, nil } @@ -204,78 +218,3 @@ func (f *faucet) getGenesisOutputFromIndexer(clt models.Client, faucetAddr iotag return faucetUnspentOutput, faucetUnspentOutputID, faucetAmount, nil } - -func (f *faucet) prepareFaucetRequest(receiveAddr iotago.Address, amount iotago.BaseToken, rmc iotago.Mana) (*iotago.SignedTransaction, error) { - txBuilder, remainderIndex, err := f.createFaucetTransactionNoManaHandling(receiveAddr, amount) - if err != nil { - return nil, err - } - - rmcAllottedTxBuilder := txBuilder.Clone() - // faucet will allot exact mana to be burnt, rest of the mana is alloted to faucet output remainder - rmcAllottedTxBuilder.AllotRequiredManaAndStoreRemainingManaInOutput(txBuilder.CreationSlot(), rmc, f.account.ID(), remainderIndex) - - var signedTx *iotago.SignedTransaction - signedTx, err = rmcAllottedTxBuilder.Build(f.genesisHdWallet.AddressSigner()) - if err != nil { - log.Infof("WARN: failed to build tx with min required mana allotted, genesis potential mana was not enough, fallback to faucet account") - txBuilder.AllotAllMana(txBuilder.CreationSlot(), f.account.ID()) - if signedTx, err = txBuilder.Build(f.genesisHdWallet.AddressSigner()); err != nil { - return nil, ierrors.Wrapf(err, "failed to build transaction with all mana allotted, after not having enough mana required based on RMC") - } - } - - // set remainder output to be reused by the Faucet wallet - //nolint:all,forcetypassert - f.unspentOutput = &models.Output{ - OutputID: iotago.OutputIDFromTransactionIDAndIndex(lo.PanicOnErr(signedTx.Transaction.ID()), uint16(remainderIndex)), - Address: f.genesisHdWallet.Address(iotago.AddressEd25519).(*iotago.Ed25519Address), - AddressIndex: 0, - Balance: signedTx.Transaction.Outputs[1].BaseTokenAmount(), - OutputStruct: signedTx.Transaction.Outputs[1], - } - - return signedTx, nil -} - -func (f *faucet) createFaucetTransactionNoManaHandling(receiveAddr iotago.Address, amount iotago.BaseToken) (*builder.TransactionBuilder, int, error) { - currentTime := time.Now() - currentSlot := f.clt.LatestAPI().TimeProvider().SlotFromTime(currentTime) - - apiForSlot := f.clt.APIForSlot(currentSlot) - txBuilder := builder.NewTransactionBuilder(apiForSlot) - - //nolint:all,forcetypassert - txBuilder.AddInput(&builder.TxInput{ - UnlockTarget: f.genesisHdWallet.Address(iotago.AddressEd25519).(*iotago.Ed25519Address), - InputID: f.unspentOutput.OutputID, - Input: f.unspentOutput.OutputStruct, - }) - - remainderAmount, err := safemath.SafeSub(f.unspentOutput.Balance, amount) - if err != nil { - return nil, 0, ierrors.Errorf("safeSub failed %d - %d: %s", f.unspentOutput.Balance, amount, err) - } - - txBuilder.AddOutput(&iotago.BasicOutput{ - Amount: amount, - Conditions: iotago.BasicOutputUnlockConditions{ - &iotago.AddressUnlockCondition{Address: receiveAddr}, - }, - Features: iotago.BasicOutputFeatures{}, - }) - - // remainder output - remainderIndex := 1 - //nolint:all,forcetypassert - txBuilder.AddOutput(&iotago.BasicOutput{ - Amount: remainderAmount, - Conditions: iotago.BasicOutputUnlockConditions{ - &iotago.AddressUnlockCondition{Address: f.genesisHdWallet.Address(iotago.AddressEd25519).(*iotago.Ed25519Address)}, - }, - }) - txBuilder.AddTaggedDataPayload(&iotago.TaggedData{Tag: []byte("Faucet funds"), Data: []byte("to addr" + receiveAddr.String())}) - txBuilder.SetCreationSlot(currentSlot) - - return txBuilder, remainderIndex, nil -} diff --git a/accountwallet/wallet.go b/accountwallet/wallet.go index 9f0ed98..8f07e15 100644 --- a/accountwallet/wallet.go +++ b/accountwallet/wallet.go @@ -280,10 +280,10 @@ func (a *AccountWallet) isAccountReady(accData *models.AccountData) bool { return true } -func (a *AccountWallet) getFunds(amount uint64, addressType iotago.AddressType) (*models.Output, ed25519.PrivateKey, error) { +func (a *AccountWallet) getFunds(addressType iotago.AddressType) (*models.Output, ed25519.PrivateKey, error) { receiverAddr, privKey, usedIndex := a.getAddress(addressType) - createdOutput, err := a.RequestFaucetFunds(a.client, receiverAddr, iotago.BaseToken(amount)) + createdOutput, err := a.RequestFaucetFunds(a.client, receiverAddr) if err != nil { return nil, nil, ierrors.Wrap(err, "failed to request funds from Faucet") } diff --git a/main.go b/main.go index 9f0f403..1ff2b89 100644 --- a/main.go +++ b/main.go @@ -97,7 +97,7 @@ func accountsSubcommand(wallet *accountwallet.AccountWallet, sub accountwallet.A return } - log.Infof("Created account %s with %d tokens", accountID, params.Amount) + log.Infof("Created account %s", accountID) case accountwallet.OperationDestroyAccount: log.Infof("Run subcommand: %s, with parametetr set: %v", accountwallet.OperationDestroyAccount, sub) diff --git a/models/connector.go b/models/connector.go index c8b4d3f..a83883e 100644 --- a/models/connector.go +++ b/models/connector.go @@ -219,7 +219,7 @@ type Client interface { // GetCongestion returns congestion data such as rmc or issuing readiness. GetCongestion(id iotago.AccountID) (resp *apimodels.CongestionResponse, err error) // RequestFaucetFunds - RequestFaucetFunds(address *iotago.Ed25519Address) (err error) + RequestFaucetFunds(address iotago.Address) (err error) iotago.APIProvider } @@ -279,7 +279,7 @@ func NewWebClient(url, faucetURL string, opts ...options.Option[WebClient]) (*We }), initErr } -func (c *WebClient) RequestFaucetFunds(address *iotago.Ed25519Address) (err error) { +func (c *WebClient) RequestFaucetFunds(address iotago.Address) (err error) { req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, c.faucetURL+"/api/enqueue", func() io.Reader { jsonData, _ := json.Marshal(&faucet.EnqueueRequest{ Address: address.Bech32(c.client.CommittedAPI().ProtocolParameters().Bech32HRP()), diff --git a/parse.go b/parse.go index 49856f2..f663d3e 100644 --- a/parse.go +++ b/parse.go @@ -229,7 +229,6 @@ func accountUsage() { func parseCreateAccountFlags(subcommands []string) (*accountwallet.CreateAccountParams, error) { flagSet := flag.NewFlagSet("create", flag.ExitOnError) alias := flagSet.String("alias", "", "The alias name of new created account") - amount := flagSet.Int64("amount", 1000, "The amount to be transferred to the new account") noBif := flagSet.Bool("noBIF", false, "Create account without Block Issuer Feature, can only be set false no if implicit is false, as each account created implicitly needs to have BIF.") implicit := flagSet.Bool("implicit", false, "Create an implicit account") transition := flagSet.Bool("transition", true, "Indicates if account should be transitioned to full account if created with implicit address.") @@ -253,7 +252,7 @@ func parseCreateAccountFlags(subcommands []string) (*accountwallet.CreateAccount *noBif = false } - log.Infof("Parsed flags: alias: %s, amount: %d, BIF: %t, implicit: %t, transition: %t", *alias, *amount, *noBif, *implicit, *transition) + log.Infof("Parsed flags: alias: %s, BIF: %t, implicit: %t, transition: %t", *alias, *noBif, *implicit, *transition) if !*implicit == *transition { log.Info("WARN: Implicit flag set to false, account will be created non-implicitly by Faucet, no need for transition, flag will be ignored") @@ -262,7 +261,6 @@ func parseCreateAccountFlags(subcommands []string) (*accountwallet.CreateAccount return &accountwallet.CreateAccountParams{ Alias: *alias, - Amount: uint64(*amount), NoBIF: *noBif, Implicit: *implicit, Transition: *transition,