From 40360faff0fd4aa3e87819ac8d7a87138e543444 Mon Sep 17 00:00:00 2001 From: satsen <95986745+satsen@users.noreply.github.com> Date: Tue, 15 Oct 2024 20:16:28 +0100 Subject: [PATCH] Added new builder methods that take lists and removed the "at least 1" requirement --- .../ergoplatform/appkit/OutBoxBuilder.java | 30 ++++++++++-- .../appkit/UnsignedTransactionBuilder.java | 48 +++++++++++++------ .../appkit/impl/OutBoxBuilderImpl.scala | 21 +++++++- .../impl/UnsignedTransactionBuilderImpl.scala | 41 ++++++++++++++-- 4 files changed, 119 insertions(+), 21 deletions(-) diff --git a/lib-api/src/main/java/org/ergoplatform/appkit/OutBoxBuilder.java b/lib-api/src/main/java/org/ergoplatform/appkit/OutBoxBuilder.java index 6c190e11..c782a87d 100644 --- a/lib-api/src/main/java/org/ergoplatform/appkit/OutBoxBuilder.java +++ b/lib-api/src/main/java/org/ergoplatform/appkit/OutBoxBuilder.java @@ -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 @@ -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 tokens); + + /** + * Mints new token according to EIP-0004 * * @param token token to mint * @see Eip4Token and Eip4TokenBuilder @@ -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> registers); + /** * Configure the height when the transaction containing the box was created. * This height, when explicitly specified, should not exceed height of the block, @@ -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 */ diff --git a/lib-api/src/main/java/org/ergoplatform/appkit/UnsignedTransactionBuilder.java b/lib-api/src/main/java/org/ergoplatform/appkit/UnsignedTransactionBuilder.java index 0385f3cd..dd35975a 100644 --- a/lib-api/src/main/java/org/ergoplatform/appkit/UnsignedTransactionBuilder.java +++ b/lib-api/src/main/java/org/ergoplatform/appkit/UnsignedTransactionBuilder.java @@ -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. * @@ -33,17 +38,28 @@ public interface UnsignedTransactionBuilder { * as {@link OutBox} and then {@link OutBox#convertToInputWith(String, short) converted} to * {@link InputBox}. */ - UnsignedTransactionBuilder addInputs(InputBox... boxes); + UnsignedTransactionBuilder addInputs(List boxes); /** - * @deprecated use {@link #addInputs(InputBox...)} + * @deprecated Use {@link #addInputs(List)} instead. */ @Deprecated UnsignedTransactionBuilder boxesToSpend(List boxes); + /** + * @see #addDataInputs(List) + */ + UnsignedTransactionBuilder addDataInputs(InputBox... boxes); + + /** + * @deprecated Use {@link #addDataInputs(List)} instead. + */ + @Deprecated + UnsignedTransactionBuilder withDataInputs(List 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 @@ -51,22 +67,21 @@ public interface UnsignedTransactionBuilder { * as {@link OutBox} and then {@link OutBox#convertToInputWith(String, short) converted} to * {@link InputBox}. */ - UnsignedTransactionBuilder addDataInputs(InputBox... boxes); + UnsignedTransactionBuilder addDataInputs(List boxes); /** - * @deprecated use {@link #addDataInputs(InputBox...)} + * @deprecated use {@link #addOutputs(OutBox...)} */ @Deprecated - UnsignedTransactionBuilder withDataInputs(List 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, @@ -75,7 +90,7 @@ public interface UnsignedTransactionBuilder { * * @param outBoxes output boxes created by the transaction */ - UnsignedTransactionBuilder addOutputs(OutBox... outBoxes); + UnsignedTransactionBuilder addOutputs(List outBoxes); /** * Adds transaction fee output. @@ -84,11 +99,16 @@ 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. @@ -96,7 +116,7 @@ public interface UnsignedTransactionBuilder { * @param tokens one or more tokens to be burnt as part of the transaction. * @see ErgoToken */ - UnsignedTransactionBuilder tokensToBurn(ErgoToken... tokens); + UnsignedTransactionBuilder tokensToBurn(List tokens); /** * Adds change output to the specified address if needed. diff --git a/lib-impl/src/main/java/org/ergoplatform/appkit/impl/OutBoxBuilderImpl.scala b/lib-impl/src/main/java/org/ergoplatform/appkit/impl/OutBoxBuilderImpl.scala index 00420035..cb77c07c 100644 --- a/lib-impl/src/main/java/org/ergoplatform/appkit/impl/OutBoxBuilderImpl.scala +++ b/lib-impl/src/main/java/org/ergoplatform/appkit/impl/OutBoxBuilderImpl.scala @@ -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 @@ -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 diff --git a/lib-impl/src/main/java/org/ergoplatform/appkit/impl/UnsignedTransactionBuilderImpl.scala b/lib-impl/src/main/java/org/ergoplatform/appkit/impl/UnsignedTransactionBuilderImpl.scala index 69a3e971..4b7c868e 100644 --- a/lib-impl/src/main/java/org/ergoplatform/appkit/impl/UnsignedTransactionBuilderImpl.scala +++ b/lib-impl/src/main/java/org/ergoplatform/appkit/impl/UnsignedTransactionBuilderImpl.scala @@ -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 = { @@ -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 } @@ -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) @@ -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)