mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-05-25 10:12:40 +08:00
Merge pull request #1592 from reedrosenbluth/feat/stx-balance
Clarity function 'stx-get-balance' for retrieving balance of STX address
This commit is contained in:
@@ -164,7 +164,7 @@ impl <'a, 'b> ReadOnlyChecker <'a, 'b> {
|
||||
ConsSome | ConsOkay | ConsError | DefaultTo | UnwrapRet | UnwrapErrRet | IsOkay | IsNone | Asserts |
|
||||
Unwrap | UnwrapErr | Match | IsErr | IsSome | TryRet |
|
||||
ToUInt | ToInt | Append | Concat | AsMaxLen |
|
||||
ListCons | GetBlockInfo | TupleGet | Len | Print | AsContract | Begin | FetchVar | GetTokenBalance | GetAssetOwner => {
|
||||
ListCons | GetBlockInfo | TupleGet | Len | Print | AsContract | Begin | FetchVar | GetStxBalance | GetTokenBalance | GetAssetOwner => {
|
||||
self.check_all_read_only(args)
|
||||
},
|
||||
AtBlock => {
|
||||
|
||||
@@ -350,6 +350,14 @@ impl TypedNativeFunction {
|
||||
TypeSignature::UIntType,
|
||||
TypeSignature::IntType],
|
||||
BUFF_32.clone()))),
|
||||
GetStxBalance =>
|
||||
Simple(SimpleNativeFunction(FunctionType::Fixed(FixedFunction {
|
||||
args: vec![
|
||||
FunctionArg::new(TypeSignature::PrincipalType,
|
||||
ClarityName::try_from("owner".to_owned())
|
||||
.expect("FAIL: ClarityName failed to accept default arg name")),
|
||||
],
|
||||
returns: TypeSignature::UIntType }))),
|
||||
StxTransfer =>
|
||||
Simple(SimpleNativeFunction(FunctionType::Fixed(FixedFunction {
|
||||
args: vec![
|
||||
|
||||
@@ -136,8 +136,9 @@ fn test_impl_trait(){
|
||||
#[test]
|
||||
fn test_stx_ops(){
|
||||
let good = ["(stx-burn? u10 'SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G)",
|
||||
"(stx-transfer? u10 tx-sender 'SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G)"];
|
||||
let expected = [ "(response bool uint)", "(response bool uint)" ];
|
||||
"(stx-transfer? u10 tx-sender 'SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G)",
|
||||
"(stx-get-balance 'SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G)"];
|
||||
let expected = [ "(response bool uint)", "(response bool uint)", "uint" ];
|
||||
|
||||
let bad = [
|
||||
"(stx-transfer? u4 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)",
|
||||
@@ -148,6 +149,8 @@ fn test_stx_ops(){
|
||||
"(stx-burn? 4 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)",
|
||||
"(stx-burn? u4 true)",
|
||||
"(stx-burn? u4 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)",
|
||||
"(stx-get-balance true)",
|
||||
"(stx-get-balance 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)"
|
||||
];
|
||||
let bad_expected = [ CheckErrors::IncorrectArgumentCount(3,2),
|
||||
CheckErrors::TypeError(UIntType, IntType),
|
||||
@@ -156,7 +159,9 @@ fn test_stx_ops(){
|
||||
CheckErrors::IncorrectArgumentCount(2,1),
|
||||
CheckErrors::TypeError(UIntType, IntType),
|
||||
CheckErrors::TypeError(PrincipalType, BoolType),
|
||||
CheckErrors::IncorrectArgumentCount(2,3) ];
|
||||
CheckErrors::IncorrectArgumentCount(2,3),
|
||||
CheckErrors::TypeError(PrincipalType, BoolType),
|
||||
CheckErrors::IncorrectArgumentCount(1,2) ];
|
||||
|
||||
for (good_test, expected) in good.iter().zip(expected.iter()) {
|
||||
assert_eq!(expected, &format!("{}", type_check_helper(&good_test).unwrap()));
|
||||
|
||||
@@ -230,6 +230,13 @@ pub const BLOCK_INFO: SimpleCostSpecification = SimpleCostSpecification {
|
||||
read_count: Constant(1),
|
||||
read_length: Constant(1) };
|
||||
|
||||
pub const STX_BALANCE: SimpleCostSpecification = SimpleCostSpecification {
|
||||
write_length: Constant(0),
|
||||
write_count: Constant(0),
|
||||
runtime: Constant(1),
|
||||
read_count: Constant(1),
|
||||
read_length: Constant(1) };
|
||||
|
||||
pub const STX_TRANSFER: SimpleCostSpecification = SimpleCostSpecification {
|
||||
write_length: Constant(1),
|
||||
write_count: Constant(1),
|
||||
|
||||
@@ -1183,6 +1183,19 @@ one of the following error codes:
|
||||
"
|
||||
};
|
||||
|
||||
const STX_GET_BALANCE: SimpleFunctionAPI = SimpleFunctionAPI {
|
||||
name: None,
|
||||
signature: "(stx-get-balance owner)",
|
||||
description: "`stx-get-balance` is used to query the STX balance of the `owner` principal.
|
||||
|
||||
This function returns the STX balance of the `owner` principal. In the event that the `owner`
|
||||
principal isn't materialized, it returns 0.
|
||||
",
|
||||
example: "
|
||||
(stx-get-balance 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR) ;; returns u100
|
||||
"
|
||||
};
|
||||
|
||||
const STX_TRANSFER: SimpleFunctionAPI = SimpleFunctionAPI {
|
||||
name: None,
|
||||
signature: "(stx-transfer? amount sender recipient)",
|
||||
@@ -1293,6 +1306,7 @@ fn make_api_reference(function: &NativeFunctions) -> FunctionAPI {
|
||||
TransferToken => make_for_special(&TOKEN_TRANSFER, name),
|
||||
TransferAsset => make_for_special(&ASSET_TRANSFER, name),
|
||||
AtBlock => make_for_special(&AT_BLOCK, name),
|
||||
GetStxBalance => make_for_simple_native(&STX_GET_BALANCE, &GetStxBalance, name),
|
||||
StxTransfer => make_for_simple_native(&STX_TRANSFER, &StxTransfer, name),
|
||||
StxBurn => make_for_simple_native(&STX_BURN, &StxBurn, name),
|
||||
}
|
||||
|
||||
@@ -20,6 +20,23 @@ macro_rules! clarity_ecode {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn special_stx_balance(args: &[SymbolicExpression],
|
||||
env: &mut Environment,
|
||||
context: &LocalContext) -> Result<Value> {
|
||||
check_argument_count(1, args)?;
|
||||
|
||||
runtime_cost!(cost_functions::STX_BALANCE, env, 0)?;
|
||||
|
||||
let owner = eval(&args[0], env, context)?;
|
||||
|
||||
if let Value::Principal(ref principal) = owner {
|
||||
let balance = env.global_context.database.get_account_stx_balance(&principal);
|
||||
Ok(Value::UInt(balance))
|
||||
} else {
|
||||
Err(CheckErrors::TypeValueError(TypeSignature::PrincipalType, owner).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn special_stx_transfer(args: &[SymbolicExpression],
|
||||
env: &mut Environment,
|
||||
context: &LocalContext) -> Result<Value> {
|
||||
|
||||
@@ -84,6 +84,7 @@ define_named_enum!(NativeFunctions {
|
||||
TransferAsset("nft-transfer?"),
|
||||
MintAsset("nft-mint?"),
|
||||
MintToken("ft-mint?"),
|
||||
GetStxBalance("stx-get-balance"),
|
||||
StxTransfer("stx-transfer?"),
|
||||
StxBurn("stx-burn?"),
|
||||
});
|
||||
@@ -160,6 +161,7 @@ pub fn lookup_reserved_functions(name: &str) -> Option<CallableType> {
|
||||
GetTokenBalance => SpecialFunction("special_get_balance", &assets::special_get_balance),
|
||||
GetAssetOwner => SpecialFunction("special_get_owner", &assets::special_get_owner),
|
||||
AtBlock => SpecialFunction("special_at_block", &database::special_at_block),
|
||||
GetStxBalance => SpecialFunction("special_stx_balance", &assets::special_stx_balance),
|
||||
StxTransfer => SpecialFunction("special_stx_transfer", &assets::special_stx_transfer),
|
||||
StxBurn => SpecialFunction("special_stx_burn", &assets::special_stx_burn),
|
||||
};
|
||||
|
||||
@@ -106,6 +106,7 @@ fn execute_transaction(env: &mut OwnedEnvironment, issuer: Value, contract_ident
|
||||
fn test_native_stx_ops(owned_env: &mut OwnedEnvironment) {
|
||||
let contract = "(define-public (burn-stx (amount uint) (p principal)) (stx-burn? amount p))
|
||||
(define-public (xfer-stx (amount uint) (p principal) (t principal)) (stx-transfer? amount p t))
|
||||
(define-read-only (balance-stx (p principal)) (stx-get-balance p))
|
||||
(define-public (to-contract (amount uint) (p principal))
|
||||
(let ((contract-principal (as-contract tx-sender)))
|
||||
(stx-transfer? amount p contract-principal)))
|
||||
@@ -210,6 +211,25 @@ fn test_native_stx_ops(owned_env: &mut OwnedEnvironment) {
|
||||
&symbols_from_values(vec![Value::UInt(2), p2.clone(), p1.clone()])).unwrap_err(),
|
||||
RuntimeErrorType::ArithmeticOverflow.into());
|
||||
|
||||
// test 6: check balance
|
||||
|
||||
let (result, _asset_map, _events) = execute_transaction(
|
||||
owned_env, p2.clone(), &token_contract_id, "balance-stx",
|
||||
&symbols_from_values(vec![p2.clone()])).unwrap();
|
||||
|
||||
assert_eq!(result, Value::UInt(1000));
|
||||
|
||||
// test 7: check balance is 0 for nonexistent principal
|
||||
|
||||
let sp_data = PrincipalData::parse_standard_principal("SPZG6BAY4JVR9RNAB1HY92B7Q208ZYY4HZEA9PX5").unwrap();
|
||||
let nonexistent_principal = Value::Principal(PrincipalData::Standard(sp_data));
|
||||
|
||||
let (result, _asset_map, _events) = execute_transaction(
|
||||
owned_env, p2.clone(), &token_contract_id, "balance-stx",
|
||||
&symbols_from_values(vec![nonexistent_principal.clone()])).unwrap();
|
||||
|
||||
assert_eq!(result, Value::UInt(0));
|
||||
|
||||
// now, let's actually do a couple transfers/burns and check the asset maps.
|
||||
|
||||
let (result, asset_map, _events) = execute_transaction(
|
||||
@@ -254,6 +274,18 @@ fn test_native_stx_ops(owned_env: &mut OwnedEnvironment) {
|
||||
.get(&AssetIdentifier::STX()).unwrap(),
|
||||
&AssetMapEntry::STX(10));
|
||||
|
||||
// now check contract balance with stx-get-balance
|
||||
|
||||
let cp_data = PrincipalData::parse_qualified_contract_principal("SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR.tokens").unwrap();
|
||||
let contract_principal = Value::Principal(cp_data);
|
||||
|
||||
let (result, _asset_map, _events) = execute_transaction(
|
||||
owned_env, p2.clone(), &token_contract_id, "balance-stx",
|
||||
&symbols_from_values(vec![contract_principal.clone()])).unwrap();
|
||||
|
||||
assert_eq!(result, Value::UInt(10));
|
||||
|
||||
|
||||
// now let's do a contract -> user transfer
|
||||
|
||||
let (result, asset_map, _events) = execute_transaction(
|
||||
|
||||
@@ -87,6 +87,7 @@ pub fn get_simple_test(function: &NativeFunctions) -> &'static str {
|
||||
TransferToken => "(ft-transfer? ft-foo u1 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)",
|
||||
TransferAsset => "(nft-transfer? nft-foo 1 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)",
|
||||
AtBlock => "(at-block 0x0000000000000000000000000000000000000000000000000000000000000000 1)",
|
||||
GetStxBalance => "(stx-get-balance 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)",
|
||||
StxTransfer => "(stx-transfer? u1 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)",
|
||||
StxBurn => "(stx-burn? u1 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR)",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user