feat: Add Credential support

This commit is contained in:
Mayukha Vadari
2026-07-06 17:21:46 -04:00
parent 7868d6ed79
commit 5bce58357f
4 changed files with 147 additions and 9 deletions

View File

@@ -5,6 +5,7 @@
#include <test/jtx/amount.h>
#include <test/jtx/batch.h>
#include <test/jtx/check.h>
#include <test/jtx/credentials.h>
#include <test/jtx/delegate.h>
#include <test/jtx/deposit.h>
#include <test/jtx/did.h>
@@ -2782,6 +2783,127 @@ public:
}
}
void
testCredential(bool cosigning)
{
testcase("Credential");
using namespace test::jtx;
Account const alice("alice");
Account const bob("bob");
Account const sponsor("sponsor");
Account const sponsor2("sponsor2");
auto const credType = std::string("test");
// Self-issued credential: alice creates for herself, sponsor covers reserve
{
Env env{*this, testableAmendments()};
env.fund(XRP(1000000), alice, bob, sponsor, sponsor2);
env.close();
testEachSponsorship(
env,
cosigning,
sponsor,
alice,
1,
1,
tecINSUFFICIENT_RESERVE,
[&](Env& env, auto const& submit) {
submit(credentials::create(alice, alice, credType));
});
auto const credKeylet = credentials::keylet(alice, alice, credType);
BEAST_EXPECT(env.le(credKeylet)->getAccountID(sfSponsor) == sponsor.id());
BEAST_EXPECT(ownerCount(env, alice) == 1);
BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 1);
BEAST_EXPECT(sponsoringOwnerCount(env, alice) == 0);
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 1);
// Transfer sponsor
if (cosigning)
{
env(sponsor::transfer(alice, tfSponsorshipReassign, credKeylet.key),
sponsor::As(sponsor2, spfSponsorReserve),
Sig(sfSponsorSignature, sponsor2));
env.close();
}
else
{
env(sponsor::set_reserve(sponsor2, 0, 1), sponsor::SponseeAcc(alice));
env.close();
env(sponsor::transfer(alice, tfSponsorshipReassign, credKeylet.key),
sponsor::As(sponsor2, spfSponsorReserve));
env.close();
}
BEAST_EXPECT(ownerCount(env, alice) == 1);
BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 1);
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 0);
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor2) == 1);
BEAST_EXPECT(env.le(credKeylet)->getAccountID(sfSponsor) == sponsor2.id());
// CredentialDelete
env(credentials::deleteCred(alice, alice, alice, credType));
env.close();
BEAST_EXPECT(ownerCount(env, alice) == 0);
BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 0);
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 0);
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor2) == 0);
}
// Issuer creates for subject; sponsorship transfers to subject on accept
{
Env env{*this, testableAmendments()};
env.fund(XRP(1000000), alice, bob, sponsor);
env.close();
// alice (issuer) creates credential for bob (subject), sponsor covers alice's reserve
testEachSponsorship(
env,
cosigning,
sponsor,
alice,
1,
1,
tecINSUFFICIENT_RESERVE,
[&](Env& env, auto const& submit) {
submit(credentials::create(bob, alice, credType));
});
// Before accept: alice (issuer) owns the credential
auto const credKeylet = credentials::keylet(bob, alice, credType);
BEAST_EXPECT(env.le(credKeylet)->getAccountID(sfSponsor) == sponsor.id());
BEAST_EXPECT(ownerCount(env, alice) == 1);
BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 1);
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 1);
BEAST_EXPECT(ownerCount(env, bob) == 0);
BEAST_EXPECT(sponsoredOwnerCount(env, bob) == 0);
// Bob accepts: ownership and sponsorship transfer to bob
env(credentials::accept(bob, alice, credType));
env.close();
BEAST_EXPECT(ownerCount(env, alice) == 0);
BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 0);
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 1); // still sponsoring, but now bob
BEAST_EXPECT(ownerCount(env, bob) == 1);
BEAST_EXPECT(sponsoredOwnerCount(env, bob) == 1);
// CredentialDelete by subject
env(credentials::deleteCred(bob, bob, alice, credType));
env.close();
BEAST_EXPECT(ownerCount(env, alice) == 0);
BEAST_EXPECT(ownerCount(env, bob) == 0);
BEAST_EXPECT(sponsoredOwnerCount(env, alice) == 0);
BEAST_EXPECT(sponsoredOwnerCount(env, bob) == 0);
BEAST_EXPECT(sponsoringOwnerCount(env, sponsor) == 0);
}
}
void
testDID(bool cosigning)
{
@@ -4411,6 +4533,7 @@ public:
testRequireFlag();
testSponsorReserveSimple(cosigning);
testCheck(cosigning);
testCredential(cosigning);
testDelegate(cosigning);
testDepositPreauth(cosigning);
testEscrow(cosigning);