add transfer amount function

This commit is contained in:
sulenn 2021-04-19 09:02:50 +08:00
parent 7f7a4e59cf
commit 2fb72d312c
9 changed files with 512 additions and 35 deletions

View File

@ -1,10 +1,12 @@
package contract
var (
RepoExisted int64 = -1001 // 在合约中创建项目时,项目已存在
BalanceOverFlow int64 = -1002 // 在合约中创建项目时预分配的用户Token累积值大于项目总Token
RepoUnexisted int64 = -1003 // 项目不存在
RepoMaxBalanceOverFlow int64 = -1004 // 当前项目总Token 数超过最大 Token 量
RepoExisted int64 = -1001 // 在合约中创建项目时,项目已存在
BalanceOverFlow int64 = -1002 // 在合约中创建项目时预分配的用户Token累积值大于项目总Token
RepoUnexisted int64 = -1003 // 项目不存在
RepoCurBalanceUpOverFlow int64 = -1004 // 当前项目总Token 数超过最大 Token 量
RepoCurBalanceDownOverFlow int64 = -1005 // 当前项目总 Token 数低于0
UserBblanceNotEnough int64 = -1006 // 用户余额不足
ContractAddress string = "0xE46EE87f19049d5705989f49305b136d0732a0Cf"
ContractAddress string = "0x48e9Ff2BbA3e6C4aCa2F93749F051E1008DD0F45"
)

View File

@ -1 +1 @@
[{"constant":true,"inputs":[{"name":"username","type":"string"},{"name":"token_name","type":"string"}],"name":"selectUserBalance","outputs":[{"name":"","type":"string[]"},{"name":"","type":"string[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"username","type":"string"}],"name":"selectUserAllBalance","outputs":[{"name":"","type":"string[]"},{"name":"","type":"string[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"token_name","type":"string"},{"name":"owner","type":"string"},{"name":"total_supply","type":"uint256"},{"name":"cur_supply","type":"uint256"},{"name":"username","type":"string[]"},{"name":"balance","type":"uint256[]"}],"name":"createRepo","outputs":[{"name":"","type":"int256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"token_name","type":"string"}],"name":"selectRepoBasicInfo","outputs":[{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"int256"},{"name":"","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]
[{"constant":true,"inputs":[{"name":"username","type":"string"},{"name":"token_name","type":"string"}],"name":"selectUserBalance","outputs":[{"name":"","type":"string[]"},{"name":"","type":"string[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"username","type":"string"},{"name":"token_name","type":"string"},{"name":"amount","type":"uint256"}],"name":"minusUserBalance","outputs":[{"name":"","type":"int256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"username","type":"string"},{"name":"token_name","type":"string"},{"name":"amount","type":"uint256"}],"name":"addUserBalance","outputs":[{"name":"","type":"int256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"payer","type":"string"},{"name":"payee","type":"string"},{"name":"token_name","type":"string"},{"name":"amount","type":"uint256"}],"name":"transferUserBalance","outputs":[{"name":"","type":"int256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"username","type":"string"}],"name":"selectUserAllBalance","outputs":[{"name":"","type":"string[]"},{"name":"","type":"string[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"token_name","type":"string"},{"name":"owner","type":"string"},{"name":"total_supply","type":"uint256"},{"name":"cur_supply","type":"uint256"},{"name":"username","type":"string[]"},{"name":"balance","type":"uint256[]"}],"name":"createRepo","outputs":[{"name":"","type":"int256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"token_name","type":"string"}],"name":"selectRepoBasicInfo","outputs":[{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"int256"},{"name":"","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -125,32 +125,202 @@ contract OpenSource {
return (username_list, token_name_list, balance_list);
}
// // add user balance
// function addUserBalance(string memory username, string memory token_name)
// public
// view
// returns (string[] memory, string[] memory, uint256[] memory)
// {
// Table user_table = tableFactory.openTable(USER_TABLE);
// add user balance
function addUserBalance(string memory username, string memory token_name, uint256 amount)
public
returns (int256)
{
// Token数 Token Token
Table repo_table = tableFactory.openTable(REPO_TABLE);
Condition condition = repo_table.newCondition();
Entries entries = repo_table.select(token_name, condition);
if (entries.size() == 0) {
return -1003;
}
Entry entry = entries.get(0);
uint256 cur_supply = entry.getUInt("cur_supply");
cur_supply += amount;
if (cur_supply > entry.getUInt("total_supply")) {
return -1004;
}
// Condition condition = user_table.newCondition();
// condition.EQ("token_name", token_name);
//
Table user_table = tableFactory.openTable(USER_TABLE);
condition = user_table.newCondition();
condition.EQ("token_name", token_name);
entries = user_table.select(username, condition);
// Entries entries = user_table.select(username, condition);
// string[] memory username_list = new string[](uint256(entries.size()));
// string[] memory token_name_list = new string[](uint256(entries.size()));
// uint256[] memory balance_list = new uint256[](uint256(entries.size()));
uint256 user_balance = amount;
int256 count = 0;
if (entries.size() == 0) {
//
entry = user_table.newEntry();
entry.set("user", username);
entry.set("token_name", token_name);
entry.set("balance", user_balance);
count = user_table.insert(username, entry);
if (count != 1) {
return count;
}
} else {
//
entry = entries.get(0);
Entry updated_user_entry = user_table.newEntry();
user_balance += entry.getUInt("balance");
updated_user_entry.set("balance", user_balance);
condition = user_table.newCondition();
condition.EQ("token_name", token_name);
condition.EQ("user", username);
count = user_table.update(username, updated_user_entry, condition);
if (count != 1) {
return count;
}
}
// repo
condition = repo_table.newCondition();
entry = repo_table.newEntry();
entry.set("cur_supply", cur_supply);
condition.EQ("token_name",token_name);
count = repo_table.update(token_name, entry, condition);
return count;
}
// for (int256 i = 0; i < entries.size(); ++i) {
// Entry entry = entries.get(i);
// minus user balance
function minusUserBalance(string memory username, string memory token_name, uint256 amount)
public
returns (int256)
{
// Token数 Token Token
Table repo_table = tableFactory.openTable(REPO_TABLE);
Condition condition = repo_table.newCondition();
Entries entries = repo_table.select(token_name, condition);
if (entries.size() == 0) {
return -1003;
}
Entry entry = entries.get(0);
uint256 cur_supply = entry.getUInt("cur_supply") - amount;
// username_list[uint256(i)] = entry.getString("user");
// token_name_list[uint256(i)] = entry.getString("token_name");
// balance_list[uint256(i)] = entry.getUInt("balance");
// }
//
Table user_table = tableFactory.openTable(USER_TABLE);
condition = user_table.newCondition();
condition.EQ("token_name", token_name);
entries = user_table.select(username, condition);
// return (username_list, token_name_list, balance_list);
// }
uint256 user_balance = amount;
int256 count = 0;
if (entries.size() == 0) {
//
entry = user_table.newEntry();
entry.set("user", username);
entry.set("token_name", token_name);
entry.set("balance", "0");
count = user_table.insert(username, entry);
if (count != 1) {
return count;
}
return -1006;
} else {
//
entry = entries.get(0);
Entry updated_user_entry = user_table.newEntry();
if (entry.getUInt("balance") < amount) {
return -1006;
}
user_balance = entry.getUInt("balance") - amount;
updated_user_entry.set("balance", user_balance);
condition = user_table.newCondition();
condition.EQ("token_name", token_name);
condition.EQ("user", username);
count = user_table.update(username, updated_user_entry, condition);
if (count != 1) {
return count;
}
}
// repo
condition = repo_table.newCondition();
entry = repo_table.newEntry();
entry.set("cur_supply", cur_supply);
condition.EQ("token_name",token_name);
count = repo_table.update(token_name, entry, condition);
return count;
}
// minus user balance
function transferUserBalance(string memory payer, string memory payee, string memory token_name, uint256 amount)
public
returns (int256)
{
//
Table repo_table = tableFactory.openTable(REPO_TABLE);
Condition condition = repo_table.newCondition();
Entries entries = repo_table.select(token_name, condition);
if (entries.size() == 0) {
return -1003;
}
//
Table user_table = tableFactory.openTable(USER_TABLE);
condition = user_table.newCondition();
condition.EQ("token_name", token_name);
entries = user_table.select(payer, condition);
int256 count = 0;
Entry entry = user_table.newEntry();
if (entries.size() == 0) {
//
entry = user_table.newEntry();
entry.set("user", payer);
entry.set("token_name", token_name);
entry.set("balance", "0");
count = user_table.insert(payer, entry);
if (count != 1) {
return count;
}
return -1006;
}
entry = entries.get(0);
Entry updated_entry = user_table.newEntry();
if (entry.getUInt("balance") < amount) {
//
return -1006;
}
//
updated_entry.set("balance", entry.getUInt("balance")-amount);
condition = user_table.newCondition();
condition.EQ("token_name", token_name);
condition.EQ("user", payer);
count = user_table.update(payer, updated_entry, condition);
if (count != 1) {
return count;
}
//
condition = user_table.newCondition();
condition.EQ("token_name", token_name);
entries = user_table.select(payee, condition);
if (entries.size() == 0) {
//
entry = user_table.newEntry();
entry.set("user", payee);
entry.set("token_name", token_name);
entry.set("balance", amount);
count = user_table.insert(payee, entry);
return count;
}
entry = entries.get(0);
updated_entry = user_table.newEntry();
//
updated_entry.set("balance", entry.getUInt("balance")+amount);
condition = user_table.newCondition();
condition.EQ("token_name", token_name);
condition.EQ("user", payee);
count = user_table.update(payee, updated_entry, condition);
return count;
}
function judgeReposExisted(string memory token_name) private returns (bool) {
Table repo_table = tableFactory.openTable(REPO_TABLE);

View File

@ -12,4 +12,7 @@ type FiscoBcos struct {
// user 相关
Username string `json:"username"` // 用户名
Amount uint64 `json:"amount"` // 转账金额
Payer string `json:"payer"` // 转账人
Payee string `json:"payee"` // 收款人
}

View File

@ -8,12 +8,22 @@ type Response struct {
}
var (
ResRepoSucc = &Response{Status: 0, Message: "create repo successfully!"} // create repo successfully!
ResRepoExisted = &Response{Status: 1, Message: "repo existed!"} // repo existed!
ResRepoBalanceOverFlow = &Response{Status: 2, Message: "username balance overflow when create repo!"} // username balance overflow when create repo!
ResRepoUnsucc = &Response{Status: 3, Message: "create repo unsuccessfully!"} // create repo unsuccessfully!
ResRepoSucc = &Response{Status: 0, Message: "create repo successfully!"} // create repo successfully!
ResRepoExisted = &Response{Status: 1, Message: "repo existed!"} // repo existed!
ResRepoNotExisted = &Response{Status: 5, Message: "repo not existed!"} // repo not existed!
ResRepoBalanceOverFlow = &Response{Status: 2, Message: "username balance overflow when create repo!"} // username balance overflow when create repo!
ResRepoUnsucc = &Response{Status: 3, Message: "create repo unsuccessfully!"} // create repo unsuccessfully!
ResRepoCurBalanceUpOverFlow = &Response{Status: 4, Message: "repo current balance up overflow when user adds amount!"} // username balance overflow when create repo!
ResRepoCurBalanceDownOverFlow = &Response{Status: 4, Message: "repo current balance less than 0 when user adds amount!"}
ResUserNotExisted = &Response{Status: 100, Message: "user not exist!"}
ResUserNotExisted = &Response{Status: 100, Message: "user not exist!"}
ResUserAddAmountSucc = &Response{Status: 0, Message: "user adds amount successfully!"}
ResUserMinusAmountSucc = &Response{Status: 0, Message: "user minus amount successfully!"}
ResUserTransferAmountSucc = &Response{Status: 0, Message: "user transfers amount successfully!"}
ResUserAddAmountUnsucc = &Response{Status: 101, Message: "user adds amount unsuccessfully!"}
ResUserMinusAmountUnsucc = &Response{Status: 101, Message: "user minus amount unsuccessfully!"}
ResUserTransferAmountUnsucc = &Response{Status: 101, Message: "user transfers amount unsuccessfully!"}
ResUserBalanceNotEnough = &Response{Status: 102, Message: "user's Balance not enough!"}
TypeTransferErr = &Response{Status: 10, Message: "type transfer error!"} // type transfer error!
StringEmpty = &Response{Status: 11, Message: "string empty!"} // string empty!

View File

@ -30,6 +30,12 @@ func HandleAllRoutes(ctx *macaron.Context, opt api.FiscoBcos, logger *log.Logger
user.SelectUserBalance(ctx, opt.Username, opt.TokenName, logger)
case "query user balance of all repos":
user.SelectUserAllBalance(ctx, opt.Username, logger)
case "add user balance":
user.AddUserAmount(ctx, opt.Username, opt.TokenName, opt.Amount, logger)
case "minus user balance":
user.MinusUserAmount(ctx, opt.Username, opt.TokenName, opt.Amount, logger)
case "transfer amount":
user.TransferAmount(ctx, opt.Payer, opt.Payee, opt.TokenName, opt.Amount, logger)
default:
ctx.JSON(http.StatusNotFound, "the request type not found!")
}

View File

@ -1,12 +1,17 @@
package user
import (
"encoding/hex"
"fmt"
"log"
"math/big"
"net/http"
"strings"
"github.com/FISCO-BCOS/go-sdk/abi"
"github.com/FISCO-BCOS/go-sdk/client"
"github.com/FISCO-BCOS/go-sdk/conf"
"github.com/FISCO-BCOS/go-sdk/core/types"
"github.com/ethereum/go-ethereum/common"
"github.com/sulenn/trustie-fisco-bcos/contract"
"github.com/sulenn/trustie-fisco-bcos/contract/opensource"
@ -125,3 +130,185 @@ func SelectUserBalance(ctx *macaron.Context, username string, tokenName string,
},
})
}
func AddUserAmount(ctx *macaron.Context, username string, tokenName string, amount uint64, logger *log.Logger) {
if username == "" || tokenName == "" {
ctx.JSON(http.StatusOK, api.StringEmpty)
return
}
configs, err := conf.ParseConfigFile("config.toml")
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
config := &configs[0]
client, err := client.Dial(config)
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
// load the contract
contractAddress := common.HexToAddress(contract.ContractAddress)
instance, err := opensource.NewOpenSource(contractAddress, client)
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
openSourceSession := &opensource.OpenSourceSession{Contract: instance, CallOpts: *client.GetCallOpts(), TransactOpts: *client.GetTransactOpts()}
tx, receipt, err := openSourceSession.AddUserBalance(username, tokenName, big.NewInt(int64(amount)))
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
logger.Printf("tx sent: %s\n", tx.Hash().Hex())
code, err := parseOutput(opensource.OpenSourceABI, "addUserBalance", receipt)
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
if code.Int64() > 0 {
logger.Printf("inserted lines: %v\n", code)
ctx.JSON(http.StatusOK, structs.ResUserAddAmountSucc)
return
} else if code.Int64() == contract.RepoUnexisted {
logger.Printf("error code: %v, message: %v\n", code, structs.ResRepoNotExisted)
ctx.JSON(http.StatusOK, structs.ResRepoNotExisted)
return
} else if code.Int64() == contract.RepoCurBalanceUpOverFlow {
logger.Printf("error code: %v, message: %v\n", code, structs.ResRepoCurBalanceUpOverFlow)
ctx.JSON(http.StatusOK, structs.ResRepoCurBalanceUpOverFlow)
return
}
ctx.JSON(http.StatusOK, structs.ResUserAddAmountUnsucc)
}
func MinusUserAmount(ctx *macaron.Context, username string, tokenName string, amount uint64, logger *log.Logger) {
if username == "" || tokenName == "" {
ctx.JSON(http.StatusOK, api.StringEmpty)
return
}
configs, err := conf.ParseConfigFile("config.toml")
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
config := &configs[0]
client, err := client.Dial(config)
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
// load the contract
contractAddress := common.HexToAddress(contract.ContractAddress)
instance, err := opensource.NewOpenSource(contractAddress, client)
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
openSourceSession := &opensource.OpenSourceSession{Contract: instance, CallOpts: *client.GetCallOpts(), TransactOpts: *client.GetTransactOpts()}
tx, receipt, err := openSourceSession.MinusUserBalance(username, tokenName, big.NewInt(int64(amount)))
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
logger.Printf("tx sent: %s\n", tx.Hash().Hex())
code, err := parseOutput(opensource.OpenSourceABI, "minusUserBalance", receipt)
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
if code.Int64() > 0 {
logger.Printf("inserted lines: %v\n", code)
ctx.JSON(http.StatusOK, structs.ResUserMinusAmountSucc)
return
} else if code.Int64() == contract.RepoUnexisted {
logger.Printf("error code: %v, message: %v\n", code, structs.ResRepoNotExisted)
ctx.JSON(http.StatusOK, structs.ResRepoNotExisted)
return
} else if code.Int64() == contract.UserBblanceNotEnough {
logger.Printf("error code: %v, message: %v\n", code, structs.ResUserBalanceNotEnough)
ctx.JSON(http.StatusOK, structs.ResUserBalanceNotEnough)
return
}
ctx.JSON(http.StatusOK, structs.ResUserMinusAmountUnsucc)
}
func TransferAmount(ctx *macaron.Context, payer string, payee string, tokenName string, amount uint64, logger *log.Logger) {
if payer == "" || payee == "" || tokenName == "" {
ctx.JSON(http.StatusOK, api.StringEmpty)
return
}
configs, err := conf.ParseConfigFile("config.toml")
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
config := &configs[0]
client, err := client.Dial(config)
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
// load the contract
contractAddress := common.HexToAddress(contract.ContractAddress)
instance, err := opensource.NewOpenSource(contractAddress, client)
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
openSourceSession := &opensource.OpenSourceSession{Contract: instance, CallOpts: *client.GetCallOpts(), TransactOpts: *client.GetTransactOpts()}
tx, receipt, err := openSourceSession.TransferUserBalance(payer, payee, tokenName, big.NewInt(int64(amount)))
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
logger.Printf("tx sent: %s\n", tx.Hash().Hex())
code, err := parseOutput(opensource.OpenSourceABI, "transferUserBalance", receipt)
if err != nil {
ctx.JSON(http.StatusOK, api.UnknownErr(err))
return
}
if code.Int64() > 0 {
logger.Printf("inserted lines: %v\n", code)
ctx.JSON(http.StatusOK, structs.ResUserTransferAmountSucc)
return
} else if code.Int64() == contract.RepoUnexisted {
logger.Printf("error code: %v, message: %v\n", code, structs.ResRepoNotExisted)
ctx.JSON(http.StatusOK, structs.ResRepoNotExisted)
return
} else if code.Int64() == contract.UserBblanceNotEnough {
logger.Printf("error code: %v, message: %v\n", code, structs.ResUserBalanceNotEnough)
ctx.JSON(http.StatusOK, structs.ResUserBalanceNotEnough)
return
}
ctx.JSON(http.StatusOK, structs.ResUserTransferAmountUnsucc)
}
func parseOutput(abiStr, name string, receipt *types.Receipt) (*big.Int, error) {
parsed, err := abi.JSON(strings.NewReader(abiStr))
if err != nil {
fmt.Printf("parse ABI failed, err: %v", err)
}
var ret *big.Int
b, err := hex.DecodeString(receipt.Output[2:])
if err != nil {
return nil, fmt.Errorf("decode receipt.Output[2:] failed, err: %v", err)
}
err = parsed.Unpack(&ret, name, b)
if err != nil {
return nil, fmt.Errorf("unpack %v failed, err: %v", name, err)
}
return ret, nil
}