github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/internal/ethapi/api_fsn.go (about) 1 package ethapi 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "math/big" 9 "sort" 10 "sync" 11 "time" 12 13 "github.com/FusionFoundation/efsn/accounts" 14 "github.com/FusionFoundation/efsn/common" 15 "github.com/FusionFoundation/efsn/common/hexutil" 16 "github.com/FusionFoundation/efsn/consensus/datong" 17 "github.com/FusionFoundation/efsn/core/rawdb" 18 "github.com/FusionFoundation/efsn/core/state" 19 "github.com/FusionFoundation/efsn/core/types" 20 "github.com/FusionFoundation/efsn/log" 21 "github.com/FusionFoundation/efsn/rlp" 22 "github.com/FusionFoundation/efsn/rpc" 23 ) 24 25 var lastBlockOfBuyTickets = int64(0) 26 var buyTicketOnBlockMap map[common.Address]bool 27 var buyTicketOnBlockMapMutex sync.Mutex 28 29 //--------------------------------------------- PublicFusionAPI ------------------------------------- 30 31 // PublicFusionAPI ss 32 type PublicFusionAPI struct { 33 b Backend 34 } 35 36 // NewPublicFusionAPI ss 37 func NewPublicFusionAPI(b Backend) *PublicFusionAPI { 38 return &PublicFusionAPI{ 39 b: b, 40 } 41 } 42 43 // IsAutoBuyTicket wacom 44 func (s *PublicFusionAPI) IsAutoBuyTicket(ctx context.Context) bool { 45 return common.AutoBuyTicket 46 } 47 48 // GetBalance wacom 49 func (s *PublicFusionAPI) GetBalance(ctx context.Context, assetID common.Hash, address common.Address, blockNr rpc.BlockNumber) (string, error) { 50 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 51 if state == nil || err != nil { 52 return "0", err 53 } 54 b := state.GetBalance(assetID, address) 55 return b.String(), state.Error() 56 } 57 58 // GetAllBalances wacom 59 func (s *PublicFusionAPI) GetAllBalances(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (map[common.Hash]string, error) { 60 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 61 if state == nil || err != nil { 62 return make(map[common.Hash]string), err 63 } 64 b := state.GetAllBalances(address) 65 return b, state.Error() 66 } 67 68 // GetTimeLockBalance wacom 69 func (s *PublicFusionAPI) GetTimeLockBalance(ctx context.Context, assetID common.Hash, address common.Address, blockNr rpc.BlockNumber) (*common.TimeLock, error) { 70 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 71 if state == nil || err != nil { 72 return new(common.TimeLock), err 73 } 74 b := state.GetTimeLockBalance(assetID, address) 75 if state.Error() == nil { 76 b = b.ToDisplay() 77 } 78 return b, state.Error() 79 } 80 81 // GetTimeLockValueByInterval wacom 82 func (s *PublicFusionAPI) GetTimeLockValueByInterval(ctx context.Context, assetID common.Hash, address common.Address, startTime, endTime uint64, blockNr rpc.BlockNumber) (string, error) { 83 state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 84 if state == nil || err != nil { 85 return "0", err 86 } 87 b := state.GetTimeLockBalance(assetID, address) 88 if state.Error() != nil { 89 return "0", state.Error() 90 } 91 if startTime < header.Time.Uint64() { 92 startTime = header.Time.Uint64() 93 } 94 if endTime == 0 { 95 endTime = common.TimeLockForever 96 } 97 return b.GetSpendableValue(startTime, endTime).String(), nil 98 } 99 100 // GetAllTimeLockBalances wacom 101 func (s *PublicFusionAPI) GetAllTimeLockBalances(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (map[common.Hash]*common.TimeLock, error) { 102 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 103 if state == nil || err != nil { 104 return make(map[common.Hash]*common.TimeLock), err 105 } 106 b := state.GetAllTimeLockBalances(address) 107 if state.Error() == nil { 108 for k, v := range b { 109 b[k] = v.ToDisplay() 110 } 111 } 112 return b, state.Error() 113 } 114 115 // GetRawTimeLockBalance wacom 116 func (s *PublicFusionAPI) GetRawTimeLockBalance(ctx context.Context, assetID common.Hash, address common.Address, blockNr rpc.BlockNumber) (*common.TimeLock, error) { 117 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 118 if state == nil || err != nil { 119 return new(common.TimeLock), err 120 } 121 b := state.GetTimeLockBalance(assetID, address) 122 return b, state.Error() 123 } 124 125 // GetAllRawTimeLockBalances wacom 126 func (s *PublicFusionAPI) GetAllRawTimeLockBalances(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (map[common.Hash]*common.TimeLock, error) { 127 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 128 if state == nil || err != nil { 129 return make(map[common.Hash]*common.TimeLock), err 130 } 131 b := state.GetAllTimeLockBalances(address) 132 return b, state.Error() 133 } 134 135 // GetNotation wacom 136 func (s *PublicFusionAPI) GetNotation(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (uint64, error) { 137 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 138 if state == nil || err != nil { 139 return 0, err 140 } 141 b := state.GetNotation(address) 142 return b, state.Error() 143 } 144 145 // GetAddressByNotation wacom 146 func (s *PublicFusionAPI) GetAddressByNotation(ctx context.Context, notation uint64, blockNr rpc.BlockNumber) (common.Address, error) { 147 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 148 if state == nil || err != nil { 149 return common.Address{}, err 150 } 151 address, err := state.GetAddressByNotation(notation) 152 if err != nil { 153 log.Error("GetAddressByNotation: error ", "err", err) 154 return common.Address{}, err 155 } 156 return address, nil 157 } 158 159 // AllNotation wacom 160 func (s *PublicFusionAPI) AllNotation(ctx context.Context, blockNr rpc.BlockNumber) (map[common.Address]uint64, error) { 161 return nil, fmt.Errorf("AllNotations has been depreciated please use api.fusionnetwork.io") 162 } 163 164 // GetAsset wacom 165 func (s *PublicFusionAPI) GetAsset(ctx context.Context, assetID common.Hash, blockNr rpc.BlockNumber) (*common.Asset, error) { 166 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 167 if state == nil || err != nil { 168 return nil, err 169 } 170 if asset, err := state.GetAsset(assetID); err == nil { 171 return &asset, nil 172 } 173 174 // treat assetID as tx hash, deduct asset id from the tx 175 if id := s.getIDByTxHash(ctx, assetID, "AssetID"); id != (common.Hash{}) { 176 if asset, err := state.GetAsset(id); err == nil { 177 return &asset, nil 178 } 179 } 180 return nil, fmt.Errorf("Asset not found") 181 } 182 183 // AllAssets wacom 184 func (s *PublicFusionAPI) AllAssets(ctx context.Context, blockNr rpc.BlockNumber) (map[common.Hash]common.Asset, error) { 185 return nil, fmt.Errorf("AllAssets has been depreciated, use api.fusionnetwork.io") 186 } 187 188 // AllAssetsByAddress wacom 189 func (s *PublicFusionAPI) AllAssetsByAddress(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (map[common.Hash]common.Asset, error) { 190 return nil, fmt.Errorf("AllAssetsByAddress has been depreciated, use api.fusionnetwork.io") 191 } 192 193 // AssetExistForAddress wacom 194 func (s *PublicFusionAPI) AssetExistForAddress(ctx context.Context, assetName string, address common.Address, blockNr rpc.BlockNumber) (common.Hash, error) { 195 return common.Hash{}, fmt.Errorf("AllAssetsByAddress has been depreciated, use api.fusionnetwork.io") 196 } 197 198 func (s *PublicFusionAPI) getAllTickets(ctx context.Context, blockNr rpc.BlockNumber) (common.TicketsDataSlice, error) { 199 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 200 if state == nil || err != nil { 201 return nil, err 202 } 203 tickets, err := state.AllTickets() 204 if err == nil { 205 err = state.Error() 206 } 207 if err != nil { 208 log.Debug("AllTickets:apifsn.go unable to retrieve previous tickets") 209 return nil, fmt.Errorf("AllTickets:apifsn.go unable to retrieve previous tickets. error: %v", err) 210 } 211 return tickets, nil 212 } 213 214 // AllTickets wacom 215 func (s *PublicFusionAPI) AllTickets(ctx context.Context, blockNr rpc.BlockNumber) (map[common.Hash]common.TicketDisplay, error) { 216 tickets, err := s.getAllTickets(ctx, blockNr) 217 if err != nil { 218 return nil, err 219 } 220 return tickets.ToMap(), nil 221 } 222 223 // TotalNumberOfTickets wacom 224 func (s *PublicFusionAPI) TotalNumberOfTickets(ctx context.Context, blockNr rpc.BlockNumber) (int, error) { 225 tickets, err := s.getAllTickets(ctx, blockNr) 226 if err != nil { 227 return 0, err 228 } 229 return int(tickets.NumberOfTickets()), err 230 } 231 232 // TotalNumberOfTicketsByAddress wacom 233 func (s *PublicFusionAPI) TotalNumberOfTicketsByAddress(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (int, error) { 234 tickets, err := s.getAllTickets(ctx, blockNr) 235 if err != nil { 236 return 0, err 237 } 238 return int(tickets.NumberOfTicketsByAddress(address)), err 239 } 240 241 // TicketPrice wacom 242 func (s *PublicFusionAPI) TicketPrice(ctx context.Context, blockNr rpc.BlockNumber) (string, error) { 243 state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 244 if state == nil || err != nil { 245 return "", err 246 } 247 return common.TicketPrice(header.Number).String(), nil 248 } 249 250 // AllTicketsByAddress wacom 251 func (s *PublicFusionAPI) AllTicketsByAddress(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (map[common.Hash]common.TicketDisplay, error) { 252 tickets, err := s.getAllTickets(ctx, blockNr) 253 if err != nil { 254 return nil, err 255 } 256 for _, v := range tickets { 257 if v.Owner == address { 258 return v.ToMap(), nil 259 } 260 } 261 return nil, nil 262 } 263 264 // TxAndReceipt wacom 265 type TxAndReceipt struct { 266 FsnTxInput interface{} `json:"fsnTxInput,omitempty"` 267 Tx *RPCTransaction `json:"tx"` 268 Receipt map[string]interface{} `json:"receipt"` 269 ReceiptFound bool `json:"receiptFound"` 270 } 271 272 // GetTransactionAndReceipt returns the transaction receipt for the given transaction hash. 273 func (s *PublicFusionAPI) GetTransactionAndReceipt(ctx context.Context, hash common.Hash) (TxAndReceipt, error) { 274 // Try to return an already finalized transaction 275 var orgTx *RPCTransaction 276 tx, blockHash, blockNumber, index := rawdb.ReadTransaction(s.b.ChainDb(), hash) 277 if tx != nil { 278 orgTx = newRPCTransaction(tx, blockHash, blockNumber, index) 279 } else if poolTx := s.b.GetPoolTransaction(hash); poolTx != nil { 280 // No finalized transaction, try to retrieve it from the pool 281 orgTx = newRPCPendingTransaction(poolTx) 282 } else { 283 return TxAndReceipt{}, fmt.Errorf("Tx not found") 284 } 285 286 var ( 287 isFsnCall = common.IsFsnCall(orgTx.To) 288 fsnLogTopic string 289 fsnLogData interface{} 290 fsnTxInput interface{} 291 ) 292 293 if isFsnCall { 294 if decoded, err := datong.DecodeTxInput(orgTx.Input); err == nil { 295 fsnTxInput = decoded 296 } 297 } 298 299 txWithoutReceipt := TxAndReceipt{ 300 Tx: orgTx, 301 Receipt: nil, 302 ReceiptFound: false, 303 FsnTxInput: fsnTxInput, 304 } 305 306 if tx == nil { 307 return txWithoutReceipt, nil 308 } 309 receipts, err := s.b.GetReceipts(ctx, blockHash) 310 if err != nil || len(receipts) <= int(index) { 311 return txWithoutReceipt, nil 312 } 313 receipt := receipts[index] 314 315 var signer types.Signer = types.FrontierSigner{} 316 if tx.Protected() { 317 signer = types.NewEIP155Signer(tx.ChainId()) 318 } 319 from, _ := types.Sender(signer, tx) 320 321 if isFsnCall && len(receipt.Logs) > 0 && len(receipt.Logs[0].Topics) > 0 { 322 log := receipt.Logs[0] 323 topic := log.Topics[0] 324 fsnCallFunc := common.FSNCallFunc(topic[common.HashLength-1]) 325 fsnLogTopic = fsnCallFunc.Name() 326 if decodedLog, err := datong.DecodeLogData(log.Data); err == nil { 327 fsnLogData = decodedLog 328 } 329 } 330 331 fields := map[string]interface{}{ 332 "blockHash": blockHash, 333 "blockNumber": hexutil.Uint64(blockNumber), 334 "transactionHash": hash, 335 "transactionIndex": hexutil.Uint64(index), 336 "from": from, 337 "to": tx.To(), 338 "gasUsed": hexutil.Uint64(receipt.GasUsed), 339 "cumulativeGasUsed": hexutil.Uint64(receipt.CumulativeGasUsed), 340 "contractAddress": nil, 341 "logs": receipt.Logs, 342 "logsBloom": receipt.Bloom, 343 } 344 345 if len(fsnLogTopic) != 0 { 346 fields["fsnLogTopic"] = fsnLogTopic 347 fields["fsnLogData"] = fsnLogData 348 } 349 350 // Assign receipt status or post state. 351 if len(receipt.PostState) > 0 { 352 fields["root"] = hexutil.Bytes(receipt.PostState) 353 } else { 354 fields["status"] = hexutil.Uint(receipt.Status) 355 } 356 if receipt.Logs == nil { 357 fields["logs"] = [][]*types.Log{} 358 } 359 // If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation 360 if receipt.ContractAddress != (common.Address{}) { 361 fields["contractAddress"] = receipt.ContractAddress 362 } 363 return TxAndReceipt{ 364 Tx: orgTx, 365 Receipt: fields, 366 ReceiptFound: true, 367 FsnTxInput: fsnTxInput, 368 }, nil 369 } 370 371 // AllInfoForAddress wacom 372 type AllInfoForAddress struct { 373 Tickets map[common.Hash]common.TicketDisplay `json:"tickets"` 374 Balances map[common.Hash]string `json:"balances"` 375 Timelocks map[common.Hash]*common.TimeLock `json:"timeLockBalances"` 376 Notation uint64 `json:"notation"` 377 } 378 379 // AllInfoByAddress wacom 380 func (s *PublicFusionAPI) AllInfoByAddress(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (AllInfoForAddress, error) { 381 allTickets, err := s.AllTicketsByAddress(ctx, address, blockNr) 382 if err != nil { 383 return AllInfoForAddress{}, err 384 } 385 allBalances, err := s.GetAllBalances(ctx, address, blockNr) 386 if err != nil { 387 return AllInfoForAddress{}, err 388 } 389 allTimeLockBalances, err := s.GetAllTimeLockBalances(ctx, address, blockNr) 390 if err != nil { 391 return AllInfoForAddress{}, err 392 } 393 notation, _ := s.GetNotation(ctx, address, blockNr) 394 395 return AllInfoForAddress{ 396 Tickets: allTickets, 397 Balances: allBalances, 398 Timelocks: allTimeLockBalances, 399 Notation: notation, 400 }, nil 401 } 402 403 func (s *PublicFusionAPI) getIDByTxHash(ctx context.Context, hash common.Hash, logKey string) common.Hash { 404 var id common.Hash 405 tx, blockHash, _, index := rawdb.ReadTransaction(s.b.ChainDb(), hash) 406 if tx == nil { 407 return id 408 } 409 // get from receipt's log 410 receipts, err := s.b.GetReceipts(ctx, blockHash) 411 if err == nil && len(receipts) > int(index) { 412 receipt := receipts[index] 413 414 for _, log := range receipt.Logs { 415 if log.Address != common.FSNCallAddress { 416 continue 417 } 418 maps := make(map[string]interface{}) 419 err := json.Unmarshal(log.Data, &maps) 420 if err != nil { 421 continue 422 } 423 424 if _, hasError := maps["Error"]; hasError { 425 continue 426 } 427 428 idstr, idok := maps[logKey].(string) 429 if idok { 430 id = common.HexToHash(idstr) 431 return id 432 } 433 434 } 435 } 436 return id 437 } 438 439 // GetSwap wacom 440 func (s *PublicFusionAPI) GetSwap(ctx context.Context, swapID common.Hash, blockNr rpc.BlockNumber) (*common.Swap, error) { 441 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 442 if state == nil || err != nil { 443 return nil, err 444 } 445 if swap, err := state.GetSwap(swapID); err == nil { 446 return &swap, nil 447 } 448 // treat swapId as tx hash, deduct swap id from the tx 449 if id := s.getIDByTxHash(ctx, swapID, "SwapID"); id != (common.Hash{}) { 450 if swap, err := state.GetSwap(id); err == nil { 451 return &swap, nil 452 } 453 } 454 return nil, fmt.Errorf("Swap not found") 455 } 456 457 // GetMultiSwap wacom 458 func (s *PublicFusionAPI) GetMultiSwap(ctx context.Context, swapID common.Hash, blockNr rpc.BlockNumber) (*common.MultiSwap, error) { 459 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 460 if state == nil || err != nil { 461 return nil, err 462 } 463 if swap, err := state.GetMultiSwap(swapID); err == nil { 464 return &swap, nil 465 } 466 // treat swapId as tx hash, deduct swap id from the tx 467 if id := s.getIDByTxHash(ctx, swapID, "SwapID"); id != (common.Hash{}) { 468 if swap, err := state.GetMultiSwap(id); err == nil { 469 return &swap, nil 470 } 471 } 472 return nil, fmt.Errorf("MultiSwap not found") 473 } 474 475 // AllSwaps wacom 476 func (s *PublicFusionAPI) AllSwaps(ctx context.Context, blockNr rpc.BlockNumber) (map[common.Hash]common.Swap, error) { 477 return nil, fmt.Errorf("AllSwaps has been depreciated please use api.fusionnetwork.io") 478 } 479 480 // AllSwapsByAddress wacom 481 func (s *PublicFusionAPI) AllSwapsByAddress(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (map[common.Hash]common.Swap, error) { 482 return nil, fmt.Errorf("AllSwapsByAddress has been depreciated please use api.fusionnetwork.io") 483 } 484 485 type Summary struct { 486 TotalMiners uint64 `json:"totalMiners"` 487 TotalTickets uint64 `json:"totalTickets"` 488 } 489 type Stake struct { 490 Owner common.Address `json:"owner"` 491 Tickets uint64 `json:"tickets"` 492 } 493 type StakeSlice []Stake 494 495 func (s StakeSlice) Len() int { 496 return len(s) 497 } 498 func (s StakeSlice) Swap(i, j int) { 499 s[i], s[j] = s[j], s[i] 500 } 501 func (s StakeSlice) Less(i, j int) bool { 502 return s[i].Tickets > s[j].Tickets 503 } 504 505 type StakeInfo struct { 506 StakeInfo StakeSlice `json:"stakeInfo"` 507 Summary Summary `json:"summary"` 508 } 509 510 // GetStakeInfo wacom 511 func (s *PublicFusionAPI) GetStakeInfo(ctx context.Context, blockNr rpc.BlockNumber) (StakeInfo, error) { 512 stakeInfo := StakeInfo{ 513 StakeInfo: make(StakeSlice, 0), 514 } 515 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 516 if state == nil || err != nil { 517 return stakeInfo, fmt.Errorf("Only node using `archive' mode can get history states. error: %v", err) 518 } 519 tickets, err := state.AllTickets() 520 if err == nil { 521 err = state.Error() 522 } 523 if err != nil { 524 return stakeInfo, fmt.Errorf("Unable to retrieve all tickets. error: %v", err) 525 } 526 stakeInfo.Summary.TotalTickets, stakeInfo.Summary.TotalMiners = tickets.NumberOfTicketsAndOwners() 527 for _, v := range tickets { 528 stakeInfo.StakeInfo = append(stakeInfo.StakeInfo, Stake{v.Owner, uint64(len(v.Tickets))}) 529 } 530 sort.Stable(stakeInfo.StakeInfo) 531 return stakeInfo, nil 532 } 533 534 // GetBlockAndReward wacom 535 func (s *PublicFusionAPI) GetBlockReward(ctx context.Context, blockNr rpc.BlockNumber) (string, error) { 536 block, err := s.b.BlockByNumber(ctx, blockNr) 537 if err != nil { 538 return "", err 539 } 540 receipts, err := s.b.GetReceipts(ctx, block.Hash()) 541 if err != nil { 542 return "", err 543 } 544 // block creation reward 545 reward := datong.CalcRewards(block.Number()) 546 gasUses := make(map[common.Hash]uint64) 547 for _, receipt := range receipts { 548 gasUses[receipt.TxHash] = receipt.GasUsed 549 } 550 for _, tx := range block.Transactions() { 551 if gasUsed, ok := gasUses[tx.Hash()]; ok { 552 gasReward := new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(gasUsed)) 553 if gasReward.Sign() > 0 { 554 // transaction gas reward 555 reward.Add(reward, gasReward) 556 } 557 } 558 if common.IsFsnCall(tx.To()) { 559 fsnCallParam := &common.FSNCallParam{} 560 rlp.DecodeBytes(tx.Data(), fsnCallParam) 561 feeReward := common.GetFsnCallFee(tx.To(), fsnCallParam.Func) 562 if feeReward.Sign() > 0 { 563 // transaction fee reward 564 reward.Add(reward, feeReward) 565 } 566 } 567 } 568 return reward.String(), nil 569 } 570 571 // GetLatestNotation wacom 572 func (s *PublicFusionAPI) GetLatestNotation(ctx context.Context, blockNr rpc.BlockNumber) (uint64, error) { 573 state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) 574 if state == nil || err != nil { 575 return 0, err 576 } 577 lastCount, err := state.GetNotationCount() 578 if err != nil { 579 return 0, err 580 } 581 latestNotation := state.CalcNotationDisplay(lastCount) 582 return latestNotation, state.Error() 583 } 584 585 type RetreatTicketInfo struct { 586 ID common.Hash 587 Owner common.Address 588 Height uint64 589 StartTime uint64 590 ExpireTime uint64 591 Value *big.Int 592 RetreatType string 593 } 594 595 // GetRetreatTickets wacom 596 func (s *PublicFusionAPI) GetRetreatTickets(ctx context.Context, blockNr rpc.BlockNumber) ([]RetreatTicketInfo, error) { 597 result := make([]RetreatTicketInfo, 0) 598 header, err := s.b.HeaderByNumber(ctx, blockNr) 599 if err != nil || header == nil { 600 return result, fmt.Errorf("get block header failed, err=%v", err) 601 } 602 if header.Number.Sign() == 0 { 603 return result, nil 604 } 605 606 var tickets common.TicketsDataSlice 607 addRetreatTickets := func(ids []common.Hash, retreatType string) (err error) { 608 if len(ids) == 0 { 609 return nil 610 } 611 if tickets == nil { 612 prevNr := rpc.BlockNumber(header.Number.Int64() - 1) 613 tickets, err = s.getAllTickets(ctx, prevNr) 614 if err != nil { 615 return err 616 } 617 } 618 for _, tid := range ids { 619 tikcet, err := tickets.Get(tid) 620 if err != nil { 621 return err 622 } 623 retreat := RetreatTicketInfo{ 624 ID: tid, 625 Owner: tikcet.Owner, 626 Height: tikcet.Height, 627 StartTime: tikcet.StartTime, 628 ExpireTime: tikcet.ExpireTime, 629 Value: tikcet.Value(), 630 RetreatType: retreatType, 631 } 632 result = append(result, retreat) 633 } 634 return nil 635 } 636 637 // add retreat tickets of miss mining 638 snap, _ := datong.NewSnapshotFromHeader(header) 639 if err := addRetreatTickets(snap.Retreat, "miss-mining"); err != nil { 640 return result, err 641 } 642 643 // add punish tickets of double blocking 644 block, err := s.b.BlockByNumber(ctx, blockNr) 645 if err != nil { 646 return result, err 647 } 648 receipts, err := s.b.GetReceipts(ctx, block.Hash()) 649 if err != nil { 650 return result, err 651 } 652 var tids []common.Hash 653 for i, tx := range block.Transactions() { 654 if !common.IsFsnCall(tx.To()) { 655 continue 656 } 657 fsnCallParam := &common.FSNCallParam{} 658 rlp.DecodeBytes(tx.Data(), fsnCallParam) 659 if fsnCallParam.Func != common.ReportIllegalFunc { 660 continue 661 } 662 for _, l := range receipts[i].Logs { 663 punishTickets, _ := datong.DecodePunishTickets(l.Data) 664 tids = append(tids, punishTickets...) 665 } 666 } 667 if err := addRetreatTickets(tids, "double-blocking"); err != nil { 668 return result, err 669 } 670 671 return result, nil 672 } 673 674 //--------------------------------------------- PublicFusionAPI buile send tx args------------------------------------- 675 func FSNCallArgsToSendTxArgs(args common.FSNBaseArgsInterface, funcType common.FSNCallFunc, funcData []byte) (*SendTxArgs, error) { 676 var param = common.FSNCallParam{Func: funcType, Data: funcData} 677 data, err := param.ToBytes() 678 if err != nil { 679 return nil, err 680 } 681 var argsData = hexutil.Bytes(data) 682 baseArgs := args.BaseArgs() 683 return &SendTxArgs{ 684 From: baseArgs.From, 685 To: &common.FSNCallAddress, 686 Gas: baseArgs.Gas, 687 GasPrice: baseArgs.GasPrice, 688 Value: (*hexutil.Big)(big.NewInt(0)), 689 Nonce: baseArgs.Nonce, 690 Data: &argsData, 691 Input: nil, 692 }, nil 693 } 694 695 func (s *PublicFusionAPI) BuildGenNotationSendTxArgs(ctx context.Context, args common.FusionBaseArgs) (*SendTxArgs, error) { 696 state, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 697 if state == nil || err != nil { 698 return nil, err 699 } 700 notation := state.GetNotation(args.From) 701 if notation != 0 { 702 return nil, fmt.Errorf("An address can have only one notation, you already have a mapped notation:%d", notation) 703 } 704 705 return FSNCallArgsToSendTxArgs(&args, common.GenNotationFunc, nil) 706 } 707 708 func (s *PublicFusionAPI) BuildGenAssetSendTxArgs(ctx context.Context, args common.GenAssetArgs) (*SendTxArgs, error) { 709 if err := args.ToParam().Check(common.BigMaxUint64); err != nil { 710 return nil, err 711 } 712 713 funcData, err := args.ToData() 714 if err != nil { 715 return nil, err 716 } 717 return FSNCallArgsToSendTxArgs(&args, common.GenAssetFunc, funcData) 718 } 719 720 func CheckAndSetToAddress(args *common.SendAssetArgs, state *state.StateDB) error { 721 if args.ToUSAN != 0 { 722 address, err := state.GetAddressByNotation(args.ToUSAN) 723 if err != nil { 724 return err 725 } 726 if args.To == (common.Address{}) { 727 args.To = address 728 } else if args.To != address { 729 return fmt.Errorf("'to' and 'toUSAN' conflicts") 730 } 731 } 732 if args.To == (common.Address{}) { 733 return fmt.Errorf("receiver address must be set and not zero address") 734 } 735 return nil 736 } 737 738 func (s *PublicFusionAPI) BuildSendAssetSendTxArgs(ctx context.Context, args common.SendAssetArgs) (*SendTxArgs, error) { 739 state, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 740 if state == nil || err != nil { 741 return nil, err 742 } 743 if err = CheckAndSetToAddress(&args, state); err != nil { 744 return nil, err 745 } 746 if err := args.ToParam().Check(common.BigMaxUint64); err != nil { 747 return nil, err 748 } 749 750 if state.GetBalance(args.AssetID, args.From).Cmp(args.Value.ToInt()) < 0 { 751 return nil, fmt.Errorf("not enough asset") 752 } 753 754 funcData, err := args.ToData() 755 if err != nil { 756 return nil, err 757 } 758 return FSNCallArgsToSendTxArgs(&args, common.SendAssetFunc, funcData) 759 } 760 761 func (s *PublicFusionAPI) BuildAssetToTimeLockSendTxArgs(ctx context.Context, args common.TimeLockArgs) (*SendTxArgs, error) { 762 state, header, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 763 if state == nil || err != nil { 764 return nil, err 765 } 766 if err = CheckAndSetToAddress(&args.SendAssetArgs, state); err != nil { 767 return nil, err 768 } 769 args.Init(common.AssetToTimeLock) 770 if err := args.ToParam().Check(common.BigMaxUint64, header.Time.Uint64()); err != nil { 771 return nil, err 772 } 773 needValue := common.NewTimeLock(&common.TimeLockItem{ 774 StartTime: common.MaxUint64(uint64(*args.StartTime), header.Time.Uint64()), 775 EndTime: uint64(*args.EndTime), 776 Value: args.Value.ToInt(), 777 }) 778 if err := needValue.IsValid(); err != nil { 779 return nil, fmt.Errorf("BuildAssetToTimeLockTx err:%v", err.Error()) 780 } 781 if state.GetBalance(args.AssetID, args.From).Cmp(args.Value.ToInt()) < 0 { 782 return nil, fmt.Errorf("not enough asset") 783 } 784 785 funcData, err := args.ToData() 786 if err != nil { 787 return nil, err 788 } 789 return FSNCallArgsToSendTxArgs(&args, common.TimeLockFunc, funcData) 790 } 791 792 func (s *PublicFusionAPI) BuildTimeLockToTimeLockSendTxArgs(ctx context.Context, args common.TimeLockArgs) (*SendTxArgs, error) { 793 state, header, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 794 if state == nil || err != nil { 795 return nil, err 796 } 797 if err = CheckAndSetToAddress(&args.SendAssetArgs, state); err != nil { 798 return nil, err 799 } 800 args.Init(common.TimeLockToTimeLock) 801 if err := args.ToParam().Check(common.BigMaxUint64, header.Time.Uint64()); err != nil { 802 return nil, err 803 } 804 needValue := common.NewTimeLock(&common.TimeLockItem{ 805 StartTime: common.MaxUint64(uint64(*args.StartTime), header.Time.Uint64()), 806 EndTime: uint64(*args.EndTime), 807 Value: args.Value.ToInt(), 808 }) 809 if err := needValue.IsValid(); err != nil { 810 return nil, fmt.Errorf("BuildTimeLockToTimeLockTx err:%v", err.Error()) 811 } 812 813 if state.GetTimeLockBalance(args.AssetID, args.From).Cmp(needValue) < 0 { 814 return nil, fmt.Errorf("not enough time lock balance") 815 } 816 817 funcData, err := args.ToData() 818 if err != nil { 819 return nil, err 820 } 821 return FSNCallArgsToSendTxArgs(&args, common.TimeLockFunc, funcData) 822 } 823 824 func (s *PublicFusionAPI) BuildTimeLockToAssetSendTxArgs(ctx context.Context, args common.TimeLockArgs) (*SendTxArgs, error) { 825 state, header, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 826 if state == nil || err != nil { 827 return nil, err 828 } 829 if err = CheckAndSetToAddress(&args.SendAssetArgs, state); err != nil { 830 return nil, err 831 } 832 args.Init(common.TimeLockToAsset) 833 *(*uint64)(args.StartTime) = header.Time.Uint64() 834 *(*uint64)(args.EndTime) = common.TimeLockForever 835 if err := args.ToParam().Check(common.BigMaxUint64, header.Time.Uint64()); err != nil { 836 return nil, err 837 } 838 needValue := common.NewTimeLock(&common.TimeLockItem{ 839 StartTime: uint64(*args.StartTime), 840 EndTime: uint64(*args.EndTime), 841 Value: args.Value.ToInt(), 842 }) 843 if err := needValue.IsValid(); err != nil { 844 return nil, fmt.Errorf("BuildTimeLockToAssetTx err:%v", err.Error()) 845 } 846 if state.GetTimeLockBalance(args.AssetID, args.From).Cmp(needValue) < 0 { 847 return nil, fmt.Errorf("not enough time lock balance") 848 } 849 850 funcData, err := args.ToData() 851 if err != nil { 852 return nil, err 853 } 854 return FSNCallArgsToSendTxArgs(&args, common.TimeLockFunc, funcData) 855 } 856 857 func (s *PublicFusionAPI) BuildSendTimeLockSendTxArgs(ctx context.Context, args common.TimeLockArgs) (*SendTxArgs, error) { 858 state, header, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 859 if state == nil || err != nil { 860 return nil, err 861 } 862 if err = CheckAndSetToAddress(&args.SendAssetArgs, state); err != nil { 863 return nil, err 864 } 865 args.Init(common.SmartTransfer) 866 if err := args.ToParam().Check(common.BigMaxUint64, header.Time.Uint64()); err != nil { 867 return nil, err 868 } 869 needValue := common.NewTimeLock(&common.TimeLockItem{ 870 StartTime: common.MaxUint64(uint64(*args.StartTime), header.Time.Uint64()), 871 EndTime: uint64(*args.EndTime), 872 Value: args.Value.ToInt(), 873 }) 874 if err := needValue.IsValid(); err != nil { 875 return nil, fmt.Errorf("BuildSendTimeLockSendTxArgs err:%v", err.Error()) 876 } 877 878 funcData, err := args.ToData() 879 if err != nil { 880 return nil, err 881 } 882 return FSNCallArgsToSendTxArgs(&args, common.TimeLockFunc, funcData) 883 } 884 885 func (s *PublicFusionAPI) BuildBuyTicketSendTxArgs(ctx context.Context, args common.BuyTicketArgs) (*SendTxArgs, error) { 886 state, header, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 887 if state == nil || err != nil { 888 return nil, err 889 } 890 891 if doesTicketPurchaseExistsForBlock(header.Number.Int64(), args.From) { 892 return nil, fmt.Errorf("Purchase of BuyTicket for this block already submitted") 893 } 894 895 parentTime := header.Time.Uint64() 896 args.Init(parentTime) 897 if err := args.ToParam().Check(common.BigMaxUint64, parentTime); err != nil { 898 return nil, err 899 } 900 901 start := uint64(*args.Start) 902 end := uint64(*args.End) 903 value := common.TicketPrice(header.Number) 904 needValue := common.NewTimeLock(&common.TimeLockItem{ 905 StartTime: common.MaxUint64(start, header.Time.Uint64()), 906 EndTime: end, 907 Value: value, 908 }) 909 if err := needValue.IsValid(); err != nil { 910 return nil, fmt.Errorf("BuildBuyTicketTx err:%v", err.Error()) 911 } 912 913 if state.GetTimeLockBalance(common.SystemAssetID, args.From).Cmp(needValue) < 0 { 914 if state.GetBalance(common.SystemAssetID, args.From).Cmp(value) < 0 { 915 return nil, fmt.Errorf("not enough time lock or asset balance") 916 } 917 } 918 919 funcData, err := args.ToData() 920 if err != nil { 921 return nil, err 922 } 923 return FSNCallArgsToSendTxArgs(&args, common.BuyTicketFunc, funcData) 924 } 925 926 func (s *PublicFusionAPI) BuildAssetValueChangeSendTxArgs(ctx context.Context, args common.AssetValueChangeExArgs) (*SendTxArgs, error) { 927 state, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 928 if state == nil || err != nil { 929 return nil, err 930 } 931 932 if err := args.ToParam().Check(common.BigMaxUint64); err != nil { 933 return nil, err 934 } 935 936 asset, assetError := state.GetAsset(args.AssetID) 937 if assetError != nil { 938 return nil, fmt.Errorf("asset not found") 939 } 940 941 if !asset.CanChange { 942 return nil, fmt.Errorf("asset can't inc or dec") 943 } 944 945 if asset.Owner != args.From { 946 return nil, fmt.Errorf("can only be changed by onwer") 947 } 948 949 if asset.Owner != args.To && !args.IsInc { 950 return nil, fmt.Errorf("decrement can only happen to asset's own account") 951 } 952 953 currentBalance := state.GetBalance(args.AssetID, args.To) 954 val := args.Value.ToInt() 955 if !args.IsInc { 956 if currentBalance.Cmp(val) < 0 { 957 return nil, fmt.Errorf("not enough asset") 958 } 959 } 960 961 funcData, err := args.ToData() 962 if err != nil { 963 return nil, err 964 } 965 return FSNCallArgsToSendTxArgs(&args, common.AssetValueChangeFunc, funcData) 966 } 967 968 func (s *PublicFusionAPI) BuildMakeSwapSendTxArgs(ctx context.Context, args common.MakeSwapArgs) (*SendTxArgs, error) { 969 state, header, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 970 if state == nil || err != nil { 971 return nil, err 972 } 973 974 args.Init(header.Time) 975 now := uint64(time.Now().Unix()) 976 if err := args.ToParam().Check(common.BigMaxUint64, now); err != nil { 977 return nil, err 978 } 979 980 total := new(big.Int).Mul(args.MinFromAmount.ToInt(), args.SwapSize) 981 start := uint64(*args.FromStartTime) 982 end := uint64(*args.FromEndTime) 983 984 if args.FromAssetID == common.OwnerUSANAssetID { 985 notation := state.GetNotation(args.From) 986 if notation == 0 { 987 return nil, fmt.Errorf("from address does not have a notation") 988 } 989 } else if start == common.TimeLockNow && end == common.TimeLockForever { 990 if state.GetBalance(args.FromAssetID, args.From).Cmp(total) < 0 { 991 return nil, fmt.Errorf("not enough from asset") 992 } 993 } else { 994 needValue := common.NewTimeLock(&common.TimeLockItem{ 995 StartTime: common.MaxUint64(start, header.Time.Uint64()), 996 EndTime: end, 997 Value: total, 998 }) 999 if err := needValue.IsValid(); err != nil { 1000 return nil, fmt.Errorf("BuildMakeSwapTx from err:%v", err.Error()) 1001 } 1002 if state.GetTimeLockBalance(args.FromAssetID, args.From).Cmp(needValue) < 0 { 1003 if state.GetBalance(args.FromAssetID, args.From).Cmp(total) < 0 { 1004 return nil, fmt.Errorf("not enough time lock or asset balance") 1005 } 1006 } 1007 } 1008 1009 funcData, err := args.ToData() 1010 if err != nil { 1011 return nil, err 1012 } 1013 return FSNCallArgsToSendTxArgs(&args, common.MakeSwapFuncExt, funcData) 1014 } 1015 1016 func (s *PublicFusionAPI) BuildRecallSwapSendTxArgs(ctx context.Context, args common.RecallSwapArgs) (*SendTxArgs, error) { 1017 state, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 1018 if state == nil || err != nil { 1019 return nil, err 1020 } 1021 1022 var swap common.Swap 1023 swap, err = state.GetSwap(args.SwapID) 1024 if err != nil { 1025 return nil, err 1026 } 1027 1028 if err := args.ToParam().Check(common.BigMaxUint64, &swap); err != nil { 1029 return nil, err 1030 } 1031 1032 if swap.Owner != args.From { 1033 return nil, fmt.Errorf("Must be swap onwer can recall") 1034 } 1035 1036 funcData, err := args.ToData() 1037 if err != nil { 1038 return nil, err 1039 } 1040 return FSNCallArgsToSendTxArgs(&args, common.RecallSwapFunc, funcData) 1041 } 1042 1043 func (s *PublicFusionAPI) BuildTakeSwapSendTxArgs(ctx context.Context, args common.TakeSwapArgs) (*SendTxArgs, error) { 1044 state, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 1045 if state == nil || err != nil { 1046 return nil, err 1047 } 1048 var swap common.Swap 1049 swap, err = state.GetSwap(args.SwapID) 1050 if err != nil { 1051 return nil, err 1052 } 1053 1054 now := uint64(time.Now().Unix()) 1055 if err := args.ToParam().Check(common.BigMaxUint64, &swap, now); err != nil { 1056 return nil, err 1057 } 1058 1059 total := new(big.Int).Mul(swap.MinToAmount, args.Size) 1060 start := swap.ToStartTime 1061 end := swap.ToEndTime 1062 1063 if start == common.TimeLockNow && end == common.TimeLockForever { 1064 if state.GetBalance(swap.ToAssetID, args.From).Cmp(total) < 0 { 1065 return nil, fmt.Errorf("not enough from asset") 1066 } 1067 } else { 1068 needValue := common.NewTimeLock(&common.TimeLockItem{ 1069 StartTime: start, 1070 EndTime: end, 1071 Value: total, 1072 }) 1073 if err := needValue.IsValid(); err != nil { 1074 return nil, fmt.Errorf("BuildTakeSwapTx to err:%v", err.Error()) 1075 } 1076 if state.GetTimeLockBalance(swap.ToAssetID, args.From).Cmp(needValue) < 0 { 1077 if state.GetBalance(swap.ToAssetID, args.From).Cmp(total) < 0 { 1078 return nil, fmt.Errorf("not enough time lock or asset balance") 1079 } 1080 } 1081 } 1082 1083 funcData, err := args.ToData() 1084 if err != nil { 1085 return nil, err 1086 } 1087 return FSNCallArgsToSendTxArgs(&args, common.TakeSwapFuncExt, funcData) 1088 } 1089 1090 func (s *PublicFusionAPI) BuildMakeMultiSwapSendTxArgs(ctx context.Context, args common.MakeMultiSwapArgs) (*SendTxArgs, error) { 1091 state, header, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 1092 if state == nil || err != nil { 1093 return nil, err 1094 } 1095 1096 args.Init(header.Time) 1097 now := uint64(time.Now().Unix()) 1098 if err := args.ToParam().Check(common.BigMaxUint64, now); err != nil { 1099 return nil, err 1100 } 1101 1102 ln := len(args.MinFromAmount) 1103 for i := 0; i < ln; i++ { 1104 total := new(big.Int).Mul(args.MinFromAmount[i].ToInt(), args.SwapSize) 1105 start := uint64(*args.FromStartTime[i]) 1106 end := uint64(*args.FromEndTime[i]) 1107 1108 if args.FromAssetID[i] == common.OwnerUSANAssetID { 1109 return nil, fmt.Errorf("USANs cannot be multi-swapped") 1110 } else if start == common.TimeLockNow && end == common.TimeLockForever { 1111 if state.GetBalance(args.FromAssetID[i], args.From).Cmp(total) < 0 { 1112 return nil, fmt.Errorf("not enough from asset") 1113 } 1114 } else { 1115 needValue := common.NewTimeLock(&common.TimeLockItem{ 1116 StartTime: common.MaxUint64(start, header.Time.Uint64()), 1117 EndTime: end, 1118 Value: total, 1119 }) 1120 if err := needValue.IsValid(); err != nil { 1121 return nil, fmt.Errorf("BuildMakeSwapTx from err:%v", err.Error()) 1122 } 1123 if state.GetTimeLockBalance(args.FromAssetID[i], args.From).Cmp(needValue) < 0 { 1124 if state.GetBalance(args.FromAssetID[i], args.From).Cmp(total) < 0 { 1125 return nil, fmt.Errorf("not enough time lock or asset balance") 1126 } 1127 } 1128 } 1129 } 1130 1131 funcData, err := args.ToData() 1132 if err != nil { 1133 return nil, err 1134 } 1135 return FSNCallArgsToSendTxArgs(&args, common.MakeMultiSwapFunc, funcData) 1136 } 1137 1138 func (s *PublicFusionAPI) BuildRecallMultiSwapSendTxArgs(ctx context.Context, args common.RecallMultiSwapArgs) (*SendTxArgs, error) { 1139 state, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 1140 if state == nil || err != nil { 1141 return nil, err 1142 } 1143 1144 var swap common.MultiSwap 1145 swap, err = state.GetMultiSwap(args.SwapID) 1146 if err != nil { 1147 return nil, err 1148 } 1149 1150 if err := args.ToParam().Check(common.BigMaxUint64, &swap); err != nil { 1151 return nil, err 1152 } 1153 1154 if swap.Owner != args.From { 1155 return nil, fmt.Errorf("Must be swap onwer can recall") 1156 } 1157 1158 funcData, err := args.ToData() 1159 if err != nil { 1160 return nil, err 1161 } 1162 return FSNCallArgsToSendTxArgs(&args, common.RecallMultiSwapFunc, funcData) 1163 } 1164 1165 func (s *PublicFusionAPI) BuildTakeMultiSwapSendTxArgs(ctx context.Context, args common.TakeMultiSwapArgs) (*SendTxArgs, error) { 1166 state, _, err := s.b.StateAndHeaderByNumber(ctx, rpc.LatestBlockNumber) 1167 if state == nil || err != nil { 1168 return nil, err 1169 } 1170 var swap common.MultiSwap 1171 swap, err = state.GetMultiSwap(args.SwapID) 1172 if err != nil { 1173 return nil, err 1174 } 1175 1176 now := uint64(time.Now().Unix()) 1177 if err := args.ToParam().Check(common.BigMaxUint64, &swap, now); err != nil { 1178 return nil, err 1179 } 1180 1181 ln := len(swap.MinToAmount) 1182 for i := 0; i < ln; i++ { 1183 total := new(big.Int).Mul(swap.MinToAmount[i], args.Size) 1184 start := swap.ToStartTime[i] 1185 end := swap.ToEndTime[i] 1186 1187 if start == common.TimeLockNow && end == common.TimeLockForever { 1188 if state.GetBalance(swap.ToAssetID[i], args.From).Cmp(total) < 0 { 1189 return nil, fmt.Errorf("not enough from asset") 1190 } 1191 } else { 1192 needValue := common.NewTimeLock(&common.TimeLockItem{ 1193 StartTime: start, 1194 EndTime: end, 1195 Value: total, 1196 }) 1197 if err := needValue.IsValid(); err != nil { 1198 return nil, fmt.Errorf("BuildTakeSwapTx to err:%v", err.Error()) 1199 } 1200 if state.GetTimeLockBalance(swap.ToAssetID[i], args.From).Cmp(needValue) < 0 { 1201 if state.GetBalance(swap.ToAssetID[i], args.From).Cmp(total) < 0 { 1202 return nil, fmt.Errorf("not enough time lock or asset balance") 1203 } 1204 } 1205 } 1206 } 1207 1208 funcData, err := args.ToData() 1209 if err != nil { 1210 return nil, err 1211 } 1212 return FSNCallArgsToSendTxArgs(&args, common.TakeMultiSwapFunc, funcData) 1213 } 1214 1215 //--------------------------------------------- PrivateFusionAPI ------------------------------------- 1216 1217 // PrivateFusionAPI ss 1218 type PrivateFusionAPI struct { 1219 PublicFusionAPI 1220 nonceLock *AddrLocker 1221 papi *PrivateAccountAPI 1222 } 1223 1224 // NewPrivateFusionAPI ss 1225 func NewPrivateFusionAPI(b Backend, nonceLock *AddrLocker, papi *PrivateAccountAPI) *PrivateFusionAPI { 1226 return &PrivateFusionAPI{ 1227 PublicFusionAPI: *NewPublicFusionAPI(b), 1228 nonceLock: nonceLock, 1229 papi: papi, 1230 } 1231 } 1232 1233 // GenNotation ss 1234 func (s *PrivateFusionAPI) GenNotation(ctx context.Context, args common.FusionBaseArgs, passwd string) (common.Hash, error) { 1235 sendArgs, err := s.BuildGenNotationSendTxArgs(ctx, args) 1236 if err != nil { 1237 return common.Hash{}, err 1238 } 1239 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1240 } 1241 1242 // GenAsset ss 1243 func (s *PrivateFusionAPI) GenAsset(ctx context.Context, args common.GenAssetArgs, passwd string) (common.Hash, error) { 1244 sendArgs, err := s.BuildGenAssetSendTxArgs(ctx, args) 1245 if err != nil { 1246 return common.Hash{}, err 1247 } 1248 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1249 } 1250 1251 // SendAsset ss 1252 func (s *PrivateFusionAPI) SendAsset(ctx context.Context, args common.SendAssetArgs, passwd string) (common.Hash, error) { 1253 sendArgs, err := s.BuildSendAssetSendTxArgs(ctx, args) 1254 if err != nil { 1255 return common.Hash{}, err 1256 } 1257 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1258 } 1259 1260 // AssetToTimeLock ss 1261 func (s *PrivateFusionAPI) AssetToTimeLock(ctx context.Context, args common.TimeLockArgs, passwd string) (common.Hash, error) { 1262 sendArgs, err := s.BuildAssetToTimeLockSendTxArgs(ctx, args) 1263 if err != nil { 1264 return common.Hash{}, err 1265 } 1266 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1267 } 1268 1269 // TimeLockToTimeLock ss 1270 func (s *PrivateFusionAPI) TimeLockToTimeLock(ctx context.Context, args common.TimeLockArgs, passwd string) (common.Hash, error) { 1271 sendArgs, err := s.BuildTimeLockToTimeLockSendTxArgs(ctx, args) 1272 if err != nil { 1273 return common.Hash{}, err 1274 } 1275 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1276 } 1277 1278 // TimeLockToAsset ss 1279 func (s *PrivateFusionAPI) TimeLockToAsset(ctx context.Context, args common.TimeLockArgs, passwd string) (common.Hash, error) { 1280 sendArgs, err := s.BuildTimeLockToAssetSendTxArgs(ctx, args) 1281 if err != nil { 1282 return common.Hash{}, err 1283 } 1284 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1285 } 1286 1287 // SendTimeLock ss 1288 func (s *PrivateFusionAPI) SendTimeLock(ctx context.Context, args common.TimeLockArgs, passwd string) (common.Hash, error) { 1289 sendArgs, err := s.BuildSendTimeLockSendTxArgs(ctx, args) 1290 if err != nil { 1291 return common.Hash{}, err 1292 } 1293 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1294 } 1295 1296 /** on our public gateways too many buyTickets are past through 1297 this cache of purchase on block will stop multiple purchase 1298 attempt on a block (which state_transistion also flags). 1299 the goals is to limit the number of buytickets being processed 1300 if it is know that they will fail anyway 1301 */ 1302 func doesTicketPurchaseExistsForBlock(blockNbr int64, from common.Address) bool { 1303 buyTicketOnBlockMapMutex.Lock() 1304 defer buyTicketOnBlockMapMutex.Unlock() 1305 if lastBlockOfBuyTickets == 0 || lastBlockOfBuyTickets != blockNbr { 1306 lastBlockOfBuyTickets = blockNbr 1307 buyTicketOnBlockMap = make(map[common.Address]bool) 1308 } 1309 _, found := buyTicketOnBlockMap[from] 1310 return found 1311 } 1312 1313 // only record on purchase ticket successfully 1314 func addTicketPurchaseForBlock(from common.Address) { 1315 buyTicketOnBlockMapMutex.Lock() 1316 defer buyTicketOnBlockMapMutex.Unlock() 1317 buyTicketOnBlockMap[from] = true 1318 } 1319 1320 // BuyTicket ss 1321 func (s *PrivateFusionAPI) BuyTicket(ctx context.Context, args common.BuyTicketArgs, passwd string) (common.Hash, error) { 1322 sendArgs, err := s.BuildBuyTicketSendTxArgs(ctx, args) 1323 if err != nil { 1324 return common.Hash{}, err 1325 } 1326 hash, err := s.papi.SendTransaction(ctx, *sendArgs, passwd) 1327 if err != nil { 1328 return common.Hash{}, err 1329 } 1330 addTicketPurchaseForBlock(args.From) 1331 return hash, err 1332 } 1333 1334 // IncAsset ss 1335 func (s *PrivateFusionAPI) IncAsset(ctx context.Context, args common.AssetValueChangeExArgs, passwd string) (common.Hash, error) { 1336 args.IsInc = true 1337 sendArgs, err := s.BuildAssetValueChangeSendTxArgs(ctx, args) 1338 if err != nil { 1339 return common.Hash{}, err 1340 } 1341 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1342 } 1343 1344 // DecAsset ss 1345 func (s *PrivateFusionAPI) DecAsset(ctx context.Context, args common.AssetValueChangeExArgs, passwd string) (common.Hash, error) { 1346 args.IsInc = false 1347 sendArgs, err := s.BuildAssetValueChangeSendTxArgs(ctx, args) 1348 if err != nil { 1349 return common.Hash{}, err 1350 } 1351 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1352 } 1353 1354 // MakeSwap ss 1355 func (s *PrivateFusionAPI) MakeSwap(ctx context.Context, args common.MakeSwapArgs, passwd string) (common.Hash, error) { 1356 sendArgs, err := s.BuildMakeSwapSendTxArgs(ctx, args) 1357 if err != nil { 1358 return common.Hash{}, err 1359 } 1360 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1361 } 1362 1363 // RecallSwap ss 1364 func (s *PrivateFusionAPI) RecallSwap(ctx context.Context, args common.RecallSwapArgs, passwd string) (common.Hash, error) { 1365 sendArgs, err := s.BuildRecallSwapSendTxArgs(ctx, args) 1366 if err != nil { 1367 return common.Hash{}, err 1368 } 1369 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1370 } 1371 1372 // TakeSwap ss 1373 func (s *PrivateFusionAPI) TakeSwap(ctx context.Context, args common.TakeSwapArgs, passwd string) (common.Hash, error) { 1374 sendArgs, err := s.BuildTakeSwapSendTxArgs(ctx, args) 1375 if err != nil { 1376 return common.Hash{}, err 1377 } 1378 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1379 } 1380 1381 // MakeMultiSwap ss 1382 func (s *PrivateFusionAPI) MakeMultiSwap(ctx context.Context, args common.MakeMultiSwapArgs, passwd string) (common.Hash, error) { 1383 sendArgs, err := s.BuildMakeMultiSwapSendTxArgs(ctx, args) 1384 if err != nil { 1385 return common.Hash{}, err 1386 } 1387 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1388 } 1389 1390 // RecallMultiSwap ss 1391 func (s *PrivateFusionAPI) RecallMultiSwap(ctx context.Context, args common.RecallMultiSwapArgs, passwd string) (common.Hash, error) { 1392 sendArgs, err := s.BuildRecallMultiSwapSendTxArgs(ctx, args) 1393 if err != nil { 1394 return common.Hash{}, err 1395 } 1396 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1397 } 1398 1399 // TakeMultiSwap ss 1400 func (s *PrivateFusionAPI) TakeMultiSwap(ctx context.Context, args common.TakeMultiSwapArgs, passwd string) (common.Hash, error) { 1401 sendArgs, err := s.BuildTakeMultiSwapSendTxArgs(ctx, args) 1402 if err != nil { 1403 return common.Hash{}, err 1404 } 1405 return s.papi.SendTransaction(ctx, *sendArgs, passwd) 1406 } 1407 1408 //--------------------------------------------- FusionTransactionAPI ------------------------------------- 1409 1410 // FusionTransactionAPI ss 1411 type FusionTransactionAPI struct { 1412 b Backend 1413 pubapi *PublicFusionAPI 1414 nonceLock *AddrLocker 1415 txapi *PublicTransactionPoolAPI 1416 } 1417 1418 var fusionTransactionAPI *FusionTransactionAPI 1419 1420 // NewFusionTransactionAPI ss 1421 func NewFusionTransactionAPI(b Backend, nonceLock *AddrLocker, txapi *PublicTransactionPoolAPI) *FusionTransactionAPI { 1422 fusionTransactionAPI = &FusionTransactionAPI{ 1423 b: b, 1424 pubapi: NewPublicFusionAPI(b), 1425 nonceLock: nonceLock, 1426 txapi: txapi, 1427 } 1428 return fusionTransactionAPI 1429 } 1430 1431 // auto buy ticket 1432 func AutoBuyTicket(enable bool) { 1433 if enable { 1434 _, err := fusionTransactionAPI.b.Coinbase() 1435 if err != nil { 1436 log.Warn("AutoBuyTicket not enabled as no coinbase account exist") 1437 enable = false 1438 } 1439 } 1440 common.AutoBuyTicket = enable 1441 1442 for { 1443 <-common.AutoBuyTicketChan 1444 COMSUMEALL: 1445 for { 1446 select { 1447 case <-common.AutoBuyTicketChan: 1448 default: 1449 break COMSUMEALL 1450 } 1451 } 1452 1453 // prevent auto buy ticket in syncing 1454 if !fusionTransactionAPI.b.IsMining() { 1455 common.DebugInfo("ignore AutoBuyTicket as isMining is false") 1456 continue 1457 } 1458 1459 coinbase, err := fusionTransactionAPI.b.Coinbase() 1460 if err == nil { 1461 fbase := common.FusionBaseArgs{From: coinbase} 1462 args := common.BuyTicketArgs{FusionBaseArgs: fbase} 1463 fusionTransactionAPI.BuyTicket(context.TODO(), args) 1464 } 1465 } 1466 } 1467 1468 // report illegal 1469 func ReportIllegal() { 1470 for { 1471 select { 1472 case content := <-common.ReportIllegalChan: 1473 coinbase, err := fusionTransactionAPI.b.Coinbase() 1474 if err == nil { 1475 args := common.FusionBaseArgs{From: coinbase} 1476 fusionTransactionAPI.ReportIllegal(context.TODO(), args, content) 1477 } 1478 } 1479 } 1480 } 1481 1482 func (s *FusionTransactionAPI) ReportIllegal(ctx context.Context, args common.FusionBaseArgs, content []byte) (common.Hash, error) { 1483 oldtx := s.b.GetPoolTransactionByPredicate(func(tx *types.Transaction) bool { 1484 param := common.FSNCallParam{} 1485 rlp.DecodeBytes(tx.Data(), ¶m) 1486 return param.Func == common.ReportIllegalFunc && bytes.Equal(param.Data, content) 1487 }) 1488 if oldtx != nil { 1489 return common.Hash{}, fmt.Errorf("ReportIllegal: already reported in txpool") 1490 } 1491 sendArgs, err := FSNCallArgsToSendTxArgs(&args, common.ReportIllegalFunc, content) 1492 if err != nil { 1493 return common.Hash{}, err 1494 } 1495 tx, err := s.buildTransaction(ctx, *sendArgs) 1496 if err != nil { 1497 return common.Hash{}, err 1498 } 1499 return s.sendTransaction(ctx, args.From, tx) 1500 } 1501 1502 func (s *FusionTransactionAPI) buildTransaction(ctx context.Context, args SendTxArgs) (*types.Transaction, error) { 1503 if args.Nonce == nil { 1504 s.nonceLock.LockAddr(args.From) 1505 defer s.nonceLock.UnlockAddr(args.From) 1506 } 1507 if err := args.setDefaults(ctx, s.b); err != nil { 1508 return nil, err 1509 } 1510 tx := args.toTransaction() 1511 return tx, nil 1512 } 1513 1514 func (s *FusionTransactionAPI) sendTransaction(ctx context.Context, from common.Address, tx *types.Transaction) (common.Hash, error) { 1515 account := accounts.Account{Address: from} 1516 wallet, err := s.b.AccountManager().Find(account) 1517 if err != nil { 1518 return common.Hash{}, err 1519 } 1520 var chainID *big.Int 1521 if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { 1522 chainID = config.ChainID 1523 } 1524 signed, err := wallet.SignTx(account, tx, chainID) 1525 if err != nil { 1526 return common.Hash{}, err 1527 } 1528 return s.SendRawTransaction(ctx, signed) 1529 } 1530 1531 // SendRawTransaction wacom 1532 func (s *FusionTransactionAPI) SendRawTransaction(ctx context.Context, tx *types.Transaction) (common.Hash, error) { 1533 encodedTx, err := rlp.EncodeToBytes(tx) 1534 if err != nil { 1535 return common.Hash{}, err 1536 } 1537 return s.txapi.SendRawTransaction(ctx, encodedTx) 1538 } 1539 1540 // BuildGenNotationTx ss 1541 func (s *FusionTransactionAPI) BuildGenNotationTx(ctx context.Context, args common.FusionBaseArgs) (*types.Transaction, error) { 1542 sendArgs, err := s.pubapi.BuildGenNotationSendTxArgs(ctx, args) 1543 if err != nil { 1544 return nil, err 1545 } 1546 return s.buildTransaction(ctx, *sendArgs) 1547 } 1548 1549 // GenNotation ss 1550 func (s *FusionTransactionAPI) GenNotation(ctx context.Context, args common.FusionBaseArgs) (common.Hash, error) { 1551 tx, err := s.BuildGenNotationTx(ctx, args) 1552 if err != nil { 1553 return common.Hash{}, err 1554 } 1555 return s.sendTransaction(ctx, args.From, tx) 1556 } 1557 1558 // BuildGenAssetTx ss 1559 func (s *FusionTransactionAPI) BuildGenAssetTx(ctx context.Context, args common.GenAssetArgs) (*types.Transaction, error) { 1560 sendArgs, err := s.pubapi.BuildGenAssetSendTxArgs(ctx, args) 1561 if err != nil { 1562 return nil, err 1563 } 1564 return s.buildTransaction(ctx, *sendArgs) 1565 } 1566 1567 // GenAsset ss 1568 func (s *FusionTransactionAPI) GenAsset(ctx context.Context, args common.GenAssetArgs) (common.Hash, error) { 1569 tx, err := s.BuildGenAssetTx(ctx, args) 1570 if err != nil { 1571 return common.Hash{}, err 1572 } 1573 return s.sendTransaction(ctx, args.From, tx) 1574 } 1575 1576 // BuildSendAssetTx ss 1577 func (s *FusionTransactionAPI) BuildSendAssetTx(ctx context.Context, args common.SendAssetArgs) (*types.Transaction, error) { 1578 sendArgs, err := s.pubapi.BuildSendAssetSendTxArgs(ctx, args) 1579 if err != nil { 1580 return nil, err 1581 } 1582 return s.buildTransaction(ctx, *sendArgs) 1583 } 1584 1585 // SendAsset ss 1586 func (s *FusionTransactionAPI) SendAsset(ctx context.Context, args common.SendAssetArgs) (common.Hash, error) { 1587 tx, err := s.BuildSendAssetTx(ctx, args) 1588 if err != nil { 1589 return common.Hash{}, err 1590 } 1591 return s.sendTransaction(ctx, args.From, tx) 1592 } 1593 1594 // BuildAssetToTimeLockTx ss 1595 func (s *FusionTransactionAPI) BuildAssetToTimeLockTx(ctx context.Context, args common.TimeLockArgs) (*types.Transaction, error) { 1596 sendArgs, err := s.pubapi.BuildAssetToTimeLockSendTxArgs(ctx, args) 1597 if err != nil { 1598 return nil, err 1599 } 1600 return s.buildTransaction(ctx, *sendArgs) 1601 } 1602 1603 // AssetToTimeLock ss 1604 func (s *FusionTransactionAPI) AssetToTimeLock(ctx context.Context, args common.TimeLockArgs) (common.Hash, error) { 1605 tx, err := s.BuildAssetToTimeLockTx(ctx, args) 1606 if err != nil { 1607 return common.Hash{}, err 1608 } 1609 return s.sendTransaction(ctx, args.From, tx) 1610 } 1611 1612 // BuildTimeLockToTimeLockTx ss 1613 func (s *FusionTransactionAPI) BuildTimeLockToTimeLockTx(ctx context.Context, args common.TimeLockArgs) (*types.Transaction, error) { 1614 sendArgs, err := s.pubapi.BuildTimeLockToTimeLockSendTxArgs(ctx, args) 1615 if err != nil { 1616 return nil, err 1617 } 1618 return s.buildTransaction(ctx, *sendArgs) 1619 } 1620 1621 // TimeLockToTimeLock ss 1622 func (s *FusionTransactionAPI) TimeLockToTimeLock(ctx context.Context, args common.TimeLockArgs) (common.Hash, error) { 1623 tx, err := s.BuildTimeLockToTimeLockTx(ctx, args) 1624 if err != nil { 1625 return common.Hash{}, err 1626 } 1627 return s.sendTransaction(ctx, args.From, tx) 1628 } 1629 1630 // BuildTimeLockToAssetTx ss 1631 func (s *FusionTransactionAPI) BuildTimeLockToAssetTx(ctx context.Context, args common.TimeLockArgs) (*types.Transaction, error) { 1632 sendArgs, err := s.pubapi.BuildTimeLockToAssetSendTxArgs(ctx, args) 1633 if err != nil { 1634 return nil, err 1635 } 1636 return s.buildTransaction(ctx, *sendArgs) 1637 } 1638 1639 // TimeLockToAsset ss 1640 func (s *FusionTransactionAPI) TimeLockToAsset(ctx context.Context, args common.TimeLockArgs) (common.Hash, error) { 1641 tx, err := s.BuildTimeLockToAssetTx(ctx, args) 1642 if err != nil { 1643 return common.Hash{}, err 1644 } 1645 return s.sendTransaction(ctx, args.From, tx) 1646 } 1647 1648 // BuildSendTimeLockTx ss 1649 func (s *FusionTransactionAPI) BuildSendTimeLockTx(ctx context.Context, args common.TimeLockArgs) (*types.Transaction, error) { 1650 sendArgs, err := s.pubapi.BuildSendTimeLockSendTxArgs(ctx, args) 1651 if err != nil { 1652 return nil, err 1653 } 1654 return s.buildTransaction(ctx, *sendArgs) 1655 } 1656 1657 // SendTimeLock ss 1658 func (s *FusionTransactionAPI) SendTimeLock(ctx context.Context, args common.TimeLockArgs) (common.Hash, error) { 1659 tx, err := s.BuildSendTimeLockTx(ctx, args) 1660 if err != nil { 1661 return common.Hash{}, err 1662 } 1663 return s.sendTransaction(ctx, args.From, tx) 1664 } 1665 1666 // BuildBuyTicketTx ss 1667 func (s *FusionTransactionAPI) BuildBuyTicketTx(ctx context.Context, args common.BuyTicketArgs) (*types.Transaction, error) { 1668 sendArgs, err := s.pubapi.BuildBuyTicketSendTxArgs(ctx, args) 1669 if err != nil { 1670 return nil, err 1671 } 1672 return s.buildTransaction(ctx, *sendArgs) 1673 } 1674 1675 // BuyTicket ss 1676 func (s *FusionTransactionAPI) BuyTicket(ctx context.Context, args common.BuyTicketArgs) (common.Hash, error) { 1677 tx, err := s.BuildBuyTicketTx(ctx, args) 1678 if err != nil { 1679 return common.Hash{}, err 1680 } 1681 hash, err := s.sendTransaction(ctx, args.From, tx) 1682 if err != nil { 1683 return common.Hash{}, err 1684 } 1685 addTicketPurchaseForBlock(args.From) 1686 return hash, err 1687 } 1688 1689 // BuildIncAssetTx ss 1690 func (s *FusionTransactionAPI) BuildIncAssetTx(ctx context.Context, args common.AssetValueChangeExArgs) (*types.Transaction, error) { 1691 args.IsInc = true 1692 sendArgs, err := s.pubapi.BuildAssetValueChangeSendTxArgs(ctx, args) 1693 if err != nil { 1694 return nil, err 1695 } 1696 return s.buildTransaction(ctx, *sendArgs) 1697 } 1698 1699 // IncAsset ss 1700 func (s *FusionTransactionAPI) IncAsset(ctx context.Context, args common.AssetValueChangeExArgs) (common.Hash, error) { 1701 tx, err := s.BuildIncAssetTx(ctx, args) 1702 if err != nil { 1703 return common.Hash{}, err 1704 } 1705 return s.sendTransaction(ctx, args.From, tx) 1706 } 1707 1708 // BuildDecAssetTx ss 1709 func (s *FusionTransactionAPI) BuildDecAssetTx(ctx context.Context, args common.AssetValueChangeExArgs) (*types.Transaction, error) { 1710 args.IsInc = false 1711 sendArgs, err := s.pubapi.BuildAssetValueChangeSendTxArgs(ctx, args) 1712 if err != nil { 1713 return nil, err 1714 } 1715 return s.buildTransaction(ctx, *sendArgs) 1716 } 1717 1718 // DecAsset ss 1719 func (s *FusionTransactionAPI) DecAsset(ctx context.Context, args common.AssetValueChangeExArgs) (common.Hash, error) { 1720 tx, err := s.BuildDecAssetTx(ctx, args) 1721 if err != nil { 1722 return common.Hash{}, err 1723 } 1724 return s.sendTransaction(ctx, args.From, tx) 1725 } 1726 1727 // BuildMakeSwapTx ss 1728 func (s *FusionTransactionAPI) BuildMakeSwapTx(ctx context.Context, args common.MakeSwapArgs) (*types.Transaction, error) { 1729 sendArgs, err := s.pubapi.BuildMakeSwapSendTxArgs(ctx, args) 1730 if err != nil { 1731 return nil, err 1732 } 1733 return s.buildTransaction(ctx, *sendArgs) 1734 } 1735 1736 // MakeSwap ss 1737 func (s *FusionTransactionAPI) MakeSwap(ctx context.Context, args common.MakeSwapArgs) (common.Hash, error) { 1738 tx, err := s.BuildMakeSwapTx(ctx, args) 1739 if err != nil { 1740 return common.Hash{}, err 1741 } 1742 return s.sendTransaction(ctx, args.From, tx) 1743 } 1744 1745 // BuildRecallSwapTx ss 1746 func (s *FusionTransactionAPI) BuildRecallSwapTx(ctx context.Context, args common.RecallSwapArgs) (*types.Transaction, error) { 1747 sendArgs, err := s.pubapi.BuildRecallSwapSendTxArgs(ctx, args) 1748 if err != nil { 1749 return nil, err 1750 } 1751 return s.buildTransaction(ctx, *sendArgs) 1752 } 1753 1754 // RecallSwap ss 1755 func (s *FusionTransactionAPI) RecallSwap(ctx context.Context, args common.RecallSwapArgs) (common.Hash, error) { 1756 tx, err := s.BuildRecallSwapTx(ctx, args) 1757 if err != nil { 1758 return common.Hash{}, err 1759 } 1760 return s.sendTransaction(ctx, args.From, tx) 1761 } 1762 1763 // BuildTakeSwapTx ss 1764 func (s *FusionTransactionAPI) BuildTakeSwapTx(ctx context.Context, args common.TakeSwapArgs) (*types.Transaction, error) { 1765 sendArgs, err := s.pubapi.BuildTakeSwapSendTxArgs(ctx, args) 1766 if err != nil { 1767 return nil, err 1768 } 1769 return s.buildTransaction(ctx, *sendArgs) 1770 } 1771 1772 // TakeSwap ss 1773 func (s *FusionTransactionAPI) TakeSwap(ctx context.Context, args common.TakeSwapArgs) (common.Hash, error) { 1774 tx, err := s.BuildTakeSwapTx(ctx, args) 1775 if err != nil { 1776 return common.Hash{}, err 1777 } 1778 return s.sendTransaction(ctx, args.From, tx) 1779 } 1780 1781 // MakeMultiSwap wacom 1782 func (s *FusionTransactionAPI) MakeMultiSwap(ctx context.Context, args common.MakeMultiSwapArgs) (common.Hash, error) { 1783 tx, err := s.BuildMakeMultiSwapTx(ctx, args) 1784 if err != nil { 1785 return common.Hash{}, err 1786 } 1787 return s.sendTransaction(ctx, args.From, tx) 1788 } 1789 1790 // BuildMakeMultiSwapTx ss 1791 func (s *FusionTransactionAPI) BuildMakeMultiSwapTx(ctx context.Context, args common.MakeMultiSwapArgs) (*types.Transaction, error) { 1792 sendArgs, err := s.pubapi.BuildMakeMultiSwapSendTxArgs(ctx, args) 1793 if err != nil { 1794 return nil, err 1795 } 1796 return s.buildTransaction(ctx, *sendArgs) 1797 } 1798 1799 // RecallMultiSwap wacom 1800 func (s *FusionTransactionAPI) RecallMultiSwap(ctx context.Context, args common.RecallMultiSwapArgs) (common.Hash, error) { 1801 tx, err := s.BuildRecallMultiSwapTx(ctx, args) 1802 if err != nil { 1803 return common.Hash{}, err 1804 } 1805 return s.sendTransaction(ctx, args.From, tx) 1806 } 1807 1808 // BuildRecallMultiSwapTx ss 1809 func (s *FusionTransactionAPI) BuildRecallMultiSwapTx(ctx context.Context, args common.RecallMultiSwapArgs) (*types.Transaction, error) { 1810 sendArgs, err := s.pubapi.BuildRecallMultiSwapSendTxArgs(ctx, args) 1811 if err != nil { 1812 return nil, err 1813 } 1814 return s.buildTransaction(ctx, *sendArgs) 1815 } 1816 1817 // TakeMultiSwap wacom 1818 func (s *FusionTransactionAPI) TakeMultiSwap(ctx context.Context, args common.TakeMultiSwapArgs) (common.Hash, error) { 1819 tx, err := s.BuildTakeMultiSwapTx(ctx, args) 1820 if err != nil { 1821 return common.Hash{}, err 1822 } 1823 return s.sendTransaction(ctx, args.From, tx) 1824 } 1825 1826 // BuildTakeSwapTx ss 1827 func (s *FusionTransactionAPI) BuildTakeMultiSwapTx(ctx context.Context, args common.TakeMultiSwapArgs) (*types.Transaction, error) { 1828 sendArgs, err := s.pubapi.BuildTakeMultiSwapSendTxArgs(ctx, args) 1829 if err != nil { 1830 return nil, err 1831 } 1832 return s.buildTransaction(ctx, *sendArgs) 1833 }