diff --git a/internal/README.md b/internal/README.md
new file mode 100644
index 000000000..c59af7f2a
--- /dev/null
+++ b/internal/README.md
@@ -0,0 +1,1191 @@
+
+
+# ledger
+
+```go
+import "github.com/formancehq/ledger/internal"
+```
+
+### Core
+
+## Index
+
+- [Constants](<#constants>)
+- [Variables](<#variables>)
+- [func ComputeIdempotencyHash\(inputs any\) string](<#ComputeIdempotencyHash>)
+- [type Account](<#Account>)
+- [type AccountMetadata](<#AccountMetadata>)
+- [type AccountsVolumes](<#AccountsVolumes>)
+- [type BalancesByAssets](<#BalancesByAssets>)
+- [type BalancesByAssetsByAccounts](<#BalancesByAssetsByAccounts>)
+- [type Configuration](<#Configuration>)
+ - [func NewDefaultConfiguration\(\) Configuration](<#NewDefaultConfiguration>)
+ - [func \(c \*Configuration\) SetDefaults\(\)](<#Configuration.SetDefaults>)
+ - [func \(c \*Configuration\) Validate\(\) error](<#Configuration.Validate>)
+- [type CreatedTransaction](<#CreatedTransaction>)
+ - [func \(p CreatedTransaction\) Type\(\) LogType](<#CreatedTransaction.Type>)
+- [type DeletedMetadata](<#DeletedMetadata>)
+ - [func \(s DeletedMetadata\) Type\(\) LogType](<#DeletedMetadata.Type>)
+ - [func \(s \*DeletedMetadata\) UnmarshalJSON\(data \[\]byte\) error](<#DeletedMetadata.UnmarshalJSON>)
+- [type ErrInvalidBucketName](<#ErrInvalidBucketName>)
+ - [func \(e ErrInvalidBucketName\) Error\(\) string](<#ErrInvalidBucketName.Error>)
+ - [func \(e ErrInvalidBucketName\) Is\(err error\) bool](<#ErrInvalidBucketName.Is>)
+- [type ErrInvalidLedgerName](<#ErrInvalidLedgerName>)
+ - [func \(e ErrInvalidLedgerName\) Error\(\) string](<#ErrInvalidLedgerName.Error>)
+ - [func \(e ErrInvalidLedgerName\) Is\(err error\) bool](<#ErrInvalidLedgerName.Is>)
+- [type FeatureSet](<#FeatureSet>)
+ - [func \(f FeatureSet\) With\(feature, value string\) FeatureSet](<#FeatureSet.With>)
+- [type Ledger](<#Ledger>)
+ - [func MustNewWithDefault\(name string\) Ledger](<#MustNewWithDefault>)
+ - [func New\(name string, configuration Configuration\) \(\*Ledger, error\)](<#New>)
+ - [func NewWithDefaults\(name string\) \(\*Ledger, error\)](<#NewWithDefaults>)
+ - [func \(l Ledger\) HasFeature\(feature, value string\) bool](<#Ledger.HasFeature>)
+ - [func \(l Ledger\) WithMetadata\(m metadata.Metadata\) Ledger](<#Ledger.WithMetadata>)
+- [type Log](<#Log>)
+ - [func NewLog\(payload LogPayload\) Log](<#NewLog>)
+ - [func \(l Log\) ChainLog\(previous \*Log\) Log](<#Log.ChainLog>)
+ - [func \(l \*Log\) ComputeHash\(previous \*Log\)](<#Log.ComputeHash>)
+ - [func \(l \*Log\) UnmarshalJSON\(data \[\]byte\) error](<#Log.UnmarshalJSON>)
+ - [func \(l Log\) WithIdempotencyKey\(key string\) Log](<#Log.WithIdempotencyKey>)
+- [type LogPayload](<#LogPayload>)
+ - [func HydrateLog\(\_type LogType, data \[\]byte\) \(LogPayload, error\)](<#HydrateLog>)
+- [type LogType](<#LogType>)
+ - [func LogTypeFromString\(logType string\) LogType](<#LogTypeFromString>)
+ - [func \(lt LogType\) MarshalJSON\(\) \(\[\]byte, error\)](<#LogType.MarshalJSON>)
+ - [func \(lt \*LogType\) Scan\(src interface\{\}\) error](<#LogType.Scan>)
+ - [func \(l LogType\) String\(\) string](<#LogType.String>)
+ - [func \(lt \*LogType\) UnmarshalJSON\(data \[\]byte\) error](<#LogType.UnmarshalJSON>)
+ - [func \(lt LogType\) Value\(\) \(driver.Value, error\)](<#LogType.Value>)
+- [type Move](<#Move>)
+- [type Moves](<#Moves>)
+ - [func \(m Moves\) ComputePostCommitEffectiveVolumes\(\) PostCommitVolumes](<#Moves.ComputePostCommitEffectiveVolumes>)
+- [type PostCommitVolumes](<#PostCommitVolumes>)
+ - [func \(a PostCommitVolumes\) AddInput\(account, asset string, input \*big.Int\)](<#PostCommitVolumes.AddInput>)
+ - [func \(a PostCommitVolumes\) AddOutput\(account, asset string, output \*big.Int\)](<#PostCommitVolumes.AddOutput>)
+ - [func \(a PostCommitVolumes\) Copy\(\) PostCommitVolumes](<#PostCommitVolumes.Copy>)
+ - [func \(a PostCommitVolumes\) Merge\(volumes PostCommitVolumes\) PostCommitVolumes](<#PostCommitVolumes.Merge>)
+- [type Posting](<#Posting>)
+ - [func NewPosting\(source string, destination string, asset string, amount \*big.Int\) Posting](<#NewPosting>)
+ - [func \(p Posting\) GetDestination\(\) string](<#Posting.GetDestination>)
+ - [func \(p Posting\) GetSource\(\) string](<#Posting.GetSource>)
+- [type Postings](<#Postings>)
+ - [func \(p Postings\) Reverse\(\) Postings](<#Postings.Reverse>)
+ - [func \(p Postings\) Validate\(\) \(int, error\)](<#Postings.Validate>)
+- [type RevertedTransaction](<#RevertedTransaction>)
+ - [func \(r RevertedTransaction\) Type\(\) LogType](<#RevertedTransaction.Type>)
+- [type SavedMetadata](<#SavedMetadata>)
+ - [func \(s SavedMetadata\) Type\(\) LogType](<#SavedMetadata.Type>)
+ - [func \(s \*SavedMetadata\) UnmarshalJSON\(data \[\]byte\) error](<#SavedMetadata.UnmarshalJSON>)
+- [type Transaction](<#Transaction>)
+ - [func NewTransaction\(\) Transaction](<#NewTransaction>)
+ - [func \(tx Transaction\) InvolvedAccountAndAssets\(\) map\[string\]\[\]string](<#Transaction.InvolvedAccountAndAssets>)
+ - [func \(tx Transaction\) InvolvedAccounts\(\) \[\]string](<#Transaction.InvolvedAccounts>)
+ - [func \(tx Transaction\) IsReverted\(\) bool](<#Transaction.IsReverted>)
+ - [func \(Transaction\) JSONSchemaExtend\(schema \*jsonschema.Schema\)](<#Transaction.JSONSchemaExtend>)
+ - [func \(tx Transaction\) MarshalJSON\(\) \(\[\]byte, error\)](<#Transaction.MarshalJSON>)
+ - [func \(tx Transaction\) Reverse\(\) Transaction](<#Transaction.Reverse>)
+ - [func \(tx Transaction\) VolumeUpdates\(\) \[\]AccountsVolumes](<#Transaction.VolumeUpdates>)
+ - [func \(tx Transaction\) WithInsertedAt\(date time.Time\) Transaction](<#Transaction.WithInsertedAt>)
+ - [func \(tx Transaction\) WithMetadata\(m metadata.Metadata\) Transaction](<#Transaction.WithMetadata>)
+ - [func \(tx Transaction\) WithPostCommitEffectiveVolumes\(volumes PostCommitVolumes\) Transaction](<#Transaction.WithPostCommitEffectiveVolumes>)
+ - [func \(tx Transaction\) WithPostings\(postings ...Posting\) Transaction](<#Transaction.WithPostings>)
+ - [func \(tx Transaction\) WithReference\(ref string\) Transaction](<#Transaction.WithReference>)
+ - [func \(tx Transaction\) WithRevertedAt\(timestamp time.Time\) Transaction](<#Transaction.WithRevertedAt>)
+ - [func \(tx Transaction\) WithTimestamp\(ts time.Time\) Transaction](<#Transaction.WithTimestamp>)
+- [type TransactionData](<#TransactionData>)
+ - [func NewTransactionData\(\) TransactionData](<#NewTransactionData>)
+ - [func \(data TransactionData\) WithPostings\(postings ...Posting\) TransactionData](<#TransactionData.WithPostings>)
+- [type Transactions](<#Transactions>)
+- [type Volumes](<#Volumes>)
+ - [func NewEmptyVolumes\(\) Volumes](<#NewEmptyVolumes>)
+ - [func NewVolumesInt64\(input, output int64\) Volumes](<#NewVolumesInt64>)
+ - [func \(v Volumes\) Balance\(\) \*big.Int](<#Volumes.Balance>)
+ - [func \(v Volumes\) Copy\(\) Volumes](<#Volumes.Copy>)
+ - [func \(Volumes\) JSONSchemaExtend\(schema \*jsonschema.Schema\)](<#Volumes.JSONSchemaExtend>)
+ - [func \(v Volumes\) MarshalJSON\(\) \(\[\]byte, error\)](<#Volumes.MarshalJSON>)
+ - [func \(v Volumes\) WithInput\(input \*big.Int\) Volumes](<#Volumes.WithInput>)
+ - [func \(v Volumes\) WithOutput\(output \*big.Int\) Volumes](<#Volumes.WithOutput>)
+- [type VolumesByAssets](<#VolumesByAssets>)
+ - [func \(v VolumesByAssets\) Balances\(\) BalancesByAssets](<#VolumesByAssets.Balances>)
+- [type VolumesWithBalance](<#VolumesWithBalance>)
+- [type VolumesWithBalanceByAssetByAccount](<#VolumesWithBalanceByAssetByAccount>)
+- [type VolumesWithBalanceByAssets](<#VolumesWithBalanceByAssets>)
+
+
+## Constants
+
+
+
+```go
+const (
+ FeatureMovesHistory = "MOVES_HISTORY"
+ // todo: depends on FeatureMovesHistory (dependency should be checked)
+ FeatureMovesHistoryPostCommitEffectiveVolumes = "MOVES_HISTORY_POST_COMMIT_EFFECTIVE_VOLUMES"
+ FeatureHashLogs = "HASH_LOGS"
+ FeatureAccountMetadataHistory = "ACCOUNT_METADATA_HISTORY"
+ FeatureTransactionMetadataHistory = "TRANSACTION_METADATA_HISTORY"
+ FeatureIndexAddressSegments = "INDEX_ADDRESS_SEGMENTS"
+ FeatureIndexTransactionAccounts = "INDEX_TRANSACTION_ACCOUNTS"
+
+ DefaultBucket = "_default"
+)
+```
+
+
+
+```go
+const (
+ MetaTargetTypeAccount = "ACCOUNT"
+ MetaTargetTypeTransaction = "TRANSACTION"
+)
+```
+
+
+
+```go
+const (
+ WORLD = "world"
+)
+```
+
+## Variables
+
+
+
+```go
+var (
+ DefaultFeatures = FeatureSet{
+ FeatureMovesHistory: "ON",
+ FeatureMovesHistoryPostCommitEffectiveVolumes: "SYNC",
+ FeatureHashLogs: "SYNC",
+ FeatureAccountMetadataHistory: "SYNC",
+ FeatureTransactionMetadataHistory: "SYNC",
+ FeatureIndexAddressSegments: "ON",
+ FeatureIndexTransactionAccounts: "ON",
+ }
+ MinimalFeatureSet = FeatureSet{
+ FeatureMovesHistory: "OFF",
+ FeatureMovesHistoryPostCommitEffectiveVolumes: "DISABLED",
+ FeatureHashLogs: "DISABLED",
+ FeatureAccountMetadataHistory: "DISABLED",
+ FeatureTransactionMetadataHistory: "DISABLED",
+ FeatureIndexAddressSegments: "OFF",
+ FeatureIndexTransactionAccounts: "OFF",
+ }
+ FeatureConfigurations = map[string][]string{
+ FeatureMovesHistory: {"ON", "OFF"},
+ FeatureMovesHistoryPostCommitEffectiveVolumes: {"SYNC", "DISABLED"},
+ FeatureHashLogs: {"SYNC", "DISABLED"},
+ FeatureAccountMetadataHistory: {"SYNC", "DISABLED"},
+ FeatureTransactionMetadataHistory: {"SYNC", "DISABLED"},
+ FeatureIndexAddressSegments: {"ON", "OFF"},
+ FeatureIndexTransactionAccounts: {"ON", "OFF"},
+ }
+)
+```
+
+
+
+```go
+var Zero = big.NewInt(0)
+```
+
+
+## func [ComputeIdempotencyHash]()
+
+```go
+func ComputeIdempotencyHash(inputs any) string
+```
+
+
+
+
+## type [Account]()
+
+
+
+```go
+type Account struct {
+ bun.BaseModel `bun:"table:accounts"`
+
+ Address string `json:"address" bun:"address"`
+ Metadata metadata.Metadata `json:"metadata" bun:"metadata,type:jsonb"`
+ FirstUsage time.Time `json:"-" bun:"first_usage"`
+ InsertionDate time.Time `json:"_" bun:"insertion_date"`
+ UpdatedAt time.Time `json:"-" bun:"updated_at"`
+ Volumes VolumesByAssets `json:"volumes,omitempty" bun:"pcv,scanonly"`
+ EffectiveVolumes VolumesByAssets `json:"effectiveVolumes,omitempty" bun:"pcev,scanonly"`
+}
+```
+
+
+## type [AccountMetadata]()
+
+
+
+```go
+type AccountMetadata map[string]metadata.Metadata
+```
+
+
+## type [AccountsVolumes]()
+
+
+
+```go
+type AccountsVolumes struct {
+ bun.BaseModel `bun:"accounts_volumes"`
+
+ Account string `bun:"accounts_address,type:varchar"`
+ Asset string `bun:"asset,type:varchar"`
+ Input *big.Int `bun:"input,type:numeric"`
+ Output *big.Int `bun:"output,type:numeric"`
+}
+```
+
+
+## type [BalancesByAssets]()
+
+
+
+```go
+type BalancesByAssets map[string]*big.Int
+```
+
+
+## type [BalancesByAssetsByAccounts]()
+
+
+
+```go
+type BalancesByAssetsByAccounts map[string]BalancesByAssets
+```
+
+
+## type [Configuration]()
+
+
+
+```go
+type Configuration struct {
+ Bucket string `json:"bucket" bun:"bucket,type:varchar(255)"`
+ Metadata metadata.Metadata `json:"metadata" bun:"metadata,type:jsonb"`
+ Features map[string]string `json:"features" bun:"features,type:jsonb"`
+}
+```
+
+
+### func [NewDefaultConfiguration]()
+
+```go
+func NewDefaultConfiguration() Configuration
+```
+
+
+
+
+### func \(\*Configuration\) [SetDefaults]()
+
+```go
+func (c *Configuration) SetDefaults()
+```
+
+
+
+
+### func \(\*Configuration\) [Validate]()
+
+```go
+func (c *Configuration) Validate() error
+```
+
+
+
+
+## type [CreatedTransaction]()
+
+
+
+```go
+type CreatedTransaction struct {
+ Transaction Transaction `json:"transaction"`
+ AccountMetadata AccountMetadata `json:"accountMetadata"`
+}
+```
+
+
+### func \(CreatedTransaction\) [Type]()
+
+```go
+func (p CreatedTransaction) Type() LogType
+```
+
+
+
+
+## type [DeletedMetadata]()
+
+
+
+```go
+type DeletedMetadata struct {
+ TargetType string `json:"targetType"`
+ TargetID any `json:"targetId"`
+ Key string `json:"key"`
+}
+```
+
+
+### func \(DeletedMetadata\) [Type]()
+
+```go
+func (s DeletedMetadata) Type() LogType
+```
+
+
+
+
+### func \(\*DeletedMetadata\) [UnmarshalJSON]()
+
+```go
+func (s *DeletedMetadata) UnmarshalJSON(data []byte) error
+```
+
+
+
+
+## type [ErrInvalidBucketName]()
+
+
+
+```go
+type ErrInvalidBucketName struct {
+ // contains filtered or unexported fields
+}
+```
+
+
+### func \(ErrInvalidBucketName\) [Error]()
+
+```go
+func (e ErrInvalidBucketName) Error() string
+```
+
+
+
+
+### func \(ErrInvalidBucketName\) [Is]()
+
+```go
+func (e ErrInvalidBucketName) Is(err error) bool
+```
+
+
+
+
+## type [ErrInvalidLedgerName]()
+
+
+
+```go
+type ErrInvalidLedgerName struct {
+ // contains filtered or unexported fields
+}
+```
+
+
+### func \(ErrInvalidLedgerName\) [Error]()
+
+```go
+func (e ErrInvalidLedgerName) Error() string
+```
+
+
+
+
+### func \(ErrInvalidLedgerName\) [Is]()
+
+```go
+func (e ErrInvalidLedgerName) Is(err error) bool
+```
+
+
+
+
+## type [FeatureSet]()
+
+
+
+```go
+type FeatureSet map[string]string
+```
+
+
+### func \(FeatureSet\) [With]()
+
+```go
+func (f FeatureSet) With(feature, value string) FeatureSet
+```
+
+
+
+
+## type [Ledger]()
+
+
+
+```go
+type Ledger struct {
+ bun.BaseModel `bun:"_system.ledgers,alias:ledgers"`
+
+ Configuration
+ ID int `json:"id" bun:"id,type:int,scanonly"`
+ Name string `json:"name" bun:"name,type:varchar(255),pk"`
+ AddedAt time.Time `json:"addedAt" bun:"addedat,type:timestamp"`
+}
+```
+
+
+### func [MustNewWithDefault]()
+
+```go
+func MustNewWithDefault(name string) Ledger
+```
+
+
+
+
+### func [New]()
+
+```go
+func New(name string, configuration Configuration) (*Ledger, error)
+```
+
+
+
+
+### func [NewWithDefaults]()
+
+```go
+func NewWithDefaults(name string) (*Ledger, error)
+```
+
+
+
+
+### func \(Ledger\) [HasFeature]()
+
+```go
+func (l Ledger) HasFeature(feature, value string) bool
+```
+
+
+
+
+### func \(Ledger\) [WithMetadata]()
+
+```go
+func (l Ledger) WithMetadata(m metadata.Metadata) Ledger
+```
+
+
+
+
+## type [Log]()
+
+Log represents atomic actions made on the ledger.
+
+```go
+type Log struct {
+ bun.BaseModel `bun:"table:logs,alias:logs"`
+
+ Type LogType `json:"type" bun:"type,type:log_type"`
+ Data LogPayload `json:"data" bun:"data,type:jsonb"`
+ Date time.Time `json:"date" bun:"date,type:timestamptz"`
+ IdempotencyKey string `json:"idempotencyKey" bun:"idempotency_key,type:varchar(256),unique,nullzero"`
+ // IdempotencyHash is a signature used when using IdempotencyKey.
+ // It allows to check if the usage of IdempotencyKey match inputs given on the first idempotency key usage.
+ IdempotencyHash string `json:"idempotencyHash" bun:"idempotency_hash,unique,nullzero"`
+ ID int `json:"id" bun:"id,unique,type:numeric"`
+ Hash []byte `json:"hash" bun:"hash,type:bytea"`
+}
+```
+
+
+### func [NewLog]()
+
+```go
+func NewLog(payload LogPayload) Log
+```
+
+
+
+
+### func \(Log\) [ChainLog]()
+
+```go
+func (l Log) ChainLog(previous *Log) Log
+```
+
+
+
+
+### func \(\*Log\) [ComputeHash]()
+
+```go
+func (l *Log) ComputeHash(previous *Log)
+```
+
+
+
+
+### func \(\*Log\) [UnmarshalJSON]()
+
+```go
+func (l *Log) UnmarshalJSON(data []byte) error
+```
+
+
+
+
+### func \(Log\) [WithIdempotencyKey]()
+
+```go
+func (l Log) WithIdempotencyKey(key string) Log
+```
+
+
+
+
+## type [LogPayload]()
+
+
+
+```go
+type LogPayload interface {
+ Type() LogType
+}
+```
+
+
+### func [HydrateLog]()
+
+```go
+func HydrateLog(_type LogType, data []byte) (LogPayload, error)
+```
+
+
+
+
+## type [LogType]()
+
+
+
+```go
+type LogType int16
+```
+
+
+
+```go
+const (
+ SetMetadataLogType LogType = iota // "SET_METADATA"
+ NewLogType // "NEW_TRANSACTION"
+ RevertedTransactionLogType // "REVERTED_TRANSACTION"
+ DeleteMetadataLogType
+)
+```
+
+
+### func [LogTypeFromString]()
+
+```go
+func LogTypeFromString(logType string) LogType
+```
+
+
+
+
+### func \(LogType\) [MarshalJSON]()
+
+```go
+func (lt LogType) MarshalJSON() ([]byte, error)
+```
+
+
+
+
+### func \(\*LogType\) [Scan]()
+
+```go
+func (lt *LogType) Scan(src interface{}) error
+```
+
+
+
+
+### func \(LogType\) [String]()
+
+```go
+func (l LogType) String() string
+```
+
+
+
+
+### func \(\*LogType\) [UnmarshalJSON]()
+
+```go
+func (lt *LogType) UnmarshalJSON(data []byte) error
+```
+
+
+
+
+### func \(LogType\) [Value]()
+
+```go
+func (lt LogType) Value() (driver.Value, error)
+```
+
+
+
+
+## type [Move]()
+
+
+
+```go
+type Move struct {
+ bun.BaseModel `bun:"table:moves"`
+
+ Ledger string `bun:"ledger,type:varchar"`
+ TransactionID int `bun:"transactions_id,type:bigint"`
+ IsSource bool `bun:"is_source,type:bool"`
+ Account string `bun:"accounts_address,type:varchar"`
+ Amount *bunpaginate.BigInt `bun:"amount,type:numeric"`
+ Asset string `bun:"asset,type:varchar"`
+ InsertionDate time.Time `bun:"insertion_date,type:timestamp"`
+ EffectiveDate time.Time `bun:"effective_date,type:timestamp"`
+ PostCommitVolumes *Volumes `bun:"post_commit_volumes,type:jsonb"`
+ PostCommitEffectiveVolumes *Volumes `bun:"post_commit_effective_volumes,type:jsonb,scanonly"`
+}
+```
+
+
+## type [Moves]()
+
+
+
+```go
+type Moves []*Move
+```
+
+
+### func \(Moves\) [ComputePostCommitEffectiveVolumes]()
+
+```go
+func (m Moves) ComputePostCommitEffectiveVolumes() PostCommitVolumes
+```
+
+
+
+
+## type [PostCommitVolumes]()
+
+
+
+```go
+type PostCommitVolumes map[string]VolumesByAssets
+```
+
+
+### func \(PostCommitVolumes\) [AddInput]()
+
+```go
+func (a PostCommitVolumes) AddInput(account, asset string, input *big.Int)
+```
+
+
+
+
+### func \(PostCommitVolumes\) [AddOutput]()
+
+```go
+func (a PostCommitVolumes) AddOutput(account, asset string, output *big.Int)
+```
+
+
+
+
+### func \(PostCommitVolumes\) [Copy]()
+
+```go
+func (a PostCommitVolumes) Copy() PostCommitVolumes
+```
+
+
+
+
+### func \(PostCommitVolumes\) [Merge]()
+
+```go
+func (a PostCommitVolumes) Merge(volumes PostCommitVolumes) PostCommitVolumes
+```
+
+
+
+
+## type [Posting]()
+
+
+
+```go
+type Posting struct {
+ Source string `json:"source"`
+ Destination string `json:"destination"`
+ Amount *big.Int `json:"amount"`
+ Asset string `json:"asset"`
+}
+```
+
+
+### func [NewPosting]()
+
+```go
+func NewPosting(source string, destination string, asset string, amount *big.Int) Posting
+```
+
+
+
+
+### func \(Posting\) [GetDestination]()
+
+```go
+func (p Posting) GetDestination() string
+```
+
+
+
+
+### func \(Posting\) [GetSource]()
+
+```go
+func (p Posting) GetSource() string
+```
+
+
+
+
+## type [Postings]()
+
+
+
+```go
+type Postings []Posting
+```
+
+
+### func \(Postings\) [Reverse]()
+
+```go
+func (p Postings) Reverse() Postings
+```
+
+
+
+
+### func \(Postings\) [Validate]()
+
+```go
+func (p Postings) Validate() (int, error)
+```
+
+
+
+
+## type [RevertedTransaction]()
+
+
+
+```go
+type RevertedTransaction struct {
+ RevertedTransaction Transaction `json:"revertedTransaction"`
+ RevertTransaction Transaction `json:"transaction"`
+}
+```
+
+
+### func \(RevertedTransaction\) [Type]()
+
+```go
+func (r RevertedTransaction) Type() LogType
+```
+
+
+
+
+## type [SavedMetadata]()
+
+
+
+```go
+type SavedMetadata struct {
+ TargetType string `json:"targetType"`
+ TargetID any `json:"targetId"`
+ Metadata metadata.Metadata `json:"metadata"`
+}
+```
+
+
+### func \(SavedMetadata\) [Type]()
+
+```go
+func (s SavedMetadata) Type() LogType
+```
+
+
+
+
+### func \(\*SavedMetadata\) [UnmarshalJSON]()
+
+```go
+func (s *SavedMetadata) UnmarshalJSON(data []byte) error
+```
+
+
+
+
+## type [Transaction]()
+
+
+
+```go
+type Transaction struct {
+ bun.BaseModel `bun:"table:transactions,alias:transactions"`
+
+ TransactionData
+ ID int `json:"id" bun:"id,type:numeric"`
+ RevertedAt *time.Time `json:"revertedAt,omitempty" bun:"reverted_at,type:timestamp without time zone"`
+ PostCommitVolumes PostCommitVolumes `json:"postCommitVolumes,omitempty" bun:"post_commit_volumes,type:jsonb"`
+ PostCommitEffectiveVolumes PostCommitVolumes `json:"postCommitEffectiveVolumes,omitempty" bun:"post_commit_effective_volumes,type:jsonb,scanonly"`
+}
+```
+
+
+### func [NewTransaction]()
+
+```go
+func NewTransaction() Transaction
+```
+
+
+
+
+### func \(Transaction\) [InvolvedAccountAndAssets]()
+
+```go
+func (tx Transaction) InvolvedAccountAndAssets() map[string][]string
+```
+
+
+
+
+### func \(Transaction\) [InvolvedAccounts]()
+
+```go
+func (tx Transaction) InvolvedAccounts() []string
+```
+
+
+
+
+### func \(Transaction\) [IsReverted]()
+
+```go
+func (tx Transaction) IsReverted() bool
+```
+
+
+
+
+### func \(Transaction\) [JSONSchemaExtend]()
+
+```go
+func (Transaction) JSONSchemaExtend(schema *jsonschema.Schema)
+```
+
+
+
+
+### func \(Transaction\) [MarshalJSON]()
+
+```go
+func (tx Transaction) MarshalJSON() ([]byte, error)
+```
+
+
+
+
+### func \(Transaction\) [Reverse]()
+
+```go
+func (tx Transaction) Reverse() Transaction
+```
+
+
+
+
+### func \(Transaction\) [VolumeUpdates]()
+
+```go
+func (tx Transaction) VolumeUpdates() []AccountsVolumes
+```
+
+
+
+
+### func \(Transaction\) [WithInsertedAt]()
+
+```go
+func (tx Transaction) WithInsertedAt(date time.Time) Transaction
+```
+
+
+
+
+### func \(Transaction\) [WithMetadata]()
+
+```go
+func (tx Transaction) WithMetadata(m metadata.Metadata) Transaction
+```
+
+
+
+
+### func \(Transaction\) [WithPostCommitEffectiveVolumes]()
+
+```go
+func (tx Transaction) WithPostCommitEffectiveVolumes(volumes PostCommitVolumes) Transaction
+```
+
+
+
+
+### func \(Transaction\) [WithPostings]()
+
+```go
+func (tx Transaction) WithPostings(postings ...Posting) Transaction
+```
+
+
+
+
+### func \(Transaction\) [WithReference]()
+
+```go
+func (tx Transaction) WithReference(ref string) Transaction
+```
+
+
+
+
+### func \(Transaction\) [WithRevertedAt]()
+
+```go
+func (tx Transaction) WithRevertedAt(timestamp time.Time) Transaction
+```
+
+
+
+
+### func \(Transaction\) [WithTimestamp]()
+
+```go
+func (tx Transaction) WithTimestamp(ts time.Time) Transaction
+```
+
+
+
+
+## type [TransactionData]()
+
+
+
+```go
+type TransactionData struct {
+ Postings Postings `json:"postings" bun:"postings,type:jsonb"`
+ Metadata metadata.Metadata `json:"metadata" bun:"metadata,type:jsonb,default:'{}'"`
+ Timestamp time.Time `json:"timestamp" bun:"timestamp,type:timestamp without time zone,nullzero"`
+ Reference string `json:"reference,omitempty" bun:"reference,type:varchar,unique,nullzero"`
+ InsertedAt time.Time `json:"insertedAt,omitempty" bun:"inserted_at,type:timestamp without time zone,nullzero"`
+}
+```
+
+
+### func [NewTransactionData]()
+
+```go
+func NewTransactionData() TransactionData
+```
+
+
+
+
+### func \(TransactionData\) [WithPostings]()
+
+```go
+func (data TransactionData) WithPostings(postings ...Posting) TransactionData
+```
+
+
+
+
+## type [Transactions]()
+
+
+
+```go
+type Transactions struct {
+ Transactions []TransactionData `json:"transactions"`
+}
+```
+
+
+## type [Volumes]()
+
+
+
+```go
+type Volumes struct {
+ Input *big.Int `json:"input"`
+ Output *big.Int `json:"output"`
+}
+```
+
+
+### func [NewEmptyVolumes]()
+
+```go
+func NewEmptyVolumes() Volumes
+```
+
+
+
+
+### func [NewVolumesInt64]()
+
+```go
+func NewVolumesInt64(input, output int64) Volumes
+```
+
+
+
+
+### func \(Volumes\) [Balance]()
+
+```go
+func (v Volumes) Balance() *big.Int
+```
+
+
+
+
+### func \(Volumes\) [Copy]()
+
+```go
+func (v Volumes) Copy() Volumes
+```
+
+
+
+
+### func \(Volumes\) [JSONSchemaExtend]()
+
+```go
+func (Volumes) JSONSchemaExtend(schema *jsonschema.Schema)
+```
+
+
+
+
+### func \(Volumes\) [MarshalJSON]()
+
+```go
+func (v Volumes) MarshalJSON() ([]byte, error)
+```
+
+
+
+
+### func \(Volumes\) [WithInput]()
+
+```go
+func (v Volumes) WithInput(input *big.Int) Volumes
+```
+
+
+
+
+### func \(Volumes\) [WithOutput]()
+
+```go
+func (v Volumes) WithOutput(output *big.Int) Volumes
+```
+
+
+
+
+## type [VolumesByAssets]()
+
+
+
+```go
+type VolumesByAssets map[string]Volumes
+```
+
+
+### func \(VolumesByAssets\) [Balances]()
+
+```go
+func (v VolumesByAssets) Balances() BalancesByAssets
+```
+
+
+
+
+## type [VolumesWithBalance]()
+
+
+
+```go
+type VolumesWithBalance struct {
+ Input *big.Int `json:"input" bun:"input"`
+ Output *big.Int `json:"output" bun:"output"`
+ Balance *big.Int `json:"balance" bun:"balance"`
+}
+```
+
+
+## type [VolumesWithBalanceByAssetByAccount]()
+
+
+
+```go
+type VolumesWithBalanceByAssetByAccount struct {
+ Account string `json:"account" bun:"account"`
+ Asset string `json:"asset" bun:"asset"`
+ VolumesWithBalance
+}
+```
+
+
+## type [VolumesWithBalanceByAssets]()
+
+
+
+```go
+type VolumesWithBalanceByAssets map[string]*VolumesWithBalance
+```
+
+Generated by [gomarkdoc]()
diff --git a/internal/controller/ledger/README.md b/internal/controller/ledger/README.md
index e50d7fed3..d18774bdc 100644
--- a/internal/controller/ledger/README.md
+++ b/internal/controller/ledger/README.md
@@ -6,7 +6,7 @@
import "github.com/formancehq/ledger/internal/controller/ledger"
```
-Controller doc
+Ledger Controller doc
## Index
diff --git a/internal/controller/ledger/doc.go b/internal/controller/ledger/doc.go
index 9d3de4247..20e775b6d 100644
--- a/internal/controller/ledger/doc.go
+++ b/internal/controller/ledger/doc.go
@@ -1,3 +1,3 @@
-// Controller doc
+// Ledger Controller doc
//go:generate gomarkdoc --output README.md .
package ledger
diff --git a/internal/controller/system/README.md b/internal/controller/system/README.md
new file mode 100644
index 000000000..d3a538c1b
--- /dev/null
+++ b/internal/controller/system/README.md
@@ -0,0 +1,189 @@
+
+
+# system
+
+```go
+import "github.com/formancehq/ledger/internal/controller/system"
+```
+
+System Controller doc
+
+## Index
+
+- [Variables](<#variables>)
+- [func NewFXModule\(configuration ModuleConfiguration\) fx.Option](<#NewFXModule>)
+- [type Controller](<#Controller>)
+- [type DefaultController](<#DefaultController>)
+ - [func NewDefaultController\(store Store, listener ledgercontroller.Listener, opts ...Option\) \*DefaultController](<#NewDefaultController>)
+ - [func \(ctrl \*DefaultController\) CreateLedger\(ctx context.Context, name string, configuration ledger.Configuration\) error](<#DefaultController.CreateLedger>)
+ - [func \(ctrl \*DefaultController\) DeleteLedgerMetadata\(ctx context.Context, param string, key string\) error](<#DefaultController.DeleteLedgerMetadata>)
+ - [func \(ctrl \*DefaultController\) GetLedger\(ctx context.Context, name string\) \(\*ledger.Ledger, error\)](<#DefaultController.GetLedger>)
+ - [func \(ctrl \*DefaultController\) GetLedgerController\(ctx context.Context, name string\) \(ledgercontroller.Controller, error\)](<#DefaultController.GetLedgerController>)
+ - [func \(ctrl \*DefaultController\) ListLedgers\(ctx context.Context, query ledgercontroller.ListLedgersQuery\) \(\*bunpaginate.Cursor\[ledger.Ledger\], error\)](<#DefaultController.ListLedgers>)
+ - [func \(ctrl \*DefaultController\) UpdateLedgerMetadata\(ctx context.Context, name string, m map\[string\]string\) error](<#DefaultController.UpdateLedgerMetadata>)
+- [type ModuleConfiguration](<#ModuleConfiguration>)
+- [type Option](<#Option>)
+ - [func WithCompiler\(compiler ledgercontroller.Compiler\) Option](<#WithCompiler>)
+- [type Store](<#Store>)
+
+
+## Variables
+
+
+
+```go
+var (
+ ErrNeedUpgradeBucket = errors.New("need to upgrade bucket before add a new ledger on it")
+ ErrLedgerAlreadyExists = errors.New("ledger already exists")
+)
+```
+
+
+## func [NewFXModule]()
+
+```go
+func NewFXModule(configuration ModuleConfiguration) fx.Option
+```
+
+
+
+
+## type [Controller]()
+
+
+
+```go
+type Controller interface {
+ GetLedgerController(ctx context.Context, name string) (ledgercontroller.Controller, error)
+ GetLedger(ctx context.Context, name string) (*ledger.Ledger, error)
+ ListLedgers(ctx context.Context, query ledgercontroller.ListLedgersQuery) (*bunpaginate.Cursor[ledger.Ledger], error)
+ // CreateLedger can return following errors:
+ // * ErrLedgerAlreadyExists
+ // * ledger.ErrInvalidLedgerName
+ // It create the ledger in system store and the underlying storage
+ CreateLedger(ctx context.Context, name string, configuration ledger.Configuration) error
+ UpdateLedgerMetadata(ctx context.Context, name string, m map[string]string) error
+ DeleteLedgerMetadata(ctx context.Context, param string, key string) error
+}
+```
+
+
+## type [DefaultController]()
+
+
+
+```go
+type DefaultController struct {
+ // contains filtered or unexported fields
+}
+```
+
+
+### func [NewDefaultController]()
+
+```go
+func NewDefaultController(store Store, listener ledgercontroller.Listener, opts ...Option) *DefaultController
+```
+
+
+
+
+### func \(\*DefaultController\) [CreateLedger]()
+
+```go
+func (ctrl *DefaultController) CreateLedger(ctx context.Context, name string, configuration ledger.Configuration) error
+```
+
+
+
+
+### func \(\*DefaultController\) [DeleteLedgerMetadata]()
+
+```go
+func (ctrl *DefaultController) DeleteLedgerMetadata(ctx context.Context, param string, key string) error
+```
+
+
+
+
+### func \(\*DefaultController\) [GetLedger]()
+
+```go
+func (ctrl *DefaultController) GetLedger(ctx context.Context, name string) (*ledger.Ledger, error)
+```
+
+
+
+
+### func \(\*DefaultController\) [GetLedgerController]()
+
+```go
+func (ctrl *DefaultController) GetLedgerController(ctx context.Context, name string) (ledgercontroller.Controller, error)
+```
+
+
+
+
+### func \(\*DefaultController\) [ListLedgers]()
+
+```go
+func (ctrl *DefaultController) ListLedgers(ctx context.Context, query ledgercontroller.ListLedgersQuery) (*bunpaginate.Cursor[ledger.Ledger], error)
+```
+
+
+
+
+### func \(\*DefaultController\) [UpdateLedgerMetadata]()
+
+```go
+func (ctrl *DefaultController) UpdateLedgerMetadata(ctx context.Context, name string, m map[string]string) error
+```
+
+
+
+
+## type [ModuleConfiguration]()
+
+
+
+```go
+type ModuleConfiguration struct {
+ NSCacheConfiguration ledgercontroller.CacheConfiguration
+}
+```
+
+
+## type [Option]()
+
+
+
+```go
+type Option func(r *DefaultController)
+```
+
+
+### func [WithCompiler]()
+
+```go
+func WithCompiler(compiler ledgercontroller.Compiler) Option
+```
+
+
+
+
+## type [Store]()
+
+
+
+```go
+type Store interface {
+ GetLedger(ctx context.Context, name string) (*ledger.Ledger, error)
+ ListLedgers(ctx context.Context, query ledgercontroller.ListLedgersQuery) (*bunpaginate.Cursor[ledger.Ledger], error)
+ UpdateLedgerMetadata(ctx context.Context, name string, m metadata.Metadata) error
+ DeleteLedgerMetadata(ctx context.Context, param string, key string) error
+ OpenLedger(context.Context, string) (ledgercontroller.Store, *ledger.Ledger, error)
+ CreateLedger(context.Context, *ledger.Ledger) error
+}
+```
+
+Generated by [gomarkdoc]()
diff --git a/internal/controller/system/doc.go b/internal/controller/system/doc.go
new file mode 100644
index 000000000..ab6e3c0b1
--- /dev/null
+++ b/internal/controller/system/doc.go
@@ -0,0 +1,3 @@
+// System Controller doc
+//go:generate gomarkdoc --output README.md .
+package system
diff --git a/internal/doc.go b/internal/doc.go
new file mode 100644
index 000000000..6bf8bda86
--- /dev/null
+++ b/internal/doc.go
@@ -0,0 +1,3 @@
+// # Core
+//go:generate gomarkdoc --output README.md .
+package ledger