mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
initial implementation of token holders
This commit is contained in:
96
include/xrpl/ledger/helpers/MPToken.h
Normal file
96
include/xrpl/ledger/helpers/MPToken.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/ledger/helpers/MPTokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHolderBase.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class MPToken : public virtual TokenHolderBase
|
||||
{
|
||||
public:
|
||||
MPToken(ReadView const& view, MPTokenIssuance const& issuance, AccountID const& holder)
|
||||
: ReadOnlySLE(view.read(keylet::mptoken(issuance.getMptID(), holder)), view)
|
||||
, TokenHolderBase(
|
||||
view,
|
||||
view.read(keylet::mptoken(issuance.getMptID(), holder)),
|
||||
issuance,
|
||||
holder)
|
||||
, issuance_(issuance)
|
||||
{
|
||||
}
|
||||
|
||||
MPTokenIssuance const&
|
||||
getIssuance() const
|
||||
{
|
||||
return issuance_;
|
||||
}
|
||||
|
||||
protected:
|
||||
MPTokenIssuance const& issuance_;
|
||||
};
|
||||
|
||||
class WritableMPToken : public virtual WritableTokenHolderBase, public virtual MPToken
|
||||
{
|
||||
public:
|
||||
WritableMPToken(ApplyView& view, WritableMPTokenIssuance& issuance, AccountID const& holder)
|
||||
: ReadOnlySLE(view.peek(keylet::mptoken(issuance.getMptID(), holder)), view)
|
||||
, TokenHolderBase(
|
||||
view,
|
||||
view.peek(keylet::mptoken(issuance.getMptID(), holder)),
|
||||
issuance,
|
||||
holder)
|
||||
, WritableSLE(view.peek(keylet::mptoken(issuance.getMptID(), holder)), view)
|
||||
, WritableTokenHolderBase(
|
||||
view,
|
||||
view.peek(keylet::mptoken(issuance.getMptID(), holder)),
|
||||
issuance,
|
||||
holder)
|
||||
, MPToken(view, issuance, holder)
|
||||
, writableIssuance_(issuance)
|
||||
{
|
||||
}
|
||||
|
||||
// Resolve ambiguity: use writable operator-> for non-const, read-only for const
|
||||
using WritableSLE::operator->;
|
||||
using MPToken::operator->;
|
||||
using WritableSLE::operator*;
|
||||
using MPToken::operator*;
|
||||
|
||||
WritableMPTokenIssuance&
|
||||
getWritableIssuance()
|
||||
{
|
||||
return writableIssuance_;
|
||||
}
|
||||
|
||||
static TER
|
||||
createMPToken(
|
||||
ApplyView& view,
|
||||
WritableMPTokenIssuance& issuance,
|
||||
AccountID const& account,
|
||||
std::uint32_t const flags)
|
||||
{
|
||||
WritableMPToken mptoken(view, issuance, account);
|
||||
|
||||
auto const ownerNode =
|
||||
view.dirInsert(keylet::ownerDir(account), mptoken.key(), describeOwnerDir(account));
|
||||
|
||||
if (!ownerNode)
|
||||
return tecDIR_FULL; // LCOV_EXCL_LINE
|
||||
|
||||
mptoken.newSLE();
|
||||
|
||||
(*mptoken)[sfAccount] = account;
|
||||
(*mptoken)[sfMPTokenIssuanceID] = issuance.getMptID();
|
||||
(*mptoken)[sfFlags] = flags;
|
||||
(*mptoken)[sfOwnerNode] = *ownerNode;
|
||||
|
||||
mptoken.insert();
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
protected:
|
||||
WritableMPTokenIssuance& writableIssuance_;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
146
include/xrpl/ledger/helpers/RippleState.h
Normal file
146
include/xrpl/ledger/helpers/RippleState.h
Normal file
@@ -0,0 +1,146 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/basics/Expected.h>
|
||||
#include <xrpl/ledger/helpers/RippleStateHelpers.h>
|
||||
#include <xrpl/ledger/helpers/TokenHolderBase.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class RippleState : public virtual TokenHolderBase
|
||||
{
|
||||
public:
|
||||
RippleState(ReadView const& view, IOUToken const& token, AccountID const& holder)
|
||||
: ReadOnlySLE(view.read(keylet::line(holder, token.getIssuer(), token.getCurrency())), view)
|
||||
, TokenHolderBase(
|
||||
view,
|
||||
view.read(keylet::line(holder, token.getIssuer(), token.getCurrency())),
|
||||
token,
|
||||
holder)
|
||||
, iouToken_(token)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor with explicit SLE (for when SLE is already available) */
|
||||
RippleState(
|
||||
ReadView const& view,
|
||||
std::shared_ptr<SLE const> sle,
|
||||
IOUToken const& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(sle, view), TokenHolderBase(view, sle, token, holder), iouToken_(token)
|
||||
{
|
||||
}
|
||||
|
||||
IOUToken const&
|
||||
getIOUToken() const
|
||||
{
|
||||
return iouToken_;
|
||||
}
|
||||
|
||||
protected:
|
||||
IOUToken const& iouToken_;
|
||||
};
|
||||
|
||||
class WritableRippleState : public virtual WritableTokenHolderBase, public virtual RippleState
|
||||
{
|
||||
public:
|
||||
WritableRippleState(ApplyView& view, WritableIOUToken& token, AccountID const& holder)
|
||||
: ReadOnlySLE(view.peek(keylet::line(holder, token.getIssuer(), token.getCurrency())), view)
|
||||
, TokenHolderBase(
|
||||
view,
|
||||
view.peek(keylet::line(holder, token.getIssuer(), token.getCurrency())),
|
||||
token,
|
||||
holder)
|
||||
, WritableSLE(view.peek(keylet::line(holder, token.getIssuer(), token.getCurrency())), view)
|
||||
, WritableTokenHolderBase(
|
||||
view,
|
||||
view.peek(keylet::line(holder, token.getIssuer(), token.getCurrency())),
|
||||
token,
|
||||
holder)
|
||||
, RippleState(view, token, holder)
|
||||
, writableIOUToken_(token)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor with explicit SLE (for creation or when SLE is already available) */
|
||||
WritableRippleState(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> sle,
|
||||
WritableIOUToken& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(sle, view)
|
||||
, TokenHolderBase(view, sle, token, holder)
|
||||
, WritableSLE(sle, view)
|
||||
, WritableTokenHolderBase(view, sle, token, holder)
|
||||
, RippleState(view, sle, token, holder)
|
||||
, writableIOUToken_(token)
|
||||
{
|
||||
}
|
||||
|
||||
// Resolve ambiguity: use writable operator-> for non-const, read-only for const
|
||||
using WritableSLE::operator->;
|
||||
using RippleState::operator->;
|
||||
using WritableSLE::operator*;
|
||||
using RippleState::operator*;
|
||||
|
||||
WritableIOUToken&
|
||||
getWritableIOUToken()
|
||||
{
|
||||
return writableIOUToken_;
|
||||
}
|
||||
|
||||
static Expected<std::unique_ptr<WritableRippleState>, TER>
|
||||
createHolding(
|
||||
ApplyView& view,
|
||||
WritableIOUToken& token,
|
||||
AccountID const& accountID,
|
||||
beast::Journal journal)
|
||||
{
|
||||
auto const ter = token.addEmptyHolding(accountID, XRPAmount{0}, journal);
|
||||
if (ter != tesSUCCESS)
|
||||
return Unexpected(ter);
|
||||
return std::make_unique<WritableRippleState>(view, token, accountID);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Trust line operations
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Create a trust line
|
||||
|
||||
This can set an initial balance.
|
||||
*/
|
||||
[[nodiscard]] static TER
|
||||
trustCreate(
|
||||
ApplyView& view,
|
||||
bool const bSrcHigh,
|
||||
AccountID const& uSrcAccountID,
|
||||
AccountID const& uDstAccountID,
|
||||
uint256 const& uIndex, // ripple state entry
|
||||
WritableAccountRoot& wrappedAcct, // the account being set.
|
||||
bool const bAuth, // authorize account.
|
||||
bool const bNoRipple, // others cannot ripple through
|
||||
bool const bFreeze, // funds cannot leave
|
||||
bool bDeepFreeze, // can neither receive nor send funds
|
||||
STAmount const& saBalance, // balance of account being set.
|
||||
// Issuer should be noAccount()
|
||||
STAmount const& saLimit, // limit for account being set.
|
||||
// Issuer should be the account being set.
|
||||
std::uint32_t uQualityIn,
|
||||
std::uint32_t uQualityOut,
|
||||
beast::Journal j);
|
||||
|
||||
[[nodiscard]] static TER
|
||||
trustDelete(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> const& sleRippleState,
|
||||
AccountID const& uLowAccountID,
|
||||
AccountID const& uHighAccountID,
|
||||
beast::Journal j);
|
||||
|
||||
protected:
|
||||
WritableIOUToken& writableIOUToken_;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -216,44 +216,6 @@ creditBalance(
|
||||
Currency const& currency);
|
||||
/** @} */
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Trust line operations
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Create a trust line
|
||||
|
||||
This can set an initial balance.
|
||||
*/
|
||||
[[nodiscard]] TER
|
||||
trustCreate(
|
||||
ApplyView& view,
|
||||
bool const bSrcHigh,
|
||||
AccountID const& uSrcAccountID,
|
||||
AccountID const& uDstAccountID,
|
||||
uint256 const& uIndex, // ripple state entry
|
||||
WritableAccountRoot& wrappedAcct, // the account being set.
|
||||
bool const bAuth, // authorize account.
|
||||
bool const bNoRipple, // others cannot ripple through
|
||||
bool const bFreeze, // funds cannot leave
|
||||
bool bDeepFreeze, // can neither receive nor send funds
|
||||
STAmount const& saBalance, // balance of account being set.
|
||||
// Issuer should be noAccount()
|
||||
STAmount const& saLimit, // limit for account being set.
|
||||
// Issuer should be the account being set.
|
||||
std::uint32_t uQualityIn,
|
||||
std::uint32_t uQualityOut,
|
||||
beast::Journal j);
|
||||
|
||||
[[nodiscard]] TER
|
||||
trustDelete(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> const& sleRippleState,
|
||||
AccountID const& uLowAccountID,
|
||||
AccountID const& uHighAccountID,
|
||||
beast::Journal j);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// IOU issuance/redemption
|
||||
|
||||
155
include/xrpl/ledger/helpers/TokenHolderBase.h
Normal file
155
include/xrpl/ledger/helpers/TokenHolderBase.h
Normal file
@@ -0,0 +1,155 @@
|
||||
#pragma once
|
||||
|
||||
#include <xrpl/ledger/ApplyView.h>
|
||||
#include <xrpl/ledger/helpers/TokenHelpers.h>
|
||||
#include <xrpl/ledger/helpers/WrappedSLEBase.h>
|
||||
#include <xrpl/protocol/STLedgerEntry.h>
|
||||
|
||||
namespace xrpl {
|
||||
|
||||
class TokenHolderBase : public virtual ReadOnlySLE
|
||||
{
|
||||
public:
|
||||
TokenHolderBase(
|
||||
ReadView const& view,
|
||||
std::shared_ptr<SLE const> sle,
|
||||
TokenBase const& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(sle, view), token_(token), holder_(holder), holderAccount_(holder, view)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor with explicit keylet (for when SLE lookup is needed) */
|
||||
TokenHolderBase(
|
||||
ReadView const& view,
|
||||
Keylet const& key,
|
||||
TokenBase const& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(key, view), token_(token), holder_(holder), holderAccount_(holder, view)
|
||||
{
|
||||
}
|
||||
|
||||
TokenHolderBase() = delete;
|
||||
|
||||
AccountID const&
|
||||
getHolder() const
|
||||
{
|
||||
return holder_;
|
||||
}
|
||||
|
||||
TokenBase const&
|
||||
getToken() const
|
||||
{
|
||||
return token_;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
isFrozen(int depth = 0) const
|
||||
{
|
||||
return token_.isFrozen(holder_, depth);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool
|
||||
isDeepFrozen(int depth = 0) const
|
||||
{
|
||||
return token_.isDeepFrozen(holder_, depth);
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
checkFrozen() const
|
||||
{
|
||||
return token_.checkFrozen(holder_);
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
checkDeepFrozen() const
|
||||
{
|
||||
return token_.checkDeepFrozen(holder_);
|
||||
}
|
||||
|
||||
STAmount
|
||||
accountHolds(
|
||||
FreezeHandling zeroIfFrozen,
|
||||
beast::Journal j,
|
||||
SpendableHandling includeFullBalance = shSIMPLE_BALANCE) const
|
||||
{
|
||||
return token_.accountHolds(holder_, zeroIfFrozen, j, includeFullBalance);
|
||||
}
|
||||
|
||||
[[nodiscard]] STAmount
|
||||
accountHolds(
|
||||
FreezeHandling zeroIfFrozen,
|
||||
AuthHandling zeroIfUnauthorized,
|
||||
beast::Journal j,
|
||||
SpendableHandling includeFullBalance = shSIMPLE_BALANCE) const
|
||||
{
|
||||
return token_.accountHolds(
|
||||
holder_, zeroIfFrozen, zeroIfUnauthorized, j, includeFullBalance);
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
requireAuth(AuthType authType = AuthType::Legacy, int depth = 0) const
|
||||
{
|
||||
return token_.requireAuth(holder_, authType, depth);
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
canTransfer(AccountID const& to) const
|
||||
{
|
||||
return token_.canTransfer(holder_, to);
|
||||
}
|
||||
|
||||
[[nodiscard]] TER
|
||||
canTransfer(TokenHolderBase const& to) const
|
||||
{
|
||||
return token_.canTransfer(holder_, to.getHolder());
|
||||
}
|
||||
|
||||
protected:
|
||||
TokenBase const& token_;
|
||||
AccountID const holder_;
|
||||
AccountRoot holderAccount_;
|
||||
};
|
||||
|
||||
class WritableTokenHolderBase : public virtual TokenHolderBase, public virtual WritableSLE
|
||||
{
|
||||
public:
|
||||
WritableTokenHolderBase(
|
||||
ApplyView& view,
|
||||
std::shared_ptr<SLE> sle,
|
||||
WritableTokenBase& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(sle, view)
|
||||
, TokenHolderBase(view, sle, token, holder)
|
||||
, WritableSLE(sle, view)
|
||||
, writableToken_(token)
|
||||
, writableHolderAccount_(holder, view)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor with explicit keylet (for creation or lookup by key) */
|
||||
WritableTokenHolderBase(
|
||||
ApplyView& view,
|
||||
Keylet const& key,
|
||||
WritableTokenBase& token,
|
||||
AccountID const& holder)
|
||||
: ReadOnlySLE(key, view)
|
||||
, TokenHolderBase(view, key, token, holder)
|
||||
, WritableSLE(key, view)
|
||||
, writableToken_(token)
|
||||
, writableHolderAccount_(holder, view)
|
||||
{
|
||||
}
|
||||
|
||||
WritableTokenBase&
|
||||
getWritableToken()
|
||||
{
|
||||
return writableToken_;
|
||||
}
|
||||
|
||||
protected:
|
||||
WritableTokenBase& writableToken_;
|
||||
WritableAccountRoot writableHolderAccount_;
|
||||
};
|
||||
|
||||
} // namespace xrpl
|
||||
@@ -60,6 +60,12 @@ public:
|
||||
return readView_;
|
||||
}
|
||||
|
||||
Keylet const&
|
||||
key() const
|
||||
{
|
||||
return key_;
|
||||
}
|
||||
|
||||
STLedgerEntry const*
|
||||
operator->() const
|
||||
{
|
||||
@@ -80,12 +86,21 @@ protected:
|
||||
|
||||
/** Constructor for read-only context (ReadView) */
|
||||
explicit ReadOnlySLE(std::shared_ptr<SLE const> sle, ReadView const& view)
|
||||
: sle_(std::move(sle)), readView_(view)
|
||||
: sle_(std::move(sle))
|
||||
, readView_(view)
|
||||
, key_(sle_ ? Keylet(sle_->getType(), sle_->key()) : Keylet(ltANY, uint256{}))
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor for read-only context (ReadView) with explicit keylet */
|
||||
explicit ReadOnlySLE(Keylet const& key, ReadView const& view)
|
||||
: sle_(view.read(key)), readView_(view), key_(key)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<SLE const> sle_; // Always valid (const view)
|
||||
ReadView const& readView_; // Always valid
|
||||
Keylet key_; // Keylet for this entry
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -192,8 +207,8 @@ protected:
|
||||
{
|
||||
}
|
||||
|
||||
ApplyView& applyView_; // ApplyView for write contexts (first for init order)
|
||||
Keylet const key_;
|
||||
ApplyView& applyView_; // ApplyView for write contexts (first for init order)
|
||||
Keylet key_; // Keylet for this entry
|
||||
std::shared_ptr<SLE> mutableSle_; // Mutable SLE for write contexts
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user