xrpl-ruby 0.6.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +155 -0
- data/README.md +99 -3
- data/lib/binary-codec/binary_codec.rb +22 -1
- data/lib/binary-codec/enums/definitions.json +3856 -456
- data/lib/binary-codec/enums/definitions.rb +46 -1
- data/lib/binary-codec/types/amount.rb +5 -2
- data/lib/binary-codec/types/currency.rb +8 -1
- data/lib/binary-codec/types/issue.rb +68 -23
- data/lib/binary-codec/types/number.rb +196 -0
- data/lib/binary-codec/types/serialized_type.rb +5 -2
- data/lib/binary-codec/types/st_array.rb +17 -19
- data/lib/binary-codec/types/st_object.rb +15 -13
- data/lib/binary-codec/types/uint.rb +55 -44
- data/lib/binary-codec/types/xchain_bridge.rb +17 -2
- data/lib/wallet/wallet.rb +32 -0
- data/lib/xrpl/client.rb +47 -9
- data/lib/xrpl/fee.rb +82 -0
- data/lib/xrpl/ledger_entry.rb +53 -0
- data/lib/xrpl/model.rb +239 -0
- data/lib/xrpl/transaction.rb +53 -0
- data/lib/xrpl/version.rb +1 -1
- data/lib/xrpl-ruby.rb +5 -0
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cb8b3e628ddf6a9d9a7e329e6e8c51e4b0cd4f872eb609e589d78795aa9f4782
|
|
4
|
+
data.tar.gz: 2f5b18b34cb386901a8ad1a7549f7cca241facce58c0841f36a10a4c200413cc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f066a56166ec0aa81ec3acb34106d504962a6e1cf2cee89eb13103719467f9ded35a34d432d9901c8a81f11b7dedc93311d8ebd184dc21564585163536e18558
|
|
7
|
+
data.tar.gz: 97397fe795b08eed3c56111b876d5476da705e2577c635f12e6aeee9ebc5ef86106fd44e525dc67c3716c11472b273bd4235764d9df2b7bf8bcc3e0d152078a7
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,161 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.8.0] - 2026-09-24
|
|
9
|
+
|
|
10
|
+
The codec now targets **rippled 3.4.0** (released 2026-09-17) and passes the
|
|
11
|
+
ripple-binary-codec 2.11.0 fixture set: 39 transactions and 263 ledger
|
|
12
|
+
entries, both directions (302 cases; 287 before). Measured before the change:
|
|
13
|
+
transactions 38/39, accountState 262/263 decode.
|
|
14
|
+
|
|
15
|
+
### Breaking
|
|
16
|
+
|
|
17
|
+
- **`definitions.json` is rippled 3.4.0.** It is what a 3.4.0 node reports
|
|
18
|
+
through `server_definitions` (s1.ripple.com), with the node's own digest in
|
|
19
|
+
`hash`. FIELDS 381 → 357: the 27 `Hook*` fields plus `EmitGeneration` and
|
|
20
|
+
`EmittedTxn` are gone, because rippled dropped Hooks; a blob carrying one
|
|
21
|
+
of them no longer decodes. Added: `VaultKind`, `SubscriptionDate`,
|
|
22
|
+
`RedemptionDate`, `LEVersion`, `ContractResult` (LendingProtocolV1_1,
|
|
23
|
+
closed-ended vaults), and `CredentialIDs` on `VaultWithdraw` and
|
|
24
|
+
`LoanBrokerCoverWithdraw`. ripple-binary-codec's `main` additionally
|
|
25
|
+
carries four `*KeyEpoch` fields from rippled's development branch; they
|
|
26
|
+
are in no release and deliberately not here.
|
|
27
|
+
- **`PermissionValue` decodes to its name.** A `DelegateSet` permission is
|
|
28
|
+
a UInt32 that rippled renders by name: a transaction type as its code plus
|
|
29
|
+
one (`"Payment"` = 1), the twelve granular permissions from 65537
|
|
30
|
+
(`"TrustlineAuthorize"`). Encoding accepts the names; they were silently
|
|
31
|
+
serialised as 0 before.
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- **Ledger entry models** — `XRPL::LedgerEntry::AccountRoot`,
|
|
36
|
+
`::RippleState`, `::Offer` and the other 28 types, generated from
|
|
37
|
+
`LEDGER_ENTRY_FORMATS` the way the transaction models are generated from
|
|
38
|
+
`TRANSACTION_FORMATS`. `XRPL::LedgerEntry.from(node)` builds the right
|
|
39
|
+
class from anything `ledger_entry`, `account_objects` or `ledger_data`
|
|
40
|
+
returns and keeps rippled's `index` alongside. Every `lsf` flag is a
|
|
41
|
+
constant on its type. All 263 reference ledger entries round-trip through
|
|
42
|
+
their model unchanged.
|
|
43
|
+
- **Flag helpers** on transactions and ledger entries: `#flag?` takes the
|
|
44
|
+
ledger's name, the constant's name or the bit, `#flag_names` lists what
|
|
45
|
+
is set.
|
|
46
|
+
- **Fees by transaction type.** `autofill` now charges what rippled charges:
|
|
47
|
+
`EscrowFinish` pays for its `Fulfillment` (base × (33 + bytes / 16)),
|
|
48
|
+
`AccountDelete`, `AMMCreate` and `VaultCreate` cost the owner reserve
|
|
49
|
+
from `server_state`, a `Batch` pays two base fees plus those of its inner
|
|
50
|
+
transactions, the confidential MPT transactions cost ten base fees, and
|
|
51
|
+
multisigning adds one base fee per signature. Ordinary fees are capped at
|
|
52
|
+
2 XRP (`Client.new(url, max_fee_drops:)`); the reserve-priced types are
|
|
53
|
+
not. The rules are a pure module, `XRPL::Fee.calculate`, and the same
|
|
54
|
+
ones xrpl.js applies. Before, every transaction paid the base fee, so an
|
|
55
|
+
AccountDelete or an EscrowFinish with a fulfillment could not be
|
|
56
|
+
autofilled.
|
|
57
|
+
- **Payment channel claims.** `Wallet#sign_payment_channel_claim(channel,
|
|
58
|
+
drops)` and `#verify_payment_channel_claim`, plus
|
|
59
|
+
`Wallet.verify_payment_channel_claim(..., public_key)` for the receiving
|
|
60
|
+
side; `BinaryCodec.signing_claim_data` underneath. Checked against the
|
|
61
|
+
xrpl.js signature vector byte for byte.
|
|
62
|
+
- The hash prefixes for batch, counterparty and sponsor signatures
|
|
63
|
+
(`fixCleanup3_4_0`) are in `BinaryCodec::HASH_PREFIX`; the signing
|
|
64
|
+
helpers for them are not written yet.
|
|
65
|
+
- `Definitions#delegatable_permissions`, and readers for the transaction
|
|
66
|
+
type, ledger entry type and result tables the codec resolves names
|
|
67
|
+
against.
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- `XRPL::Transaction` is built on a new `XRPL::Model` base shared with
|
|
72
|
+
`XRPL::LedgerEntry`. Its public surface is unchanged;
|
|
73
|
+
`Transaction::ValidationError` is now `Model::ValidationError`, reachable
|
|
74
|
+
under both names. A model rejects a hash whose type field contradicts the
|
|
75
|
+
class (`Payment.new('TransactionType' => 'TrustSet')`), where it used to
|
|
76
|
+
keep the foreign value and serialise a TrustSet.
|
|
77
|
+
- The transaction models pick up the 3.4.0 fields without a code change:
|
|
78
|
+
`VaultCreate.new(vault_kind:, subscription_date:, redemption_date:)`.
|
|
79
|
+
- A parity spec that pins `definitions.json` to the 3.4.0 digest and fails
|
|
80
|
+
if a Hook or development-branch field comes back.
|
|
81
|
+
|
|
82
|
+
### Fixed
|
|
83
|
+
|
|
84
|
+
- `ConfidentialOutstandingAmount` renders in base 10 like the other MPToken
|
|
85
|
+
amounts, not as a 16 digit hex string.
|
|
86
|
+
- `Definitions#get_field_instance` returns `nil` for an unknown field name.
|
|
87
|
+
Serialising a hash with a foreign key now fails with "Field x is not
|
|
88
|
+
defined" instead of a `NoMethodError` on `nil`.
|
|
89
|
+
|
|
90
|
+
## [0.7.0] - 2026-08-26
|
|
91
|
+
|
|
92
|
+
The binary codec now passes the full ripple-binary-codec reference fixture set
|
|
93
|
+
(287 cases, both directions). It previously passed none of them on decode: the
|
|
94
|
+
fixtures had been vendored in `spec/binary-codec/fixtures/` for a long time
|
|
95
|
+
without any spec loading them, so the suite reported green while decoding
|
|
96
|
+
0 of 261 ledger objects.
|
|
97
|
+
|
|
98
|
+
### Breaking
|
|
99
|
+
|
|
100
|
+
- **`binary_to_json` returns different types.** UInt8/16/32 fields come back as
|
|
101
|
+
numbers instead of zero-padded hex strings (`Sequence` is `1`, not
|
|
102
|
+
`"00000001"`), and native XRP amounts come back as strings instead of
|
|
103
|
+
integers (`Balance` is `"370000000"`, not `370000000`). This is what rippled
|
|
104
|
+
itself returns; the previous output matched no implementation.
|
|
105
|
+
- **`STObject#to_json` returns a Hash**, not a JSON string. The string return
|
|
106
|
+
forced every nested value through a parse on the way out, which is what
|
|
107
|
+
turned native amounts into integers.
|
|
108
|
+
- **Malformed input raises.** `STObject#to_json` and `STArray#to_json` caught
|
|
109
|
+
every parser error and returned a partially decoded object. A codec that
|
|
110
|
+
silently drops fields is worse than one that fails, so the rescues are gone.
|
|
111
|
+
- `tecHOOK_REJECTED` is no longer a known transaction result. It is a Xahau
|
|
112
|
+
code and never belonged in the XRP Ledger definitions.
|
|
113
|
+
|
|
114
|
+
### Added
|
|
115
|
+
|
|
116
|
+
- **Transaction models** — `XRPL::Transaction::Payment`, `::EscrowCreate` and
|
|
117
|
+
80 more, generated at load time from `TRANSACTION_FORMATS` so they cannot
|
|
118
|
+
drift from the definitions. Fields are written in snake_case and stored under
|
|
119
|
+
the ledger's own names; `#validate!` reports missing required fields before a
|
|
120
|
+
round trip is spent, and each type carries its flags as constants
|
|
121
|
+
(`Payment::TF_PARTIAL_PAYMENT`). A plain Hash still works everywhere a
|
|
122
|
+
transaction is accepted.
|
|
123
|
+
- **`BinaryCodec::Number`** — the STNumber type (12 bytes: int64 mantissa,
|
|
124
|
+
int32 exponent). 17 serialised fields reference it — the Vault and Lending
|
|
125
|
+
Protocol amounts — and no class existed, so those fields could not be
|
|
126
|
+
encoded at all. The gap predates this release.
|
|
127
|
+
- **`Issue` supports MPT** (`mpt_issuance_id`), in both directions.
|
|
128
|
+
- **Conformance spec** running `codec-fixtures.json`, and a definitions spec
|
|
129
|
+
that checks every type a serialised field uses resolves to a class.
|
|
130
|
+
|
|
131
|
+
### Changed
|
|
132
|
+
|
|
133
|
+
- **`definitions.json` synced verbatim with XRPLF.** FIELDS 343 → 381,
|
|
134
|
+
TRANSACTION_TYPES 76 → 83, LEDGER_ENTRY_TYPES 31 → 32, TRANSACTION_RESULTS
|
|
135
|
+
189 → 195. Adds the Sponsorship and Confidential MPT fields and transactions,
|
|
136
|
+
`TakerGetsMPT`, `TakerPaysMPT` and `ReferenceHolding`. Renames `UInt384`/
|
|
137
|
+
`UInt512` to `Hash384`/`Hash512` and `MutableFlags` to `ImmutableFlags`; the
|
|
138
|
+
type map keeps the old names resolving.
|
|
139
|
+
- `Client#autofill`, `#submit` and `#submit_and_wait` accept a transaction
|
|
140
|
+
model as well as a Hash.
|
|
141
|
+
- The gemspec packages everything under `lib/`, not only the `.rb` files. Data
|
|
142
|
+
files previously needed an entry of their own, and a forgotten one would have
|
|
143
|
+
broken the installed gem while every local run stayed green, because the
|
|
144
|
+
working copy has the file either way. `spec/packaging_spec.rb` checks it now.
|
|
145
|
+
|
|
146
|
+
### Fixed
|
|
147
|
+
|
|
148
|
+
- **`Issue` read a fixed 40 bytes.** An XRP issue is 20, so the rest came out
|
|
149
|
+
of the following field: `Asset` and `Asset2` decoded as `nil` and
|
|
150
|
+
`IssuingChainDoor` as the zero account.
|
|
151
|
+
- **`STArray.from_parser` dropped the ArrayEndMarker** it is meant to restore.
|
|
152
|
+
The reconstructed bytes had no terminator, so re-parsing them ran the array
|
|
153
|
+
on into the fields that followed — `AMMBid` lost `Asset` and `Asset2` into
|
|
154
|
+
`AuthAccounts`.
|
|
155
|
+
- **`Currency#to_json` took no arguments** while every type is called as
|
|
156
|
+
`to_json(definitions, field_name)`. It raised `ArgumentError` for every
|
|
157
|
+
nested Currency field, which the silent rescue then swallowed — that is how
|
|
158
|
+
`BaseAsset` and `QuoteAsset` disappeared from `PriceDataSeries`.
|
|
159
|
+
- **`XChainBridge` omitted the `0x14` length prefix** before each account,
|
|
160
|
+
which is why all eight XChain fixtures failed to serialise.
|
|
161
|
+
- **A zero IOU rendered as `"-0"`** instead of `"0"`.
|
|
162
|
+
|
|
8
163
|
## [0.6.1] - 2026-08-12
|
|
9
164
|
|
|
10
165
|
### Added
|
data/README.md
CHANGED
|
@@ -12,14 +12,19 @@ A pure-Ruby library to interact with the [XRP Ledger](https://xrpl.org) (XRPL) b
|
|
|
12
12
|
## Features
|
|
13
13
|
|
|
14
14
|
- Key and wallet management (secp256k1 and ed25519)
|
|
15
|
-
- Address codec and binary
|
|
15
|
+
- Address codec and binary codec, conformant with rippled 3.4.0 and the
|
|
16
|
+
ripple-binary-codec reference fixtures
|
|
17
|
+
- Transaction and ledger entry models generated from the ledger's own
|
|
18
|
+
definitions
|
|
16
19
|
- WebSocket client for the XRP Ledger public API
|
|
17
20
|
- Testnet faucet helper to create and fund wallets
|
|
18
|
-
- Transaction lifecycle: autofill, sign, submit, and
|
|
21
|
+
- Transaction lifecycle: autofill with per-type fees, sign, submit, and
|
|
22
|
+
reliable "submit and wait"
|
|
23
|
+
- Payment channel claims, signed and verified locally
|
|
19
24
|
|
|
20
25
|
## Requirements
|
|
21
26
|
|
|
22
|
-
- Ruby 3.
|
|
27
|
+
- Ruby 3.2 or later
|
|
23
28
|
|
|
24
29
|
## Installation
|
|
25
30
|
|
|
@@ -69,6 +74,97 @@ puts result.dig('result', 'meta', 'TransactionResult') # => "tesSUCCESS"
|
|
|
69
74
|
client.disconnect
|
|
70
75
|
```
|
|
71
76
|
|
|
77
|
+
## Transactions
|
|
78
|
+
|
|
79
|
+
A transaction can always be a plain Hash, as above. The transaction classes
|
|
80
|
+
are an addition on top of that: they are generated from the field formats in
|
|
81
|
+
`definitions.json`, so they know which fields a type accepts, which of them
|
|
82
|
+
are required, and what its flags are called.
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
payment = XRPL::Transaction::Payment.new(
|
|
86
|
+
account: wallet.classic_address,
|
|
87
|
+
destination: receiver.classic_address,
|
|
88
|
+
amount: '1000000',
|
|
89
|
+
flags: XRPL::Transaction::Payment::TF_PARTIAL_PAYMENT
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
payment.validate! # raises before a round trip is spent
|
|
93
|
+
client.submit_and_wait(payment, wallet: wallet)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Fields are written in snake_case and stored under the ledger's own names, so
|
|
97
|
+
`#to_h` produces exactly what the binary codec expects:
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
payment.to_h
|
|
101
|
+
# => {"TransactionType"=>"Payment", "Account"=>"r...", "Destination"=>"r...",
|
|
102
|
+
# "Amount"=>"1000000", "Flags"=>131072}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
A field the type does not define is rejected when it is set, rather than by
|
|
106
|
+
the server several seconds later:
|
|
107
|
+
|
|
108
|
+
```ruby
|
|
109
|
+
payment.limit_amount = {} # NoMethodError
|
|
110
|
+
XRPL::Transaction::Payment.new(limit_amount: {})
|
|
111
|
+
# => XRPL::Transaction::ValidationError: Payment has no field LimitAmount
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`XRPL::Transaction.from(hash)` builds the matching class from a transaction
|
|
115
|
+
hash, which is useful for anything read back off the ledger. Note that
|
|
116
|
+
`validate!` follows rippled's formats: it checks what the ledger requires for
|
|
117
|
+
serialisation, which is not always what a transaction needs to be meaningful.
|
|
118
|
+
|
|
119
|
+
Flags can be asked about by any of their names:
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
payment.flag?(:tf_partial_payment) # => true
|
|
123
|
+
payment.flag_names # => ["tfPartialPayment"]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Fees
|
|
127
|
+
|
|
128
|
+
`autofill` sets the fee the transaction type actually needs, following the
|
|
129
|
+
same rules as xrpl.js: an `EscrowFinish` pays for the size of its
|
|
130
|
+
`Fulfillment`, `AccountDelete`, `AMMCreate` and `VaultCreate` cost the owner
|
|
131
|
+
reserve, a `Batch` pays for its inner transactions, and multisigning adds one
|
|
132
|
+
base fee per signature. Ordinary fees are capped at 2 XRP; pass
|
|
133
|
+
`max_fee_drops:` to `Client.new` to change that. The rules are available on
|
|
134
|
+
their own as `XRPL::Fee.calculate`.
|
|
135
|
+
|
|
136
|
+
## Ledger entries
|
|
137
|
+
|
|
138
|
+
The objects that make up the ledger's state - `AccountRoot`, `RippleState`,
|
|
139
|
+
`Offer`, `Escrow` and the rest - have models too, generated from
|
|
140
|
+
`LEDGER_ENTRY_FORMATS` the same way:
|
|
141
|
+
|
|
142
|
+
```ruby
|
|
143
|
+
node = client.request_with_retry('ledger_entry', account_root: address).dig('result', 'node')
|
|
144
|
+
entry = XRPL::LedgerEntry.from(node)
|
|
145
|
+
|
|
146
|
+
entry.class # => XRPL::LedgerEntry::AccountRoot
|
|
147
|
+
entry.balance # => "370000000"
|
|
148
|
+
entry.flag?(:lsf_default_ripple) # => true
|
|
149
|
+
entry.flag_names # => ["lsfDefaultRipple", "lsfDisableMaster"]
|
|
150
|
+
entry.index # the entry's hash, as rippled reports it
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Every flag rippled defines is a constant on its type, e.g.
|
|
154
|
+
`XRPL::LedgerEntry::AccountRoot::LSF_DEPOSIT_AUTH`.
|
|
155
|
+
|
|
156
|
+
## Payment channel claims
|
|
157
|
+
|
|
158
|
+
A claim is signed off-ledger and redeemed later with a `PaymentChannelClaim`
|
|
159
|
+
transaction. Amounts are in drops:
|
|
160
|
+
|
|
161
|
+
```ruby
|
|
162
|
+
signature = wallet.sign_payment_channel_claim(channel_id, '1000000')
|
|
163
|
+
|
|
164
|
+
# On the receiving side, against the channel's PublicKey:
|
|
165
|
+
Wallet::Wallet.verify_payment_channel_claim(channel_id, '1000000', signature, public_key)
|
|
166
|
+
```
|
|
167
|
+
|
|
72
168
|
The client is silent by default. To see diagnostic output, pass a logger:
|
|
73
169
|
|
|
74
170
|
```ruby
|
|
@@ -6,7 +6,15 @@ module BinaryCodec
|
|
|
6
6
|
transaction_sig: 0x53545800, # 'STX\0'
|
|
7
7
|
transaction_multi_sig: 0x534D5400, # 'SMT\0'
|
|
8
8
|
validation: 0x56414C00, # 'VAL\0'
|
|
9
|
-
proposal: 0x50525000 # 'PRP\0'
|
|
9
|
+
proposal: 0x50525000, # 'PRP\0'
|
|
10
|
+
payment_channel_claim: 0x434C4D00, # 'CLM\0'
|
|
11
|
+
batch: 0x42434800, # 'BCH\0'
|
|
12
|
+
# Role-specific prefixes from fixCleanup3_4_0, so a signature made for
|
|
13
|
+
# one role cannot be replayed as another.
|
|
14
|
+
counterparty_sig: 0x43505400, # 'CPT\0'
|
|
15
|
+
counterparty_multi_sig: 0x43504D00, # 'CPM\0'
|
|
16
|
+
sponsor_sig: 0x53504E00, # 'SPN\0'
|
|
17
|
+
sponsor_multi_sig: 0x53504D00 # 'SPM\0'
|
|
10
18
|
}.freeze
|
|
11
19
|
|
|
12
20
|
# from here: https://github.com/XRPLF/xrpl.js/blob/main/packages/ripple-binary-codec/src/binary.ts
|
|
@@ -38,6 +46,19 @@ module BinaryCodec
|
|
|
38
46
|
st_object.from(json).to_hex
|
|
39
47
|
end
|
|
40
48
|
|
|
49
|
+
# The bytes a payment channel claim is signed over: the 'CLM\0' prefix,
|
|
50
|
+
# the channel ID and the amount in drops. Same as xrpl.js
|
|
51
|
+
# encodeForSigningClaim.
|
|
52
|
+
#
|
|
53
|
+
# @param channel [String] the channel ID, 64 hex characters
|
|
54
|
+
# @param amount [String, Integer] the amount in drops
|
|
55
|
+
# @return [Array<Integer>] the signing data
|
|
56
|
+
def signing_claim_data(channel:, amount:)
|
|
57
|
+
int_to_bytes(HASH_PREFIX[:payment_channel_claim], 4) +
|
|
58
|
+
Hash256.from(channel).to_bytes +
|
|
59
|
+
Uint64.from(Integer(amount)).to_bytes
|
|
60
|
+
end
|
|
61
|
+
|
|
41
62
|
# Generates signing data for a transaction.
|
|
42
63
|
# @param transaction [Hash] The transaction to serialize.
|
|
43
64
|
# @param prefix [Integer] The prefix to add to the serialized data.
|