7 "github.com/vapor/common/arithmetic"
8 "github.com/vapor/errors"
9 "github.com/vapor/protocol/bc/types"
12 // NewBuilder return new TemplateBuilder instance
13 func NewBuilder(maxTime time.Time) *TemplateBuilder {
14 return &TemplateBuilder{maxTime: maxTime}
17 // TemplateBuilder is struct of building transactions
18 type TemplateBuilder struct {
20 inputs []*types.TxInput
21 outputs []*types.TxOutput
22 signingInstructions []*SigningInstruction
27 callbacks []func() error
30 // AddInput add inputs of transactions
31 func (b *TemplateBuilder) AddInput(in *types.TxInput, sigInstruction *SigningInstruction) error {
32 if in.InputType() != types.CoinbaseInputType && in.Amount() > math.MaxInt64 {
33 return errors.WithDetailf(ErrBadAmount, "amount %d exceeds maximum value 2^63", in.Amount())
35 b.inputs = append(b.inputs, in)
36 b.signingInstructions = append(b.signingInstructions, sigInstruction)
40 // AddOutput add outputs of transactions
41 func (b *TemplateBuilder) AddOutput(o *types.TxOutput) error {
42 if o.AssetAmount().Amount > math.MaxInt64 {
43 return errors.WithDetailf(ErrBadAmount, "amount %d exceeds maximum value 2^63", o.AssetAmount().Amount)
45 b.outputs = append(b.outputs, o)
49 // InputCount return number of input in the template builder
50 func (b *TemplateBuilder) InputCount() int {
54 // RestrictMinTime set minTime
55 func (b *TemplateBuilder) RestrictMinTime(t time.Time) {
56 if t.After(b.minTime) {
61 // RestrictMaxTime set maxTime
62 func (b *TemplateBuilder) RestrictMaxTime(t time.Time) {
63 if t.Before(b.maxTime) {
68 // MaxTime return maxTime
69 func (b *TemplateBuilder) MaxTime() time.Time {
73 // OnRollback registers a function that can be
74 // used to attempt to undo any side effects of building
75 // actions. For example, it might cancel any reservations
76 // reservations that were made on UTXOs in a spend action.
77 // Rollback is a "best-effort" operation and not guaranteed
78 // to succeed. Each action's side effects, if any, must be
79 // designed with this in mind.
80 func (b *TemplateBuilder) OnRollback(rollbackFn func()) {
81 b.rollbacks = append(b.rollbacks, rollbackFn)
84 // OnBuild registers a function that will be run after all
85 // actions have been successfully built.
86 func (b *TemplateBuilder) OnBuild(buildFn func() error) {
87 b.callbacks = append(b.callbacks, buildFn)
90 // Rollback action for handle fail build
91 func (b *TemplateBuilder) Rollback() {
92 for _, f := range b.rollbacks {
97 // Build build transactions with template
98 func (b *TemplateBuilder) Build() (*Template, *types.TxData, error) {
99 // Run any building callbacks.
100 for _, cb := range b.callbacks {
115 if b.timeRange != 0 {
116 tx.TimeRange = b.timeRange
119 // Add all the built outputs.
120 tx.Outputs = append(tx.Outputs, b.outputs...)
122 // Add all the built inputs and their corresponding signing instructions.
123 for i, in := range b.inputs {
124 instruction := b.signingInstructions[i]
125 instruction.Position = uint32(len(tx.Inputs))
127 // Empty signature arrays should be serialized as empty arrays, not null.
128 if instruction.WitnessComponents == nil {
129 instruction.WitnessComponents = []witnessComponent{}
131 tpl.SigningInstructions = append(tpl.SigningInstructions, instruction)
132 tx.Inputs = append(tx.Inputs, in)
136 tpl.Transaction = types.NewTx(*tx)
137 if tpl.Fee, err = arithmetic.CalculateTxFee(tpl.Transaction); err != nil {