create_transfers
Create one or more Transfer
s. A successfully created transfer will modify the
amount fields of its debit and
credit accounts.
Event
The transfer to create. See Transfer
for constraints.
Result
Results are listed in this section in order of descending precedence — that is, if more than one error is applicable to the transfer being created, only the result listed first is returned.
ok
The transfer was successfully created; did not previously exist.
Note that ok
is generated by the client implementation; the network protocol does not include a
result when the transfer was successfully created.
linked_event_failed
The transfer was not created. One or more of the other transfers in the linked chain is invalid, so the whole chain failed.
linked_event_chain_open
The transfer was not created.
The Transfer.flags.linked
flag was set on the last event in the
batch, which is not legal. (flags.linked
indicates that the chain continues to the next
operation).
timestamp_must_be_zero
The transfer was not created.
The Transfer.timestamp
is nonzero, but must be zero.
The cluster is responsible for setting this field.
reserved_flag
The transfer was not created.
Transfer.flags.reserved
is nonzero, but must be zero.
id_must_not_be_zero
The transfer was not created.
Transfer.id
is zero, which is a reserved value.
id_must_not_be_int_max
The transfer was not created.
Transfer.id
is 2^128 - 1
, which is a reserved value.
flags_are_mutually_exclusive
The transfer was not created.
An account cannot be created with the specified combination of
Transfer.flags
.
Flag compatibility (✓ = compatible, ✗ = mutually exclusive):
flags.pending
flags.post_pending_transfer
flags.void_pending_transfer
flags.balancing_debit
flags.balancing_credit
debit_account_id_must_not_be_zero
The transfer was not created.
Transfer.debit_account_id
is zero, but must be a valid
account id.
debit_account_id_must_not_be_int_max
The transfer was not created.
Transfer.debit_account_id
is 2^128 - 1
, but must be a
valid account id.
credit_account_id_must_not_be_zero
The transfer was not created.
Transfer.credit_account_id
is zero, but must be a valid
account id.
credit_account_id_must_not_be_int_max
The transfer was not created.
Transfer.credit_account_id
is 2^128 - 1
, but must be a
valid account id.
accounts_must_be_different
The transfer was not created.
Transfer.debit_account_id
and
Transfer.credit_account_id
must not be equal.
That is, an account cannot transfer money to itself.
pending_id_must_be_zero
The transfer was not created. Only post/void transfers can reference a pending transfer.
Either:
Transfer.flags.post_pending_transfer
must be set, orTransfer.flags.void_pending_transfer
must be set, orTransfer.pending_id
must be zero.
pending_id_must_not_be_zero
The transfer was not created.
Transfer.flags.post_pending_transfer
or
Transfer.flags.void_pending_transfer
is set,
but Transfer.pending_id
is zero. A posting or voiding transfer must
reference a pending
transfer.
pending_id_must_not_be_int_max
The transfer was not created.
Transfer.pending_id
is 2^128 - 1
, which is a reserved value.
pending_id_must_be_different
The transfer was not created.
Transfer.pending_id
is set to the same id as
Transfer.id
. Instead it should refer to a different (existing) transfer.
timeout_reserved_for_pending_transfer
The transfer was not created.
Transfer.timeout
is nonzero, but only
pending transfers have nonzero timeouts.
amount_must_not_be_zero
The transfer was not created.
Transfer.amount
is zero, but must be nonzero.
Every transfer must move value. Only posting and voiding transfer amounts may be zero — when zero, they will move the full pending amount.
ledger_must_not_be_zero
The transfer was not created.
Transfer.ledger
is zero, but must be nonzero.
code_must_not_be_zero
The transfer was not created.
Transfer.code
is zero, but must be nonzero.
debit_account_not_found
The transfer was not created.
Transfer.debit_account_id
must refer to an existing Account
.
credit_account_not_found
The transfer was not created.
Transfer.credit_account_id
must refer to an existing Account
.
accounts_must_have_the_same_ledger
The transfer was not created. The accounts referred to by
Transfer.debit_account_id
and
Transfer.credit_account_id
must have an identical
ledger
.
Currency exchange is implemented with multiple transfers.
transfer_must_have_the_same_ledger_as_accounts
The transfer was not created. The accounts referred to by
Transfer.debit_account_id
and
Transfer.credit_account_id
are equivalent, but
differ from the Transfer.ledger
.
pending_transfer_not_found
The transfer was not created.
The transfer referenced by Transfer.pending_id
does not exist.
pending_transfer_not_pending
The transfer was not created.
The transfer referenced by Transfer.pending_id
exists, but does not
have flags.pending
set.
pending_transfer_has_different_debit_account_id
The transfer was not created.
The transfer referenced by Transfer.pending_id
exists, but with a
different debit_account_id
.
The post/void transfer's debit_account_id
must either be 0
or identical to the pending
transfer's debit_account_id
.
pending_transfer_has_different_credit_account_id
The transfer was not created.
The transfer referenced by Transfer.pending_id
exists, but with a
different credit_account_id
.
The post/void transfer's credit_account_id
must either be 0
or identical to the pending
transfer's credit_account_id
.
pending_transfer_has_different_ledger
The transfer was not created.
The transfer referenced by Transfer.pending_id
exists, but with a
different ledger
.
The post/void transfer's ledger
must either be 0
or identical to the pending
transfer's ledger
.
pending_transfer_has_different_code
The transfer was not created.
The transfer referenced by Transfer.pending_id
exists, but with a
different code
.
The post/void transfer's code
must either be 0
or identical to the pending
transfer's code
.
exceeds_pending_transfer_amount
The transfer was not created.
The transfer's amount
exceeds the amount
of its
pending transfer.
pending_transfer_has_different_amount
The transfer was not created.
The transfer is attempting to void a pending transfer.
The voiding transfer's amount
must be either 0
or exactly the amount
of the pending transfer.
To partially void a transfer, create a posting transfer
with an amount between 0
and the pending transfer's amount
.
pending_transfer_already_posted
The transfer was not created.
The referenced pending transfer was already posted by a
post_pending_transfer
.
pending_transfer_already_voided
The transfer was not created.
The referenced pending transfer was already voided by a
void_pending_transfer
.
pending_transfer_expired
The transfer was not created. The referenced pending transfer was already voided because its timeout has passed.
exists_with_different_flags
A transfer with the same id
already exists, but with different flags
.
exists_with_different_debit_account_id
A transfer with the same id
already exists, but with a different
debit_account_id
.
exists_with_different_credit_account_id
A transfer with the same id
already exists, but with a different
credit_account_id
.
exists_with_different_amount
A transfer with the same id
already exists, but with a different
amount
.
If the transfer has flags.balancing_debit
or flags.balancing_credit
set, this error refers
to the actual amount transferred, not the original (possibly higher) balancing amount.
exists_with_different_pending_id
A transfer with the same id
already exists, but with a different
pending_id
.
exists_with_different_user_data_128
A transfer with the same id
already exists, but with a different
user_data_128
.
exists_with_different_user_data_64
A transfer with the same id
already exists, but with a different
user_data_64
.
exists_with_different_user_data_32
A transfer with the same id
already exists, but with a different
user_data_32
.
exists_with_different_timeout
A transfer with the same id
already exists, but with a different
timeout
.
exists_with_different_code
A transfer with the same id
already exists, but with a different code
.
exists
A transfer with the same id
already exists, and is identical to the transfer in the request.
To correctly recover from application crashes
many applications should handle
exists
exactly as ok
.
overflows_debits_pending
The transfer was not created.
debit_account.debits_pending + transfer.amount
would overflow a 128-bit unsigned integer.
overflows_credits_pending
The transfer was not created.
credit_account.credits_pending + transfer.amount
would overflow a 128-bit unsigned integer.
overflows_debits_posted
The transfer was not created.
debit_account.debits_posted + transfer.amount
would overflow a 128-bit unsigned integer.
overflows_credits_posted
The transfer was not created.
debit_account.credits_posted + transfer.amount
would overflow a 128-bit unsigned integer.
overflows_debits
The transfer was not created.
debit_account.debits_pending + debit_account.debits_posted + transfer.amount
would overflow a 128-bit unsigned integer.
overflows_credits
The transfer was not created.
credit_account.credits_pending + credit_account.credits_posted + transfer.amount
would overflow a 128-bit unsigned integer.
overflows_timeout
The transfer was not created.
transfer.timestamp + (transfer.timeout * 1_000_000_000)
would overflow a 64-bit unsigned integer.
Transfer.timeout
is converted to nanoseconds.
This computation uses the Transfer.timestamp
value assigned by the
replica, not the 0
value sent by the client.
exceeds_credits
The transfer was not created.
If flags.balancing_debit
is set, then
debit_account.debits_pending + debit_account.debits_posted + 1
would exceed
debit_account.credits_posted
.
Otherwise, the debit account has
flags.debits_must_not_exceed_credits
set, but debit_account.debits_pending + debit_account.debits_posted + transfer.amount
would exceed debit_account.credits_posted
.
exceeds_debits
The transfer was not created.
If flags.balancing_credit
is set, then
credit_account.credits_pending + credit_account.credits_posted + 1
would exceed
credit_account.debits_posted
.
Otherwise, the credit account has
flags.credits_must_not_exceed_debits
set, but credit_account.credits_pending + credit_account.credits_posted + transfer.amount
would exceed credit_account.debits_posted
.
Client libraries
For language-specific docs see:
Internals
If you're curious and want to learn more, you can find the source code
for creating a transfer in
src/state_machine.zig. Search
for fn create_transfer(
and fn execute(
.