-
Notifications
You must be signed in to change notification settings - Fork 31
Description
Currently in ccc
, the fee provider for a transaction is tightly coupled with the Signer
. The Signer
is not only responsible
for signing the transaction but also implicitly acts as the fee provider, responsible for completing the transaction's inputs
to cover the fee.
While this design works for many common scenarios, it lacks flexibility. We want to support more complex transaction scenarios,
for instance, where the fee is not paid by the primary Signer
's CKB, but by the extra CKB Capacity
from a cell that contains
an asset (like a Spore or mNFT).
The current architecture makes it difficult to implement such features because the fee-handling logic is encapsulated within the
Transaction
class and is strongly tied to the Signer
's implementation, making it hard to extend.
Describe the solution you'd like
We propose introducing a new abstraction layer: FeePayer
.
FeePayer
is a concept dedicated to providing fees for a transaction and completing it (by populating inputs
/outputs
). Its
core responsibility is to provide the necessary Capacity
to pay the fee and to implement the corresponding transaction
completion logic.
The specific changes are proposed as follows:
-
Define the
FeePayer
Interface
A newFeePayer
interface will be created. It will define the methods required to complete a transaction, establishing a
standard for fee payment logic. The existingSigner
interface will be updated to implement this new interface. -
Refactor the
Transaction
Class for Compatibility
The methods in theTransaction
class responsible for fee calculation and completion (e.g.,complete
) will be updated. The
parameter that currently accepts aSigner
will be changed to accept aFeePayer
.This change is fully backward-compatible and will not break existing code. Since the
Signer
interface will implement
the newFeePayer
interface, any existing code that passes aSigner
to these methods will continue to work seamlessly. This
polymorphic approach avoids the need for new parameters or conditional logic, resulting in a cleaner API. -
Signer
Provides the Default Behavior
By implementing theFeePayer
interface, theSigner
will continue to provide the default fee payment behavior. Its
implementation will be consistent with the current logic, using the CKB from theSigner
's own address to pay the fee. -
Support for Custom
FeePayer
s
With this new interface, developers can easily implement diverse fee payment strategies. For example, aSporeFeePayer
could
be created. Its logic would be to find a specific Spore asset in the transaction and use the surplusCapacity
from that Spore's
cell to cover the transaction fee.
Affected Codebase
packages/core/src/ckb/transaction.ts
: Will need to be refactored so that itscomplete
method accepts aFeePayer
.packages/core/src/signer/index.ts
: TheSigner
interface will be updated to implementFeePayer
.- All call sites for
transaction.complete()
will remain compatible due to polymorphism.
Conclusion
Introducing the FeePayer
abstraction will greatly enhance the flexibility and extensibility of ccc
, allowing us to support a
broader and more innovative range of application scenarios. At the same time, through careful backward-compatible design, it
ensures the stability of the existing API. This is a significant architectural improvement that will contribute to the long-term
growth of the ccc
ecosystem.