7 "github.com/vapor/errors"
8 "github.com/vapor/protocol/bc/types"
11 // NewBuilder return new TemplateBuilder instance
12 func NewBuilder(maxTime time.Time) *TemplateBuilder {
13 return &TemplateBuilder{maxTime: maxTime}
16 // TemplateBuilder is struct of building transactions
17 type TemplateBuilder struct {
19 inputs []*types.TxInput
20 outputs []*types.TxOutput
21 signingInstructions []*SigningInstruction
26 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.Amount > math.MaxInt64 {
43 return errors.WithDetailf(ErrBadAmount, "amount %d exceeds maximum value 2^63", o.Amount)
45 b.outputs = append(b.outputs, o)
49 func (b *TemplateBuilder) SetReferenceData(referenceData []byte) {
50 b.referenceData = referenceData
53 // InputCount return number of input in the template builder
54 func (b *TemplateBuilder) InputCount() int {
58 // RestrictMinTime set minTime
59 func (b *TemplateBuilder) RestrictMinTime(t time.Time) {
60 if t.After(b.minTime) {
65 // RestrictMaxTime set maxTime
66 func (b *TemplateBuilder) RestrictMaxTime(t time.Time) {
67 if t.Before(b.maxTime) {
72 // MaxTime return maxTime
73 func (b *TemplateBuilder) MaxTime() time.Time {
77 // OnRollback registers a function that can be
78 // used to attempt to undo any side effects of building
79 // actions. For example, it might cancel any reservations
80 // reservations that were made on UTXOs in a spend action.
81 // Rollback is a "best-effort" operation and not guaranteed
82 // to succeed. Each action's side effects, if any, must be
83 // designed with this in mind.
84 func (b *TemplateBuilder) OnRollback(rollbackFn func()) {
85 b.rollbacks = append(b.rollbacks, rollbackFn)
88 // OnBuild registers a function that will be run after all
89 // actions have been successfully built.
90 func (b *TemplateBuilder) OnBuild(buildFn func() error) {
91 b.callbacks = append(b.callbacks, buildFn)
94 // Rollback action for handle fail build
95 func (b *TemplateBuilder) Rollback() {
96 for _, f := range b.rollbacks {
101 // Build build transactions with template
102 func (b *TemplateBuilder) Build() (*Template, *types.TxData, error) {
103 // Run any building callbacks.
104 for _, cb := range b.callbacks {
119 if b.timeRange != 0 {
120 tx.TimeRange = b.timeRange
123 // Add all the built outputs.
124 tx.Outputs = append(tx.Outputs, b.outputs...)
126 // Add all the built inputs and their corresponding signing instructions.
127 for i, in := range b.inputs {
128 instruction := b.signingInstructions[i]
129 instruction.Position = uint32(len(tx.Inputs))
131 // Empty signature arrays should be serialized as empty arrays, not null.
132 if instruction.WitnessComponents == nil {
133 instruction.WitnessComponents = []witnessComponent{}
135 tpl.SigningInstructions = append(tpl.SigningInstructions, instruction)
136 tx.Inputs = append(tx.Inputs, in)
139 tx.ReferenceData = b.referenceData
141 tpl.Transaction = types.NewTx(*tx)
142 tpl.Fee = CalculateTxFee(tpl.Transaction)