Skip to content

Commit

Permalink
Added new builder methods that take lists and removed the "at least 1…
Browse files Browse the repository at this point in the history
…" requirement
  • Loading branch information
satsen committed Oct 20, 2024
1 parent 9aafd8a commit 40360fa
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 21 deletions.
30 changes: 27 additions & 3 deletions lib-api/src/main/java/org/ergoplatform/appkit/OutBoxBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import org.ergoplatform.SigmaConstants;
import org.ergoplatform.sdk.ErgoToken;

import java.util.List;

/**
* This interface is used to build a new output box, which can be included
* in the new unsigned transaction. When transaction is signed, sent to the
Expand Down Expand Up @@ -32,13 +34,22 @@ public interface OutBoxBuilder {
* Configures amounts for one or more tokens (up to {@link SigmaConstants.MaxTokens}).
* Each Ergo box can store zero or more tokens (aka assets).
*
* @param tokens one or more tokens to be added to the constructed output box.
* @param tokens tokens to be added to the constructed output box.
* @see ErgoToken
*/
OutBoxBuilder tokens(ErgoToken... tokens);

/**
* Mints new token according to https://github.com/ergoplatform/eips/blob/master/eip-0004.md
* Configures amounts for tokens (up to {@link SigmaConstants.MaxTokens}).
* Each Ergo box can store zero or more tokens (aka assets).
*
* @param tokens tokens to be added to the constructed output box.
* @see ErgoToken
*/
OutBoxBuilder tokens(List<ErgoToken> tokens);

/**
* Mints new token according to <a href="https://github.com/ergoplatform/eips/blob/master/eip-0004.md">EIP-0004</a>
*
* @param token token to mint
* @see Eip4Token and Eip4TokenBuilder
Expand All @@ -58,6 +69,19 @@ public interface OutBoxBuilder {
*/
OutBoxBuilder registers(ErgoValue<?>... registers);

/**
* Configures one or more optional registers of the output box.
* Each box have 4 mandatory registers holding value of NanoErgs, guarding script,
* tokens, creation info.
* Optional (aka non-mandatory) registers numbered from index 4 up to 9.
*
* @param registers list of optional register values,
* where registers[0] corresponds to R4, registers[1] - R5, etc.
* @see ErgoValue
* @see org.ergoplatform.ErgoBox.NonMandatoryRegisterId
*/
OutBoxBuilder registers(List<ErgoValue<?>> registers);

/**
* Configure the height when the transaction containing the box was created.
* This height, when explicitly specified, should not exceed height of the block,
Expand All @@ -71,7 +95,7 @@ public interface OutBoxBuilder {
/**
* Creates {@link OutBox} instance using specified parameters.
*
* @return output box which can be {@link UnsignedTransactionBuilder#outputs(OutBox...) added}
* @return output box which can be {@link UnsignedTransactionBuilder#addOutputs(List) added}
* to {@link UnsignedTransaction}
* @see UnsignedTransaction
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ public interface UnsignedTransactionBuilder {
UnsignedTransactionBuilder preHeader(PreHeader ph);

/**
* Adds input boxes to an already specified list of inputs or, if no input boxes defined yet,
* @see #addInputs(List)
*/
UnsignedTransactionBuilder addInputs(InputBox... boxes);

/**
* Adds input boxes to an already specified list of inputs or, if no input boxes are defined yet,
* as the boxes to spend. The order is preserved.
* The boxes that will be spent by the transaction when it will be included in a block.
*
Expand All @@ -33,40 +38,50 @@ public interface UnsignedTransactionBuilder {
* as {@link OutBox} and then {@link OutBox#convertToInputWith(String, short) converted} to
* {@link InputBox}.
*/
UnsignedTransactionBuilder addInputs(InputBox... boxes);
UnsignedTransactionBuilder addInputs(List<InputBox> boxes);

/**
* @deprecated use {@link #addInputs(InputBox...)}
* @deprecated Use {@link #addInputs(List)} instead.
*/
@Deprecated
UnsignedTransactionBuilder boxesToSpend(List<InputBox> boxes);

/**
* @see #addDataInputs(List)
*/
UnsignedTransactionBuilder addDataInputs(InputBox... boxes);

/**
* @deprecated Use {@link #addDataInputs(List)} instead.
*/
@Deprecated
UnsignedTransactionBuilder withDataInputs(List<InputBox> boxes);

/**
* Adds input boxes to an already specified list of data inputs or, if no data input boxes
* defined yet, set the boxes as the data input boxes to be used. The order is preserved.
* are defined yet, set the boxes as the data input boxes to be used. The order is preserved.
*
* @param boxes list of boxes to be used as data-inputs by the transaction. The boxes can either be
* {@link BlockchainContext#getBoxesById(String...) obtained} from context of created from
* scratch
* as {@link OutBox} and then {@link OutBox#convertToInputWith(String, short) converted} to
* {@link InputBox}.
*/
UnsignedTransactionBuilder addDataInputs(InputBox... boxes);
UnsignedTransactionBuilder addDataInputs(List<InputBox> boxes);

/**
* @deprecated use {@link #addDataInputs(InputBox...)}
* @deprecated use {@link #addOutputs(OutBox...)}
*/
@Deprecated
UnsignedTransactionBuilder withDataInputs(List<InputBox> boxes);
UnsignedTransactionBuilder outputs(OutBox... outputs);

/**
* @deprecated use {@link #addOutputs(OutBox...)}
* @see #addOutputs(List)
*/
@Deprecated
UnsignedTransactionBuilder outputs(OutBox... outputs);
UnsignedTransactionBuilder addOutputs(OutBox... outBoxes);

/**
* Adds output boxes to an already specified list of outputs or, if no output boxes defined yet,
* Adds output boxes to an already specified list of outputs or, if no output boxes are defined yet,
* as the boxes to be output. The order is preserved.
* After this transaction is {@link UnsignedTransactionBuilder#build() built},
* {@link ErgoProver#sign(UnsignedTransaction)} signed,
Expand All @@ -75,7 +90,7 @@ public interface UnsignedTransactionBuilder {
*
* @param outBoxes output boxes created by the transaction
*/
UnsignedTransactionBuilder addOutputs(OutBox... outBoxes);
UnsignedTransactionBuilder addOutputs(List<OutBox> outBoxes);

/**
* Adds transaction fee output.
Expand All @@ -84,19 +99,24 @@ public interface UnsignedTransactionBuilder {
*/
UnsignedTransactionBuilder fee(long feeAmount);

/**
* @see #tokensToBurn(List)
*/
UnsignedTransactionBuilder tokensToBurn(ErgoToken... tokens);

/**
* Configures amounts for tokens to be burnt.
* Each Ergo box can store zero or more tokens (aka assets).
* In contrast to strict requirement on ERG balance between transaction inputs and outputs,
* the amounts of output tokens can be less then the amounts of input tokens.
* the amounts of output tokens can be less than the amounts of input tokens.
* This is interpreted as token burning i.e. reducing the total amount of tokens in
* circulation in the blockchain.
* Note, once issued/burnt, the amount of tokens in circulation cannot be increased.
*
* @param tokens one or more tokens to be burnt as part of the transaction.
* @see ErgoToken
*/
UnsignedTransactionBuilder tokensToBurn(ErgoToken... tokens);
UnsignedTransactionBuilder tokensToBurn(List<ErgoToken> tokens);

/**
* Adds change output to the specified address if needed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,22 @@ class OutBoxBuilderImpl(_txB: UnsignedTransactionBuilderImpl) extends OutBoxBuil
}

override def tokens(tokens: ErgoToken*): OutBoxBuilderImpl = {
require(tokens.nonEmpty, "At least one token should be specified")
val maxTokens = SigmaConstants.MaxTokens.value
require(tokens.size <= maxTokens, SigmaConstants.MaxTokens.description + s": $maxTokens")
_tokens ++= tokens
this
}

override def tokens(tokens: java.util.List[ErgoToken]): OutBoxBuilderImpl = {
val maxTokens = SigmaConstants.MaxTokens.value
require(tokens.size <= maxTokens, SigmaConstants.MaxTokens.description + s": $maxTokens")
val iterator = tokens.iterator()
while (iterator.hasNext) {
_tokens += iterator.next
}
this
}

override def mintToken(token: Eip4Token): OutBoxBuilder = {
val tokenNameVal = token.getMintingBoxR4
val tokenDescVal = token.getMintingBoxR5
Expand Down Expand Up @@ -70,6 +79,16 @@ class OutBoxBuilderImpl(_txB: UnsignedTransactionBuilderImpl) extends OutBoxBuil
this
}

override def registers(registers: java.util.List[ErgoValue[_]]): OutBoxBuilderImpl = {
InternalUtil.checkArgument(!registers.isEmpty,
"At least one register should be specified": Any)
_registers.clear()
val iterator = registers.iterator()
while (iterator.hasNext)
_registers += iterator.next()
this
}

override def creationHeight(height: Int): OutBoxBuilder = {
_creationHeightOpt = Some(height)
this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,19 @@ class UnsignedTransactionBuilderImpl(val _ctx: BlockchainContextImpl) extends Un
this
}

override def addInputs(boxes: util.List[InputBox]): UnsignedTransactionBuilder = {
val iterator = boxes.iterator()
while (iterator.hasNext) {
iterator.next() match {
case b: InputBoxImpl => _inputs.add(b)
}
}
this
}

override def boxesToSpend(inputBoxes: List[InputBox]): UnsignedTransactionBuilder = {
require(_inputs.isEmpty, "inputs already specified")
addInputs(JavaHelpers.toIndexedSeq(inputBoxes): _*)
this
addInputs(inputBoxes)
}

override def addDataInputs(boxes: InputBox*): UnsignedTransactionBuilder = {
Expand All @@ -53,7 +62,17 @@ class UnsignedTransactionBuilderImpl(val _ctx: BlockchainContextImpl) extends Un

override def withDataInputs(inputBoxes: List[InputBox]): UnsignedTransactionBuilder = {
require(_dataInputs.isEmpty, "dataInputs list is already specified")
addDataInputs(JavaHelpers.toIndexedSeq(inputBoxes): _*)
addDataInputs(inputBoxes)
this
}

override def addDataInputs(boxes: util.List[InputBox]): UnsignedTransactionBuilder = {
val iterator = boxes.iterator()
while (iterator.hasNext) {
iterator.next() match {
case b: InputBoxImpl => _dataInputs.add(b)
}
}
this
}

Expand All @@ -70,6 +89,16 @@ class UnsignedTransactionBuilderImpl(val _ctx: BlockchainContextImpl) extends Un
this
}

override def addOutputs(outBoxes: util.List[OutBox]): UnsignedTransactionBuilder = {
val iterator = outBoxes.iterator()
while (iterator.hasNext) {
iterator.next() match {
case b: OutBoxImpl => _outputs.add(b)
}
}
this
}

override def fee(feeAmount: Long): UnsignedTransactionBuilder = {
require(_feeAmount.isEmpty, "Fee already defined")
_feeAmount = Some(feeAmount)
Expand All @@ -86,6 +115,12 @@ class UnsignedTransactionBuilderImpl(val _ctx: BlockchainContextImpl) extends Un
this
}

override def tokensToBurn(tokens: util.List[ErgoToken]): UnsignedTransactionBuilder = {
require(_tokensToBurn.isEmpty, "Tokens to burn already specified.")
_tokensToBurn = Some(new util.ArrayList[ErgoToken](tokens))
this
}

override def sendChangeTo(changeAddress: ErgoAddress): UnsignedTransactionBuilder = {
require(_changeAddress.isEmpty, "Change address is already specified")
_changeAddress = Some(changeAddress)
Expand Down

0 comments on commit 40360fa

Please sign in to comment.