You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I suggest we consider deprecating 'simple transaction builder' in the long run.
More practically, we should first have to get proper debug tooling for the advanced tx builder but afterwards we can mark the 'simple tx builder' as deprecated (but still available). Then in the V1 release it could be fully removed.
The Simple Transaction Builder
The simple transaction builder is the original way to spend from Contracts using the CashScript SDK. It has the following features:
Automatic UTXO selection
Automatic change output
Call transaction building directly on the contract object
Together they try to abstract away 'transaction building' in favor of a wallet-like API where you can "just spend from a balance":
This method breaks down fast: what if you want to send the contract.getBalance() amount, how to spend this full contractBalance when taking into account fees without knowing the number of inputs? What if you want to spend from covenants, where having multiple inputs requires the shape of the transaction to change?
Bad Abstraction
The simple transaction builder is a bad abstraction, it hides the fact that transactions are built with in- and outputs and assumes that a similar to a wallet smart contracts usage involves 'spending some amount from a total balance, returning the change".
The 'simple transaction builder' has a lot of extra settings to override this default fee/change behavior making the API less simple and more complex than the 'advanced tx builder'.
In practice most usage of the simple transaction builder involves .from() and .withoutChange(), at which point you'd be better just using the advanced builder. It defeats the point of the simple transaction builder and is a good indication it is a bad abstraction.
I argue the 3 features of the simple tx builder are actually anti-features:
This assumes the selected inputs don't affect the transaction shape besides the changeAmount, but in many cases the inputs DO define the full tx shape (including outputs) like when sending the max balance or working with (self replicating) covenants where the inputs decide the structure of the outputs.
Sending change back to the contract is a bad, weird default that only makes sense in this weird abstraction level where contracts are seen as a 'wallet' where to spend a balance from. However this is rarely how contracts really work.
calling a function on an object seems like a nice abstraction but it hides the core of the UTXO model: transactions have in and outputs. This causes new developers to have a wrong mental model from the start and causes them to have to learn about the 'simple tx builder' workarounds like .from() and .withoutChange(), when they'd be better just using the advanced builder
2 Ways of doing things
I consider it very bad that there are two ways of doing things, both with different abstraction levels and their own API documentation.
It introduces the questions what the difference is between the two and causes people to understand both at some basic level.
The advanced ts builder is also just accessible to beginner devs, but it starts them of with the correct mental model instead of confusing abstractions. Instead of calling 'functions on contracts' the mental model becomes 'creating a transaction with in- and outputs'
There would just be one 'transaction builder' and one documentation page. This definitely feels like the correct direction long term
The text was updated successfully, but these errors were encountered:
I would agree, having two different ways to do the same thing can cause some confusion.
Also agree that abstracting away the change output management in the simple builder can lead to some potentially bad situations if someone learns to ignore change outputs then applies that logic to the advanced builder.
I think it also does help with learning the UTXO mental model, and I would keep .addInput/.addOutput of the advanced builder to reinforce this over .to/.from of the simple builder.
I myself immediately defaulted to always using .withoutChange() and .withoutTokenChange() on the simple builder.
All assuming the advanced builder gets debugging 😁
Hard to argue with this. I would argue that a "Simple" Builder might be a good idea as a higher level abstraction, but the current one isn't it because usage of it isn't actually simple and it makes bad choices as you outlined well. A simple builder would be much more complex under the hood.
In the meantime, as you also pointed out, the standard builder is not complicated to use and provides a correct mental model.
I suggest we consider deprecating 'simple transaction builder' in the long run.
More practically, we should first have to get proper debug tooling for the advanced tx builder but afterwards we can mark the 'simple tx builder' as deprecated (but still available). Then in the V1 release it could be fully removed.
The Simple Transaction Builder
The simple transaction builder is the original way to spend from Contracts using the CashScript SDK. It has the following features:
Together they try to abstract away 'transaction building' in favor of a wallet-like API where you can "just spend from a balance":
This method breaks down fast: what if you want to send the
contract.getBalance()
amount, how to spend this fullcontractBalance
when taking into account fees without knowing the number of inputs? What if you want to spend from covenants, where having multiple inputs requires the shape of the transaction to change?Bad Abstraction
The simple transaction builder is a bad abstraction, it hides the fact that transactions are built with in- and outputs and assumes that a similar to a wallet smart contracts usage involves 'spending some amount from a total balance, returning the change".
The 'simple transaction builder' has a lot of extra settings to override this default fee/change behavior making the API less simple and more complex than the 'advanced tx builder'.
In practice most usage of the simple transaction builder involves
.from()
and.withoutChange()
, at which point you'd be better just using the advanced builder. It defeats the point of the simple transaction builder and is a good indication it is a bad abstraction.Anti-features
I argue the 3 features of the simple tx builder are actually anti-features:
changeAmount
, but in many cases the inputs DO define the full tx shape (including outputs) like when sending the max balance or working with (self replicating) covenants where the inputs decide the structure of the outputs.Sending change back to the contract is a bad, weird default that only makes sense in this weird abstraction level where contracts are seen as a 'wallet' where to spend a balance from. However this is rarely how contracts really work.
calling a function on an object seems like a nice abstraction but it hides the core of the UTXO model: transactions have in and outputs. This causes new developers to have a wrong mental model from the start and causes them to have to learn about the 'simple tx builder' workarounds like
.from()
and.withoutChange()
, when they'd be better just using the advanced builder2 Ways of doing things
I consider it very bad that there are two ways of doing things, both with different abstraction levels and their own API documentation.
It introduces the questions what the difference is between the two and causes people to understand both at some basic level.
The advanced ts builder is also just accessible to beginner devs, but it starts them of with the correct mental model instead of confusing abstractions. Instead of calling 'functions on contracts' the mental model becomes 'creating a transaction with in- and outputs'
There would just be one 'transaction builder' and one documentation page. This definitely feels like the correct direction long term
The text was updated successfully, but these errors were encountered: