Skip to content

Commit

Permalink
feat: implement generate unsigned issuing cheque tx
Browse files Browse the repository at this point in the history
  • Loading branch information
shaojunda committed Dec 10, 2020
1 parent 73b7898 commit d2d09d7
Showing 1 changed file with 129 additions and 0 deletions.
129 changes: 129 additions & 0 deletions payment/cheque.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package payment

import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/nervosnetwork/ckb-sdk-go/address"
"github.com/nervosnetwork/ckb-sdk-go/collector"
"github.com/nervosnetwork/ckb-sdk-go/indexer"
"github.com/nervosnetwork/ckb-sdk-go/rpc"
"github.com/nervosnetwork/ckb-sdk-go/transaction"
"github.com/nervosnetwork/ckb-sdk-go/types"
"github.com/nervosnetwork/ckb-sdk-go/utils"
"github.com/pkg/errors"
"math"
"math/big"
)

var (
chequeCellCapacity = uint64(162 * math.Pow10(8))
udtCellCapacity = uint64(142 * math.Pow10(8))
)

type Cheque struct {
Sender *types.Script
Receiver *types.Script
UUID string
Amount *big.Int
FeeRate uint64
tx *types.Transaction
}

func NewCheque(senderAddr, receiverAddr, uuid, amount string, feeRate uint64) (*Cheque, error) {
parsedSenderAddr, err := address.Parse(senderAddr)
if err != nil {
return nil, errors.WithMessage(err, "invalid sender address")
}
parsedReceiverAddr, err := address.Parse(receiverAddr)
if err != nil {
return nil, errors.WithMessage(err, "invalid receiver address")
}
n, b := big.NewInt(0).SetString(amount, 10)
if !b {
return nil, errors.WithMessage(err, "invalid amount")
}
return &Cheque{
Sender: parsedSenderAddr.Script,
Receiver: parsedReceiverAddr.Script,
UUID: uuid,
Amount: n,
FeeRate: feeRate,
}, nil
}

func (c *Cheque) GenerateIssueChequeTx(client rpc.Client) (*types.Transaction, error) {
systemScripts, err := utils.NewSystemScripts(client)
if err != nil {
return nil, err
}
udtType := &types.Script{
CodeHash: systemScripts.SUDTCell.CellHash,
HashType: systemScripts.SUDTCell.HashType,
Args: common.FromHex(c.UUID),
}

tx := transaction.NewSecp256k1SingleSigTx(systemScripts)
// set sudt and cheque scripts cell deps
tx.CellDeps = append(tx.CellDeps, &types.CellDep{
OutPoint: systemScripts.SUDTCell.OutPoint,
DepType: systemScripts.SUDTCell.DepType,
}, &types.CellDep{
OutPoint: systemScripts.ChequeCell.OutPoint,
DepType: systemScripts.ChequeCell.DepType,
})

// cheque output
chequeCellArgs, err := utils.ChequeCellArgs(c.Sender, c.Receiver)
if err != nil {
return nil, err
}
tx.Outputs = append(tx.Outputs, &types.CellOutput{
Capacity: chequeCellCapacity,
Lock: &types.Script{
CodeHash: systemScripts.ChequeCell.CellHash,
HashType: systemScripts.ChequeCell.HashType,
Args: chequeCellArgs,
},
Type: udtType,
})
tx.OutputsData = append(tx.OutputsData, utils.GenerateSudtAmount(c.Amount))

// ckb change output
tx.Outputs = append(tx.Outputs, &types.CellOutput{
Capacity: 0,
Lock: c.Sender,
})
tx.OutputsData = append(tx.OutputsData, []byte{})

// sudt change output
tx.Outputs = append(tx.Outputs, &types.CellOutput{
Capacity: udtCellCapacity,
Lock: c.Sender,
Type: udtType,
})
tx.OutputsData = append(tx.OutputsData, utils.GenerateSudtAmount(big.NewInt(0)))

// collect udt cells
searchKey := &indexer.SearchKey{
Script: c.Sender,
ScriptType: indexer.ScriptTypeLock,
}
processor := collector.NewUDTLiveCellProcessor(c.Amount)
processor.CkbChangeOutputIndex = &collector.ChangeOutputIndex{Value: 1}
processor.SUDTChangeOutputIndex = &collector.ChangeOutputIndex{Value: 2}
processor.TypeScript = udtType
processor.Tx = tx
processor.FeeRate = c.FeeRate
nCollector := utils.NewLiveCellCollector(client, searchKey, indexer.SearchOrderAsc, indexer.SearchLimit, "", processor)
cells, err := nCollector.Collect()
if err != nil {
return nil, fmt.Errorf("collect cell error: %v", err)
}
totalAmount := cells.Options["totalAmount"].(*big.Int)
if totalAmount.Cmp(c.Amount) < 0 {
return nil, errors.New("insufficient udt balance")
}
c.tx = tx

return tx, nil
}

0 comments on commit d2d09d7

Please sign in to comment.