xrpl-ruby 0.7.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e07e1a6fd2b134d36dbbdaaa977cc39e8e9176499a29e69bd84e69ddfd6f6979
4
- data.tar.gz: bcca5b159608288c0cdeffc562a76332fe4e831e4dc9813676f66d46c53546ac
3
+ metadata.gz: cb8b3e628ddf6a9d9a7e329e6e8c51e4b0cd4f872eb609e589d78795aa9f4782
4
+ data.tar.gz: 2f5b18b34cb386901a8ad1a7549f7cca241facce58c0841f36a10a4c200413cc
5
5
  SHA512:
6
- metadata.gz: fffeb72058c2a328c01bda6e6bfd63718147fc12326385c18c304b9d0e92013e60ba9ad11424af2ee6bd72c69e016494113db5c05ed26e10ee2501bc0873288a
7
- data.tar.gz: 3aa7f43f67c50faaf0139a5f42737a35c5fd59408dc3098144a7a0b3a57bab5dad3eac3fa68fb9819749ba2dd0b7f91460de5e87899279e49b6ab07fcae87c83
6
+ metadata.gz: f066a56166ec0aa81ec3acb34106d504962a6e1cf2cee89eb13103719467f9ded35a34d432d9901c8a81f11b7dedc93311d8ebd184dc21564585163536e18558
7
+ data.tar.gz: 97397fe795b08eed3c56111b876d5476da705e2577c635f12e6aeee9ebc5ef86106fd44e525dc67c3716c11472b273bd4235764d9df2b7bf8bcc3e0d152078a7
data/CHANGELOG.md CHANGED
@@ -5,6 +5,88 @@ 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
+
8
90
  ## [0.7.0] - 2026-08-26
9
91
 
10
92
  The binary codec now passes the full ripple-binary-codec reference fixture set
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 (transaction) codec
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 reliable "submit and wait"
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.0 or later
27
+ - Ruby 3.2 or later
23
28
 
24
29
  ## Installation
25
30
 
@@ -111,6 +116,55 @@ hash, which is useful for anything read back off the ledger. Note that
111
116
  `validate!` follows rippled's formats: it checks what the ledger requires for
112
117
  serialisation, which is not always what a transaction needs to be meaningful.
113
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
+
114
168
  The client is silent by default. To see diagnostic output, pass a logger:
115
169
 
116
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.