diff --git a/convex-core/src/main/cvx/convex/core/metadata.cvx b/convex-core/src/main/cvx/convex/core/metadata.cvx index 3b471d179..3fb089f11 100644 --- a/convex-core/src/main/cvx/convex/core/metadata.cvx +++ b/convex-core/src/main/cvx/convex/core/metadata.cvx @@ -626,6 +626,12 @@ :examples [{:code "(get-in [[1 2] [3 4]] [1 1])"}] :signature [{:params [coll keys]} {:params [coll keys not-found]}]}} + + get-stake + {:doc {:description "Gets the delgated stake for an account on a specific peer." + :errors {:CAST "If the account is not an address."} + :examples [{:code "(get-stake my-peer-key *address*)"}] + :signature [{:params [peer-key addr]}]}} halt {:doc {:description ["Completes execution in the current context with the specified result, or null if not provided. Does not roll back any state changes made." diff --git a/convex-core/src/main/java/convex/core/lang/Core.java b/convex-core/src/main/java/convex/core/lang/Core.java index 1d4ba8d8e..57fc699a2 100644 --- a/convex-core/src/main/java/convex/core/lang/Core.java +++ b/convex-core/src/main/java/convex/core/lang/Core.java @@ -35,6 +35,7 @@ import convex.core.data.List; import convex.core.data.MapEntry; import convex.core.data.Maps; +import convex.core.data.PeerStatus; import convex.core.data.Sets; import convex.core.data.Strings; import convex.core.data.Symbol; @@ -961,7 +962,7 @@ public Context invoke(Context context, ACell[] args) { ABlob b=RT.ensureBlob(args[0]); if (b == null) return context.withCastError(0,args, Types.BLOB); AccountKey accountKey = AccountKey.create(b); - if (accountKey==null) return context.withArgumentError("Account Key for stake must be 32 bytes"); + if (accountKey==null) return context.withArgumentError("Peer Key for stake must be 32 bytes"); CVMLong amount = RT.ensureLong(args[1]); if (amount == null) return context.withCastError(1,args, Types.LONG); @@ -969,6 +970,27 @@ public Context invoke(Context context, ACell[] args) { return context.setDelegatedStake(accountKey, amount.longValue()).consumeJuice(Juice.TRANSFER); } }); + + public static final CoreFn GET_STAKE = reg(new CoreFn<>(Symbols.GET_STAKE,69) { + + @Override + public Context invoke(Context context, ACell[] args) { + if (args.length != 2) return context.withArityError(exactArityMessage(2, args.length)); + + ABlob b=RT.ensureBlob(args[0]); + if (b == null) return context.withCastError(0,args, Types.BLOB); + AccountKey accountKey = AccountKey.create(b); + if (accountKey==null) return context.withArgumentError("Peer Key must be 32 bytes"); + + Address acct = RT.ensureAddress(args[1]); + if (acct == null) return context.withCastError(1,args, Types.ADDRESS); + + PeerStatus ps=context.getState().getPeer(accountKey); + CVMLong stake=(ps==null)?null:CVMLong.create(ps.getDelegatedStake(acct)); + + return context.withResult(Juice.LOOKUP,stake); + } + }); public static final CoreFn CREATE_PEER = reg(new CoreFn<>(Symbols.CREATE_PEER,65) { diff --git a/convex-core/src/main/java/convex/core/lang/Symbols.java b/convex-core/src/main/java/convex/core/lang/Symbols.java index 137cd234e..d5aa54007 100644 --- a/convex-core/src/main/java/convex/core/lang/Symbols.java +++ b/convex-core/src/main/java/convex/core/lang/Symbols.java @@ -108,6 +108,8 @@ public class Symbols { public static final Symbol SET_PEER_DATA = intern("set-peer-data"); public static final Symbol SET_PEER_STAKE = intern("set-peer-stake"); public static final Symbol EVICT_PEER = intern("evict-peer"); + + public static final Symbol GET_STAKE = intern("get-stake");; public static final Symbol CALL = intern("call"); public static final Symbol CALL_STAR = intern("call*"); @@ -346,6 +348,7 @@ public class Symbols { public static final Symbol CREATE = intern("create"); + public static Symbol intern(String s) { AString name=Strings.create(s); diff --git a/convex-core/src/test/java/convex/core/lang/CoreTest.java b/convex-core/src/test/java/convex/core/lang/CoreTest.java index 2acea2573..51b130467 100644 --- a/convex-core/src/test/java/convex/core/lang/CoreTest.java +++ b/convex-core/src/test/java/convex/core/lang/CoreTest.java @@ -3389,6 +3389,22 @@ public void testStake() { assertArityError(step(ctx,"(set-stake my-peer)")); assertArityError(step(ctx,"(set-stake my-peer 1000 :foo)")); } + + @Test + public void testGetStake() { + Context ctx=step(context(),"(def my-peer 0x"+InitTest.FIRST_PEER_KEY.toHexString()+")"); + + // zero for existing peer but no stake + assertCVMEquals(0L,eval(ctx,"(get-stake my-peer *address*)")); + + // null for non-existing peer + assertNull(eval(ctx,"(get-stake 0x1234567812345678123456781234567812345678123456781234567812345678 *address*)")); + + assertCastError(step(ctx,"(get-stake my-peer :foo)")); + + assertArityError(step(ctx,"(get-stake my-peer)")); + assertArityError(step(ctx,"(get-stake my-peer *address* :foo)")); + } @Test public void testSetPeerStake() {