diff --git a/Base/Xrpl.AddressCodec/Utils.cs b/Base/Xrpl.AddressCodec/Utils.cs
index 80b33746..2b8ba338 100644
--- a/Base/Xrpl.AddressCodec/Utils.cs
+++ b/Base/Xrpl.AddressCodec/Utils.cs
@@ -6,21 +6,21 @@
namespace Xrpl.AddressCodec
{
- public class Utils
+ public static class Utils
{
///
/// from bytes array to hex row
///
/// bytes array
///
- public static string FromBytesToHex(byte[] bytes) => Hex.ToHexString(bytes).ToUpper();
+ public static string FromBytesToHex(this byte[] bytes) => Hex.ToHexString(bytes).ToUpper();
///
/// hex row to bytes array
///
/// hex row
///
- public static byte[] FromHexToBytes(string hex) => Hex.Decode(hex);
+ public static byte[] FromHexToBytes(this string hex) => Hex.Decode(hex);
///
/// combine bytes arrays to single array
diff --git a/Base/Xrpl.AddressCodec/Xrpl.AddressCodec.csproj b/Base/Xrpl.AddressCodec/Xrpl.AddressCodec.csproj
index 64c5f958..708704fb 100644
--- a/Base/Xrpl.AddressCodec/Xrpl.AddressCodec.csproj
+++ b/Base/Xrpl.AddressCodec/Xrpl.AddressCodec.csproj
@@ -13,7 +13,7 @@
https://github.com/Transia-RnD/XrplCSharp/LICENSE
https://github.com/Transia-RnD/XrplCSharp
XrplCSharp
- 1.0.0
+ 2.0.0
@@ -21,7 +21,7 @@
bin\Debug\net6.0\XrplCSharp.xml
-
+
diff --git a/Base/Xrpl.BinaryCodec/Binary/BytesList.cs b/Base/Xrpl.BinaryCodec/Binary/BytesList.cs
index 5e5c3109..c6b80510 100644
--- a/Base/Xrpl.BinaryCodec/Binary/BytesList.cs
+++ b/Base/Xrpl.BinaryCodec/Binary/BytesList.cs
@@ -42,15 +42,6 @@ public void Put(byte[] bytes)
}
/// Get all bytes
/// Bytes
- public byte[] Bytes()
- {
- var n = BytesLength();
- var bytes = new byte[n];
- AddBytes(bytes, 0);
- return bytes;
- }
- /// Get all bytes
- /// Bytes
public byte[] ToBytes()
{
var n = BytesLength();
diff --git a/Base/Xrpl.BinaryCodec/Enums/Field.cs b/Base/Xrpl.BinaryCodec/Enums/Field.cs
index e17fe111..4a70375a 100644
--- a/Base/Xrpl.BinaryCodec/Enums/Field.cs
+++ b/Base/Xrpl.BinaryCodec/Enums/Field.cs
@@ -86,13 +86,14 @@ private bool IsVlEncodedType()
public static readonly TransactionTypeField TransactionType = new TransactionTypeField(nameof(TransactionType), 2);
public static readonly Uint16Field SignerWeight = new Uint16Field(nameof(SignerWeight), 3);
public static readonly Uint16Field TransferFee = new Uint16Field(nameof(TransferFee), 4);
- public static readonly Uint16Field TradingFee = new Uint16Field(nameof(TradingFee), 4);
+ public static readonly Uint16Field TradingFee = new Uint16Field(nameof(TradingFee), 4);
public static readonly Uint16Field Version = new Uint16Field(nameof(Version), 16);
public static readonly Uint16Field HookStateChangeCount = new Uint16Field(nameof(HookStateChangeCount), 17);
public static readonly Uint16Field HookStateEmitCount = new Uint16Field(nameof(HookStateEmitCount), 18);
public static readonly Uint16Field HookStateExecutionIndex = new Uint16Field(nameof(HookStateExecutionIndex), 19);
public static readonly Uint16Field HookApiVersion = new Uint16Field(nameof(HookApiVersion), 20);
+ public static readonly Uint32Field NetworkID = new Uint32Field(nameof(NetworkID), 1);
public static readonly Uint32Field Flags = new Uint32Field(nameof(Flags), 2);
public static readonly Uint32Field SourceTag = new Uint32Field(nameof(SourceTag), 3);
public static readonly Uint32Field Sequence = new Uint32Field(nameof(Sequence), 4);
@@ -214,7 +215,7 @@ private bool IsVlEncodedType()
public static readonly AmountField DeliverMin = new AmountField(nameof(DeliverMin), 10);
public static readonly AmountField Amount2 = new AmountField(nameof(Amount2), 11);
public static readonly AmountField BidMin = new AmountField(nameof(BidMin), 12);
- public static readonly AmountField BidMax = new AmountField(nameof(BidMax), 13);
+ public static readonly AmountField BidMax = new AmountField(nameof(BidMax), 13);
public static readonly AmountField MinimumOffer = new AmountField(nameof(MinimumOffer), 16);
public static readonly AmountField RippleEscrow = new AmountField(nameof(RippleEscrow), 17);
public static readonly AmountField DeliveredAmount = new AmountField(nameof(DeliveredAmount), 18);
@@ -314,7 +315,6 @@ private bool IsVlEncodedType()
public static readonly StArrayField HookParameters = new StArrayField(nameof(HookParameters), 19);
public static readonly StArrayField HookGrants = new StArrayField(nameof(HookGrants), 19);
public static readonly StArrayField AuthAccounts = new StArrayField(nameof(AuthAccounts), 26);
-
public static readonly Field Generic = new Field(nameof(Generic), 0, FieldType.Unknown, isSigningField: false);
public static readonly Field Invalid = new Field(nameof(Invalid), -1, FieldType.Unknown, isSigningField: false);
diff --git a/Base/Xrpl.BinaryCodec/Enums/LedgerEntryType.cs b/Base/Xrpl.BinaryCodec/Enums/LedgerEntryType.cs
index 834d80c9..e71c8e1d 100644
--- a/Base/Xrpl.BinaryCodec/Enums/LedgerEntryType.cs
+++ b/Base/Xrpl.BinaryCodec/Enums/LedgerEntryType.cs
@@ -1,5 +1,4 @@
using Newtonsoft.Json.Linq;
-using Xrpl.BinaryCodec.Enums;
//todo not found doc
diff --git a/Base/Xrpl.BinaryCodec/Enums/TransactionType.cs b/Base/Xrpl.BinaryCodec/Enums/TransactionType.cs
index 25428afd..d7a7d91d 100644
--- a/Base/Xrpl.BinaryCodec/Enums/TransactionType.cs
+++ b/Base/Xrpl.BinaryCodec/Enums/TransactionType.cs
@@ -1,6 +1,6 @@
using Xrpl.BinaryCodec.Enums;
-namespace Xrpl.BinaryCodec.Enums
+namespace Xrpl.BinaryCodec.Types
{
public class TransactionType : SerializedEnumItem
{
@@ -86,6 +86,7 @@ private static TransactionType Add(string name, int ordinal)
public static readonly TransactionType AMMWithdraw = Add(nameof(AMMWithdraw), 37);
public static readonly TransactionType AMMVote = Add(nameof(AMMVote), 38);
public static readonly TransactionType AMMBid = Add(nameof(AMMBid), 39);
+ public static readonly TransactionType AMMDelete = Add(nameof(AMMDelete), 40);
// ...
///
diff --git a/Base/Xrpl.BinaryCodec/Enums/definitions.json b/Base/Xrpl.BinaryCodec/Enums/definitions.json
new file mode 100644
index 00000000..b6b48f44
--- /dev/null
+++ b/Base/Xrpl.BinaryCodec/Enums/definitions.json
@@ -0,0 +1,2846 @@
+{
+ "TYPES": {
+ "Done": -1,
+ "Unknown": -2,
+ "NotPresent": 0,
+ "UInt16": 1,
+ "UInt32": 2,
+ "UInt64": 3,
+ "Hash128": 4,
+ "Hash256": 5,
+ "Amount": 6,
+ "Blob": 7,
+ "AccountID": 8,
+ "STObject": 14,
+ "STArray": 15,
+ "UInt8": 16,
+ "Hash160": 17,
+ "PathSet": 18,
+ "Vector256": 19,
+ "UInt96": 20,
+ "UInt192": 21,
+ "UInt384": 22,
+ "UInt512": 23,
+ "Issue": 24,
+ "XChainBridge": 25,
+ "Transaction": 10001,
+ "LedgerEntry": 10002,
+ "Validation": 10003,
+ "Metadata": 10004
+ },
+ "LEDGER_ENTRY_TYPES": {
+ "Invalid": -1,
+ "AccountRoot": 97,
+ "DirectoryNode": 100,
+ "RippleState": 114,
+ "Ticket": 84,
+ "SignerList": 83,
+ "Offer": 111,
+ "Bridge": 105,
+ "LedgerHashes": 104,
+ "Amendments": 102,
+ "XChainOwnedClaimID": 113,
+ "XChainOwnedCreateAccountClaimID": 116,
+ "FeeSettings": 115,
+ "Escrow": 117,
+ "PayChannel": 120,
+ "Check": 67,
+ "DepositPreauth": 112,
+ "NegativeUNL": 78,
+ "NFTokenPage": 80,
+ "NFTokenOffer": 55,
+ "AMM": 121,
+ "Any": -3,
+ "Child": -2,
+ "Nickname": 110,
+ "Contract": 99,
+ "GeneratorMap": 103
+ },
+ "FIELDS": [
+ [
+ "Generic",
+ {
+ "nth": 0,
+ "isVLEncoded": false,
+ "isSerialized": false,
+ "isSigningField": false,
+ "type": "Unknown"
+ }
+ ],
+ [
+ "Invalid",
+ {
+ "nth": -1,
+ "isVLEncoded": false,
+ "isSerialized": false,
+ "isSigningField": false,
+ "type": "Unknown"
+ }
+ ],
+ [
+ "ObjectEndMarker",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "ArrayEndMarker",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "hash",
+ {
+ "nth": 257,
+ "isVLEncoded": false,
+ "isSerialized": false,
+ "isSigningField": false,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "index",
+ {
+ "nth": 258,
+ "isVLEncoded": false,
+ "isSerialized": false,
+ "isSigningField": false,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "taker_gets_funded",
+ {
+ "nth": 258,
+ "isVLEncoded": false,
+ "isSerialized": false,
+ "isSigningField": false,
+ "type": "Amount"
+ }
+ ],
+ [
+ "taker_pays_funded",
+ {
+ "nth": 259,
+ "isVLEncoded": false,
+ "isSerialized": false,
+ "isSigningField": false,
+ "type": "Amount"
+ }
+ ],
+ [
+ "LedgerEntry",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": false,
+ "isSigningField": true,
+ "type": "LedgerEntry"
+ }
+ ],
+ [
+ "Transaction",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": false,
+ "isSigningField": true,
+ "type": "Transaction"
+ }
+ ],
+ [
+ "Validation",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": false,
+ "isSigningField": true,
+ "type": "Validation"
+ }
+ ],
+ [
+ "Metadata",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Metadata"
+ }
+ ],
+ [
+ "CloseResolution",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt8"
+ }
+ ],
+ [
+ "Method",
+ {
+ "nth": 2,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt8"
+ }
+ ],
+ [
+ "TransactionResult",
+ {
+ "nth": 3,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt8"
+ }
+ ],
+ [
+ "TickSize",
+ {
+ "nth": 16,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt8"
+ }
+ ],
+ [
+ "UNLModifyDisabling",
+ {
+ "nth": 17,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt8"
+ }
+ ],
+ [
+ "HookResult",
+ {
+ "nth": 18,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt8"
+ }
+ ],
+ [
+ "WasLockingChainSend",
+ {
+ "nth": 19,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt8"
+ }
+ ],
+ [
+ "LedgerEntryType",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt16"
+ }
+ ],
+ [
+ "TransactionType",
+ {
+ "nth": 2,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt16"
+ }
+ ],
+ [
+ "SignerWeight",
+ {
+ "nth": 3,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt16"
+ }
+ ],
+ [
+ "TransferFee",
+ {
+ "nth": 4,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt16"
+ }
+ ],
+ [
+ "TradingFee",
+ {
+ "nth": 5,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt16"
+ }
+ ],
+ [
+ "DiscountedFee",
+ {
+ "nth": 6,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt16"
+ }
+ ],
+ [
+ "Version",
+ {
+ "nth": 16,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt16"
+ }
+ ],
+ [
+ "HookStateChangeCount",
+ {
+ "nth": 17,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt16"
+ }
+ ],
+ [
+ "HookEmitCount",
+ {
+ "nth": 18,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt16"
+ }
+ ],
+ [
+ "HookExecutionIndex",
+ {
+ "nth": 19,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt16"
+ }
+ ],
+ [
+ "HookApiVersion",
+ {
+ "nth": 20,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt16"
+ }
+ ],
+ [
+ "NetworkID",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "Flags",
+ {
+ "nth": 2,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "SourceTag",
+ {
+ "nth": 3,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "Sequence",
+ {
+ "nth": 4,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "PreviousTxnLgrSeq",
+ {
+ "nth": 5,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "LedgerSequence",
+ {
+ "nth": 6,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "CloseTime",
+ {
+ "nth": 7,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "ParentCloseTime",
+ {
+ "nth": 8,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "SigningTime",
+ {
+ "nth": 9,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "Expiration",
+ {
+ "nth": 10,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "TransferRate",
+ {
+ "nth": 11,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "WalletSize",
+ {
+ "nth": 12,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "OwnerCount",
+ {
+ "nth": 13,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "DestinationTag",
+ {
+ "nth": 14,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "HighQualityIn",
+ {
+ "nth": 16,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "HighQualityOut",
+ {
+ "nth": 17,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "LowQualityIn",
+ {
+ "nth": 18,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "LowQualityOut",
+ {
+ "nth": 19,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "QualityIn",
+ {
+ "nth": 20,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "QualityOut",
+ {
+ "nth": 21,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "StampEscrow",
+ {
+ "nth": 22,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "BondAmount",
+ {
+ "nth": 23,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "LoadFee",
+ {
+ "nth": 24,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "OfferSequence",
+ {
+ "nth": 25,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "FirstLedgerSequence",
+ {
+ "nth": 26,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "LastLedgerSequence",
+ {
+ "nth": 27,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "TransactionIndex",
+ {
+ "nth": 28,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "OperationLimit",
+ {
+ "nth": 29,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "ReferenceFeeUnits",
+ {
+ "nth": 30,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "ReserveBase",
+ {
+ "nth": 31,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "ReserveIncrement",
+ {
+ "nth": 32,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "SetFlag",
+ {
+ "nth": 33,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "ClearFlag",
+ {
+ "nth": 34,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "SignerQuorum",
+ {
+ "nth": 35,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "CancelAfter",
+ {
+ "nth": 36,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "FinishAfter",
+ {
+ "nth": 37,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "SignerListID",
+ {
+ "nth": 38,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "SettleDelay",
+ {
+ "nth": 39,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "TicketCount",
+ {
+ "nth": 40,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "TicketSequence",
+ {
+ "nth": 41,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "NFTokenTaxon",
+ {
+ "nth": 42,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "MintedNFTokens",
+ {
+ "nth": 43,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "BurnedNFTokens",
+ {
+ "nth": 44,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "HookStateCount",
+ {
+ "nth": 45,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "EmitGeneration",
+ {
+ "nth": 46,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "VoteWeight",
+ {
+ "nth": 48,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "FirstNFTokenSequence",
+ {
+ "nth": 50,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt32"
+ }
+ ],
+ [
+ "IndexNext",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "IndexPrevious",
+ {
+ "nth": 2,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "BookNode",
+ {
+ "nth": 3,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "OwnerNode",
+ {
+ "nth": 4,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "BaseFee",
+ {
+ "nth": 5,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "ExchangeRate",
+ {
+ "nth": 6,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "LowNode",
+ {
+ "nth": 7,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "HighNode",
+ {
+ "nth": 8,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "DestinationNode",
+ {
+ "nth": 9,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "Cookie",
+ {
+ "nth": 10,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "ServerVersion",
+ {
+ "nth": 11,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "NFTokenOfferNode",
+ {
+ "nth": 12,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "EmitBurden",
+ {
+ "nth": 13,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "HookOn",
+ {
+ "nth": 16,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "HookInstructionCount",
+ {
+ "nth": 17,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "HookReturnCode",
+ {
+ "nth": 18,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "ReferenceCount",
+ {
+ "nth": 19,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "XChainClaimID",
+ {
+ "nth": 20,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "XChainAccountCreateCount",
+ {
+ "nth": 21,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "XChainAccountClaimCount",
+ {
+ "nth": 22,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "UInt64"
+ }
+ ],
+ [
+ "EmailHash",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash128"
+ }
+ ],
+ [
+ "TakerPaysCurrency",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash160"
+ }
+ ],
+ [
+ "TakerPaysIssuer",
+ {
+ "nth": 2,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash160"
+ }
+ ],
+ [
+ "TakerGetsCurrency",
+ {
+ "nth": 3,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash160"
+ }
+ ],
+ [
+ "TakerGetsIssuer",
+ {
+ "nth": 4,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash160"
+ }
+ ],
+ [
+ "LedgerHash",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "ParentHash",
+ {
+ "nth": 2,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "TransactionHash",
+ {
+ "nth": 3,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "AccountHash",
+ {
+ "nth": 4,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "PreviousTxnID",
+ {
+ "nth": 5,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "LedgerIndex",
+ {
+ "nth": 6,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "WalletLocator",
+ {
+ "nth": 7,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "RootIndex",
+ {
+ "nth": 8,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "AccountTxnID",
+ {
+ "nth": 9,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "NFTokenID",
+ {
+ "nth": 10,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "EmitParentTxnID",
+ {
+ "nth": 11,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "EmitNonce",
+ {
+ "nth": 12,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "EmitHookHash",
+ {
+ "nth": 13,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "AMMID",
+ {
+ "nth": 14,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "BookDirectory",
+ {
+ "nth": 16,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "InvoiceID",
+ {
+ "nth": 17,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "Nickname",
+ {
+ "nth": 18,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "Amendment",
+ {
+ "nth": 19,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "Digest",
+ {
+ "nth": 21,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "Channel",
+ {
+ "nth": 22,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "ConsensusHash",
+ {
+ "nth": 23,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "CheckID",
+ {
+ "nth": 24,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "ValidatedHash",
+ {
+ "nth": 25,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "PreviousPageMin",
+ {
+ "nth": 26,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "NextPageMin",
+ {
+ "nth": 27,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "NFTokenBuyOffer",
+ {
+ "nth": 28,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "NFTokenSellOffer",
+ {
+ "nth": 29,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "HookStateKey",
+ {
+ "nth": 30,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "HookHash",
+ {
+ "nth": 31,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "HookNamespace",
+ {
+ "nth": 32,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "HookSetTxnID",
+ {
+ "nth": 33,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Hash256"
+ }
+ ],
+ [
+ "Amount",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "Balance",
+ {
+ "nth": 2,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "LimitAmount",
+ {
+ "nth": 3,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "TakerPays",
+ {
+ "nth": 4,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "TakerGets",
+ {
+ "nth": 5,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "LowLimit",
+ {
+ "nth": 6,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "HighLimit",
+ {
+ "nth": 7,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "Fee",
+ {
+ "nth": 8,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "SendMax",
+ {
+ "nth": 9,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "DeliverMin",
+ {
+ "nth": 10,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "Amount2",
+ {
+ "nth": 11,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "BidMin",
+ {
+ "nth": 12,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "BidMax",
+ {
+ "nth": 13,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "MinimumOffer",
+ {
+ "nth": 16,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "RippleEscrow",
+ {
+ "nth": 17,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "DeliveredAmount",
+ {
+ "nth": 18,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "NFTokenBrokerFee",
+ {
+ "nth": 19,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "BaseFeeDrops",
+ {
+ "nth": 22,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "ReserveBaseDrops",
+ {
+ "nth": 23,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "ReserveIncrementDrops",
+ {
+ "nth": 24,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "LPTokenOut",
+ {
+ "nth": 25,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "LPTokenIn",
+ {
+ "nth": 26,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "EPrice",
+ {
+ "nth": 27,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "Price",
+ {
+ "nth": 28,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "SignatureReward",
+ {
+ "nth": 29,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "MinAccountCreateAmount",
+ {
+ "nth": 30,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "LPTokenBalance",
+ {
+ "nth": 31,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Amount"
+ }
+ ],
+ [
+ "PublicKey",
+ {
+ "nth": 1,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "MessageKey",
+ {
+ "nth": 2,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "SigningPubKey",
+ {
+ "nth": 3,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "TxnSignature",
+ {
+ "nth": 4,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": false,
+ "type": "Blob"
+ }
+ ],
+ [
+ "URI",
+ {
+ "nth": 5,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "Signature",
+ {
+ "nth": 6,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": false,
+ "type": "Blob"
+ }
+ ],
+ [
+ "Domain",
+ {
+ "nth": 7,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "FundCode",
+ {
+ "nth": 8,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "RemoveCode",
+ {
+ "nth": 9,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "ExpireCode",
+ {
+ "nth": 10,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "CreateCode",
+ {
+ "nth": 11,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "MemoType",
+ {
+ "nth": 12,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "MemoData",
+ {
+ "nth": 13,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "MemoFormat",
+ {
+ "nth": 14,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "Fulfillment",
+ {
+ "nth": 16,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "Condition",
+ {
+ "nth": 17,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "MasterSignature",
+ {
+ "nth": 18,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": false,
+ "type": "Blob"
+ }
+ ],
+ [
+ "UNLModifyValidator",
+ {
+ "nth": 19,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "ValidatorToDisable",
+ {
+ "nth": 20,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "ValidatorToReEnable",
+ {
+ "nth": 21,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "HookStateData",
+ {
+ "nth": 22,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "HookReturnString",
+ {
+ "nth": 23,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "HookParameterName",
+ {
+ "nth": 24,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "HookParameterValue",
+ {
+ "nth": 25,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Blob"
+ }
+ ],
+ [
+ "Account",
+ {
+ "nth": 1,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "Owner",
+ {
+ "nth": 2,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "Destination",
+ {
+ "nth": 3,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "Issuer",
+ {
+ "nth": 4,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "Authorize",
+ {
+ "nth": 5,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "Unauthorize",
+ {
+ "nth": 6,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "RegularKey",
+ {
+ "nth": 8,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "NFTokenMinter",
+ {
+ "nth": 9,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "EmitCallback",
+ {
+ "nth": 10,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "HookAccount",
+ {
+ "nth": 16,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "OtherChainSource",
+ {
+ "nth": 18,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "OtherChainDestination",
+ {
+ "nth": 19,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "AttestationSignerAccount",
+ {
+ "nth": 20,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "AttestationRewardAccount",
+ {
+ "nth": 21,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "LockingChainDoor",
+ {
+ "nth": 22,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "IssuingChainDoor",
+ {
+ "nth": 23,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "AccountID"
+ }
+ ],
+ [
+ "Indexes",
+ {
+ "nth": 1,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Vector256"
+ }
+ ],
+ [
+ "Hashes",
+ {
+ "nth": 2,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Vector256"
+ }
+ ],
+ [
+ "Amendments",
+ {
+ "nth": 3,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Vector256"
+ }
+ ],
+ [
+ "NFTokenOffers",
+ {
+ "nth": 4,
+ "isVLEncoded": true,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Vector256"
+ }
+ ],
+ [
+ "Paths",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "PathSet"
+ }
+ ],
+ [
+ "LockingChainIssue",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Issue"
+ }
+ ],
+ [
+ "IssuingChainIssue",
+ {
+ "nth": 2,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Issue"
+ }
+ ],
+ [
+ "Asset",
+ {
+ "nth": 3,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Issue"
+ }
+ ],
+ [
+ "Asset2",
+ {
+ "nth": 4,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "Issue"
+ }
+ ],
+ [
+ "XChainBridge",
+ {
+ "nth": 1,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "XChainBridge"
+ }
+ ],
+ [
+ "TransactionMetaData",
+ {
+ "nth": 2,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "CreatedNode",
+ {
+ "nth": 3,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "DeletedNode",
+ {
+ "nth": 4,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "ModifiedNode",
+ {
+ "nth": 5,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "PreviousFields",
+ {
+ "nth": 6,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "FinalFields",
+ {
+ "nth": 7,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "NewFields",
+ {
+ "nth": 8,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "TemplateEntry",
+ {
+ "nth": 9,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "Memo",
+ {
+ "nth": 10,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "SignerEntry",
+ {
+ "nth": 11,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "NFToken",
+ {
+ "nth": 12,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "EmitDetails",
+ {
+ "nth": 13,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "Hook",
+ {
+ "nth": 14,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "Signer",
+ {
+ "nth": 16,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "Majority",
+ {
+ "nth": 18,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "DisabledValidator",
+ {
+ "nth": 19,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "EmittedTxn",
+ {
+ "nth": 20,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "HookExecution",
+ {
+ "nth": 21,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "HookDefinition",
+ {
+ "nth": 22,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "HookParameter",
+ {
+ "nth": 23,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "HookGrant",
+ {
+ "nth": 24,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "VoteEntry",
+ {
+ "nth": 25,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "AuctionSlot",
+ {
+ "nth": 26,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "AuthAccount",
+ {
+ "nth": 27,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "XChainClaimProofSig",
+ {
+ "nth": 28,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "XChainCreateAccountProofSig",
+ {
+ "nth": 29,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "XChainClaimAttestationCollectionElement",
+ {
+ "nth": 30,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "XChainCreateAccountAttestationCollectionElement",
+ {
+ "nth": 31,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STObject"
+ }
+ ],
+ [
+ "Signers",
+ {
+ "nth": 3,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": false,
+ "type": "STArray"
+ }
+ ],
+ [
+ "SignerEntries",
+ {
+ "nth": 4,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "Template",
+ {
+ "nth": 5,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "Necessary",
+ {
+ "nth": 6,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "Sufficient",
+ {
+ "nth": 7,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "AffectedNodes",
+ {
+ "nth": 8,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "Memos",
+ {
+ "nth": 9,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "NFTokens",
+ {
+ "nth": 10,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "Hooks",
+ {
+ "nth": 11,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "VoteSlots",
+ {
+ "nth": 12,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "Majorities",
+ {
+ "nth": 16,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "DisabledValidators",
+ {
+ "nth": 17,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "HookExecutions",
+ {
+ "nth": 18,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "HookParameters",
+ {
+ "nth": 19,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "HookGrants",
+ {
+ "nth": 20,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "XChainClaimAttestations",
+ {
+ "nth": 21,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "XChainCreateAccountAttestations",
+ {
+ "nth": 22,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ],
+ [
+ "AuthAccounts",
+ {
+ "nth": 25,
+ "isVLEncoded": false,
+ "isSerialized": true,
+ "isSigningField": true,
+ "type": "STArray"
+ }
+ ]
+ ],
+ "TRANSACTION_RESULTS": {
+ "telLOCAL_ERROR": -399,
+ "telBAD_DOMAIN": -398,
+ "telBAD_PATH_COUNT": -397,
+ "telBAD_PUBLIC_KEY": -396,
+ "telFAILED_PROCESSING": -395,
+ "telINSUF_FEE_P": -394,
+ "telNO_DST_PARTIAL": -393,
+ "telCAN_NOT_QUEUE": -392,
+ "telCAN_NOT_QUEUE_BALANCE": -391,
+ "telCAN_NOT_QUEUE_BLOCKS": -390,
+ "telCAN_NOT_QUEUE_BLOCKED": -389,
+ "telCAN_NOT_QUEUE_FEE": -388,
+ "telCAN_NOT_QUEUE_FULL": -387,
+ "telWRONG_NETWORK": -386,
+ "telREQUIRES_NETWORK_ID": -385,
+ "telNETWORK_ID_MAKES_TX_NON_CANONICAL": -384,
+
+ "temMALFORMED": -299,
+ "temBAD_AMOUNT": -298,
+ "temBAD_CURRENCY": -297,
+ "temBAD_EXPIRATION": -296,
+ "temBAD_FEE": -295,
+ "temBAD_ISSUER": -294,
+ "temBAD_LIMIT": -293,
+ "temBAD_OFFER": -292,
+ "temBAD_PATH": -291,
+ "temBAD_PATH_LOOP": -290,
+ "temBAD_REGKEY": -289,
+ "temBAD_SEND_XRP_LIMIT": -288,
+ "temBAD_SEND_XRP_MAX": -287,
+ "temBAD_SEND_XRP_NO_DIRECT": -286,
+ "temBAD_SEND_XRP_PARTIAL": -285,
+ "temBAD_SEND_XRP_PATHS": -284,
+ "temBAD_SEQUENCE": -283,
+ "temBAD_SIGNATURE": -282,
+ "temBAD_SRC_ACCOUNT": -281,
+ "temBAD_TRANSFER_RATE": -280,
+ "temDST_IS_SRC": -279,
+ "temDST_NEEDED": -278,
+ "temINVALID": -277,
+ "temINVALID_FLAG": -276,
+ "temREDUNDANT": -275,
+ "temRIPPLE_EMPTY": -274,
+ "temDISABLED": -273,
+ "temBAD_SIGNER": -272,
+ "temBAD_QUORUM": -271,
+ "temBAD_WEIGHT": -270,
+ "temBAD_TICK_SIZE": -269,
+ "temINVALID_ACCOUNT_ID": -268,
+ "temCANNOT_PREAUTH_SELF": -267,
+ "temINVALID_COUNT": -266,
+ "temUNCERTAIN": -265,
+ "temUNKNOWN": -264,
+ "temSEQ_AND_TICKET": -263,
+ "temBAD_NFTOKEN_TRANSFER_FEE": -262,
+ "temBAD_AMM_TOKENS": -261,
+ "temXCHAIN_EQUAL_DOOR_ACCOUNTS": -260,
+ "temXCHAIN_BAD_PROOF": -259,
+ "temXCHAIN_BRIDGE_BAD_ISSUES": -258,
+ "temXCHAIN_BRIDGE_NONDOOR_OWNER": -257,
+ "temXCHAIN_BRIDGE_BAD_MIN_ACCOUNT_CREATE_AMOUNT": -256,
+ "temXCHAIN_BRIDGE_BAD_REWARD_AMOUNT": -255,
+
+ "tefFAILURE": -199,
+ "tefALREADY": -198,
+ "tefBAD_ADD_AUTH": -197,
+ "tefBAD_AUTH": -196,
+ "tefBAD_LEDGER": -195,
+ "tefCREATED": -194,
+ "tefEXCEPTION": -193,
+ "tefINTERNAL": -192,
+ "tefNO_AUTH_REQUIRED": -191,
+ "tefPAST_SEQ": -190,
+ "tefWRONG_PRIOR": -189,
+ "tefMASTER_DISABLED": -188,
+ "tefMAX_LEDGER": -187,
+ "tefBAD_SIGNATURE": -186,
+ "tefBAD_QUORUM": -185,
+ "tefNOT_MULTI_SIGNING": -184,
+ "tefBAD_AUTH_MASTER": -183,
+ "tefINVARIANT_FAILED": -182,
+ "tefTOO_BIG": -181,
+ "tefNO_TICKET": -180,
+ "tefNFTOKEN_IS_NOT_TRANSFERABLE": -179,
+
+ "terRETRY": -99,
+ "terFUNDS_SPENT": -98,
+ "terINSUF_FEE_B": -97,
+ "terNO_ACCOUNT": -96,
+ "terNO_AUTH": -95,
+ "terNO_LINE": -94,
+ "terOWNERS": -93,
+ "terPRE_SEQ": -92,
+ "terLAST": -91,
+ "terNO_RIPPLE": -90,
+ "terQUEUED": -89,
+ "terPRE_TICKET": -88,
+ "terNO_AMM": -87,
+ "terSUBMITTED": -86,
+
+ "tesSUCCESS": 0,
+
+ "tecCLAIM": 100,
+ "tecPATH_PARTIAL": 101,
+ "tecUNFUNDED_ADD": 102,
+ "tecUNFUNDED_OFFER": 103,
+ "tecUNFUNDED_PAYMENT": 104,
+ "tecFAILED_PROCESSING": 105,
+ "tecDIR_FULL": 121,
+ "tecINSUF_RESERVE_LINE": 122,
+ "tecINSUF_RESERVE_OFFER": 123,
+ "tecNO_DST": 124,
+ "tecNO_DST_INSUF_XRP": 125,
+ "tecNO_LINE_INSUF_RESERVE": 126,
+ "tecNO_LINE_REDUNDANT": 127,
+ "tecPATH_DRY": 128,
+ "tecUNFUNDED": 129,
+ "tecNO_ALTERNATIVE_KEY": 130,
+ "tecNO_REGULAR_KEY": 131,
+ "tecOWNERS": 132,
+ "tecNO_ISSUER": 133,
+ "tecNO_AUTH": 134,
+ "tecNO_LINE": 135,
+ "tecINSUFF_FEE": 136,
+ "tecFROZEN": 137,
+ "tecNO_TARGET": 138,
+ "tecNO_PERMISSION": 139,
+ "tecNO_ENTRY": 140,
+ "tecINSUFFICIENT_RESERVE": 141,
+ "tecNEED_MASTER_KEY": 142,
+ "tecDST_TAG_NEEDED": 143,
+ "tecINTERNAL": 144,
+ "tecOVERSIZE": 145,
+ "tecCRYPTOCONDITION_ERROR": 146,
+ "tecINVARIANT_FAILED": 147,
+ "tecEXPIRED": 148,
+ "tecDUPLICATE": 149,
+ "tecKILLED": 150,
+ "tecHAS_OBLIGATIONS": 151,
+ "tecTOO_SOON": 152,
+ "tecHOOK_ERROR": 153,
+ "tecMAX_SEQUENCE_REACHED": 154,
+ "tecNO_SUITABLE_NFTOKEN_PAGE": 155,
+ "tecNFTOKEN_BUY_SELL_MISMATCH": 156,
+ "tecNFTOKEN_OFFER_TYPE_MISMATCH": 157,
+ "tecCANT_ACCEPT_OWN_NFTOKEN_OFFER": 158,
+ "tecINSUFFICIENT_FUNDS": 159,
+ "tecOBJECT_NOT_FOUND": 160,
+ "tecINSUFFICIENT_PAYMENT": 161,
+ "tecUNFUNDED_AMM": 162,
+ "tecAMM_BALANCE": 163,
+ "tecAMM_FAILED": 164,
+ "tecAMM_INVALID_TOKENS": 165,
+ "tecAMM_EMPTY": 166,
+ "tecAMM_NOT_EMPTY": 167,
+ "tecAMM_ACCOUNT": 168,
+ "tecINCOMPLETE": 169,
+ "tecXCHAIN_BAD_TRANSFER_ISSUE": 170,
+ "tecXCHAIN_NO_CLAIM_ID": 171,
+ "tecXCHAIN_BAD_CLAIM_ID": 172,
+ "tecXCHAIN_CLAIM_NO_QUORUM": 173,
+ "tecXCHAIN_PROOF_UNKNOWN_KEY": 174,
+ "tecXCHAIN_CREATE_ACCOUNT_NONXRP_ISSUE": 175,
+ "tecXCHAIN_WRONG_CHAIN": 176,
+ "tecXCHAIN_REWARD_MISMATCH": 177,
+ "tecXCHAIN_NO_SIGNERS_LIST": 178,
+ "tecXCHAIN_SENDING_ACCOUNT_MISMATCH": 179,
+ "tecXCHAIN_INSUFF_CREATE_AMOUNT": 180,
+ "tecXCHAIN_ACCOUNT_CREATE_PAST": 181,
+ "tecXCHAIN_ACCOUNT_CREATE_TOO_MANY": 182,
+ "tecXCHAIN_PAYMENT_FAILED": 183,
+ "tecXCHAIN_SELF_COMMIT": 184,
+ "tecXCHAIN_BAD_PUBLIC_KEY_ACCOUNT_PAIR": 185,
+ "tecXCHAIN_CREATE_ACCOUNT_DISABLED": 186
+ },
+ "TRANSACTION_TYPES": {
+ "Invalid": -1,
+ "Payment": 0,
+ "EscrowCreate": 1,
+ "EscrowFinish": 2,
+ "AccountSet": 3,
+ "EscrowCancel": 4,
+ "SetRegularKey": 5,
+ "NickNameSet": 6,
+ "OfferCreate": 7,
+ "OfferCancel": 8,
+ "Contract": 9,
+ "TicketCreate": 10,
+ "TicketCancel": 11,
+ "SignerListSet": 12,
+ "PaymentChannelCreate": 13,
+ "PaymentChannelFund": 14,
+ "PaymentChannelClaim": 15,
+ "CheckCreate": 16,
+ "CheckCash": 17,
+ "CheckCancel": 18,
+ "DepositPreauth": 19,
+ "TrustSet": 20,
+ "AccountDelete": 21,
+ "SetHook": 22,
+ "NFTokenMint": 25,
+ "NFTokenBurn": 26,
+ "NFTokenCreateOffer": 27,
+ "NFTokenCancelOffer": 28,
+ "NFTokenAcceptOffer": 29,
+ "Clawback": 30,
+ "AMMCreate": 35,
+ "AMMDeposit": 36,
+ "AMMWithdraw": 37,
+ "AMMVote": 38,
+ "AMMBid": 39,
+ "AMMDelete": 40,
+ "XChainCreateClaimID": 41,
+ "XChainCommit": 42,
+ "XChainClaim": 43,
+ "XChainAccountCreateCommit": 44,
+ "XChainAddClaimAttestation": 45,
+ "XChainAddAccountCreateAttestation": 46,
+ "XChainModifyBridge": 47,
+ "XChainCreateBridge": 48,
+ "EnableAmendment": 100,
+ "SetFee": 101,
+ "UNLModify": 102
+ }
+}
diff --git a/Base/Xrpl.BinaryCodec/Exceptions.cs b/Base/Xrpl.BinaryCodec/Exceptions.cs
index f3c60c04..7f02def7 100644
--- a/Base/Xrpl.BinaryCodec/Exceptions.cs
+++ b/Base/Xrpl.BinaryCodec/Exceptions.cs
@@ -8,14 +8,13 @@ public BinaryCodecException() { }
public BinaryCodecException(string message) : base(message){ }
}
-
///
/// Thrown when JSON is not valid.
///
public class InvalidJsonException : Exception
{
///
- public InvalidJsonException()
+ public InvalidJsonException()
{
}
diff --git a/Base/Xrpl.BinaryCodec/Types/StObject.cs b/Base/Xrpl.BinaryCodec/Types/StObject.cs
index 3b460d8f..6a235b72 100644
--- a/Base/Xrpl.BinaryCodec/Types/StObject.cs
+++ b/Base/Xrpl.BinaryCodec/Types/StObject.cs
@@ -227,7 +227,7 @@ public byte[] SigningData()
var list = new BytesList();
list.Put(HashPrefix.TransactionSig.Bytes());
ToBytes(list, f => f.IsSigningField);
- return list.Bytes();
+ return list.ToBytes();
}
///
/// this object to bytes array
@@ -237,7 +237,7 @@ public byte[] ToBytes()
{
var list = new BytesList();
ToBytes(list, f => f.IsSerialised);
- return list.Bytes();
+ return list.ToBytes();
}
///
/// add field to this object
diff --git a/Base/Xrpl.BinaryCodec/Xrpl.BinaryCodec.csproj b/Base/Xrpl.BinaryCodec/Xrpl.BinaryCodec.csproj
index effbac48..063bc389 100644
--- a/Base/Xrpl.BinaryCodec/Xrpl.BinaryCodec.csproj
+++ b/Base/Xrpl.BinaryCodec/Xrpl.BinaryCodec.csproj
@@ -13,7 +13,7 @@
https://github.com/Transia-RnD/XrplCSharp/LICENSE
https://github.com/Transia-RnD/XrplCSharp
XrplCSharp
- 1.0.0
+ 2.0.0
@@ -21,7 +21,7 @@
bin\Debug\net6.0\XrplCSharp.xml
-
+
diff --git a/Base/Xrpl.BinaryCodec/XrplBinaryCodec.cs b/Base/Xrpl.BinaryCodec/XrplBinaryCodec.cs
index 594af65e..b0880aa7 100644
--- a/Base/Xrpl.BinaryCodec/XrplBinaryCodec.cs
+++ b/Base/Xrpl.BinaryCodec/XrplBinaryCodec.cs
@@ -53,7 +53,7 @@ public static string Encode(object json)
///
///
/// string
- public static string EncodeForSigning(Dictionary json)
+ public static string EncodeForSigning(object json)
{
JToken token = JToken.FromObject(json);
return SerializeJson(token, HashPrefix.TransactionSig.Bytes(), null, true);
@@ -62,10 +62,12 @@ public static string EncodeForSigning(Dictionary json)
///
/// Encode a `payment channel here`_ Claim to be signed.
///
- ///
+ ///
/// string The binary-encoded claim, ready to be signed.
- public static string EncodeForSigningClaim(Dictionary json)
+ public static string EncodeForSigningClaim(object obj)
{
+ JToken json = JToken.FromObject(obj);
+
byte[] prefix = Bits.GetBytes(PAYMENT_CHANNEL_CLAIM_PREFIX);
byte[] channel = Hash256.FromHex((string)json["channel"]).Buffer;
byte[] amount = Uint64.FromValue(int.Parse((string)json["amount"])).ToBytes();
@@ -82,7 +84,7 @@ public static string EncodeForSigningClaim(Dictionary json)
///
///
/// string
- public static string EncodeForMulitSigning(Dictionary json, string signingAccount)
+ public static string EncodeForMulitSigning(object json, string signingAccount)
{
string accountID = new AccountId(signingAccount).ToHex();
JToken token = JToken.FromObject(json);
@@ -92,7 +94,7 @@ public static string EncodeForMulitSigning(Dictionary json, str
///
///
///
- ///
+ ///
/// string
public static string SerializeJson(JToken json, byte[]? prefix = null, byte[]? suffix = null, bool signingOnly = false)
{
diff --git a/Base/Xrpl.Keypairs/Ed25519/EdKeyPair.cs b/Base/Xrpl.Keypairs/Ed25519/EdKeyPair.cs
index 18401435..9b44be08 100644
--- a/Base/Xrpl.Keypairs/Ed25519/EdKeyPair.cs
+++ b/Base/Xrpl.Keypairs/Ed25519/EdKeyPair.cs
@@ -29,9 +29,9 @@ internal static IXrplKeyPair From128Seed(byte[] seed)
return new EdKeyPair(publicKey, expandedPrivateKey);
}
- public string Id() => prefix + FromBytesToHex(this._pubBytes);
+ public string Id() => prefix + _pubBytes.FromBytesToHex();
- public string Pk() => prefix + FromBytesToHex(this._privBytes[0..32]);
+ public string Pk() => prefix + _privBytes[0..32].FromBytesToHex();
public static byte[] Sign(byte[] message, byte[] privateKey) => Chaos.NaCl.Ed25519.Sign(message, privateKey);
diff --git a/Base/Xrpl.Keypairs/K256/K256KeyPair.cs b/Base/Xrpl.Keypairs/K256/K256KeyPair.cs
index 798dfe85..99c0a6c9 100644
--- a/Base/Xrpl.Keypairs/K256/K256KeyPair.cs
+++ b/Base/Xrpl.Keypairs/K256/K256KeyPair.cs
@@ -32,7 +32,7 @@ public string Id()
public string Pk()
{
- return $"00{FromBytesToHex(this._privKey.ToByteArrayUnsigned())}";
+ return $"00{_privKey.ToByteArrayUnsigned().FromBytesToHex()}";
}
public static byte[] Sign(byte[] message, byte[] privateKey)
diff --git a/Base/Xrpl.Keypairs/Xrpl.Keypairs.csproj b/Base/Xrpl.Keypairs/Xrpl.Keypairs.csproj
index effbac48..063bc389 100644
--- a/Base/Xrpl.Keypairs/Xrpl.Keypairs.csproj
+++ b/Base/Xrpl.Keypairs/Xrpl.Keypairs.csproj
@@ -13,7 +13,7 @@
https://github.com/Transia-RnD/XrplCSharp/LICENSE
https://github.com/Transia-RnD/XrplCSharp
XrplCSharp
- 1.0.0
+ 2.0.0
@@ -21,7 +21,7 @@
bin\Debug\net6.0\XrplCSharp.xml
-
+
diff --git a/Base/Xrpl.Keypairs/XrplKeypairs.cs b/Base/Xrpl.Keypairs/XrplKeypairs.cs
index 3b14216b..0224f78d 100644
--- a/Base/Xrpl.Keypairs/XrplKeypairs.cs
+++ b/Base/Xrpl.Keypairs/XrplKeypairs.cs
@@ -1,11 +1,12 @@
using System.Security.Cryptography;
+using System.Text;
+
using Xrpl.AddressCodec;
using Xrpl.Keypairs.Ed25519;
using Xrpl.Keypairs.K256;
-using static Xrpl.AddressCodec.XrplCodec;
+
using static Xrpl.AddressCodec.Utils;
-using System.Diagnostics;
-using System.Text;
+using static Xrpl.AddressCodec.XrplCodec;
// https://github.com/XRPLF/xrpl.js/blob/main/packages/ripple-keypairs/src/index.ts
@@ -75,7 +76,7 @@ public static IXrplKeyPair DeriveKeypair(string seed, string? algorithm = null,
///
public static string GetAlgorithmFromKey(string key)
{
- byte[] data = FromHexToBytes(key);
+ byte[] data = key.FromHexToBytes();
return data.Length == 33 && data[0] == 0xED ? "ed25519" : "secp256k1";
}
@@ -94,6 +95,12 @@ public static string Sign(byte[] message, string privateKey)
return K256KeyPair.Sign(message, privateKey.FromHex()).ToHex();
}
+ /// Sing message
+ /// Hex Message
+ /// private key
+ ///
+ public static string Sign(string HexMessage, string privateKey) => Sign(HexMessage.FromHexToBytes(), privateKey);
+
public static bool Verify(byte[] message, string signature, string publicKey)
{
string algorithm = GetAlgorithmFromKey(publicKey);
@@ -102,10 +109,12 @@ public static bool Verify(byte[] message, string signature, string publicKey)
: K256KeyPair.Verify(signature.FromHex(), message, publicKey.FromHex());
}
+ public static bool Verify(string HexMessage, string signature, string publicKey) => Verify(HexMessage.FromHexToBytes(), signature, publicKey);
+
public static string DeriveAddressFromBytes(byte[] publicKeyBytes)
=> XrplCodec.EncodeAccountID(Utils.HashUtils.PublicKeyHash(publicKeyBytes));
public static string DeriveAddress(string publicKey)
- => XrplKeypairs.DeriveAddressFromBytes(FromHexToBytes(publicKey));
+ => XrplKeypairs.DeriveAddressFromBytes(publicKey.FromHexToBytes());
}
}
\ No newline at end of file
diff --git a/Tests/TestsClients/Test.ClonsoleApp/Program.cs b/Tests/TestsClients/Test.ClonsoleApp/Program.cs
index 9bf2f412..bff9dd9f 100644
--- a/Tests/TestsClients/Test.ClonsoleApp/Program.cs
+++ b/Tests/TestsClients/Test.ClonsoleApp/Program.cs
@@ -56,7 +56,7 @@ static async Task SubmitTestTx()
var client = new XrplClient("wss://s.altnet.rippletest.net:51233");
- client.OnConnected += async () =>
+ client.connection.OnConnected += async () =>
{
Console.WriteLine("CONNECTED");
};
@@ -85,8 +85,7 @@ static async Task SubmitTestTx()
// sign and submit the transaction
Dictionary txJson = JsonConvert.DeserializeObject>(tx.ToJson());
Submit response = await client.Submit(txJson, wallet);
- Console.WriteLine(response);
-
+ Console.WriteLine(response.EngineResult);
}
static async Task WebsocketTest()
@@ -97,7 +96,7 @@ static async Task WebsocketTest()
var client = new XrplClient(server);
- client.OnConnected += async () =>
+ client.connection.OnConnected += async () =>
{
Console.WriteLine("CONNECTED");
var subscribe = await client.Subscribe(
@@ -110,14 +109,14 @@ static async Task WebsocketTest()
});
};
- client.OnDisconnect += (code) =>
+ client.connection.OnDisconnect += (code) =>
{
Console.WriteLine($"DISCONECTED CODE: {code}");
Console.WriteLine("DISCONECTED");
return Task.CompletedTask;
};
- client.OnError += (errorCode, errorMessage, error, data) =>
+ client.connection.OnError += (errorCode, errorMessage, error, data) =>
{
Console.WriteLine(errorCode);
Console.WriteLine(errorMessage);
@@ -125,13 +124,13 @@ static async Task WebsocketTest()
return Task.CompletedTask;
};
- client.OnTransaction += Response =>
+ client.connection.OnTransaction += Response =>
{
Console.WriteLine(Response.Transaction.TransactionType.ToString());
return Task.CompletedTask;
};
- client.OnLedgerClosed += r =>
+ client.connection.OnLedgerClosed += r =>
{
Console.WriteLine($"MESSAGE RECEIVED: {r}");
isFinished = true;
@@ -148,6 +147,121 @@ static async Task WebsocketTest()
await client.Disconnect();
}
+ static async Task WebsocketChangeServerTest()
+ {
+ bool isFinished = false;
+ var server1 = "wss://s1.ripple.com/";
+ var server2 = "wss://s2.ripple.com/";
+ var server3 = "wss://xrplcluster.com/";
+
+ var client = new XrplClient(server1);
+
+ client.connection.OnConnected += async () =>
+ {
+ Console.WriteLine("CONNECTED");
+ var subscribe = await client.Subscribe(
+ new SubscribeRequest()
+ {
+ Streams = new List(new[]
+ {
+ "ledger",
+ })
+ });
+ };
+
+ client.connection.OnDisconnect += (code) =>
+ {
+ Console.WriteLine($"DISCONECTED CODE: {code}");
+ return Task.CompletedTask;
+ };
+
+ client.connection.OnError += (errorCode, errorMessage, error, data) =>
+ {
+ Console.WriteLine(errorCode);
+ Console.WriteLine(errorMessage);
+ Console.WriteLine(data);
+ return Task.CompletedTask;
+ };
+
+ client.connection.OnTransaction += Response =>
+ {
+ Console.WriteLine(Response.Transaction.TransactionType.ToString());
+ return Task.CompletedTask;
+ };
+
+ client.connection.OnLedgerClosed += r =>
+ {
+ Console.WriteLine($"MESSAGE RECEIVED: {r}");
+ isFinished = true;
+ return Task.CompletedTask;
+ };
+
+ await client.Connect();
+
+ while (!isFinished)
+ {
+ Debug.WriteLine($"WAITING: {DateTime.Now}");
+ System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
+ }
+
+ await Task.Delay(3000);
+ isFinished = false;
+
+ await client.connection.ChangeServer(server2);
+ while (!isFinished)
+ {
+ Debug.WriteLine($"WAITING: {DateTime.Now}");
+ System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
+ }
+ await Task.Delay(3000);
+ isFinished = false;
+
+ await client.connection.ChangeServer(server3);
+ while (!isFinished)
+ {
+ Debug.WriteLine($"WAITING: {DateTime.Now}");
+ System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
+ }
+ await Task.Delay(3000);
+ isFinished = false;
+
+ await client.connection.ChangeServer(server1);
+ while (!isFinished)
+ {
+ Debug.WriteLine($"WAITING: {DateTime.Now}");
+ System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
+ }
+ await Task.Delay(3000);
+ isFinished = false;
+
+ await client.connection.ChangeServer(server2);
+ while (!isFinished)
+ {
+ Debug.WriteLine($"WAITING: {DateTime.Now}");
+ System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
+ }
+ await Task.Delay(3000);
+ isFinished = false;
+
+ await client.connection.ChangeServer(server3);
+ while (!isFinished)
+ {
+ Debug.WriteLine($"WAITING: {DateTime.Now}");
+ System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
+ }
+ await Task.Delay(3000);
+ isFinished = false;
+
+ await client.connection.ChangeServer(server1);
+ while (!isFinished)
+ {
+ Debug.WriteLine($"WAITING: {DateTime.Now}");
+ System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
+ }
+ await Task.Delay(3000);
+
+ await client.Disconnect();
+ }
static async Task Main(string[] args)
{
@@ -156,6 +270,7 @@ static async Task Main(string[] args)
//WalletGenerate();
//await SubmitTestTx();
//await WebsocketTest();
+ await WebsocketChangeServerTest();
}
}
}
diff --git a/Tests/Xrpl.AddressCodec.Test/Xrpl.AddressCodec.Test.csproj b/Tests/Xrpl.AddressCodec.Test/Xrpl.AddressCodec.Test.csproj
index 6440d535..69cb3651 100644
--- a/Tests/Xrpl.AddressCodec.Test/Xrpl.AddressCodec.Test.csproj
+++ b/Tests/Xrpl.AddressCodec.Test/Xrpl.AddressCodec.Test.csproj
@@ -14,11 +14,11 @@
-
-
-
+
+
+
-
+
diff --git a/Tests/Xrpl.BinaryCodec.Test/Xrpl.BinaryCodec.Test.csproj b/Tests/Xrpl.BinaryCodec.Test/Xrpl.BinaryCodec.Test.csproj
index d1610fa8..6a672438 100644
--- a/Tests/Xrpl.BinaryCodec.Test/Xrpl.BinaryCodec.Test.csproj
+++ b/Tests/Xrpl.BinaryCodec.Test/Xrpl.BinaryCodec.Test.csproj
@@ -14,11 +14,11 @@
-
-
-
+
+
+
-
+
diff --git a/Tests/Xrpl.Keypairs.Test/Xrpl.Keypairs.Test.csproj b/Tests/Xrpl.Keypairs.Test/Xrpl.Keypairs.Test.csproj
index 399d491f..f78f8b2d 100644
--- a/Tests/Xrpl.Keypairs.Test/Xrpl.Keypairs.Test.csproj
+++ b/Tests/Xrpl.Keypairs.Test/Xrpl.Keypairs.Test.csproj
@@ -14,11 +14,11 @@
-
-
-
+
+
+
-
+
diff --git a/Tests/Xrpl.Tests/Client/TestSubscribe.cs b/Tests/Xrpl.Tests/Client/TestSubscribe.cs
index f4f815d4..83e1687e 100644
--- a/Tests/Xrpl.Tests/Client/TestSubscribe.cs
+++ b/Tests/Xrpl.Tests/Client/TestSubscribe.cs
@@ -67,7 +67,7 @@ public async Task TestUnsubscribe()
public void TestEmitsTransaction()
{
bool isDone = false;
- runner.client.OnTransaction += r =>
+ runner.client.connection.OnTransaction += r =>
{
Assert.IsTrue(r.Type == ResponseStreamType.transaction);
isDone = true;
@@ -86,7 +86,7 @@ public void TestEmitsTransaction()
[TestMethod]
public void TestEmitsLedger()
{
- runner.client.OnLedgerClosed += r =>
+ runner.client.connection.OnLedgerClosed += r =>
{
//Assert.IsTrue(r.Type == ResponseStreamType.ledgerClosed);
return Task.CompletedTask;
@@ -99,7 +99,7 @@ public void TestEmitsLedger()
[TestMethod]
public void TestEmitsPeerStatusChange()
{
- runner.client.OnPeerStatusChange += r =>
+ runner.client.connection.OnPeerStatusChange += r =>
{
Assert.IsTrue(r.Type == ResponseStreamType.consensusPhase);
return Task.CompletedTask;
@@ -112,7 +112,7 @@ public void TestEmitsPeerStatusChange()
[TestMethod]
public void TestEmitsPathFind()
{
- runner.client.OnPathFind += r =>
+ runner.client.connection.OnPathFind += r =>
{
Assert.IsTrue(r.Type == ResponseStreamType.path_find);
return Task.CompletedTask;
@@ -125,7 +125,7 @@ public void TestEmitsPathFind()
[TestMethod]
public void TestEmitsValidationReceived()
{
- runner.client.OnManifestReceived += r =>
+ runner.client.connection.OnManifestReceived += r =>
{
Assert.IsTrue(r.Type == ResponseStreamType.validationReceived);
return Task.CompletedTask;
@@ -162,20 +162,20 @@ public async Task TestSubscribe()
var client = new XrplClient(server);
- client.OnConnected += () =>
+ client.connection.OnConnected += () =>
{
Console.WriteLine("CONNECTED");
return Task.CompletedTask;
};
- client.OnDisconnect += (code) =>
+ client.connection.OnDisconnect += (code) =>
{
Console.WriteLine($"DISCONNECTED: {code}");
isFinished = true;
return Task.CompletedTask;
};
- client.OnLedgerClosed += (message) =>
+ client.connection.OnLedgerClosed += (message) =>
{
Console.WriteLine($"MESSAGE RECEIVED: {message}");
//Dictionary json = JsonConvert.DeserializeObject>(message);
diff --git a/Tests/Xrpl.Tests/Client/TestWebSocketClient.cs b/Tests/Xrpl.Tests/Client/TestWebSocketClient.cs
index 66601a05..de7b84b9 100644
--- a/Tests/Xrpl.Tests/Client/TestWebSocketClient.cs
+++ b/Tests/Xrpl.Tests/Client/TestWebSocketClient.cs
@@ -32,11 +32,10 @@ public void TestSome()
var response = JsonConvert.DeserializeObject>(message);
var message1 = JsonConvert.SerializeObject(response);
var response1 = JsonConvert.DeserializeObject(message1);
- Debug.WriteLine(response1);
}
[TestMethod]
- public async Task _TestSubscribeWebSocket()
+ public async Task TestSubscribeWebSocket()
{
bool isTested = false;
@@ -44,133 +43,56 @@ public async Task _TestSubscribeWebSocket()
var server = "wss://xrplcluster.com/";
- var client = WebSocketClient.Create(server);
-
- //client.OnConnected += (ws, t) =>
- //{
- // Console.WriteLine($"CONNECTED");
- //};
-
- //client.OnConnectionException += (ws, ex) =>
- //{
- // Console.WriteLine($"CONNECTION EXCEPTION: {ex.Message}");
- // isFinished = true;
- //};
-
- //client.OnException += (ws, ex) =>
- //{
- // Console.WriteLine($"EXCEPTION: {ex.Message}");
- // isFinished = true;
- //};
-
- //client.OnDisconnect += (ws, code) =>
- //{
- // Console.WriteLine($"DISCONNECTED: {code}");
- // isFinished = true;
- //};
-
- //client.OnMessageReceived += (ws, message) =>
- //{
- // Console.WriteLine($"MESSAGE RECEIVED: {message}");
- // Dictionary json = JsonConvert.DeserializeObject>(message);
- // if (json["type"] == "ledgerClosed")
- // {
- // isTested = true;
- // isFinished = true;
- // }
- //};
+ var client = new XrplClient(server);
- Timer timer = new Timer(5000);
- timer.Elapsed += (sender, e) =>
- {
- Debug.WriteLine("TIMEOUT!!");
- client.Dispose();
- isFinished = true;
- };
- timer.Start();
-
- _ = client.Connect();
-
- //while (!client.State == WebSocketState.Open)
- //{
- // Debug.WriteLine($"CONNECTING... {DateTime.Now}");
- // System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
- //}
-
- var request = new SubscribeRequest()
+ client.connection.OnConnected += async () =>
{
- Streams = new List(new[]
+ Console.WriteLine("CONNECTED");
+ var subscribe = await client.Subscribe(
+ new SubscribeRequest()
+ {
+ Streams = new List(new[]
{
"ledger",
})
+ });
};
- var serializerSettings = new JsonSerializerSettings();
- serializerSettings.NullValueHandling = NullValueHandling.Ignore;
- serializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
- serializerSettings.FloatParseHandling = FloatParseHandling.Double;
- serializerSettings.FloatFormatHandling = FloatFormatHandling.DefaultValue;
- string jsonString = JsonConvert.SerializeObject(request, serializerSettings);
- client.SendMessage(jsonString);
-
- Debug.WriteLine($"BEFORE: {DateTime.Now}");
- while (!isFinished)
+ client.connection.OnError += (error, errorMessage, message, data) =>
{
- Debug.WriteLine($"WAITING: {DateTime.Now}");
- System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
- }
- Debug.WriteLine($"AFTER: {DateTime.Now}");
- Debug.WriteLine($"IS FINISHED: {isFinished}");
- Debug.WriteLine($"IS TESTER: {isTested}");
- Assert.IsTrue(isTested);
- }
-
+ Console.WriteLine($"CONN ERROR: {error}");
+ Console.WriteLine($"CONN ERROR MESSAGE: {errorMessage}");
+ Console.WriteLine($"CONN MESSAGE: {message}");
+ Console.WriteLine($"CONN ERROR DATA: {data}");
+ isFinished = true;
+ return Task.CompletedTask;
+ };
- [TestMethod]
- public async Task _TestWebSocketClientTimeout()
- {
- bool isFinished = false;
+ client.connection.OnDisconnect += (code) =>
+ {
+ Console.WriteLine($"DISCONNECTED: {code}");
+ isFinished = true;
+ return Task.CompletedTask;
+ };
- var server = "wss://xrplcluster.com/";
+ client.connection.OnLedgerClosed += (message) =>
+ {
+ Console.WriteLine($"LEDGER CLOSED: {message}");
+ isFinished = true;
+ isTested = true;
+ return Task.CompletedTask;
+ };
- var client = WebSocketClient.Create(server);
-
- //client.OnConnected += (ws, t) =>
- //{
- // Debug.WriteLine($"CONNECTED");
- // Assert.IsNotNull(t);
- // Assert.IsFalse(t.IsCancellationRequested);
- // isFinished = true;
- //};
-
- //client.OnConnectionException += (ws, ex) =>
- //{
- // Debug.WriteLine($"CONNECTION EXCEPTION: {ex.Message}");
- // isFinished = true;
- //};
-
- //client.OnException += (ws, ex) =>
- //{
- // Debug.WriteLine($"EXCEPTION: {ex.Message}");
- // //Debug.WriteLine(message);
- // isFinished = true;
- //};
-
- //client.OnDisconnect += (ws, code) =>
- //{
- // Debug.WriteLine($"DISCONNECTED: {code}");
- // isFinished = true;
- //};
-
- Timer timer = new Timer(2000);
+ Timer timer = new Timer(5000);
timer.Elapsed += (sender, e) =>
{
+ Debug.WriteLine("TIMEOUT!!");
client.Dispose();
isFinished = true;
};
timer.Start();
- client.Connect();
+ await client.Connect();
Debug.WriteLine($"BEFORE: {DateTime.Now}");
@@ -180,6 +102,9 @@ public async Task _TestWebSocketClientTimeout()
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
}
Debug.WriteLine($"AFTER: {DateTime.Now}");
+ Debug.WriteLine($"IS FINISHED: {isFinished}");
+ Debug.WriteLine($"IS TESTER: {isTested}");
+ Assert.IsTrue(isTested);
}
}
}
diff --git a/Tests/Xrpl.Tests/Integration/SetupIClient.cs b/Tests/Xrpl.Tests/Integration/SetupIClient.cs
index 9d69c178..c6982454 100644
--- a/Tests/Xrpl.Tests/Integration/SetupIClient.cs
+++ b/Tests/Xrpl.Tests/Integration/SetupIClient.cs
@@ -18,17 +18,17 @@ public async Task SetupClient(string serverUrl)
wallet = XrplWallet.Generate();
var promise = new TaskCompletionSource();
client = new XrplClient(serverUrl);
- client.OnConnected += () =>
+ client.connection.OnConnected += () =>
{
Console.WriteLine($"SetupIntegration CONNECTED");
return Task.CompletedTask;
};
- client.OnDisconnect += (code) =>
+ client.connection.OnDisconnect += (code) =>
{
Console.WriteLine($"SetupIntegration DISCONNECTED: {code}");
return Task.CompletedTask;
};
- client.OnError += (error, errorMessage, message, data) =>
+ client.connection.OnError += (error, errorMessage, message, data) =>
{
Console.WriteLine($"SetupIntegration ERROR: {message}");
return Task.CompletedTask;
diff --git a/Tests/Xrpl.Tests/Models/TestAMMBid.cs b/Tests/Xrpl.Tests/Models/TestAMMBid.cs
index 1f3e8f3f..00483c45 100644
--- a/Tests/Xrpl.Tests/Models/TestAMMBid.cs
+++ b/Tests/Xrpl.Tests/Models/TestAMMBid.cs
@@ -131,13 +131,104 @@ public async Task TestVerifyValid()
},
};
await Assert.ThrowsExceptionAsync(() => Validation.Validate(bid), "AMMBid: invalid ClearFlag - no ERROR");
+
+ //throws w/ AuthAccounts must be an AuthAccount array
+ bid["AuthAccounts"] = 1234;
+ await Assert.ThrowsExceptionAsync(() => Validation.Validate(bid), "AMMBid: AuthAccounts must be an AuthAccount array");
+
bid["AuthAccounts"] = new List>()
{
new Dictionary()
+ {
+ {"AuthAccount",null}
+ }, new Dictionary()
{
{"AuthAccount",new Dictionary()
{
- { "Account", "rNZdsTBP5tH1M6GHC6bTreHAp6ouP8iZSh" }
+ { "Account", "rfpFv97Dwu89FTyUwPjtpZBbuZxTqqgTmH" }
+ }}
+ }, new Dictionary()
+ {
+ {"AuthAccount",new Dictionary()
+ {
+ { "Account", "rzzYHPGb8Pa64oqxCzmuffm122bitq3Vb" }
+ }}
+ }, new Dictionary()
+ {
+ {"AuthAccount",new Dictionary()
+ {
+ { "Account", "rhwxHxaHok86fe4LykBom1jSJ3RYQJs1h4" }
+ }}
+ }
+ };
+
+ //throws w/ invalid AuthAccounts when AuthAccount is undefined
+ await Assert.ThrowsExceptionAsync(() => Validation.Validate(bid), "AMMBid: invalid AuthAccounts");
+ //throws w/ invalid AuthAccounts when AuthAccount is not an object
+ bid["AuthAccounts"] = new List>()
+ {
+ new Dictionary()
+ {
+ {"AuthAccount",1234}
+ }, new Dictionary()
+ {
+ {"AuthAccount",new Dictionary()
+ {
+ { "Account", "rfpFv97Dwu89FTyUwPjtpZBbuZxTqqgTmH" }
+ }}
+ }, new Dictionary()
+ {
+ {"AuthAccount",new Dictionary()
+ {
+ { "Account", "rzzYHPGb8Pa64oqxCzmuffm122bitq3Vb" }
+ }}
+ }, new Dictionary()
+ {
+ {"AuthAccount",new Dictionary()
+ {
+ { "Account", "rhwxHxaHok86fe4LykBom1jSJ3RYQJs1h4" }
+ }}
+ }
+ };
+ await Assert.ThrowsExceptionAsync(() => Validation.Validate(bid), "AMMBid: invalid AuthAccounts");
+ // throws w/ invalid AuthAccounts when AuthAccount.Account is not a string
+ bid["AuthAccounts"] = new List>()
+ {
+ new Dictionary()
+ {
+ {"AuthAccount",new Dictionary()
+ {
+ { "Account", 1234 }
+ }}
+ }, new Dictionary()
+ {
+ {"AuthAccount",new Dictionary()
+ {
+ { "Account", "rfpFv97Dwu89FTyUwPjtpZBbuZxTqqgTmH" }
+ }}
+ }, new Dictionary()
+ {
+ {"AuthAccount",new Dictionary()
+ {
+ { "Account", "rzzYHPGb8Pa64oqxCzmuffm122bitq3Vb" }
+ }}
+ }, new Dictionary()
+ {
+ {"AuthAccount",new Dictionary()
+ {
+ { "Account", "rhwxHxaHok86fe4LykBom1jSJ3RYQJs1h4" }
+ }}
+ }
+ };
+ await Assert.ThrowsExceptionAsync(() => Validation.Validate(bid), "AMMBid: invalid AuthAccounts");
+ //throws w/ AuthAccounts must not include sender's address
+ bid["AuthAccounts"] = new List>()
+ {
+ new Dictionary()
+ {
+ {"AuthAccount",new Dictionary()
+ {
+ { "Account", bid["Account"] }
}}
}, new Dictionary()
{
@@ -159,6 +250,8 @@ public async Task TestVerifyValid()
}}
}
};
+ await Assert.ThrowsExceptionAsync(() => Validation.Validate(bid), "AMMBid: AuthAccounts must not include sender's address");
+
}
}
}
diff --git a/Tests/Xrpl.Tests/Models/TestAMMVote.cs b/Tests/Xrpl.Tests/Models/TestAMMVote.cs
index 044afbc0..318964d3 100644
--- a/Tests/Xrpl.Tests/Models/TestAMMVote.cs
+++ b/Tests/Xrpl.Tests/Models/TestAMMVote.cs
@@ -24,7 +24,7 @@ public static void MyClassInitialize(TestContext testContext)
{"Account", "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm"},
{"Asset", new Dictionary(){{"currency","XRP"}}},
{"Asset2", new Dictionary(){{"currency","ETH"},{"issuer", "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd" } }},
- {"TradingFee", 12u},
+ {"TradingFee", 25u},
{"Sequence", 1337u},
};
}
diff --git a/Tests/Xrpl.Tests/SetupClient.cs b/Tests/Xrpl.Tests/SetupClient.cs
index 9f58758f..2ee0722b 100644
--- a/Tests/Xrpl.Tests/SetupClient.cs
+++ b/Tests/Xrpl.Tests/SetupClient.cs
@@ -29,17 +29,17 @@ public async Task SetupClient()
Timer timer = new Timer(25000);
timer.Elapsed += (sender, e) => tcpListenerThread.Abort();
client = new XrplClient($"ws://127.0.0.1:{port}");
- client.OnConnected += () =>
+ client.connection.OnConnected += () =>
{
Debug.WriteLine("SETUP CLIENT: CONECTED");
return Task.CompletedTask;
};
- client.OnDisconnect += (code) =>
+ client.connection.OnDisconnect += (code) =>
{
Debug.WriteLine("SETUP CLIENT: DISCONECTED");
return Task.CompletedTask;
};
- client.OnError += (e, em, m, d) =>
+ client.connection.OnError += (e, em, m, d) =>
{
Debug.WriteLine($"SETUP CLIENT: ERROR: {e}");
return Task.CompletedTask;
diff --git a/Tests/Xrpl.Tests/Utils/ParseNFTokenID.cs b/Tests/Xrpl.Tests/Utils/ParseNFTokenID.cs
index 7ec2bfe9..9757edb5 100644
--- a/Tests/Xrpl.Tests/Utils/ParseNFTokenID.cs
+++ b/Tests/Xrpl.Tests/Utils/ParseNFTokenID.cs
@@ -22,13 +22,13 @@ public void ParsingNFTokenID()
{
const string nftokenId = "000813886377BBDA772433D7FCF16A9710D9D958D9F7129F376D5FC200005026";
- NFTokenIDData nftokenIDData = ParseNFTID.GetNFTokenIDData(nftokenId);
+ NFTokenIDData nftokenIDData = nftokenId.ParseNFTokenID();
- Assert.AreEqual((UInt32)8, nftokenIDData.Flags);
+ Assert.AreEqual((uint)8, nftokenIDData.Flags);
Assert.AreEqual("rwhALEr1jdhuxKqoTno8cyGXw9yLSsqC6A", nftokenIDData.Issuer);
Assert.AreEqual(nftokenId, nftokenIDData.NFTokenID);
- Assert.AreEqual((UInt32)3, nftokenIDData.Taxon);
- Assert.AreEqual((UInt32)5000, nftokenIDData.TransferFee);
+ Assert.AreEqual((uint)3, nftokenIDData.Taxon);
+ Assert.AreEqual((uint)5000, nftokenIDData.TransferFee);
}
[TestMethod]
diff --git a/Tests/Xrpl.Tests/Wallet/WalletTest.cs b/Tests/Xrpl.Tests/Wallet/WalletTest.cs
index 5a6147b9..6bd79cc4 100644
--- a/Tests/Xrpl.Tests/Wallet/WalletTest.cs
+++ b/Tests/Xrpl.Tests/Wallet/WalletTest.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
@@ -754,3 +755,69 @@ public void TestVerifyMainnet()
}
}
}
+namespace Xrpl.Tests.Wallet.Tests.XummNumbers
+{
+ [TestClass]
+ public class TestUXummNumbers
+ {
+ string[] xummNumbers = new[] { "556863", "404730", "402495", "038856", "113360", "465825", "112585", "283320" };
+
+ string wallet_num = "rNUhe55ffGjezrVwTQfpL73aP5qKdofZMy";
+ string wallet_seed = "snjnsXBywtRUzVQagnjfXHwo97x1E";
+ private string wallet_private_key = "00FC5D3ACE7236F40683947E68575316959D07C2425EE12F41E534EA4295BABFAA";
+
+ [TestMethod]
+ public void TestVerify_EntropyFromXummNumbers()
+ {
+ XrplWallet result = XrplWallet.FromXummNumbers(xummNumbers, "secp256k1");
+ //sEdVLhsR1xkLWWLX9KbErLTo6EEaHFi WRONG SEED
+ //rJP8D3Mpntnp7T1YZyz51xwtdeYKcz5hpR WRONG ADDRESS
+
+ Assert.AreEqual(result.Seed, wallet_seed);
+ Assert.AreEqual(result.ClassicAddress, wallet_num);
+ Assert.AreEqual(result.PrivateKey, wallet_private_key);
+ }
+
+ [TestMethod]
+ public void TestVerify_InValid_EntropyFromXummNumbers()
+ {
+ var numbers = new string[8];
+ Array.Copy(xummNumbers, numbers, 8);
+ numbers[0] = "556862";
+ Assert.ThrowsException(() => XrplWallet.FromXummNumbers(numbers), "Wrong numbers");
+ }
+
+ [TestMethod]
+ public void TestVerify_CheckXummSum()
+ {
+ var number = xummNumbers[0];
+ var position = 0;
+ var valid_sum = XummExtension.CheckXummSum(position, number);
+ Assert.AreEqual(true, valid_sum);
+
+ number = xummNumbers[2];
+ position = 2;
+ valid_sum = XummExtension.CheckXummSum(position, number);
+ Assert.AreEqual(true, valid_sum);
+
+ number = xummNumbers[6];
+ position = 6;
+ valid_sum = XummExtension.CheckXummSum(position, number);
+ Assert.AreEqual(true, valid_sum);
+
+ number = xummNumbers[7];
+ position = 7;
+ valid_sum = XummExtension.CheckXummSum(position, number);
+ Assert.AreEqual(true, valid_sum);
+ }
+ [TestMethod]
+ public void TestVerify_InValid_CheckXummSum()
+ {
+ var number = xummNumbers[3];
+ var position = 2;
+ var valid_sum = XummExtension.CheckXummSum(position, number);
+ Assert.AreNotEqual(true, valid_sum);
+ }
+ }
+}
+
diff --git a/Tests/Xrpl.Tests/Xrpl.Tests.csproj b/Tests/Xrpl.Tests/Xrpl.Tests.csproj
index 2c780c9c..6312d133 100644
--- a/Tests/Xrpl.Tests/Xrpl.Tests.csproj
+++ b/Tests/Xrpl.Tests/Xrpl.Tests.csproj
@@ -14,11 +14,11 @@
-
-
-
+
+
+
-
+
diff --git a/Xrpl/Client/IXrplClient.cs b/Xrpl/Client/IXrplClient.cs
index 587e0ea5..0fa6d90b 100644
--- a/Xrpl/Client/IXrplClient.cs
+++ b/Xrpl/Client/IXrplClient.cs
@@ -15,6 +15,8 @@
using Xrpl.Sugar;
using Xrpl.Wallet;
using static Xrpl.Client.Connection;
+using static Xrpl.Client.XrplClient;
+
using BookOffers = Xrpl.Models.Transactions.BookOffers;
using Submit = Xrpl.Models.Transactions.Submit;
@@ -27,7 +29,7 @@ namespace Xrpl.Client
public delegate Task OnError(string error, string errorMessage, string message, dynamic data);
public delegate Task OnConnected();
public delegate Task OnDisconnect(int? code);
- public delegate Task OnLedgerClosed(object response);
+ public delegate Task OnLedgerClosed(LedgerStream response);
public delegate Task OnTransaction(TransactionStream response);
public delegate Task OnManifestReceived(ValidationStream response);
public delegate Task OnPeerStatusChange(PeerStatusStream response);
@@ -40,16 +42,26 @@ public interface IXrplClient : IDisposable
Connection connection { get; set; }
double feeCushion { get; set; }
string maxFeeXRP { get; set; }
+ uint? networkID { get; set; }
- event OnError OnError;
- event OnConnected OnConnected;
- event OnDisconnect OnDisconnect;
- event OnLedgerClosed OnLedgerClosed;
- event OnTransaction OnTransaction;
- event OnManifestReceived OnManifestReceived;
- event OnPeerStatusChange OnPeerStatusChange;
- event OnConsensusPhase OnConsensusPhase;
- event OnPathFind OnPathFind;
+ ///
+ /// Set network id for transactions, required in network where Id > 1024
+ ///
+ /// network id
+ public void SetNetworkId(uint? networkID)
+ {
+ this.networkID = networkID;
+ }
+
+ //event OnError OnError;
+ //event OnConnected OnConnected;
+ //event OnDisconnect OnDisconnect;
+ //event OnLedgerClosed OnLedgerClosed;
+ //event OnTransaction OnTransaction;
+ //event OnManifestReceived OnManifestReceived;
+ //event OnPeerStatusChange OnPeerStatusChange;
+ //event OnConsensusPhase OnConsensusPhase;
+ //event OnPathFind OnPathFind;
#region Server
/// the url
@@ -191,8 +203,9 @@ public interface IXrplClient : IDisposable
/// To be successful, the weights of the signatures must be equal or higher than the quorum of the SignerList.
///
/// //todo add description
- /// An response.
+ /// An response.
Task Submit(Dictionary tx, XrplWallet wallet);
+ Task Submit(ITransactionCommon tx, XrplWallet wallet);
///
/// The tx method retrieves information on a single transaction, by its identifying hash
///
@@ -247,11 +260,18 @@ public interface IXrplClient : IDisposable
#endregion
+
+ ///
+ /// The amm_info method gets information about an Automated Market Maker (AMM) instance.
+ ///
+ /// An request.
+ /// An response.
+ Task AmmInfo(AMMInfoRequest request);
///
/// The book_offers method retrieves a list of offers, also known as the order book , between two currencies
///
/// An request.
- /// An response.
+ /// An response.
Task BookOffers(BookOffersRequest request);
///
/// The random command provides a random number to be used as a source of entropy for random number generation by clients.
@@ -276,6 +296,7 @@ public interface IXrplClient : IDisposable
Task> Autofill(Dictionary tx);
Task GetLedgerIndex();
Task GetXrpBalance(string address);
+ Task ChangeServer(string server, ClientOptions? options = null);
}
@@ -284,6 +305,7 @@ public class XrplClient : IXrplClient
public class ClientOptions : ConnectionOptions
{
+ public uint? NetworkID { get; set; }
public double? feeCushion { get; set; }
public string? maxFeeXRP { get; set; }
}
@@ -291,16 +313,17 @@ public class ClientOptions : ConnectionOptions
public Connection connection { get; set; }
public double feeCushion { get; set; }
public string maxFeeXRP { get; set; }
-
- public event OnError OnError;
- public event OnConnected OnConnected;
- public event OnDisconnect OnDisconnect;
- public event OnLedgerClosed OnLedgerClosed;
- public event OnTransaction OnTransaction;
- public event OnManifestReceived OnManifestReceived;
- public event OnPeerStatusChange OnPeerStatusChange;
- public event OnConsensusPhase OnConsensusPhase;
- public event OnPathFind OnPathFind;
+ public uint? networkID { get; set; }
+
+ //public event OnError OnError;
+ //public event OnConnected OnConnected;
+ //public event OnDisconnect OnDisconnect;
+ //public event OnLedgerClosed OnLedgerClosed;
+ //public event OnTransaction OnTransaction;
+ //public event OnManifestReceived OnManifestReceived;
+ //public event OnPeerStatusChange OnPeerStatusChange;
+ //public event OnConsensusPhase OnConsensusPhase;
+ //public event OnPathFind OnPathFind;
///// Current web socket client state
//public WebSocketState SocketState => client.State;
@@ -316,17 +339,30 @@ public XrplClient(string server, ClientOptions? options = null)
}
feeCushion = options?.feeCushion ?? 1.2;
maxFeeXRP = options?.maxFeeXRP ?? "2";
+ networkID = options?.NetworkID;
connection = new Connection(server, options);
- connection.OnError += (e, em, m, d) => OnError(e, em, m, d);
- connection.OnConnected += () => OnConnected();
- connection.OnDisconnect += (c) => OnDisconnect(c);
- connection.OnLedgerClosed += (s) => OnLedgerClosed(s);
- connection.OnTransaction += (s) => OnTransaction(s);
- connection.OnManifestReceived += (s) => OnManifestReceived(s);
- connection.OnPeerStatusChange += (s) => OnPeerStatusChange(s);
- connection.OnConsensusPhase += (s) => OnConsensusPhase(s);
- connection.OnPathFind += (s) => OnPathFind(s);
+ //connection.OnError += (e, em, m, d) => OnError?.Invoke(e, em, m, d);
+ //connection.OnConnected += () => OnConnected?.Invoke();
+ //connection.OnDisconnect += (c) => OnDisconnect?.Invoke(c);
+ //connection.OnLedgerClosed += (s) => OnLedgerClosed?.Invoke(s);
+ //connection.OnTransaction += (s) => OnTransaction?.Invoke(s);
+ //connection.OnManifestReceived += (s) => OnManifestReceived?.Invoke(s);
+ //connection.OnPeerStatusChange += (s) => OnPeerStatusChange?.Invoke(s);
+ //connection.OnConsensusPhase += (s) => OnConsensusPhase?.Invoke(s);
+ //connection.OnPathFind += (s) => OnPathFind?.Invoke(s);
+ }
+
+ public async Task ChangeServer(string server, ClientOptions? options = null)
+ {
+ if (!IsValidWss(server))
+ {
+ throw new Exception("Invalid WSS Server Url");
+ }
+ feeCushion = options?.feeCushion ?? 1.2;
+ maxFeeXRP = options?.maxFeeXRP ?? "2";
+
+ await connection.ChangeServer(server, options);
}
///
@@ -361,13 +397,25 @@ public bool IsConnected()
// SUGARS
public Task> Autofill(Dictionary tx)
{
- return AutofillSugar.Autofill(this, tx, null);
+ return this.Autofill(tx, null);
}
///
public Task Submit(Dictionary tx, XrplWallet wallet)
{
- return SubmitSugar.Submit(this, tx, true, false, wallet);
+ return this.Submit(tx, true, false, wallet);
+ }
+ ///
+ public Task Submit(ITransactionCommon tx, XrplWallet wallet)
+ {
+ if (networkID is { } network)
+ {
+ tx.NetworkID = network;
+ }
+ var json = tx.ToJson();
+ //var json = JsonConvert.SerializeObject(tx);
+ Dictionary txJson = JsonConvert.DeserializeObject>(json);
+ return this.Submit(txJson, true, false, wallet);
}
///
@@ -430,6 +478,12 @@ public Task AccountTransactions(AccountTransactionsRequest
return this.GRequest(request);
}
+ ///
+ public Task AmmInfo(AMMInfoRequest request)
+ {
+ return this.GRequest(request);
+ }
+
///
public Task BookOffers(BookOffersRequest request)
{
@@ -602,7 +656,7 @@ public async Task GRequest(R request)
public string EnsureClassicAddress(string address)
{
- return address;
+ return Xrpl.Sugar.Utils.EnsureClassicAddress(address);
}
#region IDisposable
diff --git a/Xrpl/Client/Json/Converters/CurrencyConverter.cs b/Xrpl/Client/Json/Converters/CurrencyConverter.cs
index 61c1c186..e1033f3a 100644
--- a/Xrpl/Client/Json/Converters/CurrencyConverter.cs
+++ b/Xrpl/Client/Json/Converters/CurrencyConverter.cs
@@ -62,4 +62,61 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
/// bool result
public override bool CanConvert(Type objectType) => objectType == typeof(Currency);
}
+ /// currency json converter
+ public class IssuedCurrencyConverter : JsonConverter
+ {
+ ///
+ /// write to json object
+ ///
+ /// writer
+ /// value
+ /// json serializer
+ /// Cannot write this object type
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ if (value is Common.IssuedCurrency currency)
+ {
+ if (currency.Currency == "XRP")
+ {
+ JToken t = JToken.FromObject(new Common.XRP());
+ t.WriteTo(writer);
+ }
+ else
+ {
+ JToken t = JToken.FromObject(currency);
+ t.WriteTo(writer);
+ }
+ }
+ else
+ {
+ throw new NotSupportedException("Cannot write this object type");
+ }
+ }
+ /// read from json object
+ /// json reader
+ /// object type
+ /// object value
+ /// json serializer
+ ///
+ /// Cannot convert value
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
+ JsonSerializer serializer)
+ {
+ return reader.TokenType switch
+ {
+ JsonToken.Null => null,
+ JsonToken.String => new Common.IssuedCurrency()
+ {
+ Currency = "XRP",
+ },
+
+ JsonToken.StartObject => serializer.Deserialize(reader),
+ _ => throw new NotSupportedException("Cannot convert value " + objectType)
+ };
+ }
+ /// Can convert object to currency
+ /// object type
+ /// bool result
+ public override bool CanConvert(Type objectType) => objectType == typeof(Common.IssuedCurrency);
+ }
}
diff --git a/Xrpl/Client/Json/Converters/LONFTokenConverter.cs b/Xrpl/Client/Json/Converters/LONFTokenConverter.cs
new file mode 100644
index 00000000..a8d5be98
--- /dev/null
+++ b/Xrpl/Client/Json/Converters/LONFTokenConverter.cs
@@ -0,0 +1,51 @@
+using System;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Xrpl.Models.Ledger;
+using Xrpl.Models.Methods;
+
+namespace Xrpl.Client.Json.Converters;
+
+///
+/// json converter
+///
+public class LONFTokenConverter : JsonConverter
+{
+
+ ///
+ /// write to json object
+ ///
+ /// writer
+ /// value
+ /// json serializer
+ /// Can't create ledger type
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ /// read from json object
+ /// json reader
+ /// object type
+ /// object value
+ /// json serializer
+ ///
+ /// Cannot convert value
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ JObject jObject = JObject.Load(reader);
+ var value = jObject.GetValue("NFToken");
+ var target = new NFToken();
+ serializer.Populate(value.CreateReader(), target);
+
+ return target;
+ }
+
+ public override bool CanConvert(Type objectType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override bool CanWrite => false;
+}
\ No newline at end of file
diff --git a/Xrpl/Client/Json/Converters/LedgerObjectConverter.cs b/Xrpl/Client/Json/Converters/LedgerObjectConverter.cs
index a4bc381d..52108a31 100644
--- a/Xrpl/Client/Json/Converters/LedgerObjectConverter.cs
+++ b/Xrpl/Client/Json/Converters/LedgerObjectConverter.cs
@@ -3,6 +3,7 @@
using Newtonsoft.Json.Linq;
using Xrpl.Models;
using Xrpl.Models.Ledger;
+using Xrpl.Models.Methods;
namespace Xrpl.Client.Json.Converters
{
@@ -31,10 +32,12 @@ public static BaseLedgerEntry GetBaseRippleLO(LedgerEntryType type, object field
LedgerEntryType.PayChannel => JsonConvert.DeserializeObject($"{field}"),
LedgerEntryType.RippleState => JsonConvert.DeserializeObject($"{field}"),
LedgerEntryType.SignerList => JsonConvert.DeserializeObject($"{field}"),
- //LedgerEntryType.NegativeUNL => expr,
+ LedgerEntryType.NFTokenOffer => JsonConvert.DeserializeObject($"{field}"),
+ LedgerEntryType.NegativeUNL => JsonConvert.DeserializeObject($"{field}"),
//LedgerEntryType.NFTokenOffer => expr,
- //LedgerEntryType.NFTokenPage => expr,
- //LedgerEntryType.Ticket => expr,
+ LedgerEntryType.NFTokenPage => JsonConvert.DeserializeObject($"{field}"),
+ LedgerEntryType.Ticket => JsonConvert.DeserializeObject($"{field}"),
+ LedgerEntryType.AMM => JsonConvert.DeserializeObject($"{field}"),
//LedgerEntryType.Check => expr,
//LedgerEntryType.DepositPreauth => expr,
_ => throw new ArgumentOutOfRangeException()
@@ -81,8 +84,16 @@ public BaseLedgerEntry Create(Type objectType, JObject jObject)
return new LORippleState();
case "LOSignerList":
return new LOSignerList();
- // case "Ticket":
- // return new LOTicket();
+ case "LONFTokenOffer":
+ return new LONFTokenOffer();
+ case "LONFTokenPage":
+ return new LONFTokenPage();
+ case "LOTicket":
+ return new LOTicket();
+ case "LONegativeUNL":
+ return new LONegativeUNL();
+ case "LOAmm":
+ return new LOAmm();
}
string ledgerEntryType = jObject.Property("LedgerEntryType")?.Value.ToString();
@@ -98,12 +109,13 @@ public BaseLedgerEntry Create(Type objectType, JObject jObject)
"PayChannel" => new LOPayChannel(),
"RippleState" => new LORippleState(),
"SignerList" => new LOSignerList(),
- //"NegativeUNL" => new NegativeUNL(),
- //"NFTokenOffer" => new NFTokenOffer(),
- //"NFTokenPage" => new NFTokenPage(),
+ "NegativeUNL" => new LONegativeUNL(),
+ "NFTokenOffer" => new LONFTokenOffer(),
+ "NFTokenPage" => new LONFTokenPage(),
"Ticket" => new LOTicket(),
"Check" => new LOCheck(),
"DepositPreauth" => new LODepositPreauth(),
+ "Amm" => new LOAmm(),
_ => throw new Exception("Can't create ledger type" + ledgerEntryType)
};
}
diff --git a/Xrpl/Client/Json/Converters/MetaBinaryConverter.cs b/Xrpl/Client/Json/Converters/MetaBinaryConverter.cs
index f21cc484..fcba25d1 100644
--- a/Xrpl/Client/Json/Converters/MetaBinaryConverter.cs
+++ b/Xrpl/Client/Json/Converters/MetaBinaryConverter.cs
@@ -16,7 +16,7 @@ public class MetaBinaryConverter : JsonConverter
/// Cannot write this object type
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
- throw new NotImplementedException();
+ serializer.Serialize(writer, value);
}
/// read from json object
/// json reader
diff --git a/Xrpl/Client/Json/Converters/TransactionConverter.cs b/Xrpl/Client/Json/Converters/TransactionConverter.cs
index ef36d76d..8b310e8e 100644
--- a/Xrpl/Client/Json/Converters/TransactionConverter.cs
+++ b/Xrpl/Client/Json/Converters/TransactionConverter.cs
@@ -1,6 +1,8 @@
-using System;
-using Newtonsoft.Json;
+using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+
+using System;
+
using Xrpl.Models.Transactions;
//https://xrpl.org/transaction-types.html
@@ -25,20 +27,17 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
///
/// create
///
- ///
/// json object LedgerEntity
///
- public ITransactionResponseCommon Create(Type objectType, JObject jObject)
+ public ITransactionResponseCommon Create(JObject jObject)
{
- var transactionType = jObject.Property("TransactionType");
-
return jObject.Property("TransactionType")?.Value.ToString() switch
{
"AccountSet" => new AccountSetResponse(),
"AccountDelete" => new AccountDeleteResponse(),
- "CheckCancel" => new AccountDeleteResponse(),
- "CheckCash" => new AccountDeleteResponse(),
- "CheckCreate" => new AccountDeleteResponse(),
+ "CheckCancel" => new CheckCancelResponse(),
+ "CheckCash" => new CheckCashResponse(),
+ "CheckCreate" => new CheckCancelResponse(),
"DepositPreauth" => new DepositPreauthResponse(),
"EscrowCancel" => new EscrowCancelResponse(),
"EscrowCreate" => new EscrowCreateResponse(),
@@ -58,10 +57,27 @@ public ITransactionResponseCommon Create(Type objectType, JObject jObject)
"SignerListSet" => new SignerListSetResponse(),
"TicketCreate" => new TicketCreateResponse(),
"TrustSet" => new TrustSetResponse(),
- _ => throw new Exception("Can't create transaction type" + transactionType)
+ "EnableAmendment" => new EnableAmendmentResponse(),
+ "SetFee" => new SetFeeResponse(),
+ "UNLModify" => new UNLModifyResponse(),
+ "AMMBid" => new AMMBidResponse(),
+ "AMMCreate" => new AMMCreateResponse(),
+ "AMMDelete" => new AMMDeleteResponse(),
+ "AMMDeposit" => new AMMDepositResponse(),
+ "AMMVote" => new AMMVoteResponse(),
+ "AMMWithdraw" => new AMMWithdrawResponse(),
+ "Clawback" => new ClawBackResponse(),
+ //_ => throw new Exception("Can't create transaction type" + transactionType)
+ _ => SetUnknownType(jObject),
};
}
+ static TransactionResponseCommon SetUnknownType(JObject jObject)
+ {
+ jObject.Property("TransactionType").Value = "Unknown";
+ return new TransactionResponseCommon();
+ }
+
/// read from json object
/// json reader
/// object type
@@ -71,7 +87,8 @@ public ITransactionResponseCommon Create(Type objectType, JObject jObject)
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
- ITransactionResponseCommon transactionCommon = Create(objectType, jObject);
+
+ ITransactionResponseCommon transactionCommon = Create(jObject);
serializer.Populate(jObject.CreateReader(), transactionCommon);
return transactionCommon;
}
diff --git a/Xrpl/Client/RequestManager.cs b/Xrpl/Client/RequestManager.cs
index 981ec458..afe2fc8e 100644
--- a/Xrpl/Client/RequestManager.cs
+++ b/Xrpl/Client/RequestManager.cs
@@ -71,7 +71,7 @@ public void Resolve(Guid id, BaseResponse response)
if (hasTimer)
timer.Stop();
- var deserialized = JsonConvert.DeserializeObject(response.Result.ToString(), taskInfo.Type, serializerSettings);
+ var deserialized = JsonConvert.DeserializeObject($"{response.Result}", taskInfo.Type, serializerSettings);
var setResult = taskInfo.TaskCompletionResult.GetType().GetMethod("TrySetResult");
setResult.Invoke(taskInfo.TaskCompletionResult, new[] { deserialized });
this.DeletePromise(id, taskInfo);
diff --git a/Xrpl/Client/connection.cs b/Xrpl/Client/connection.cs
index e73fdad5..7e73fca6 100644
--- a/Xrpl/Client/connection.cs
+++ b/Xrpl/Client/connection.cs
@@ -100,13 +100,13 @@ static WebSocketClient CreateWebSocket(string url, ConnectionOptions config)
int CONNECTION_TIMEOUT = 5;
int INTENTIONAL_DISCONNECT_CODE = 4000;
- public readonly string url;
+ public string url { get; private set; }
public WebSocketClient ws;
private int? reconnectTimeoutID = null;
private int? heartbeatIntervalID = null;
- public readonly ConnectionOptions config;
+ public ConnectionOptions config { get; private set; }
public RequestManager requestManager = new RequestManager();
public ConnectionManager connectionManager = new ConnectionManager();
@@ -119,6 +119,16 @@ public Connection(string server, ConnectionOptions? options = null)
}
+ public async Task ChangeServer(string server, ConnectionOptions? options = null)
+ {
+ await Disconnect();
+ url = server;
+ config = options ?? new ConnectionOptions();
+ config.timeout = TIMEOUT * 1000;
+ config.connectionTimeout = CONNECTION_TIMEOUT * 1000;
+ await Task.Delay(3000);
+ await Connect();
+ }
public bool IsConnected()
{
return this.State() == WebSocketState.Open;
@@ -161,14 +171,16 @@ public async Task Connect()
ws.OnConnect(async (ws) => { await OnceOpen(); });
- ws.OnConnectionError(async (e, ws) => {
+ ws.OnConnectionError(async (e, ws) =>
+ {
timer.Stop();
await OnConnectionFailed(e);
});
ws.OnMessageReceived(async (m, ws) => { await IOnMessage(m); });
//ws.OnError(async (e, ws) => { await OnConnectionFailed(e); });
- ws.OnDisconnect(async (ws) => {
+ ws.OnDisconnect(async (ws) =>
+ {
timer.Stop();
await OnceClose(1000);
});
@@ -284,7 +296,8 @@ private async Task OnceOpen()
//this.retryConnectionBackoff.reset();
//this.startHeartbeatInterval();
this.connectionManager.ResolveAllAwaiting();
- await this.OnConnected?.Invoke();
+ if (OnConnected is not null)
+ await this.OnConnected?.Invoke();
}
catch (Exception error)
{
@@ -347,7 +360,6 @@ private async Task IOnMessage(string message)
try
{
data = JsonConvert.DeserializeObject(message);
- Console.WriteLine(message);
}
catch (Exception error)
{
@@ -370,10 +382,10 @@ private async Task IOnMessage(string message)
{
case ResponseStreamType.ledgerClosed:
{
- object response = JsonConvert.DeserializeObject
public class NFT
{
+ ///
+ /// A bit-map of boolean flags enabled for this NFToken.
+ /// See NFToken Flags for possible values.
+ ///
+ [JsonProperty("Flags")]
+ public string Flags { get; set; }
+ ///
+ /// The TransferFee value specifies the percentage fee, in units of 1/100,000, charged by the issuer for secondary sales of the token.
+ /// Valid values for this field are between 0 and 50,000, inclusive.
+ /// A value of 1 is equivalent to 0.001% or 1/10 of a basis point (bps), allowing transfer rates between 0% and 50%.
+ ///
+ [JsonProperty("TransferFee")]
+ public string TransferFee { get; set; }
+
[JsonProperty("account")]
public string Account { get; set; } //todo unknown field
///
@@ -61,17 +75,17 @@ public class NFT
///
/// The unique identifier of this NFToken, in hexadecimal.
///
- [JsonProperty("nft_id")]
+ [JsonProperty("NFTokenID")]
public string NFTokenID { get; set; }
///
/// The unscrambled version of this token's taxon. Several tokens with the same taxon might represent instances of a limited series.
///
- [JsonProperty("token_taxon")]
+ [JsonProperty("NFTokenTaxon")]
public uint NFTokenTaxon { get; set; }
///
/// The URI data associated with this NFToken, in hexadecimal.
///
- [JsonProperty("uri")]
+ [JsonProperty("URI")]
public string URI { get; set; }
[JsonIgnore]
@@ -84,8 +98,6 @@ public class NFT
///
[JsonProperty("nft_serial")]
public string NFTSerial { get; set; }
-
- //todo not found field Flags: number (https://xrpl.org/nftoken.html#nftoken-flags)
}
///
/// The `account_nfts` method retrieves all of the NFTs currently owned by the specified account.
diff --git a/Xrpl/Models/Methods/AccountTransactions.cs b/Xrpl/Models/Methods/AccountTransactions.cs
index b8250d41..67a2c022 100644
--- a/Xrpl/Models/Methods/AccountTransactions.cs
+++ b/Xrpl/Models/Methods/AccountTransactions.cs
@@ -152,5 +152,13 @@ public AccountTransactionsRequest(string account)
///
[JsonProperty("marker")]
public object Marker { get; set; }
+
+ ///
+ /// Optional) Clio Only Return only transactions of a specific type,
+ /// such as "Clawback", "AccountSet", "AccountDelete", et al. Case-insensitive.
+ /// Supports any transaction type except AMM* (See Transaction Types https://xrpl.org/transaction-types.html)
+ ///
+ [JsonProperty("tx_type")]
+ public string TxType { get; set; }
}
}
diff --git a/Xrpl/Models/Methods/ServerInfo.cs b/Xrpl/Models/Methods/ServerInfo.cs
index 7546ad5f..4d7fcc78 100644
--- a/Xrpl/Models/Methods/ServerInfo.cs
+++ b/Xrpl/Models/Methods/ServerInfo.cs
@@ -83,6 +83,17 @@ public class Info
[JsonProperty("build_version")]
public string BuildVersion { get; set; }
+ ///
+ /// he NetworkID field is a protection against "cross-chain" transaction replay attacks,
+ /// preventing the same transaction from being copied over
+ /// and executing on a parallel network that it wasn't intended for.
+ /// For compatibility with existing chains, the NetworkID field
+ /// must be omitted on any network with a Network ID of 1024 or less,
+ /// but must be included on any network with a Network ID of 1025 or greater.
+ ///
+ [JsonProperty("network_id")]
+ public uint? NetworkID { get; set; }
+
///
/// Range expression indicating the sequence numbers of the ledger versions the local rippled has in its database.
///
diff --git a/Xrpl/Models/Subscriptions/BaseResponse.cs b/Xrpl/Models/Subscriptions/BaseResponse.cs
index 578bf893..b1d2eaad 100644
--- a/Xrpl/Models/Subscriptions/BaseResponse.cs
+++ b/Xrpl/Models/Subscriptions/BaseResponse.cs
@@ -40,7 +40,7 @@ public class BaseResponse
/// Some client libraries omit this field on success.
///
[JsonProperty("result")]
- public object Result { get; set; }
+ public dynamic Result { get; set; }
///
/// (May be omitted) If this field is provided, the value is the string load.
/// This means the client is approaching the rate limiting threshold where the server will disconnect this client.
diff --git a/Xrpl/Models/Transactions/AMMBid.cs b/Xrpl/Models/Transactions/AMMBid.cs
index 189dfb6c..c7591518 100644
--- a/Xrpl/Models/Transactions/AMMBid.cs
+++ b/Xrpl/Models/Transactions/AMMBid.cs
@@ -1,11 +1,16 @@
#nullable enable
+using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-
+using Newtonsoft.Json;
using Xrpl.Client.Exceptions;
+using Xrpl.Client.Json.Converters;
+using Xrpl.Models.Common;
using Xrpl.Models.Ledger;
using Xrpl.Models.Methods;
+using static Xrpl.Models.Common.Common;
+
// https://github.com/XRPLF/xrpl.js/blob/amm/packages/xrpl/src/models/transactions/AMMBid.ts
namespace Xrpl.Models.Transactions
@@ -24,12 +29,16 @@ public AMMBid()
}
///
- public Xrpl.Models.Common.Currency Asset { get; set; }
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset { get; set; }
///
- public Xrpl.Models.Common.Currency Asset2 { get; set; }
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset2 { get; set; }
///
+ [JsonConverter(typeof(CurrencyConverter))]
public Xrpl.Models.Common.Currency? BidMin { get; set; }
///
+ [JsonConverter(typeof(CurrencyConverter))]
public Xrpl.Models.Common.Currency? BidMax { get; set; }
///
public List AuthAccounts { get; set; }
@@ -44,11 +53,11 @@ public interface IAMMBid : ITransactionCommon
///
/// Specifies one of the pool assets (XRP or token) of the AMM instance.
///
- public Xrpl.Models.Common.Currency Asset { get; set; }
+ public IssuedCurrency Asset { get; set; }
///
/// Specifies the other pool asset of the AMM instance.
///
- public Xrpl.Models.Common.Currency Asset2 { get; set; }
+ public IssuedCurrency Asset2 { get; set; }
///
/// This field represents the minimum price that the bidder wants to pay for the slot.
/// It is specified in units of LPToken.If specified let BidMin be X and let
@@ -69,6 +78,28 @@ public interface IAMMBid : ITransactionCommon
public List AuthAccounts { get; set; }
}
+ ///
+ public class AMMBidResponse : TransactionResponseCommon, IAMMBid
+ {
+ #region Implementation of IAMMBid
+
+ ///
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset { get; set; }
+ ///
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset2 { get; set; }
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency? BidMin { get; set; }
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency? BidMax { get; set; }
+ ///
+ public List AuthAccounts { get; set; }
+
+ #endregion
+ }
public partial class Validation
{
private const int MAX_AUTH_ACCOUNTS = 4;
@@ -82,7 +113,7 @@ public static async Task ValidateAMMBid(Dictionary tx)
{
await Common.ValidateBaseTransaction(tx);
- if (!tx.TryGetValue("Asset",out var Asset1) || Asset1 is null)
+ if (!tx.TryGetValue("Asset", out var Asset1) || Asset1 is null)
{
throw new ValidationException("AMMBid: missing field Asset");
}
@@ -114,7 +145,7 @@ public static async Task ValidateAMMBid(Dictionary tx)
if (tx.TryGetValue("AuthAccounts", out var AuthAccounts) && AuthAccounts is not null)
{
- if (AuthAccounts is not List> auth_accounts )
+ if (AuthAccounts is not List> auth_accounts)
{
throw new ValidationException("AMMBid: AuthAccounts must be an AuthAccount array");
}
@@ -127,7 +158,7 @@ public static async Task ValidateAMMBid(Dictionary tx)
}
}
- public static async Task ValidateAuthAccounts(string senderAddress, List> authAccounts)
+ public static bool ValidateAuthAccounts(string senderAddress, List> authAccounts)
{
foreach (var account in authAccounts)
{
@@ -136,9 +167,9 @@ public static async Task ValidateAuthAccounts(string senderAddress, List
+ [JsonConverter(typeof(CurrencyConverter))]
public Xrpl.Models.Common.Currency Amount { get; set; }
///
+ [JsonConverter(typeof(CurrencyConverter))]
public Xrpl.Models.Common.Currency Amount2 { get; set; }
///
public uint TradingFee { get; set; }
@@ -52,6 +57,23 @@ public interface IAMMCreate : ITransactionCommon
public uint TradingFee { get; set; }
}
+ ///
+ public class AMMCreateResponse : TransactionResponseCommon, IAMMCreate
+ {
+ #region Implementation of IAMMCreate
+
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency Amount { get; set; }
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency Amount2 { get; set; }
+ ///
+ public uint TradingFee { get; set; }
+
+ #endregion
+ }
+
public partial class Validation
{
public const uint AMM_MAX_TRADING_FEE = 1000;
diff --git a/Xrpl/Models/Transactions/AMMDelete.cs b/Xrpl/Models/Transactions/AMMDelete.cs
index 9b38bbac..a2c005a8 100644
--- a/Xrpl/Models/Transactions/AMMDelete.cs
+++ b/Xrpl/Models/Transactions/AMMDelete.cs
@@ -3,7 +3,13 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Newtonsoft.Json;
using Xrpl.Client.Exceptions;
+using Xrpl.Client.Json.Converters;
+using Xrpl.Models.Common;
+using Xrpl.Models.Ledger;
+
+using static Xrpl.Models.Common.Common;
namespace Xrpl.Models.Transactions
{
@@ -25,11 +31,11 @@ public AMMDelete()
}
///
- public Xrpl.Models.Common.Currency Asset { get; set; }
- ///
- public Xrpl.Models.Common.Currency Asset2 { get; set; }
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset { get; set; }
///
- public uint TradingFee { get; set; }
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset2 { get; set; }
}
///
/// Delete an empty Automated Market Maker (AMM) instance that could not be fully deleted automatically.
@@ -46,11 +52,26 @@ public interface IAMMDelete : ITransactionCommon
///
/// The definition for one of the assets in the AMM's pool.
///
- public Xrpl.Models.Common.Currency Asset { get; set; }
+ public IssuedCurrency Asset { get; set; }
///
/// The definition for the other asset in the AMM's pool.
///
- public Xrpl.Models.Common.Currency Asset2 { get; set; }
+ public IssuedCurrency Asset2 { get; set; }
+ }
+
+ ///
+ public class AMMDeleteResponse : TransactionResponseCommon, IAMMDelete
+ {
+ #region Implementation of IAMMDelete
+
+ ///
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset { get; set; }
+ ///
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset2 { get; set; }
+
+ #endregion
}
public partial class Validation
diff --git a/Xrpl/Models/Transactions/AMMDeposit.cs b/Xrpl/Models/Transactions/AMMDeposit.cs
index d6349bff..814e28d6 100644
--- a/Xrpl/Models/Transactions/AMMDeposit.cs
+++ b/Xrpl/Models/Transactions/AMMDeposit.cs
@@ -3,10 +3,13 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-
+using Newtonsoft.Json;
using static Xrpl.Models.Common.Common;
using Xrpl.BinaryCodec.Types;
using Xrpl.Client.Exceptions;
+using Xrpl.Models.Ledger;
+using Currency = Xrpl.Models.Common.Currency;
+using Xrpl.Client.Json.Converters;
namespace Xrpl.Models.Transactions
{
@@ -63,21 +66,27 @@ public AMMDeposit()
TransactionType = TransactionType.AMMDeposit;
}
///
- public Xrpl.Models.Common.Currency Asset { get; set; }
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset { get; set; }
///
- public Xrpl.Models.Common.Currency Asset2 { get; set; }
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset2 { get; set; }
///
+ [JsonConverter(typeof(CurrencyConverter))]
public Xrpl.Models.Common.Currency? LPTokenOut { get; set; }
///
+ [JsonConverter(typeof(CurrencyConverter))]
public Xrpl.Models.Common.Currency? Amount { get; set; }
///
+ [JsonConverter(typeof(CurrencyConverter))]
public Xrpl.Models.Common.Currency? Amount2 { get; set; }
///
+ [JsonConverter(typeof(CurrencyConverter))]
public Xrpl.Models.Common.Currency? EPrice { get; set; }
}
@@ -96,12 +105,12 @@ public interface IAMMDeposit : ITransactionCommon
///
/// Specifies one of the pool assets (XRP or token) of the AMM instance.
///
- public Xrpl.Models.Common.Currency Asset { get; set; }
+ public IssuedCurrency Asset { get; set; }
///
/// Specifies the other pool asset of the AMM instance.
///
- public Xrpl.Models.Common.Currency Asset2 { get; set; }
+ public IssuedCurrency Asset2 { get; set; }
///
/// Specifies the amount of shares of the AMM instance pools that the trader wants to redeem or trade in.
@@ -124,6 +133,32 @@ public interface IAMMDeposit : ITransactionCommon
public Xrpl.Models.Common.Currency? EPrice { get; set; }
}
+ ///
+ public class AMMDepositResponse : TransactionResponseCommon, IAMMDeposit
+ {
+ #region Implementation of IAMMDeposit
+
+ ///
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset { get; set; }
+ ///
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset2 { get; set; }
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency LPTokenOut { get; set; }
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency Amount { get; set; }
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency Amount2 { get; set; }
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency EPrice { get; set; }
+
+ #endregion
+ }
public partial class Validation
{
diff --git a/Xrpl/Models/Transactions/AMMVote.cs b/Xrpl/Models/Transactions/AMMVote.cs
index db6387c1..e2b9f205 100644
--- a/Xrpl/Models/Transactions/AMMVote.cs
+++ b/Xrpl/Models/Transactions/AMMVote.cs
@@ -1,7 +1,11 @@
using System.Collections.Generic;
using System.Threading.Tasks;
-
+using Newtonsoft.Json;
using Xrpl.Client.Exceptions;
+using Xrpl.Client.Json.Converters;
+using Xrpl.Models.Common;
+
+using static Xrpl.Models.Common.Common;
namespace Xrpl.Models.Transactions
{
@@ -12,9 +16,11 @@ public AMMVote()
TransactionType = TransactionType.AMMVote;
}
///
- public Xrpl.Models.Common.Currency Asset { get; set; }
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset { get; set; }
///
- public Xrpl.Models.Common.Currency Asset2 { get; set; }
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset2 { get; set; }
///
public uint TradingFee { get; set; }
}
@@ -24,11 +30,11 @@ public interface IAMMVote : ITransactionCommon
///
/// Specifies one of the pool assets (XRP or token) of the AMM instance.
///
- public Xrpl.Models.Common.Currency Asset { get; set; }
+ public IssuedCurrency Asset { get; set; }
///
/// Specifies the other pool asset of the AMM instance.
///
- public Xrpl.Models.Common.Currency Asset2 { get; set; }
+ public IssuedCurrency Asset2 { get; set; }
///
/// Specifies the fee, in basis point.
/// Valid values for this field are between 0 and 1000 inclusive.
@@ -37,6 +43,24 @@ public interface IAMMVote : ITransactionCommon
///
public uint TradingFee { get; set; }
}
+
+ ///
+ public class AMMVoteResponse : TransactionResponseCommon, IAMMVote
+ {
+ #region Implementation of IAMMVote
+
+ ///
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset { get; set; }
+ ///
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset2 { get; set; }
+ ///
+ public uint TradingFee { get; set; }
+
+ #endregion
+ }
+
public partial class Validation
{
///
diff --git a/Xrpl/Models/Transactions/AMMWithdraw.cs b/Xrpl/Models/Transactions/AMMWithdraw.cs
index 5a2318d4..65963492 100644
--- a/Xrpl/Models/Transactions/AMMWithdraw.cs
+++ b/Xrpl/Models/Transactions/AMMWithdraw.cs
@@ -3,10 +3,11 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-
+using Newtonsoft.Json;
using static Xrpl.Models.Common.Common;
-using Xrpl.BinaryCodec.Types;
using Xrpl.Client.Exceptions;
+using Xrpl.Models.Common;
+using Xrpl.Client.Json.Converters;
namespace Xrpl.Models.Transactions
{
@@ -71,22 +72,28 @@ public AMMWithdraw()
#region Implementation of IAMMWithdraw
///
- public Xrpl.Models.Common.Currency Asset { get; set; }
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset { get; set; }
///
- public Xrpl.Models.Common.Currency Asset2 { get; set; }
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset2 { get; set; }
///
- public Xrpl.Models.Common.Currency LPTokenIn { get; set; }
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency LPTokenIn { get; set; }
///
- public Amount Amount { get; set; }
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency Amount { get; set; }
///
- public Amount Amount2 { get; set; }
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency Amount2 { get; set; }
///
- public Amount EPrice { get; set; }
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency EPrice { get; set; }
#endregion
}
@@ -100,37 +107,65 @@ public interface IAMMWithdraw : ITransactionCommon
///
/// Specifies one of the pool assets (XRP or token) of the AMM instance.
///
- Xrpl.Models.Common.Currency Asset { get; set; }
+ IssuedCurrency Asset { get; set; }
///
/// Specifies the other pool asset of the AMM instance.
///
- Xrpl.Models.Common.Currency Asset2 { get; set; }
+ IssuedCurrency Asset2 { get; set; }
///
/// Specifies the amount of shares of the AMM instance pools that the trader
/// wants to redeem or trade in.
///
- Xrpl.Models.Common.Currency LPTokenIn { get; set; }
+ Currency LPTokenIn { get; set; }
///
/// Specifies one of the pools assets that the trader wants to remove.
/// If the asset is XRP, then the Amount is a string specifying the number of drops.
/// Otherwise it is an IssuedCurrencyAmount object.
///
- Amount Amount { get; set; }
+ Currency Amount { get; set; }
///
/// Specifies the other pool asset that the trader wants to remove.
///
- Amount Amount2 { get; set; }
+ Currency Amount2 { get; set; }
///
/// Specifies the effective-price of the token out after successful execution of
/// the transaction.
///
- Amount EPrice { get; set; }
+ Currency EPrice { get; set; }
}
+
+ ///
+ public class AMMWithdrawResponse : TransactionResponseCommon, IAMMWithdraw
+ {
+ #region Implementation of IAMMWithdraw
+
+ ///
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset { get; set; }
+ ///
+ [JsonConverter(typeof(IssuedCurrencyConverter))]
+ public IssuedCurrency Asset2 { get; set; }
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency LPTokenIn { get; set; }
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency Amount { get; set; }
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency Amount2 { get; set; }
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency EPrice { get; set; }
+
+ #endregion
+ }
+
public partial class Validation
{
diff --git a/Xrpl/Models/Transactions/AccountSet.cs b/Xrpl/Models/Transactions/AccountSet.cs
index e0cf164a..991eb584 100644
--- a/Xrpl/Models/Transactions/AccountSet.cs
+++ b/Xrpl/Models/Transactions/AccountSet.cs
@@ -5,13 +5,13 @@
using System.Linq;
using System.Threading.Tasks;
using Xrpl.Client.Exceptions;
-
+// https://github.com/XRPLF/xrpl.js/blob/b20c05c3680d80344006d20c44b4ae1c3b0ffcac/packages/xrpl/src/models/transactions/accountSet.ts#L11
namespace Xrpl.Models.Transactions
{
///
/// Enum for AccountSet Flags.
///
- public enum AccountSetTfFlags //todo rename to AccountSetAsfFlags https://github.com/XRPLF/xrpl.js/blob/b20c05c3680d80344006d20c44b4ae1c3b0ffcac/packages/xrpl/src/models/transactions/accountSet.ts#L11
+ public enum AccountSetAsfFlags
{
///
/// Require a destination tag to send transactions to this account.
@@ -97,6 +97,8 @@ public AccountSet(string account) : this()
public uint? TransferRate { get; set; }
///
public uint? TickSize { get; set; }
+ ///
+ public string NFTokenMinter { get; set; }
}
///
@@ -136,7 +138,10 @@ public interface IAccountSet : ITransactionCommon
/// Valid values are 3 to 15 inclusive, or 0 to disable.
///
uint? TickSize { get; set; }
-
+ ///
+ /// Optional) Another account that can mint NFTokens for you.
+ ///
+ public string NFTokenMinter { get; set; }
//todo not found field NFTokenMinter?: string
}
@@ -157,6 +162,9 @@ public class AccountSetResponse : TransactionResponseCommon, IAccountSet
public uint? TransferRate { get; set; }
///
public uint? TickSize { get; set; }
+
+ ///
+ public string NFTokenMinter { get; set; }
}
public partial class Validation
@@ -178,7 +186,7 @@ public static async Task ValidateAccountSet(Dictionary tx)
if (ClearFlag is not uint { } flag )
throw new ValidationException("AccountSet: invalid ClearFlag");
- if (Enum.GetValues().All(c => (uint)c != flag))
+ if (Enum.GetValues().All(c => (uint)c != flag))
throw new ValidationException("AccountSet: invalid ClearFlag");
}
if (tx.TryGetValue("Domain", out var Domain) && Domain is not string { })
@@ -195,7 +203,7 @@ public static async Task ValidateAccountSet(Dictionary tx)
if (SetFlag is not uint { })
throw new ValidationException("AccountSet: invalid SetFlag");
- if (Enum.GetValues().All(c => (uint)c != SetFlag))
+ if (Enum.GetValues().All(c => (uint)c != SetFlag))
throw new ValidationException("AccountSet: missing field Destination");
}
diff --git a/Xrpl/Models/Transactions/BookOffers.cs b/Xrpl/Models/Transactions/BookOffers.cs
index 9bff168d..83226cae 100644
--- a/Xrpl/Models/Transactions/BookOffers.cs
+++ b/Xrpl/Models/Transactions/BookOffers.cs
@@ -175,6 +175,6 @@ public decimal AmountEach
/// For fairness, offers that have the same quality are automatically taken first-in, first-out.
///
[JsonProperty("quality")]
- public double? Quality { get; set; }
+ public decimal? Quality { get; set; }
}
}
diff --git a/Xrpl/Models/Transactions/CheckCash.cs b/Xrpl/Models/Transactions/CheckCash.cs
index 9e15e6af..cfd70477 100644
--- a/Xrpl/Models/Transactions/CheckCash.cs
+++ b/Xrpl/Models/Transactions/CheckCash.cs
@@ -1,7 +1,8 @@
using System.Collections.Generic;
using System.Threading.Tasks;
-
+using Newtonsoft.Json;
using Xrpl.Client.Exceptions;
+using Xrpl.Client.Json.Converters;
using Xrpl.Models.Common;
@@ -19,8 +20,10 @@ public CheckCash()
///
public string CheckID { get; set; }
///
+ [JsonConverter(typeof(CurrencyConverter))]
public Currency? Amount { get; set; }
///
+ [JsonConverter(typeof(CurrencyConverter))]
public Currency? DeliverMin { get; set; }
}
@@ -41,6 +44,7 @@ public interface ICheckCash : ITransactionCommon
/// You.
/// must provide either this field or DeliverMin.
///
+ [JsonConverter(typeof(CurrencyConverter))]
Currency? Amount { get; set; }
///
/// Redeem the Check for at least this amount and for as much as possible.
@@ -48,6 +52,7 @@ public interface ICheckCash : ITransactionCommon
/// transaction.
/// You must provide either this field or Amount.
///
+ [JsonConverter(typeof(CurrencyConverter))]
Currency? DeliverMin { get; set; }
}
@@ -57,9 +62,11 @@ public class CheckCashResponse : TransactionResponseCommon, ICheckCash
///
public string CheckID { get; set; }
///
+ [JsonConverter(typeof(CurrencyConverter))]
public Currency? Amount { get; set; }
///
+ [JsonConverter(typeof(CurrencyConverter))]
public Currency? DeliverMin { get; set; }
}
diff --git a/Xrpl/Models/Transactions/ClawBack.cs b/Xrpl/Models/Transactions/ClawBack.cs
new file mode 100644
index 00000000..edc347e8
--- /dev/null
+++ b/Xrpl/Models/Transactions/ClawBack.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using Xrpl.Client.Exceptions;
+using static Xrpl.Models.Common.Common;
+using Xrpl.Client.Json.Converters;
+using Xrpl.Models.Common;
+using Xrpl.Models.Ledger;
+using Xrpl.BinaryCodec.Types;
+using Currency = Xrpl.Models.Common.Currency;
+
+namespace Xrpl.Models.Transactions
+{
+ ///
+ /// The Clawback transaction is used by the token issuer to claw back issued tokens from a holder.
+ ///
+ public class ClawBack : TransactionCommon, IClawBack
+ {
+ public ClawBack()
+ {
+ TransactionType = TransactionType.Clawback;
+ }
+
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Xrpl.Models.Common.Currency Amount { get; set; }
+ }
+ ///
+ /// ClawBack is used for submitting a vote for the trading fee of an AMM Instance.
+ /// Any XRPL account that holds LPToken for an AMM instance may submit this
+ /// transaction to vote for the trading fee for that instance.
+ ///
+ public interface IClawBack : ITransactionCommon
+ {
+ ///
+ /// The amount of currency to deliver, and it must be non-XRP.
+ /// The nested field names MUST be lower-case. The `issuer` field MUST be the holder's address, whom to be clawed back.
+ ///
+ public Xrpl.Models.Common.Currency Amount { get; set; }
+ }
+
+ ///
+ public class ClawBackResponse : TransactionResponseCommon, IClawBack
+ {
+ #region Implementation of IClawBack
+
+ ///
+ [JsonConverter(typeof(CurrencyConverter))]
+ public Currency Amount { get; set; }
+
+ #endregion
+ }
+ public partial class Validation
+ {
+ ///
+ /// Verify the form and type of an ClawBack at runtime.
+ ///
+ /// An ClawBack Transaction.
+ ///
+ /// When the ClawBack is Malformed.
+ public static async Task ValidateClawBack(Dictionary tx)
+ {
+ await Common.ValidateBaseTransaction(tx);
+
+ if (!tx.TryGetValue("Amount", out var Amount) || Amount is null)
+ {
+ throw new ValidationException("ClawBack: missing field Amount");
+ }
+
+ if (!Xrpl.Models.Transactions.Common.IsIssuedCurrency(Amount))
+ {
+ throw new ValidationException("ClawBack: invalid Amount");
+ }
+
+ if (!tx.TryGetValue("Account", out var acc) || acc is null)
+ throw new ValidationException("ClawBack: invalid Account");
+ var amount = JsonConvert.DeserializeObject($"{Amount}");
+ if (amount.Issuer == acc)
+ {
+ throw new ValidationException("ClawBack: invalid holder Account");
+ }
+ }
+ }
+
+}
diff --git a/Xrpl/Models/Transactions/Common.cs b/Xrpl/Models/Transactions/Common.cs
index 56e7d836..0694e8cc 100644
--- a/Xrpl/Models/Transactions/Common.cs
+++ b/Xrpl/Models/Transactions/Common.cs
@@ -14,6 +14,7 @@
using Xrpl.Models.Common;
using Xrpl.Models.Ledger;
using Xrpl.Models.Utils;
+
using Index = Xrpl.Models.Utils.Index;
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/models/transactions/common.ts
@@ -77,7 +78,7 @@ public static bool IsSigner(dynamic signer)
/// Whether the Memo is malformed.
public static bool IsMemo(dynamic memo)
{
- if (memo is not Dictionary { } value)
+ if (memo is not Dictionary { } value)
return false;
var size = value.Count;
@@ -255,6 +256,8 @@ public abstract class TransactionCommon : ITransactionCommon //todo rename to Ba
// Fee = new Currency { Value = "10" };
//}
+ public uint? NetworkID { get; set; }
+
///
public string Account { get; set; }
@@ -269,6 +272,7 @@ public abstract class TransactionCommon : ITransactionCommon //todo rename to Ba
public uint? LastLedgerSequence { get; set; }
///
public List Memos { get; set; }
+
///
public uint? Sequence { get; set; }
///
@@ -316,6 +320,11 @@ public string ToJson()
return JsonConvert.SerializeObject(this, serializerSettings);
}
+ ///
+ public uint? SourceTag { get; set; }
+ ///
+ public uint? TicketSequence { get; set; }
+
//todo not found fields - SourceTag?: number, TicketSequence?: number
}
@@ -422,6 +431,17 @@ public class Meta
///
public string TransactionResult { get; set; }
+ ///
+ /// OfferID for create NFT offers.
+ ///
+ [JsonProperty("offer_id")]
+ public string OfferID { get; set; }
+ ///
+ /// NFTokenID for nft accept offer.
+ ///
+ [JsonProperty("nftoken_id")]
+ public string NFTokenID { get; set; }
+
///
/// (Omitted for non-Payment transactions) The Currency Amount actually received by the Destination account.
/// Use this field to determine how much was delivered, regardless of whether the transaction is a partial payment.
@@ -559,6 +579,7 @@ public class NodeInfo
///
public interface ITransactionCommon
{
+ public uint? NetworkID { get; set; }
///
/// This is a required field
/// The unique address of the account that initiated the transaction.
@@ -594,6 +615,8 @@ public interface ITransactionCommon
/// Additional arbitrary information used to identify this transaction.
///
List Memos { get; set; }
+ [JsonIgnore]
+ public string MemoValue => Memos is not { } memos ? null : memos.Aggregate(string.Empty, (current, memo) => current + $"{memo.Memo.MemoData.FromHexString()}");
///
/// Transaction metadata is a section of data that gets added to a transaction after it is processed.
@@ -640,7 +663,17 @@ public interface ITransactionCommon
///
///
string ToJson();
- //todo not found fields - SourceTag: Number (UInt32), TicketSequence:Number(UInt32), TxnSignature:string
+ ///
+ /// (Optional) Arbitrary integer used to identify the reason for this payment, or a sender on whose behalf this transaction is made.
+ /// Conventionally, a refund should specify the initial payment's SourceTag as the refund payment's DestinationTag.
+ ///
+ public uint? SourceTag { get; set; }
+ ///
+ /// (Optional) The sequence number of the ticket to use in place of a Sequence number.
+ /// If this is provided, Sequence must be 0. Cannot be used with AccountTxnID.
+ ///
+ public uint? TicketSequence { get; set; }
+
}
///
@@ -652,8 +685,10 @@ public interface ITransactionResponseCommon : IBaseTransactionResponse, ITransac
///
[JsonConverter(typeof(TransactionConverter))]
- public abstract class TransactionResponseCommon : BaseTransactionResponse, ITransactionResponseCommon
+ public class TransactionResponseCommon : BaseTransactionResponse, ITransactionResponseCommon
{
+ public uint? NetworkID { get; set; }
+
///
public string Account { get; set; }
@@ -672,6 +707,8 @@ public abstract class TransactionResponseCommon : BaseTransactionResponse, ITran
///
public List Memos { get; set; }
+ [JsonIgnore]
+ public string MemoValue => Memos is not { } memos ? null : memos.Aggregate(string.Empty, (current, memo) => current + $"{memo.Memo.MemoData.FromHexString()}");
///
public uint? Sequence { get; set; }
///
@@ -699,8 +736,13 @@ public string ToJson()
JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
serializerSettings.NullValueHandling = NullValueHandling.Ignore;
serializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
-
+
return JsonConvert.SerializeObject(this, serializerSettings);
}
+
+ ///
+ public uint? SourceTag { get; set; }
+ ///
+ public uint? TicketSequence { get; set; }
}
}
diff --git a/Xrpl/Models/Transactions/EnableAmendment.cs b/Xrpl/Models/Transactions/EnableAmendment.cs
new file mode 100644
index 00000000..1a342c44
--- /dev/null
+++ b/Xrpl/Models/Transactions/EnableAmendment.cs
@@ -0,0 +1,40 @@
+//https://xrpl.org/enableamendment.html
+namespace Xrpl.Models.Transactions
+{
+ public class EnableAmendment : TransactionCommon, IEnableAmendment
+ {
+ public EnableAmendment()
+ {
+ TransactionType = TransactionType.EnableAmendment;
+ }
+
+ ///
+ public string Amendment { get; set; }
+
+ ///
+ public uint LedgerSequence { get; set; }
+ }
+
+ public interface IEnableAmendment : ITransactionCommon
+ {
+ ///
+ /// A unique identifier for the amendment.
+ /// This is not intended to be a human-readable name.
+ /// See Amendments for a list of known amendments.
+ ///
+ string Amendment { get; set; }
+ ///
+ /// The ledger index where this pseudo-transaction appears.
+ /// This distinguishes the pseudo-transaction from other occurrences of the same change.
+ ///
+ uint LedgerSequence { get; set; }
+ }
+
+ public class EnableAmendmentResponse : TransactionResponseCommon, IEnableAmendment
+ {
+ ///
+ public string Amendment { get; set; }
+ ///
+ public uint LedgerSequence { get; set; }
+ }
+}
diff --git a/Xrpl/Models/Transactions/Metadata.cs b/Xrpl/Models/Transactions/Metadata.cs
new file mode 100644
index 00000000..5077b226
--- /dev/null
+++ b/Xrpl/Models/Transactions/Metadata.cs
@@ -0,0 +1,54 @@
+using Newtonsoft.Json;
+
+using System.Collections.Generic;
+
+using Xrpl.Client.Json.Converters;
+
+using Xrpl.Models.Common;
+
+//https://github.com/XRPLF/xrpl.js/blob/45963b70356f4609781a6396407e2211fd15bcf1/packages/xrpl/src/models/transactions/metadata.ts#L32
+namespace Xrpl.Models.Transactions
+{
+ //todo replace Meta in transactionCommon to this interfaces;
+
+ public interface ICreatedNode
+ {
+ string LedgerEntryType { get; set; }
+ string LedgerIndex { get; set; }
+ Dictionary NewFields { get; set; }
+ }
+
+ public interface IModifiedNode
+ {
+ string LedgerEntryType { get; set; }
+ string LedgerIndex { get; set; }
+ Dictionary FinalFields { get; set; }
+ Dictionary PreviousFields { get; set; }
+ string PreviousTxnID { get; set; }
+ int PreviousTxnLgrSeq { get; set; }
+ }
+
+ public interface IDeletedNode
+ {
+ string LedgerEntryType { get; set; }
+ string LedgerIndex { get; set; }
+ Dictionary FinalFields { get; set; }
+ }
+
+ public interface INode : ICreatedNode, IModifiedNode, IDeletedNode
+ {
+ }
+
+ public interface TransactionMetadata
+ {
+ List AffectedNodes { get; set; }
+ [JsonConverter(typeof(CurrencyConverter))]
+ [JsonProperty("DeliveredAmount")]
+ Currency DeliveredAmount { get; set; }
+ [JsonConverter(typeof(CurrencyConverter))]
+ [JsonProperty("delivered_amount")]
+ Currency Delivered_amount { get; set; }
+ int TransactionIndex { get; set; }
+ string TransactionResult { get; set; }
+ }
+}
diff --git a/Xrpl/Models/Transactions/SetFee.cs b/Xrpl/Models/Transactions/SetFee.cs
new file mode 100644
index 00000000..54bba131
--- /dev/null
+++ b/Xrpl/Models/Transactions/SetFee.cs
@@ -0,0 +1,67 @@
+//https://xrpl.org/setfee.html
+namespace Xrpl.Models.Transactions
+{
+ public class SetFee : TransactionCommon, ISetFee
+ {
+ public SetFee()
+ {
+ TransactionType = TransactionType.SetFee;
+ }
+
+ ///
+ public string BaseFee { get; set; }
+
+ ///
+ public uint ReferenceFeeUnits { get; set; }
+
+ ///
+ public uint ReserveBase { get; set; }
+
+ ///
+ public uint ReserveIncrement { get; set; }
+
+ ///
+ public uint LedgerSequence { get; set; }
+ }
+
+ public interface ISetFee : ITransactionCommon
+ {
+ ///
+ /// The charge, in drops of XRP, for the reference transaction, as hex.
+ /// (This is the transaction cost before scaling for load.)
+ ///
+ string BaseFee { get; set; }
+ ///
+ /// (Omitted for some historical SetFee pseudo-transactions)
+ /// The index of the ledger version where this pseudo-transaction appears.
+ /// This distinguishes the pseudo-transaction from other occurrences of the same change.
+ ///
+ uint LedgerSequence { get; set; }
+ ///
+ /// The cost, in fee units, of the reference transaction
+ ///
+ uint ReferenceFeeUnits { get; set; }
+ ///
+ /// The base reserve, in drops
+ ///
+ uint ReserveBase { get; set; }
+ ///
+ /// The incremental reserve, in drops
+ ///
+ uint ReserveIncrement { get; set; }
+ }
+
+ public class SetFeeResponse : TransactionResponseCommon, ISetFee
+ {
+ ///
+ public string BaseFee { get; set; }
+ ///
+ public uint LedgerSequence { get; set; }
+ ///
+ public uint ReferenceFeeUnits { get; set; }
+ ///
+ public uint ReserveBase { get; set; }
+ ///
+ public uint ReserveIncrement { get; set; }
+ }
+}
diff --git a/Xrpl/Models/Transactions/Submit.cs b/Xrpl/Models/Transactions/Submit.cs
index d4bb002d..3f6f1a74 100644
--- a/Xrpl/Models/Transactions/Submit.cs
+++ b/Xrpl/Models/Transactions/Submit.cs
@@ -1,52 +1,76 @@
using Newtonsoft.Json;
+
using Xrpl.Models.Methods;
//https://github.com/XRPLF/xrpl.js/blob/b20c05c3680d80344006d20c44b4ae1c3b0ffcac/packages/xrpl/src/models/methods/submit.ts#L28
-namespace Xrpl.Models.Transactions
+namespace Xrpl.Models.Transactions;
+
+///
+/// Response expected from a .
+///
+public class Submit //todo rename to SubmitResponse extends BaseResponse
{
+ [JsonProperty("Accepted")]
+ public bool Accepted { get; set; }
+
+ [JsonProperty("applied")]
+ public bool Applied { get; set; }
+
+ [JsonProperty("broadcast")]
+ public bool Broadcast { get; set; }
+
+ [JsonProperty("open_ledger_cost")]
+ public string OpenLedgerCost { get; set; }
+
+ ///
+ /// Text result code indicating the preliminary result of the transaction, for example `tesSUCCESS`.
+ ///
+ [JsonProperty("engine_result")]
+ public string EngineResult { get; set; }
+
+ ///
+ /// Numeric version of the result code.
+ ///
+ [JsonProperty("engine_result_code")]
+ public int EngineResultCode { get; set; }
+
+ ///
+ /// Human-readable explanation of the transaction's preliminary result.
+ ///
+ [JsonProperty("engine_result_message")]
+ public string EngineResultMessage { get; set; }
+
///
- /// Response expected from a .
- ///
- public class Submit //todo rename to SubmitResponse extends BaseResponse
- {
- ///
- /// Text result code indicating the preliminary result of the transaction, for example `tesSUCCESS`.
- ///
- [JsonProperty("engine_result")]
- public string EngineResult { get; set; }
-
- ///
- /// Numeric version of the result code.
- ///
- [JsonProperty("engine_result_code")]
- public int EngineResultCode { get; set; }
-
- ///
- /// Human-readable explanation of the transaction's preliminary result.
- ///
- [JsonProperty("engine_result_message")]
- public string EngineResultMessage { get; set; }
-
- ///
- /// The complete transaction in hex string format.
- ///
- [JsonProperty("tx_blob")]
- public string TxBlob { get; set; }
-
- ///
- /// The complete transaction in JSON format.
- ///
- [JsonProperty("tx_json")]
- public dynamic TxJson { get; set; }
-
- //[JsonIgnore]
- ///
- /// The complete transaction.
- ///
- public ITransactionResponseCommon Transaction => JsonConvert.DeserializeObject(TxJson.ToString());
-
-
- //todo not found fields accepted: boolean, account_sequence_available: number, account_sequence_next: number, applied: boolean, broadcast: boolean
- //kept: boolean, queued: boolean, open_ledger_cost: string, validated_ledger_index: number
- }
-}
+ /// The complete transaction in hex string format.
+ ///
+ [JsonProperty("tx_blob")]
+ public string TxBlob { get; set; }
+
+ ///
+ /// Next account sequence number.
+ ///
+ [JsonProperty("account_sequence_next")]
+ public uint? AccountSequenceNext { get; set; }
+
+ ///
+ /// Available account sequence number.
+ ///
+ [JsonProperty("account_sequence_available")]
+ public uint? AccountSequenceAvailable { get; set; }
+
+ ///
+ /// The complete transaction in JSON format.
+ ///
+ [JsonProperty("tx_json")]
+ public dynamic TxJson { get; set; }
+
+ //[JsonIgnore]
+ ///
+ /// The complete transaction.
+ ///
+ public ITransactionResponseCommon Transaction => JsonConvert.DeserializeObject(TxJson.ToString());
+
+
+ //todo not found fields accepted: boolean, account_sequence_available: number, account_sequence_next: number, applied: boolean, broadcast: boolean
+ //kept: boolean, queued: boolean, open_ledger_cost: string, validated_ledger_index: number
+}
\ No newline at end of file
diff --git a/Xrpl/Models/Transactions/TxFormat.cs b/Xrpl/Models/Transactions/TxFormat.cs
index 9849710b..b510215c 100644
--- a/Xrpl/Models/Transactions/TxFormat.cs
+++ b/Xrpl/Models/Transactions/TxFormat.cs
@@ -24,7 +24,9 @@ public TxFormat()
this[Field.Fee] = Requirement.Required;
this[Field.Sequence] = Requirement.Required;
this[Field.SigningPubKey] = Requirement.Required;
+ this[Field.TicketSequence] = Requirement.Optional;
+ this[Field.NetworkID] = Requirement.Optional;
this[Field.Flags] = Requirement.Optional;
this[Field.SourceTag] = Requirement.Optional;
this[Field.PreviousTxnID] = Requirement.Optional;
@@ -92,13 +94,13 @@ internal static void Validate(StObject obj, Action onError)
}
}
- public static Dictionary Formats;
+ public static Dictionary Formats;
static TxFormat()
{
- Formats = new Dictionary
+ Formats = new Dictionary
{
- [BinaryCodec.Enums.TransactionType.Payment] = new TxFormat
+ [BinaryCodec.Types.TransactionType.Payment] = new TxFormat
{
[Field.Destination] = Requirement.Required,
[Field.Amount] = Requirement.Required,
@@ -108,7 +110,7 @@ static TxFormat()
[Field.DestinationTag] = Requirement.Optional,
[Field.DeliverMin] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.EscrowCreate] = new TxFormat
+ [BinaryCodec.Types.TransactionType.EscrowCreate] = new TxFormat
{
[Field.Amount] = Requirement.Required,
[Field.Destination] = Requirement.Required,
@@ -117,14 +119,14 @@ static TxFormat()
[Field.FinishAfter] = Requirement.Optional,
[Field.DestinationTag] = Requirement.Optional,
},
- [BinaryCodec.Enums.TransactionType.EscrowFinish] = new TxFormat
+ [BinaryCodec.Types.TransactionType.EscrowFinish] = new TxFormat
{
[Field.Owner] = Requirement.Required,
[Field.OfferSequence] = Requirement.Required,
[Field.Condition] = Requirement.Optional,
[Field.Fulfillment] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.AccountSet] = new TxFormat
+ [BinaryCodec.Types.TransactionType.AccountSet] = new TxFormat
{
[Field.EmailHash] = Requirement.Optional,
[Field.WalletLocator] = Requirement.Optional,
@@ -134,42 +136,44 @@ static TxFormat()
[Field.TransferRate] = Requirement.Optional,
[Field.SetFlag] = Requirement.Optional,
[Field.ClearFlag] = Requirement.Optional,
- [Field.TickSize] = Requirement.Optional
+ [Field.TickSize] = Requirement.Optional,
+ [Field.NFTokenMinter] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.EscrowCancel] = new TxFormat
+ [BinaryCodec.Types.TransactionType.EscrowCancel] = new TxFormat
{
[Field.Owner] = Requirement.Required,
[Field.OfferSequence] = Requirement.Required
},
- [BinaryCodec.Enums.TransactionType.SetRegularKey] = new TxFormat
+ [BinaryCodec.Types.TransactionType.SetRegularKey] = new TxFormat
{
[Field.RegularKey] = Requirement.Optional
},
// 6
- [BinaryCodec.Enums.TransactionType.OfferCreate] = new TxFormat
+ [BinaryCodec.Types.TransactionType.OfferCreate] = new TxFormat
{
[Field.TakerPays] = Requirement.Required,
[Field.TakerGets] = Requirement.Required,
[Field.Expiration] = Requirement.Optional,
[Field.OfferSequence] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.OfferCancel] = new TxFormat
+ [BinaryCodec.Types.TransactionType.OfferCancel] = new TxFormat
{
[Field.OfferSequence] = Requirement.Required
},
// 9
- [BinaryCodec.Enums.TransactionType.TicketCreate] = new TxFormat
+ [BinaryCodec.Types.TransactionType.TicketCreate] = new TxFormat
{
[Field.Target] = Requirement.Optional,
- [Field.Expiration] = Requirement.Optional
+ [Field.Expiration] = Requirement.Optional,
+ [Field.TicketCount] = Requirement.Required
},
// 11
- [BinaryCodec.Enums.TransactionType.SignerListSet] = new TxFormat
+ [BinaryCodec.Types.TransactionType.SignerListSet] = new TxFormat
{
[Field.SignerQuorum] = Requirement.Required,
[Field.SignerEntries] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.PaymentChannelCreate] = new TxFormat()
+ [BinaryCodec.Types.TransactionType.PaymentChannelCreate] = new TxFormat()
{
[Field.Destination] = Requirement.Required,
[Field.Amount] = Requirement.Required,
@@ -178,13 +182,13 @@ static TxFormat()
[Field.CancelAfter] = Requirement.Optional,
[Field.DestinationTag] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.PaymentChannelFund] = new TxFormat()
+ [BinaryCodec.Types.TransactionType.PaymentChannelFund] = new TxFormat()
{
[Field.Channel] = Requirement.Required,
[Field.Amount] = Requirement.Required,
[Field.Expiration] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.PaymentChannelClaim] = new TxFormat()
+ [BinaryCodec.Types.TransactionType.PaymentChannelClaim] = new TxFormat()
{
[Field.Channel] = Requirement.Required,
[Field.Amount] = Requirement.Optional,
@@ -192,7 +196,7 @@ static TxFormat()
[Field.Signature] = Requirement.Optional,
[Field.PublicKey] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.CheckCreate] = new TxFormat()
+ [BinaryCodec.Types.TransactionType.CheckCreate] = new TxFormat()
{
[Field.Channel] = Requirement.Required,
[Field.Amount] = Requirement.Optional,
@@ -200,7 +204,7 @@ static TxFormat()
[Field.Signature] = Requirement.Optional,
[Field.PublicKey] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.CheckCash] = new TxFormat()
+ [BinaryCodec.Types.TransactionType.CheckCash] = new TxFormat()
{
[Field.Channel] = Requirement.Required,
[Field.Amount] = Requirement.Optional,
@@ -208,7 +212,7 @@ static TxFormat()
[Field.Signature] = Requirement.Optional,
[Field.PublicKey] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.CheckCancel] = new TxFormat()
+ [BinaryCodec.Types.TransactionType.CheckCancel] = new TxFormat()
{
[Field.Channel] = Requirement.Required,
[Field.Amount] = Requirement.Optional,
@@ -216,7 +220,7 @@ static TxFormat()
[Field.Signature] = Requirement.Optional,
[Field.PublicKey] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.DepositPreauth] = new TxFormat()
+ [BinaryCodec.Types.TransactionType.DepositPreauth] = new TxFormat()
{
[Field.Channel] = Requirement.Required,
[Field.Amount] = Requirement.Optional,
@@ -224,30 +228,31 @@ static TxFormat()
[Field.Signature] = Requirement.Optional,
[Field.PublicKey] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.TrustSet] = new TxFormat
+ [BinaryCodec.Types.TransactionType.TrustSet] = new TxFormat
{
[Field.LimitAmount] = Requirement.Optional,
[Field.QualityIn] = Requirement.Optional,
[Field.QualityOut] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.AccountDelete] = new TxFormat
+ [BinaryCodec.Types.TransactionType.AccountDelete] = new TxFormat
{
[Field.Destination] = Requirement.Required,
[Field.DestinationTag] = Requirement.Optional,
},
- [BinaryCodec.Enums.TransactionType.NFTokenMint] = new TxFormat
+ [BinaryCodec.Types.TransactionType.NFTokenMint] = new TxFormat
{
[Field.NFTokenTaxon] = Requirement.Required,
[Field.Issuer] = Requirement.Optional,
[Field.TransferFee] = Requirement.Optional,
[Field.URI] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.NFTokenBurn] = new TxFormat
+ [BinaryCodec.Types.TransactionType.NFTokenBurn] = new TxFormat
{
- [Field.NFTokenID] = Requirement.Required
+ [Field.NFTokenID] = Requirement.Required,
+ [Field.Owner] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.NFTokenCreateOffer] = new TxFormat
+ [BinaryCodec.Types.TransactionType.NFTokenCreateOffer] = new TxFormat
{
[Field.NFTokenID] = Requirement.Required,
[Field.Amount] = Requirement.Required,
@@ -255,15 +260,18 @@ static TxFormat()
[Field.Destination] = Requirement.Optional,
[Field.Expiration] = Requirement.Optional
},
- [BinaryCodec.Enums.TransactionType.NFTokenCancelOffer] = new TxFormat
+ [BinaryCodec.Types.TransactionType.NFTokenCancelOffer] = new TxFormat
{
[Field.NFTokenOffers] = Requirement.Required
},
- [BinaryCodec.Enums.TransactionType.NFTokenAcceptOffer] = new TxFormat
+ [BinaryCodec.Types.TransactionType.NFTokenAcceptOffer] = new TxFormat
{
- [Field.NFTokenID] = Requirement.Required
+ //[Field.NFTokenID] = Requirement.Required, //no need this field
+ [Field.NFTokenSellOffer] = Requirement.Optional,
+ [Field.NFTokenBuyOffer] = Requirement.Optional,
+ [Field.NFTokenBrokerFee] = Requirement.Optional,
},
- [BinaryCodec.Enums.TransactionType.UNLModify] = new TxFormat
+ [BinaryCodec.Types.TransactionType.UNLModify] = new TxFormat
{
[Field.LedgerSequence] = Requirement.Optional,
[Field.BaseFee] = Requirement.Required,
@@ -271,6 +279,50 @@ static TxFormat()
[Field.ReserveBase] = Requirement.Required,
[Field.ReserveIncrement] = Requirement.Required
},
+ [BinaryCodec.Types.TransactionType.AMMBid] = new TxFormat
+ {
+ [Field.Asset] = Requirement.Required,
+ [Field.Asset2] = Requirement.Required,
+ [Field.BidMin] = Requirement.Optional,
+ [Field.BidMax] = Requirement.Optional,
+ [Field.AuthAccounts] = Requirement.Optional
+ },
+ [BinaryCodec.Types.TransactionType.AMMCreate] = new TxFormat
+ {
+ [Field.Amount] = Requirement.Required,
+ [Field.Amount2] = Requirement.Required,
+ [Field.TradingFee] = Requirement.Required,
+ },
+ [BinaryCodec.Types.TransactionType.AMMDelete] = new TxFormat
+ {
+ [Field.Asset] = Requirement.Required,
+ [Field.Asset2] = Requirement.Required,
+ },
+ [BinaryCodec.Types.TransactionType.AMMDeposit] = new TxFormat
+ {
+ [Field.Asset] = Requirement.Required,
+ [Field.Asset2] = Requirement.Required,
+ [Field.Amount] = Requirement.Optional,
+ [Field.Amount2] = Requirement.Optional,
+ [Field.EPrice] = Requirement.Optional,
+ [Field.LPTokenOut] = Requirement.Optional,
+ },
+ [BinaryCodec.Types.TransactionType.AMMVote] = new TxFormat
+ {
+ [Field.Asset] = Requirement.Required,
+ [Field.Asset2] = Requirement.Required,
+ [Field.TradingFee] = Requirement.Required,
+ },
+ [BinaryCodec.Types.TransactionType.AMMWithdraw] = new TxFormat
+ {
+ [Field.Asset] = Requirement.Required,
+ [Field.Asset2] = Requirement.Required,
+ [Field.Amount] = Requirement.Optional,
+ [Field.Amount2] = Requirement.Optional,
+ [Field.EPrice] = Requirement.Optional,
+ [Field.LPTokenIn] = Requirement.Optional,
+ },
+
};
}
}
@@ -281,4 +333,4 @@ public TxFormatValidationException(string msg) : base(msg)
{
}
}
-}
+}
\ No newline at end of file
diff --git a/Xrpl/Models/Transactions/UNLModify.cs b/Xrpl/Models/Transactions/UNLModify.cs
new file mode 100644
index 00000000..faaec500
--- /dev/null
+++ b/Xrpl/Models/Transactions/UNLModify.cs
@@ -0,0 +1,55 @@
+//https://xrpl.org/unlmodify.html
+namespace Xrpl.Models.Transactions
+{
+ public class UNLModify : TransactionCommon, IUNLModify
+ {
+ public UNLModify()
+ {
+ //The value 0x0066, mapped to the string UNLModify, indicates that this object is an UNLModify pseudo-transaction
+ TransactionType = TransactionType.UNLModify;
+ }
+
+ ///
+ public string UNLModifyValidator { get; set; }
+
+ ///
+ public uint UNLModifyDisabling { get; set; }
+
+ ///
+ public uint LedgerSequence { get; set; }
+ }
+
+ public interface IUNLModify : ITransactionCommon
+ {
+ ///
+ /// The validator to add or remove, as identified by its master public key.
+ ///
+ string UNLModifyValidator { get; set; }
+
+ ///
+ /// If 1, this change represents adding a validator to the Negative UNL.
+ /// If 0, this change represents removing a validator from the Negative UNL.
+ /// (No other values are allowed.)
+ ///
+ uint UNLModifyDisabling { get; set; }
+
+ ///
+ /// The ledger index where this pseudo-transaction appears.
+ /// This distinguishes the pseudo-transaction from other occurrences of the same change.
+ ///
+ uint LedgerSequence { get; set; }
+ }
+
+ public class UNLModifyResponse : TransactionResponseCommon, IUNLModify
+ {
+ ///
+ public string UNLModifyValidator { get; set; }
+
+ ///
+ public uint UNLModifyDisabling { get; set; }
+
+ ///
+ public uint LedgerSequence { get; set; }
+ }
+
+}
diff --git a/Xrpl/Models/Transactions/Validation.cs b/Xrpl/Models/Transactions/Validation.cs
index 1e84206b..f51d6955 100644
--- a/Xrpl/Models/Transactions/Validation.cs
+++ b/Xrpl/Models/Transactions/Validation.cs
@@ -142,7 +142,6 @@ public static async Task Validate(Dictionary tx)
case "AMMWithdraw":
await ValidateAMMWithdraw(tx);
break;
-
default:
throw new ValidationException($"Invalid field TransactionType: {type}");
}
diff --git a/Xrpl/Models/Utils/Flags.cs b/Xrpl/Models/Utils/Flags.cs
index 2ddcbf97..3cb111a1 100644
--- a/Xrpl/Models/Utils/Flags.cs
+++ b/Xrpl/Models/Utils/Flags.cs
@@ -55,20 +55,19 @@ public static void SetTransactionFlagsToNumber(Dictionary tx)
"OfferCreate" => ConvertOfferCreateFlagsToNumber(Flags),
"Payment" => ConvertPaymentTransactionFlagsToNumber(Flags),
"PaymentChannelClaim" => ConvertPaymentChannelClaimFlagsToNumber(Flags),
- "AMMDeposit" => ConvertAMMDepositFlagsToNumber(Flags),
- "AMMWithdraw" => ConvertAMMWithdrawFlagsToNumber(Flags),
//TransactionType.PaymentChannelCreate => expr,
//TransactionType.PaymentChannelFund => expr,
//TransactionType.SetRegularKey => expr,
//TransactionType.SignerListSet => expr,
//TransactionType.TicketCreate => expr,
"TrustSet" => ConvertTrustSetFlagsToNumber(Flags),
+ "AMMDeposit" => ConvertAMMDepositFlagsToNumber(Flags),
+ "AMMWithdraw" => ConvertAMMWithdrawFlagsToNumber(Flags),
_ => 0
};
break;
}
}
-
public static uint ConvertAMMDepositFlagsToNumber(dynamic flags)
{
if (flags is not Dictionary flag)
@@ -85,7 +84,7 @@ public static uint ConvertAccountSetFlagsToNumber(dynamic flags)
{
if (flags is not Dictionary flag)
return 0;
- return ReduceFlags(flag, Enum.GetValues().ToDictionary(c => c.ToString(), c => (uint)c));
+ return ReduceFlags(flag, Enum.GetValues().ToDictionary(c => c.ToString(), c => (uint)c));
}
public static uint ConvertOfferCreateFlagsToNumber(dynamic flags)
diff --git a/Xrpl/Sugar/Autofill.cs b/Xrpl/Sugar/Autofill.cs
index 5ae2c4a2..317dafc2 100644
--- a/Xrpl/Sugar/Autofill.cs
+++ b/Xrpl/Sugar/Autofill.cs
@@ -1,42 +1,36 @@
-using System;
-using System.Linq;
+using Newtonsoft.Json;
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Numerics;
using System.Threading.Tasks;
+
using Xrpl.AddressCodec;
+using Xrpl.Client;
+using Xrpl.Client.Exceptions;
using Xrpl.Models.Common;
using Xrpl.Models.Ledger;
using Xrpl.Models.Methods;
-using System.Numerics;
-using static Xrpl.AddressCodec.XrplAddressCodec;
-using System.Collections.Generic;
-using Xrpl.Client;
-using Xrpl.Client.Exceptions;
using Xrpl.Utils;
-using System.Globalization;
-using Newtonsoft.Json.Linq;
-using Org.BouncyCastle.Math.EC.Multiplier;
-using Xrpl.BinaryCodec.Types;
-using System.IO;
-using System.Diagnostics;
-using Newtonsoft.Json;
-using Org.BouncyCastle.Asn1.Ocsp;
-using Xrpl.BinaryCodec.Enums;
-using Org.BouncyCastle.Utilities;
-using System.Security.Principal;
+
+using static Xrpl.AddressCodec.XrplAddressCodec;
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/sugar/autofill.ts
namespace Xrpl.Sugar
{
- public class AutofillSugar
+ public class AddressNTag
{
+ public string ClassicAddress { get; set; }
+ public int? Tag { get; set; }
+ }
- static readonly int LEDGER_OFFSET = 20;
+ public static class AutofillSugar
+ {
+
+ const int LEDGER_OFFSET = 20;
- public class AddressNTag
- {
- public string ClassicAddress { get; set; }
- public int? Tag { get; set; }
- }
///
/// Autofills fields in a transaction. This will set `Sequence`, `Fee`,
@@ -48,31 +42,32 @@ public class AddressNTag
/// A {@link Transaction} in JSON format
/// The expected number of signers for this transaction. Only used for multisigned transactions.
// The autofilled transaction.
- public static async Task> Autofill(IXrplClient client, Dictionary transaction, int? signersCount)
+ public static async Task> Autofill(this IXrplClient client, Dictionary transaction, int? signersCount)
{
Dictionary tx = transaction;
- SetValidAddresses(tx);
+ tx.SetValidAddresses();
//Flags.SetTransactionFlagsToNumber(tx);
List promises = new List();
bool hasTT = tx.TryGetValue("TransactionType", out var tt);
if (!tx.ContainsKey("Sequence"))
{
- promises.Add(SetNextValidSequenceNumber(client, tx));
+ promises.Add(client.SetNextValidSequenceNumber(tx));
}
if (!tx.ContainsKey("Fee"))
{
- promises.Add(CalculateFeePerTransactionType(client, tx, signersCount ?? 0));
+ promises.Add(client.CalculateFeePerTransactionType(tx, signersCount ?? 0));
}
if (!tx.ContainsKey("LastLedgerSequence"))
{
- promises.Add(SetLatestValidatedLedgerSequence(client, tx));
+ promises.Add(client.SetLatestValidatedLedgerSequence(tx));
}
if (tt == "AccountDelete")
{
- promises.Add(CheckAccountDeleteBlockers(client, tx));
+ //todo error here
+ //promises.Add(client.CheckAccountDeleteBlockers(tx));
}
await Task.WhenAll(promises);
string jsonData = JsonConvert.SerializeObject(tx);
@@ -80,24 +75,24 @@ public static async Task> Autofill(IXrplClient clien
}
- public static void SetValidAddresses(Dictionary tx)
+ public static void SetValidAddresses(this Dictionary tx)
{
- ValidateAccountAddress(tx, "Account", "SourceTag");
+ tx.ValidateAccountAddress("Account", "SourceTag");
if (tx.ContainsKey("Destination"))
{
- ValidateAccountAddress(tx, "Destination", "DestinationTag");
+ tx.ValidateAccountAddress("Destination", "DestinationTag");
}
// DepositPreauth:
- ConvertToClassicAddress(tx, "Authorize");
- ConvertToClassicAddress(tx, "Unauthorize");
+ tx.ConvertToClassicAddress("Authorize");
+ tx.ConvertToClassicAddress("Unauthorize");
// EscrowCancel, EscrowFinish:
- ConvertToClassicAddress(tx, "Owner");
+ tx.ConvertToClassicAddress("Owner");
// SetRegularKey:
- ConvertToClassicAddress(tx, "RegularKey");
+ tx.ConvertToClassicAddress("RegularKey");
}
- public static void ValidateAccountAddress(Dictionary tx, string accountField, string tagField)
+ public static void ValidateAccountAddress(this Dictionary tx, string accountField, string tagField)
{
// if X-address is given, convert it to classic address
var ainfo = tx.TryGetValue(accountField, out var aField);
@@ -119,7 +114,7 @@ public static void ValidateAccountAddress(Dictionary tx, string
}
}
- public static AddressNTag GetClassicAccountAndTag(string account, int? expectedTag)
+ public static AddressNTag GetClassicAccountAndTag(this string account, int? expectedTag)
{
if (XrplAddressCodec.IsValidXAddress(account))
{
@@ -133,20 +128,20 @@ public static AddressNTag GetClassicAccountAndTag(string account, int? expectedT
return new AddressNTag { ClassicAddress = account, Tag = expectedTag };
}
- public static void ConvertToClassicAddress(Dictionary tx, string fieldName)
+ public static void ConvertToClassicAddress(this Dictionary tx, string fieldName)
{
if (tx.ContainsKey(fieldName))
{
string account = (string)tx[fieldName];
if (account is string)
{
- AddressNTag addressntag = GetClassicAccountAndTag(account, null);
+ AddressNTag addressntag = account.GetClassicAccountAndTag(null);
tx[fieldName] = addressntag.ClassicAddress;
}
}
}
- public static async Task SetNextValidSequenceNumber(IXrplClient client, Dictionary tx)
+ public static async Task SetNextValidSequenceNumber(this IXrplClient client, Dictionary tx)
{
LedgerIndex index = new LedgerIndex(LedgerIndexType.Current);
AccountInfoRequest request = new AccountInfoRequest((string)tx["Account"]) { LedgerIndex = index };
@@ -154,7 +149,7 @@ public static async Task SetNextValidSequenceNumber(IXrplClient client, Dictiona
tx.TryAdd("Sequence", data.AccountData.Sequence);
}
- public static async Task FetchAccountDeleteFee(IXrplClient client)
+ public static async Task FetchAccountDeleteFee(this IXrplClient client)
{
ServerStateRequest request = new ServerStateRequest();
ServerState data = await client.ServerState(request);
@@ -167,9 +162,9 @@ public static async Task FetchAccountDeleteFee(IXrplClient client)
return BigInteger.Parse(fee.ToString());
}
- public static async Task CalculateFeePerTransactionType(IXrplClient client, Dictionary tx, int signersCount = 0)
+ public static async Task CalculateFeePerTransactionType(this IXrplClient client, Dictionary tx, int signersCount = 0)
{
- var netFeeXRP = await GetFeeXrpSugar.GetFeeXrp(client);
+ var netFeeXRP = await client.GetFeeXrp();
var netFeeDrops = XrpConversion.XrpToDrops(netFeeXRP);
var baseFee = BigInteger.Parse(netFeeDrops, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent);
@@ -209,13 +204,13 @@ public static string ScaleValue(string value, double multiplier)
return (double.Parse(value)! * multiplier).ToString();
}
- public static async Task SetLatestValidatedLedgerSequence(IXrplClient client, Dictionary tx)
+ public static async Task SetLatestValidatedLedgerSequence(this IXrplClient client, Dictionary tx)
{
uint ledgerSequence = await client.GetLedgerIndex();
tx.TryAdd("LastLedgerSequence", ledgerSequence + LEDGER_OFFSET);
}
- public static async Task CheckAccountDeleteBlockers(IXrplClient client, Dictionary tx)
+ public static async Task CheckAccountDeleteBlockers(this IXrplClient client, Dictionary tx)
{
LedgerIndex index = new LedgerIndex(LedgerIndexType.Validated);
AccountObjectsRequest request = new AccountObjectsRequest((string)tx["Account"])
diff --git a/Xrpl/Sugar/Balances.cs b/Xrpl/Sugar/Balances.cs
index 61adce32..520780c8 100644
--- a/Xrpl/Sugar/Balances.cs
+++ b/Xrpl/Sugar/Balances.cs
@@ -1,5 +1,9 @@
using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Channels;
using System.Threading.Tasks;
+
using Xrpl.Client;
using Xrpl.Models.Common;
using Xrpl.Models.Ledger;
@@ -9,22 +13,34 @@
namespace Xrpl.Sugar
{
- public class BalancesSugar
+ public class Balance
{
- public class Balance
- {
- public string value { get; set; }
- public string currency { get; set; }
- public string issuer { get; set; }
- }
+ public string Value { get; set; }
+ public string Currency { get; set; }
+ public string Issuer { get; set; }
+ }
- public class GetBalancesOptions
- {
- public string? LedgerHash { get; set; }
- public LedgerIndex? LedgerIndex { get; set; }
- public string Peer { get; set; }
- public int Limit { get; set; }
- }
+ public class GetBalancesOptions
+ {
+ public string? LedgerHash { get; set; }
+ public LedgerIndex? LedgerIndex { get; set; }
+ public string Peer { get; set; }
+ public int? Limit { get; set; }
+ }
+
+ public static class BalancesSugar
+ {
+
+ public static IEnumerable FormatBalances(this IEnumerable trustlines) =>
+ trustlines.Select(Map);
+
+ public static Balance Map(this TrustLine trustline) =>
+ new Balance()
+ {
+ Value = trustline.Balance,
+ Currency = trustline.Currency,
+ Issuer = trustline.Account,
+ };
///
/// Get the XRP balance for an account.
@@ -34,7 +50,7 @@ public class GetBalancesOptions
/// Retrieve the account balances at a given ledgerIndex.
/// Retrieve the account balances at the ledger with a given ledger_hash.
/// The XRP balance of the account (as a string).
- public static async Task GetXrpBalance(XrplClient client, string address, string? ledgerHash = null, LedgerIndex? lederIndex = null)
+ public static async Task GetXrpBalance(this XrplClient client, string address, string? ledgerHash = null, LedgerIndex? lederIndex = null)
{
LedgerIndex index = new LedgerIndex(LedgerIndexType.Validated);
AccountInfoRequest xrpRequest = new AccountInfoRequest(address)
@@ -47,38 +63,41 @@ public static async Task GetXrpBalance(XrplClient client, string address
return accountInfo.AccountData.Balance.ValueAsXrp.ToString();
}
- //public async Task> GetBalances(XrplClient client, string address, GetBalancesOptions options = null)
- //{
- // var balances = new List();
- // var xrpPromise = Task.FromResult("");
- // if (options?.Peer == null)
- // {
- // xrpPromise = GetXrpBalance(client, address, options?.LedgerHash, options?.LedgerIndex);
- // }
+ public static async Task> GetBalances(this XrplClient client, string address, GetBalancesOptions options = null)
+ {
+ var linesRequest = new AccountLinesRequest(address)
+ {
+ Command = "account_lines",
+ LedgerIndex = options?.LedgerIndex ?? new LedgerIndex(LedgerIndexType.Validated),
+ LedgerHash = options?.LedgerHash,
+ Peer = options?.Peer,
+ Limit = options?.Limit
+ };
+
+ var response = await client.AccountLines(linesRequest);
+ var lines = response.TrustLines;
+ while (response.Marker is not null && lines.Count > 0)
+ {
+ linesRequest.Marker = response.Marker;
+ response = await client.AccountLines(linesRequest);
+ if (response.TrustLines.Count > 0)
+ lines.AddRange(response.TrustLines);
+ if (options?.Limit is not null && lines.Count >= options.Limit)
+ break;
+ }
+ var balances = lines.FormatBalances().ToList();
- // var linesRequest = new AccountLinesRequest
- // {
- // Command = "account_lines",
- // Account = address,
- // LedgerIndex = options?.LedgerIndex ?? new LedgerIndex(LedgerIndexType.Validated),
- // LedgerHash = options?.LedgerHash,
- // Peer = options?.Peer,
- // Limit = options?.Limit
- // };
- // var linesPromise = RequestAll(linesRequest);
+ if (options?.Peer == null)
+ {
+ var xrp_balance = await GetXrpBalance(client, address, options?.LedgerHash, options?.LedgerIndex);
+ if (!string.IsNullOrWhiteSpace(xrp_balance))
+ {
+ balances.Insert(0, new Balance { Currency = "XRP", Value = xrp_balance });
+ }
- // await Task.WhenAll(xrpPromise, linesPromise).ContinueWith(async (t) =>
- // {
- // var xrpBalance = await xrpPromise;
- // var linesResponses = await linesPromise;
- // var accountLinesBalance = linesResponses.SelectMany(response => FormatBalances(response.Result.Lines));
- // if (xrpBalance != "")
- // {
- // balances.Add(new Balance { Currency = "XRP", Value = xrpBalance });
- // }
- // balances.AddRange(accountLinesBalance);
- // });
- // return balances.Take(options?.Limit ?? balances.Count).ToList();
- //}
+ }
+
+ return balances;
+ }
}
}
\ No newline at end of file
diff --git a/Xrpl/Sugar/GetFeeXrp.cs b/Xrpl/Sugar/GetFeeXrp.cs
index 08758348..9de960e4 100644
--- a/Xrpl/Sugar/GetFeeXrp.cs
+++ b/Xrpl/Sugar/GetFeeXrp.cs
@@ -1,41 +1,40 @@
using System;
-using System.Diagnostics;
+using System.Globalization;
+using System.Runtime.CompilerServices;
using System.Threading.Tasks;
-using Xrpl;
-using Xrpl.Client.Exceptions;
-using Xrpl.Models.Common;
-using Xrpl.Models.Ledger;
-using Xrpl.Models.Methods;
-using System.Numerics;
+
using Xrpl.Client;
using Xrpl.Client.Exceptions;
+using Xrpl.Models.Methods;
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/sugar/getFeeXrp.ts
namespace Xrpl.Sugar
{
- public class GetFeeXrpSugar
+ public static class GetFeeXrpSugar
{
- private static int NUM_DECIMAL_PLACES = 6;
+ private const int NUM_DECIMAL_PLACES = 6;
+ private const int BASE_10 = 10;
///
/// Calculates the current transaction fee for the ledger.
/// Note: This is a public API that can be called directly.
///
/// The Client used to connect to the ledger.
- ///
- // The most recently validated ledger index.
- public async static Task GetFeeXrp(IXrplClient client, double? cushion = null)
+ /// The fee cushion to use
+ /// The transaction fee
+ public static async Task GetFeeXrp(this IXrplClient client, double? cushion = null)
{
double feeCushion = cushion ?? client.feeCushion;
ServerInfoRequest request = new ServerInfoRequest();
ServerInfo serverInfo = await client.ServerInfo(request);
- double? baseFee = serverInfo.Info.ValidatedLedger.BaseFeeXrp;
+ double? baseFee = serverInfo.Info.ValidatedLedger?.BaseFeeXrp;
if (baseFee == null)
{
throw new XrplException("getFeeXrp: Could not get base_fee_xrp from server_info");
}
- decimal baseFeeXrp = decimal.Parse(baseFee.ToString(), System.Globalization.NumberStyles.AllowExponent);
+
+ decimal baseFeeXrp = (decimal)baseFee;
if (serverInfo.Info.LoadFactor == null)
{
@@ -43,13 +42,13 @@ public async static Task GetFeeXrp(IXrplClient client, double? cushion =
serverInfo.Info.LoadFactor = 1;
}
- decimal fee = baseFeeXrp * decimal.Parse(serverInfo.Info.LoadFactor.ToString()) * ((decimal)feeCushion);
+ decimal fee = baseFeeXrp * (decimal)serverInfo.Info.LoadFactor * (decimal)feeCushion;
// Cap fee to `client.maxFeeXRP`
fee = Math.Min(fee, decimal.Parse(client.maxFeeXRP));
// Round fee to 6 decimal places
// TODO: Review To Fixed
- return fee.ToString();
+ return fee.ToString(CultureInfo.InvariantCulture);
}
}
}
diff --git a/Xrpl/Sugar/GetLedgerIndex.cs b/Xrpl/Sugar/GetLedgerIndex.cs
index 42d96ea3..707d1d35 100644
--- a/Xrpl/Sugar/GetLedgerIndex.cs
+++ b/Xrpl/Sugar/GetLedgerIndex.cs
@@ -1,7 +1,6 @@
using System;
-using System.Diagnostics;
using System.Threading.Tasks;
-using Newtonsoft.Json;
+
using Xrpl.Client;
using Xrpl.Models.Common;
using Xrpl.Models.Ledger;
@@ -11,14 +10,14 @@
namespace Xrpl.Sugar
{
- public class GetLedgerSugar
+ public static class GetLedgerSugar
{
///
/// Returns the index of the most recently validated ledger.
///
/// The Client used to connect to the ledger.
// The most recently validated ledger index.
- public static async Task GetLedgerIndex(IXrplClient client)
+ public static async Task GetLedgerIndex(this IXrplClient client)
{
LedgerIndex index = new LedgerIndex(LedgerIndexType.Current);
LedgerRequest request = new LedgerRequest() { LedgerIndex = index };
diff --git a/Xrpl/Sugar/GetOrderBook.cs b/Xrpl/Sugar/GetOrderBook.cs
index be27aca0..5c183227 100644
--- a/Xrpl/Sugar/GetOrderBook.cs
+++ b/Xrpl/Sugar/GetOrderBook.cs
@@ -1,51 +1,67 @@
-//// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/sugar/utils.ts
-
-//namespace Xrpl.Sugar
-//{
-// public class UtilsSugar
-// {
-// private const int DEFAULT_LIMIT = 20;
-
-// private static BookOffer[] SortOffers(BookOffer[] offers)
-// {
-// return offers.OrderBy(offer => offer.Quality ?? 0).ToArray();
-// }
-
-// public async Task<(List buy, List sell)> GetOrderbook(TakerAmount takerPays, TakerAmount takerGets, int limit = DEFAULT_LIMIT, int ledgerIndex = -1, string ledgerHash = null, string taker = null)
-// {
-// var request = new BookOffersRequest
-// {
-// Command = "book_offers",
-// TakerPays = takerPays,
-// TakerGets = takerGets,
-// LedgerIndex = ledgerIndex == -1 ? "validated" : ledgerIndex.ToString(),
-// LedgerHash = ledgerHash,
-// Limit = limit,
-// Taker = taker
-// };
-// var directOfferResults = await RequestAll(request);
-// request.TakerGets = takerPays;
-// request.TakerPays = takerGets;
-// var reverseOfferResults = await RequestAll(request);
-// var directOffers = directOfferResults.SelectMany(directOfferResult => directOfferResult.Result.Offers).ToList();
-// var reverseOffers = reverseOfferResults.SelectMany(reverseOfferResult => reverseOfferResult.Result.Offers).ToList();
-// var orders = directOffers.Concat(reverseOffers).ToList();
-// var buy = new List();
-// var sell = new List();
-// orders.ForEach(order =>
-// {
-// if ((order.Flags & OfferFlags.lsfSell) == 0)
-// {
-// buy.Add(order);
-// }
-// else
-// {
-// sell.Add(order);
-// }
-// });
-// return (SortOffers(buy).Take(limit).ToList(), SortOffers(sell).Take(limit).ToList());
-// }
-// }
-//}
+// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/sugar/utils.ts
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Xrpl.Client;
+using Xrpl.Models.Common;
+using Xrpl.Models.Ledger;
+using Xrpl.Models.Methods;
+using Xrpl.Models.Transactions;
+
+namespace Xrpl.Sugar
+{
+ public static class GetOrderBookSugar
+ {
+ private const uint DEFAULT_LIMIT = 20;
+
+ private static List SortOffers(List offers)
+ {
+ return offers.OrderBy(offer => offer.Quality ?? 0).ToList();
+ }
+
+ public static async Task<(List buy, List sell)> GetOrderbook(this IXrplClient Client,
+ TakerAmount takerPays, TakerAmount takerGets,
+ uint limit = DEFAULT_LIMIT, int ledgerIndex = -1, string ledgerHash = null, string taker = null)
+ {
+ var request = new BookOffersRequest
+ {
+ Command = "book_offers",
+ TakerPays = takerPays,
+ TakerGets = takerGets,
+ LedgerIndex = new LedgerIndex(ledgerIndex==-1? LedgerIndexType.Validated: (LedgerIndexType)ledgerIndex),
+ LedgerHash = ledgerHash,
+ Limit = limit,
+ Taker = taker
+ };
+ var directOfferResults = await Client.BookOffers(request);
+ request.TakerGets = takerPays;
+ request.TakerPays = takerGets;
+ var reverseOfferResults = await Client.BookOffers(request);
+ var directOffers = directOfferResults.Offers;
+ var reverseOffers = reverseOfferResults.Offers;
+ var orders = directOffers.Concat(reverseOffers).ToList();
+ var buy = new List();
+ var sell = new List();
+ orders.ForEach(order =>
+ {
+ if ((order.Flags & OfferFlags.lsfSell) == 0)
+ {
+ buy.Add(order);
+ }
+ else
+ {
+ sell.Add(order);
+ }
+ });
+ return (SortOffers(buy).Take((int)limit).ToList(), SortOffers(sell).Take((int)limit).ToList());
+ }
+ }
+
+}
diff --git a/Xrpl/Sugar/Submit.cs b/Xrpl/Sugar/Submit.cs
index 5abc7cd0..692c6aec 100644
--- a/Xrpl/Sugar/Submit.cs
+++ b/Xrpl/Sugar/Submit.cs
@@ -2,19 +2,26 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
+
using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+using Xrpl.BinaryCodec;
using Xrpl.Client;
using Xrpl.Client.Exceptions;
+using Xrpl.Models;
using Xrpl.Models.Methods;
using Xrpl.Models.Transactions;
+using Xrpl.Utils.Hashes;
using Xrpl.Wallet;
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/sugar/submit.ts
namespace Xrpl.Sugar
{
- public class SubmitSugar
+ public static class SubmitSugar
{
+ private const int LEDGER_CLOSE_TIME = 1000;
///
/// Submits a signed/unsigned transaction.
/// Steps performed on a transaction:
@@ -30,18 +37,49 @@ public class SubmitSugar
/// If true, autofill a transaction.
/// If true, and the transaction fails locally, do not retry or relay the transaction to other servers.
/// A wallet to sign a transaction. It must be provided when submitting an unsigned transaction.
- /// A Wallet derived from a seed.
- public static async Task Submit(
- IXrplClient client,
+ /// A promise that contains SubmitResponse
+ public static async Task Submit(this IXrplClient client,
Dictionary transaction,
bool autofill = false,
bool failHard = false,
XrplWallet wallet = null
)
{
- string signedTx = await SubmitSugar.GetSignedTx(client, transaction, autofill, false, wallet);
+ string signedTx = await client.GetSignedTx(transaction, autofill, false, wallet);
return await SubmitRequest(client, signedTx, failHard);
}
+ ///
+ /// Asynchronously submits a transaction and verifies that it has been included in a
+ /// validated ledger(or has errored/will not be included for some reason).
+ /// See[Reliable Transaction Submission] (https://xrpl.org/reliable-transaction-submission.html).
+ ///
+ /// A Client.
+ /// A transaction to autofill, sign and encode, and submit.
+ /// If true, autofill a transaction.
+ /// If true, and the transaction fails locally, do not retry or relay the transaction to other servers.
+ /// A wallet to sign a transaction. It must be provided when submitting an unsigned transaction.
+ /// A promise that contains TxResponse, that will return when the transaction has been validated.
+ public static async Task SubmitAndWait(this IXrplClient client,
+ Dictionary transaction,
+ bool autofill = false,
+ bool failHard = false,
+ XrplWallet wallet = null)
+ {
+ var signedTx = await client.GetSignedTx(transaction, autofill, failHard, wallet);
+ var lastLedger = GetLastLedgerSequence(signedTx);
+ if (lastLedger == null)
+ {
+ throw new ValidationException("Transaction must contain a LastLedgerSequence value for reliable submission.");
+ }
+
+ var response = await client.SubmitRequest(signedTx, failHard);
+ var txHash = HashLedger.HashSignedTx(signedTx);
+ return await WaitForFinalTransactionOutcome(
+ client,
+ txHash,
+ lastLedger,
+ response.EngineResult);
+ }
///
/// Encodes and submits a signed transaction.
@@ -50,20 +88,65 @@ public static async Task Submit(
/// signed Transaction
/// If true, and the transaction fails locally, do not retry or relay the transaction to other servers.
///
- public static async Task SubmitRequest(IXrplClient client, string signedTransaction, bool failHard)
+ public static async Task SubmitRequest(this IXrplClient client, object signedTransaction, bool failHard)
{
- //if (!isSigned(signedTransaction)) {
- // throw new ValidationException('Transaction must be signed')
+ //todo activate after fix
+ //if (!IsSigned(signedTransaction))
+ //{
+ // throw new ValidationException("Transaction must be signed");
//}
- //string signedTxEncoded = typeof signedTransaction === 'string' ? signedTransaction : encode(signedTransaction)
- //string signedTxEncoded = BinaryCodec.Encode(signedTransaction);
- string signedTxEncoded = signedTransaction;
- //SubmitBlobRequest request = new SubmitBlobRequest { Command = "submit", TxBlob = signedTxEncoded, FailHard = isAccountDelete(signedTransaction) || failHard };
- SubmitRequest request = new SubmitRequest { Command = "submit", TxBlob = signedTxEncoded, FailHard = false };
+ string signedTxEncoded = signedTransaction is string transaction ? transaction : XrplBinaryCodec.Encode(signedTransaction);
+ SubmitRequest request = new SubmitRequest { Command = "submit", TxBlob = signedTxEncoded, FailHard = failHard };
var response = await client.GRequest(request);
return response;
}
+ ///
+ /// The core logic of reliable submission.This polls the ledger until the result of the
+ /// transaction can be considered final, meaning it has either been included in a
+ /// validated ledger, or the transaction's lastLedgerSequence has been surpassed by the
+ /// latest ledger sequence (meaning it will never be included in a validated ledger).
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private static async Task WaitForFinalTransactionOutcome(this IXrplClient Client, string TxHash, uint? lastLedger, string submissionResult)
+ {
+ await Task.Delay(LEDGER_CLOSE_TIME);
+ var latestLedger = await Client.GetLedgerIndex();
+ if (lastLedger < latestLedger)
+ {
+ throw new ValidationException(
+ "The latest ledger sequence ${ latestLedger } is greater than the transaction's LastLedgerSequence (${lastLedger}).\n" +
+ $"Preliminary result: {submissionResult}");
+ }
+
+ TransactionResponseCommon txResponse = null;
+ try
+ {
+ txResponse = await Client.Tx(new TxRequest(TxHash));
+
+ }
+ catch (Exception error)
+ {
+ // error is of an unknown type and hence we assert type to extract the value we need.
+ var message = error?.Data["Error"] as string;
+ if (message == "txnNotFound")
+ {
+ return await WaitForFinalTransactionOutcome(Client, TxHash, lastLedger, submissionResult);
+ }
+ throw new ValidationException($"{message} \n Preliminary result: {submissionResult}.\nFull error details: {error.Message}");
+ }
+ if (txResponse.Validated == true)
+ {
+ return txResponse;
+ }
+
+ return await WaitForFinalTransactionOutcome(Client, TxHash, lastLedger, submissionResult);
+ }
///
/// Initializes a transaction for a submit request
@@ -74,15 +157,14 @@ public static async Task SubmitRequest(IXrplClient client, string signed
/// If true, and the transaction fails locally, do not retry or relay the transaction to other servers.
/// A wallet to sign a transaction. It must be provided when submitting an unsigned transaction.
/// A Wallet derived from a seed.
- public static async Task GetSignedTx(
- IXrplClient client,
+ public static async Task GetSignedTx(this IXrplClient client,
Dictionary transaction,
bool autofill = false,
bool failHard = false,
XrplWallet? wallet = null
)
{
- //if (isSigned(transaction))
+ //if (IsSigned(transaction))
//{
// return transaction
//}
@@ -92,10 +174,9 @@ public static async Task GetSignedTx(
throw new ValidationException("Wallet must be provided when submitting an unsigned transaction");
}
Dictionary tx = transaction;
- //let tx =
- // typeof transaction === 'string'
+ //var tx = transaction is string
// ? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- converts JsonObject to correct Transaction type
- // (decode(transaction) as unknown as Transaction)
+ // (decode(transaction) as unknown as TransactionCommon)
// : transaction
if (autofill)
{
@@ -103,6 +184,76 @@ public static async Task GetSignedTx(
}
return wallet.Sign(tx, false).TxBlob;
}
+
+ public static bool IsSigned(object transaction)
+ {
+ if (transaction is Dictionary { } tx)
+ {
+ return tx.TryGetValue("SigningPubKey", out var SigningPubKey) && SigningPubKey is not null ||
+ tx.TryGetValue("TxnSignature", out var TxnSignature) && TxnSignature is not null;
+ }
+ else
+ {
+ var ob = XrplBinaryCodec.Encode(transaction);
+ var json = JObject.Parse($"{ob}");
+ return json.TryGetValue("SigningPubKey", out var SigningPubKey) && !string.IsNullOrWhiteSpace(SigningPubKey.ToString()) ||
+ json.TryGetValue("TxnSignature", out var TxnSignature) && !string.IsNullOrWhiteSpace(TxnSignature.ToString());
+ }
+ }
+ ///
+ /// checks if there is a LastLedgerSequence as a part of the transaction
+ ///
+ /// tx
+ ///
+ public static uint? GetLastLedgerSequence(object transaction)
+ {
+ if (transaction is Dictionary { } tx)
+ {
+ return tx.TryGetValue("LastLedgerSequence", out var LastLedgerSequence) && LastLedgerSequence is uint
+ ? LastLedgerSequence
+ : null;
+ }
+ else if (transaction is TransactionCommon txc)
+ {
+ return txc.LastLedgerSequence;
+ }
+
+ else
+ {
+ var ob = XrplBinaryCodec.Encode(transaction);
+ var json = JObject.Parse($"{ob}");
+
+ return json.TryGetValue("LastLedgerSequence", out var LastLedgerSequence) && uint.TryParse(LastLedgerSequence.ToString(), out var seq)
+ ? seq
+ : null;
+ }
+
+ }
+
+ ///
+ /// checks if the transaction is an AccountDelete transaction
+ ///
+ /// tx
+ ///
+ public static bool IsAccountDelete(object transaction)
+ {
+ if (transaction is Dictionary { } tx)
+ {
+ return tx.TryGetValue("TransactionType", out var TransactionType) && $"{TransactionType}" == "AccountDelete";
+ }
+ else if (transaction is TransactionCommon txc)
+ {
+ return txc.TransactionType == TransactionType.AccountDelete;
+ }
+ else
+ {
+ var ob = XrplBinaryCodec.Encode(transaction);
+ var json = JObject.Parse($"{ob}");
+
+ return json.TryGetValue("TransactionType", out var TransactionType) && TransactionType.ToString() == "AccountDelete";
+ }
+
+ }
}
}
diff --git a/Xrpl/Sugar/Utils.cs b/Xrpl/Sugar/Utils.cs
new file mode 100644
index 00000000..58b7d08b
--- /dev/null
+++ b/Xrpl/Sugar/Utils.cs
@@ -0,0 +1,27 @@
+using Xrpl.AddressCodec;
+using Xrpl.Client.Exceptions;
+
+namespace Xrpl.Sugar
+{
+ public class Utils
+ {
+ ///
+ /// If an address is an X-Address, converts it to a classic address.
+ ///
+ /// A classic address or X-address.
+ /// The account's classic address.
+ public static string EnsureClassicAddress(string account)
+ {
+ if (XrplAddressCodec.IsValidXAddress(account))
+ {
+ var codec = XrplAddressCodec.XAddressToClassicAddress(account);
+ if (codec.Tag is not null)
+ throw new RippleException("This command does not support the use of a tag. Use an address without a tag.");
+
+ // For rippled requests that use an account, always use a classic address.
+ return codec.ClassicAddress;
+ }
+ return account;
+ }
+ }
+}
diff --git a/Xrpl/Utils/CreateCrossChainPayment.cs b/Xrpl/Utils/CreateCrossChainPayment.cs
new file mode 100644
index 00000000..03a960ba
--- /dev/null
+++ b/Xrpl/Utils/CreateCrossChainPayment.cs
@@ -0,0 +1,67 @@
+//https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/createCrossChainPayment.ts
+using System.Collections.Generic;
+using System.Linq;
+
+using Xrpl.Client.Exceptions;
+using Xrpl.Models.Transactions;
+
+namespace Xrpl.Utils
+{
+ public static class CrossChainPayment
+ {
+ ///
+ /// Creates a cross-chain payment transaction.
+ ///
+ /// he initial payment transaction. If the transaction is
+ /// signed, then it will need to be re-signed.There must be no more than 2
+ /// memos, since one memo is used for the sidechain destination account.The
+ /// destination must be the sidechain's door account.
+ /// the destination account on the sidechain.
+ /// A cross-chain payment transaction, where the mainchain door account
+ ///is the `Destination` and the destination account on the sidechain is encoded
+ ///in the memos.
+ /// if there are more than 2 memos.
+ public static Payment CreateCrossChainPayment(this Payment payment, string destAccount) //todo check it
+ {
+ var destAccountHex = destAccount.ConvertStringToHex();
+ var destAccountMemo = new Memo { MemoData = destAccountHex };
+
+ var memos = payment.Memos?.Select(c => c.Memo).ToList() ?? new List();
+ if (memos.Count > 2)
+ {
+ throw new XrplException("Cannot have more than 2 memos in a cross-chain transaction.");
+ }
+ var newMemos = new List { destAccountMemo };
+ newMemos.AddRange(memos);
+
+ var newPayment = new Payment
+ {
+ TransactionType = payment.TransactionType,
+ Account = payment.Account,
+ AccountTxnID = payment.AccountTxnID,
+ Amount = payment.Amount,
+ DeliverMin = payment.DeliverMin,
+ Destination = payment.Destination,
+ DestinationTag = payment.DestinationTag,
+ Fee = payment.Fee,
+ Flags = payment.Flags,
+ InvoiceID = payment.InvoiceID,
+ LastLedgerSequence = payment.LastLedgerSequence,
+ Meta = payment.Meta,
+ Paths = payment.Paths,
+ SendMax = payment.SendMax,
+ Sequence = payment.Sequence,
+ Signers = payment.Signers,
+ SigningPublicKey = payment.SigningPublicKey,
+ date = payment.date,
+ inLedger = payment.inLedger,
+ ledger_index = payment.ledger_index,
+
+ Memos = newMemos.Select(c => new MemoWrapper() { Memo = c }).ToList(),
+ TransactionSignature = null
+ };
+
+ return newPayment;
+ }
+ }
+}
diff --git a/Xrpl/Utils/Derive.cs b/Xrpl/Utils/Derive.cs
index be301142..49a35e80 100644
--- a/Xrpl/Utils/Derive.cs
+++ b/Xrpl/Utils/Derive.cs
@@ -3,12 +3,27 @@
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/derive.ts
//todo DO
+
+using Xrpl.AddressCodec;
+using Xrpl.Keypairs;
+
namespace Xrpl.Utils
{
- public class Derive
+ public static class Derive
{
- public Derive()
+ ///
+ /// Derive an X-Address from a public key and a destination tag.
+ /// Options - Public key and destination tag to encode as an X-Address.
+ ///
+ /// The public key corresponding to an address.
+ /// A destination tag to encode into an X-address. False indicates no destination tag.
+ /// Whether this address is for use in Testnet.
+ /// X-Address.
+ /// Utilities
+ public static string DeriveXAddress(string publicKey, int? tag, bool test)
{
+ var classicAddress = XrplKeypairs.DeriveAddress(publicKey);
+ return XrplAddressCodec.ClassicAddressToXAddress(classicAddress, tag, test);
}
}
}
diff --git a/Xrpl/Utils/GetBalanceChanges.cs b/Xrpl/Utils/GetBalanceChanges.cs
index c7ac35a8..94a62ea5 100644
--- a/Xrpl/Utils/GetBalanceChanges.cs
+++ b/Xrpl/Utils/GetBalanceChanges.cs
@@ -3,13 +3,227 @@
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/getBalanceChanges.ts
//todo DO
+using static Xrpl.Models.Common.Common;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Numerics;
+using Xrpl.Models.Transactions;
+using Xrpl.Sugar;
+using Xrpl.Utils.Hashes.ShaMap;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Xrpl.Models.Common;
+
namespace Xrpl.Utils
{
- public class GetBalanceChanges
+
+ public class BalanceChange
+ {
+ public string Account { get; set; }
+ public Balance Balance { get; set; }
+ }
+
+ public class Fields
+ {
+ public string Account { get; set; }
+ public Currency Balance { get; set; }
+ public IssuedCurrencyAmount LowLimit { get; set; }
+ public IssuedCurrencyAmount HighLimit { get; set; }
+ public Dictionary FieldDict { get; set; }
+ }
+
+ public class NormalizedNode
+ {
+ public string NodeType { get; set; }
+ public string LedgerEntryType { get; set; }
+ public string LedgerIndex { get; set; }
+ public Fields NewFields { get; set; }
+ public Fields FinalFields { get; set; }
+ public Fields PreviousFields { get; set; }
+ public string PreviousTxnID { get; set; }
+ public int PreviousTxnLgrSeq { get; set; }
+ }
+
+ public static class GetBalanceChanges
{
- public GetBalanceChanges()
+
+ //todo need help with NormalizeNodes
+ //public static NormalizedNode NormalizeNode(this INode affectedNode)
+ //{
+ // var diffType = affectedNode[0];
+ // NormalizedNode node = affectedNode[diffType] as NormalizedNode;
+ // return new NormalizedNode
+ // {
+ // NodeType = diffType,
+ // LedgerEntryType = node.LedgerEntryType,
+ // LedgerIndex = node.LedgerIndex,
+ // NewFields = node.NewFields,
+ // FinalFields = node.FinalFields,
+ // PreviousFields = node.PreviousFields
+ // };
+ //}
+
+ //public static List NormalizeNodes(this TransactionMetadata metadata)
+ //{
+ // if (metadata.AffectedNodes.Count == 0)
+ // {
+ // return new List();
+ // }
+
+ // return metadata.AffectedNodes.Select(NormalizeNodes).ToList();
+ //}
+
+ public static List<(string account, List balances)> GroupByAccount(this List balanceChanges)
+ {
+ var grouped = balanceChanges.GroupBy(node => node.Account);
+ return grouped.Select(item => (item.Key, item.Select(i => i.Balance).ToList())).ToList();
+ }
+
+ public static BigInteger GetValue(object balance) //todo need to check
+ {
+ if (balance is string val)
+ {
+ return BigInteger.Parse(val, NumberStyles.AllowLeadingSign
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | NumberStyles.AllowExponent
+ | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);
+ }
+
+ var json = JObject.Parse(JsonConvert.SerializeObject(balance));
+ return BigInteger.Parse(json["Value"].ToString(), NumberStyles.AllowLeadingSign
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | NumberStyles.AllowExponent
+ | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);
+ }
+
+ public static BigInteger? ComputeBalanceChange(this NormalizedNode node)
+ {
+ BigInteger? value = null;
+ if (node.NewFields?.Balance != null)
+ {
+ value = GetValue(node.NewFields.Balance);
+ }
+ else if (node.PreviousFields?.Balance != null && node.FinalFields?.Balance != null)
+ {
+ value = GetValue(node.FinalFields.Balance) - GetValue(node.PreviousFields.Balance);
+ }
+
+ if (value is null || value.Value.IsZero)
+ {
+ return null;
+ }
+
+ return value;
+ }
+
+ public static (string account, Balance balance) GetXRPQuantity(this NormalizedNode node)
+ {
+ var value = ComputeBalanceChange(node);
+
+ if (value == null)
+ {
+ return (null, null);
+ }
+
+ return (node.FinalFields?.Account ?? node.NewFields?.Account,
+ new Balance
+ {
+ Currency = "XRP",
+ Value = XrpConversion.DropsToXrp(value.Value.ToString())
+ });
+ }
+
+ public static BalanceChange FlipTrustlinePerspective(this BalanceChange balanceChange)
+ {
+ var negatedBalance = BigInteger.Parse(
+ balanceChange.Balance.Value, NumberStyles.AllowLeadingSign
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | NumberStyles.AllowExponent
+ | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);//.Negate();
+ return new BalanceChange
+ {
+ Account = balanceChange.Balance.Issuer,
+ Balance = new Balance
+ {
+ Issuer = balanceChange.Account,
+ Currency = balanceChange.Balance.Currency,
+ Value = negatedBalance.ToString()
+ }
+ };
+ }
+
+ public static List GetTrustlineQuantity(this NormalizedNode node)
{
+ var value = ComputeBalanceChange(node);
+
+ if (value == null)
+ {
+ return null;
+ }
+ /*
+ * A trustline can be created with a non-zero starting balance.
+ * If an offer is placed to acquire an asset with no existing trustline,
+ * the trustline can be created when the offer is taken.
+ */
+ var fields = node.NewFields ?? node.FinalFields;
+ var result = new BalanceChange
+ {
+ Account = fields?.LowLimit?.Issuer,
+ Balance = new Balance
+ {
+ Issuer = fields?.HighLimit?.Issuer,
+ Currency = fields?.Balance.CurrencyCode,
+ Value = value.ToString()
+ }
+ };
+ return new List { result, FlipTrustlinePerspective(result) };
}
+ ///// //todo need help with NormalizeNodes
+ ///// Computes the complete list of every balance that changed in the ledger as a result of the given transaction.
+ /////
+ ///// Transaction metadata.
+ ///// Parsed balance changes.
+ //public static List<(string account, List balances)> GetBalanceChanges(this TransactionMetadata metadata)
+ //{
+ // var quantities = NormalizeNodes(metadata).Select(
+ // node =>
+ // {
+ // if (node.LedgerEntryType == "AccountRoot")
+ // {
+ // var xrpQuantity = GetXRPQuantity(node);
+ // if (xrpQuantity.account == null)
+ // {
+ // return new List();
+ // }
+
+ // return new List() { new BalanceChange() { Account = xrpQuantity.account, Balance = xrpQuantity.balance } };
+ // }
+
+ // if (node.LedgerEntryType == "RippleState")
+ // {
+ // var trustlineQuantity = GetTrustlineQuantity(node);
+ // if (trustlineQuantity == null)
+ // {
+ // return new List();
+ // }
+
+ // return trustlineQuantity;
+ // }
+
+ // return new List();
+ // }).ToList();
+ // return GroupByAccount(quantities.SelectMany(q => q).ToList());
+ //}
}
}
diff --git a/Xrpl/Utils/Hashes/HashLedger.cs b/Xrpl/Utils/Hashes/HashLedger.cs
index 26ef0917..826b8de6 100644
--- a/Xrpl/Utils/Hashes/HashLedger.cs
+++ b/Xrpl/Utils/Hashes/HashLedger.cs
@@ -1,15 +1,31 @@
-using System.Collections.Generic;
-using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Linq;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
using Xrpl.BinaryCodec;
using Xrpl.BinaryCodec.Hashing;
+using Xrpl.BinaryCodec.ShaMapTree;
using Xrpl.BinaryCodec.Util;
using Xrpl.Client.Exceptions;
+using Xrpl.Models.Ledger;
+using Xrpl.Models.Transactions;
+using Xrpl.Utils.Hashes.ShaMap;
+
using static Xrpl.AddressCodec.Utils;
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/hashes/hashLedger.ts
namespace Xrpl.Utils.Hashes
{
+ public interface HashLedgerHeaderOptions
+ {
+ public bool? ComputeTreeHashes { get; set; }
+
+ }
+
public class HashLedger
{
public static string HashSignedTx(string tx)
@@ -20,7 +36,8 @@ public static string HashSignedTx(string tx)
{
new ValidationException("The transaction must be signed to hash it.");
}
- return B16.Encode(Sha512.Half(input: FromHexToBytes(txBlob), prefix: (uint)HashPrefix.TransactionId));
+
+ return B16.Encode(Sha512.Half(input: txBlob.FromHexToBytes(), prefix: (uint)Xrpl.BinaryCodec.Hashing.HashPrefix.TransactionId));
}
public static string HashSignedTx(JToken tx)
@@ -31,7 +48,8 @@ public static string HashSignedTx(JToken tx)
{
new ValidationException("The transaction must be signed to hash it.");
}
- return B16.Encode(Sha512.Half(input: FromHexToBytes(txBlob), prefix: (uint)HashPrefix.TransactionId));
+
+ return B16.Encode(Sha512.Half(input: txBlob.FromHexToBytes(), prefix: (uint)Xrpl.BinaryCodec.Hashing.HashPrefix.TransactionId));
}
}
}
diff --git a/Xrpl/Utils/Hashes/HashPrefix.cs b/Xrpl/Utils/Hashes/HashPrefix.cs
index 3b44a001..ab45ee60 100644
--- a/Xrpl/Utils/Hashes/HashPrefix.cs
+++ b/Xrpl/Utils/Hashes/HashPrefix.cs
@@ -4,11 +4,42 @@
namespace Xrpl.Utils.Hashes
{
- public class rHashPrefix
+ ///
+ /// Prefix for hashing functions.
+ /// These prefixes are inserted before the source material used to
+ /// generate various hashes.This is done to put each hash in its own "space."
+ /// This way, two different types of objects with the
+ /// same binary data will produce different hashes.
+ /// Each prefix is a 4-byte value with the last byte set to zero
+ /// and the first three bytes formed from the ASCII equivalent of
+ /// some arbitrary string.
+ /// For example "TXN".
+ ///
+ public enum HashPrefix
{
- public rHashPrefix()
- {
- }
+ // transaction plus signature to give transaction ID 'TXN'
+ TRANSACTION_ID = 0x54584e00,
+
+ // transaction plus metadata 'TND'
+ TRANSACTION_NODE = 0x534e4400,
+
+ // inner node in tree 'MIN'
+ INNER_NODE = 0x4d494e00,
+
+ // leaf node in tree 'MLN'
+ LEAF_NODE = 0x4d4c4e00,
+
+ // inner transaction to sign 'STX'
+ TRANSACTION_SIGN = 0x53545800,
+
+ // inner transaction to sign (TESTNET) 'stx'
+ TRANSACTION_SIGN_TESTNET = 0x73747800,
+
+ // inner transaction to multisign 'SMT'
+ TRANSACTION_MULTISIGN = 0x534d5400,
+
+ // ledger 'LWR'
+ LEDGER = 0x4c575200,
}
}
diff --git a/Xrpl/Utils/Hashes/Hashes.cs b/Xrpl/Utils/Hashes/Hashes.cs
index e63e59ae..8c640cd3 100644
--- a/Xrpl/Utils/Hashes/Hashes.cs
+++ b/Xrpl/Utils/Hashes/Hashes.cs
@@ -1,16 +1,22 @@
-using System.Diagnostics;
-using Org.BouncyCastle.Utilities.Encoders;
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Numerics;
+using System.Text.RegularExpressions;
+
using Xrpl.AddressCodec;
+using Xrpl.Client.Exceptions;
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/hashes/index.ts
namespace Xrpl.Utils.Hashes
{
- public class Hashes
+ //todo double need check
+ public static class Hashes
{
const int HEX = 16;
const int BYTE_LENGTH = 4;
-
+ const byte MASK = 0xff;
public static string AddressToHex(string address)
{
return XrplCodec.DecodeAccountID(address).ToHex();
@@ -21,15 +27,107 @@ public static string LedgerSpaceHex(LedgerSpace name)
return ((int)name).ToString("X4");
}
+ public static string LedgerSpaceHex(string name)
+ {
+ var enums = Enum.GetValues(typeof(LedgerSpace)).Cast().ToList();
+
+ var res = enums.FirstOrDefault(f => f.ToString() == name).ToString();
+ var val = Convert.ToString(res.ToCharArray(0, 1)[0], HEX);
+ while (val.Length < 4)
+ val = "0" + val;
+ return val;
+ }
+ ///
+ /// check currency code for HEX
+ ///
+ /// currency code
+ ///
+ public static bool IsHexCurrencyCode(this string code) => Regex.IsMatch(code, @"[0-9a-fA-F]{40}", RegexOptions.IgnoreCase);
+
+ public static string CurrencyToHex(string currency)
+ {
+ var cur_code = currency.Trim();
+ if (cur_code.Length <= 3)
+ return cur_code;
+
+ if (cur_code.IsHexCurrencyCode())
+ return cur_code;
+
+ cur_code = cur_code.ConvertStringToHex();
+
+ if (cur_code.Length > 40)
+ throw new XrplException("wrong currency code format");
+
+ cur_code += new string('0', 40 - cur_code.Length);
+
+ return cur_code;
+
+ }
+ ///
+ /// Hash the given binary transaction data with the single-signing prefix.
+ /// See [Serialization Format](https://xrpl.org/serialization.html).
+ ///
+ /// The binary transaction blob as a hexadecimal string.
+ /// The hash to sign.
+ public static string HashTx(string txBlobHex)
+ {
+
+ var prefix = HashPrefix.TRANSACTION_SIGN.ToString("X").ToUpper();
+ return (prefix + txBlobHex).Sha512Half();
+ }
+
+
public static string HashPaymentChannel(string address, string dstAddress, int sequence)
{
- return Sha512HalfUtil.Sha512Half(
- LedgerSpaceHex(LedgerSpace.Paychan) +
- AddressToHex(address) +
- AddressToHex(dstAddress) +
- sequence.ToString("X").PadLeft(BYTE_LENGTH * 2, '0')
- );
+ return (LedgerSpaceHex(LedgerSpace.Paychan) +
+ AddressToHex(address) +
+ AddressToHex(dstAddress) +
+ sequence.ToString("X").PadLeft(BYTE_LENGTH * 2, '0')).Sha512Half();
}
+
+ public static string HashTX(string txBlobHex)
+ {
+ string prefix = ((int)HashPrefix.TRANSACTION_SIGN).ToString("X").ToUpper();
+ return (prefix + txBlobHex).Sha512Half();
+ }
+
+ public static string HashAccountRoot(string address)
+ {
+ return (LedgerSpaceHex(LedgerSpace.Account) + AddressToHex(address)).Sha512Half();
+ }
+
+ public static string HashSignerListId(string address)
+ {
+ return (LedgerSpaceHex(LedgerSpace.SignerList) + AddressToHex(address) + "00000000").Sha512Half();
+ }
+
+ public static string HashOfferId(string address, int sequence)
+ {
+
+ string hexPrefix = LedgerSpaceHex(LedgerSpace.Offer).PadLeft(2, '0');
+ string hexSequence = sequence.ToString("X").PadLeft(8, '0');
+ string prefix = "00" + hexPrefix;
+ return (prefix + AddressToHex(address) + hexSequence).Sha512Half();
+ }
+
+ public static string HashTrustline(string address1, string address2, string currency)
+ {
+ string address1Hex = AddressToHex(address1);
+ string address2Hex = AddressToHex(address2);
+
+ bool swap = (BigInteger.Parse(address1Hex, NumberStyles.HexNumber)>(BigInteger.Parse(address2Hex, NumberStyles.HexNumber)));
+ string lowAddressHex = swap ? address2Hex : address1Hex;
+ string highAddressHex = swap ? address1Hex : address2Hex;
+
+ string prefix = LedgerSpaceHex(LedgerSpace.RippleState);
+ return (prefix + lowAddressHex + highAddressHex + CurrencyToHex(currency)).Sha512Half();
+ }
+
+ public static string HashEscrow(string address, int sequence)
+ {
+ return (LedgerSpaceHex(LedgerSpace.Escrow) + AddressToHex(address) + sequence.ToString("X").PadLeft(BYTE_LENGTH * 2, '0')).Sha512Half();
+ }
+
}
}
diff --git a/Xrpl/Utils/Hashes/LedgerSpaces.cs b/Xrpl/Utils/Hashes/LedgerSpaces.cs
index 96732ee1..e5f8fdb8 100644
--- a/Xrpl/Utils/Hashes/LedgerSpaces.cs
+++ b/Xrpl/Utils/Hashes/LedgerSpaces.cs
@@ -4,6 +4,13 @@
namespace Xrpl.Utils.Hashes
{
+ ///
+ /// XRP Ledger namespace prefixes.
+ /// The XRP Ledger is a key-value store.In order to avoid name collisions,
+ /// names are partitioned into namespaces.
+ /// Each namespace is just a single character prefix.
+ /// See[LedgerNameSpace enum](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/LedgerFormats.h#L100).
+ ///
public enum LedgerSpace
{
Account = 'a',
diff --git a/Xrpl/Utils/Hashes/Sha512Half.cs b/Xrpl/Utils/Hashes/Sha512Half.cs
index d8c524b3..27a9156f 100644
--- a/Xrpl/Utils/Hashes/Sha512Half.cs
+++ b/Xrpl/Utils/Hashes/Sha512Half.cs
@@ -6,9 +6,15 @@
namespace Xrpl.Utils.Hashes
{
- public class Sha512HalfUtil
+ public static class Sha512HalfUtil
{
- static public string Sha512Half(string hex)
+ public const int HASH_SIZE = 64;
+ ///
+ /// Compute a sha512Half Hash of a hex string.
+ ///
+ /// Hex string to hash.
+ /// Hash of hex.
+ public static string Sha512Half(this string hex)
{
return Sha512.Half(input: hex.FromHex()).ToHex();
}
diff --git a/Xrpl/Utils/Hashes/ShaMap/InnerNode.cs b/Xrpl/Utils/Hashes/ShaMap/InnerNode.cs
index 0b74b8b5..f389f4f2 100644
--- a/Xrpl/Utils/Hashes/ShaMap/InnerNode.cs
+++ b/Xrpl/Utils/Hashes/ShaMap/InnerNode.cs
@@ -2,12 +2,113 @@
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/hashes/SHAMap/InnerNode.ts
+using System.Collections.Generic;
+
+using Xrpl.Client.Exceptions;
+
namespace Xrpl.Utils.Hashes.ShaMap
{
- public class InnerNode
+ public class InnerNode : Node
{
- public InnerNode()
+ public readonly string HEX_ZERO = "0000000000000000000000000000000000000000000000000000000000000000";
+
+ public const int SLOT_MAX = 15;
+ public const int HEX = 16;
+
+ public Dictionary Leaves { get; set; }
+ public NodeType Type { get; set; }
+ public int Depth { get; set; }
+ public bool Empty { get; set; }
+
+ public InnerNode(int depth = 0)
{
+ Leaves = new Dictionary();
+ Type = NodeType.INNER;
+ Depth = depth;
+ Empty = true;
+ }
+
+ ///
+ public override void AddItem(string tag, Node node)
+ {
+ var existingNode = GetNode(int.Parse($"{tag[Depth]}", System.Globalization.NumberStyles.HexNumber));
+
+ if (existingNode == null)
+ {
+ SetNode(int.Parse($"{tag[Depth]}", System.Globalization.NumberStyles.HexNumber), node);
+ return;
+ }
+
+ if (existingNode is InnerNode)
+ {
+ existingNode.AddItem(tag, node);
+ }
+ else if (existingNode is LeafNode leaf)
+ {
+ if (leaf.Tag == tag)
+ {
+ throw new XrplException("Tried to add a node to a SHAMap that was already in there.");
+ }
+ else
+ {
+ var newInnerNode = new InnerNode(Depth + 1);
+ newInnerNode.AddItem(leaf.Tag, leaf);
+ newInnerNode.AddItem(tag, node);
+ SetNode(int.Parse($"{tag[Depth]}", System.Globalization.NumberStyles.HexNumber), newInnerNode);
+ }
+ }
+ }
+ ///
+ /// Overwrite the node that is currently in a given slot.
+ ///
+ /// A number 0-15.
+ /// To place.
+ /// If slot is out of range.
+ public void SetNode(int slot, Node node)
+ {
+ if (slot is < 0 or > SLOT_MAX)
+ {
+ throw new XrplException("Invalid slot: slot must be between 0-15.");
+ }
+ Leaves[slot] = node;
+ Empty = false;
+ }
+ ///
+ /// Get the node that is currently in a given slot.
+ ///
+ /// A number 0-15.
+ /// Node currently in a slot.
+ /// If slot is out of range.
+ public Node GetNode(int slot)
+ {
+ if (slot is < 0 or > SLOT_MAX)
+ {
+ throw new XrplException("Invalid slot: slot must be between 0-15.");
+ }
+ return Leaves[slot];
+ }
+
+ ///
+ public override string Hash
+ {
+ get
+ {
+ if (Empty)
+ {
+ return HEX_ZERO;
+ }
+
+ string hex = "";
+ for (var iter = 0; iter <= SLOT_MAX; iter++)
+ {
+ Node child = Leaves[iter];
+ string hash = child == null ? HEX_ZERO : child.Hash;
+ hex += hash;
+ }
+
+ string prefix = HashPrefix.INNER_NODE.ToString("X");
+ return Sha512HalfUtil.Sha512Half(prefix + hex);
+ }
}
}
}
diff --git a/Xrpl/Utils/Hashes/ShaMap/LeafNode.cs b/Xrpl/Utils/Hashes/ShaMap/LeafNode.cs
index 51849418..1e8040b4 100644
--- a/Xrpl/Utils/Hashes/ShaMap/LeafNode.cs
+++ b/Xrpl/Utils/Hashes/ShaMap/LeafNode.cs
@@ -2,12 +2,62 @@
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/hashes/SHAMap/LeafNode.ts
+using Xrpl.Client.Exceptions;
+
namespace Xrpl.Utils.Hashes.ShaMap
{
- public class LeafNode
+ public class LeafNode : Node
{
- public LeafNode()
+ public string Tag { get; set; }
+ public NodeType Type { get; set; }
+ public string Data { get; set; }
+
+ ///
+ /// Leaf node in a SHAMap tree.
+ ///
+ /// Equates to a ledger entry `index`.
+ /// Hex of account state, transaction etc.
+ /// One of TYPE_ACCOUNT_STATE, TYPE_TRANSACTION_MD etc.
+ public LeafNode(string tag, string data, NodeType type)
+ {
+ Tag = tag;
+ Data = data;
+ Type = type;
+ }
+
+ ///
+ public override void AddItem(string tag, Node node)
+ {
+ throw new XrplException("Cannot call addItem on a LeafNode");
+ //AddItem(tag, node);
+ }
+
+ ///
+ public override string Hash
{
+ get
+ {
+ switch (Type)
+ {
+ case NodeType.ACCOUNT_STATE:
+ {
+ var leafPrefix = HashPrefix.LEAF_NODE.ToString("X");
+ return Sha512HalfUtil.Sha512Half(leafPrefix + Data + Tag);
+ }
+ case NodeType.TRANSACTION_NO_METADATA:
+ {
+ var txIDPrefix = HashPrefix.TRANSACTION_ID.ToString("X");
+ return Sha512HalfUtil.Sha512Half(txIDPrefix + Data);
+ }
+ case NodeType.TRANSACTION_METADATA:
+ {
+ var txNodePrefix = HashPrefix.TRANSACTION_NODE.ToString("X");
+ return Sha512HalfUtil.Sha512Half(txNodePrefix + Data + Tag);
+ }
+ default:
+ throw new XrplException("Tried to hash a SHAMap node of unknown type.");
+ }
+ }
}
}
}
diff --git a/Xrpl/Utils/Hashes/ShaMap/Node.cs b/Xrpl/Utils/Hashes/ShaMap/Node.cs
index 6b092974..eb3a8504 100644
--- a/Xrpl/Utils/Hashes/ShaMap/Node.cs
+++ b/Xrpl/Utils/Hashes/ShaMap/Node.cs
@@ -1,14 +1,30 @@
-
-
-// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/hashes/SHAMap/node.ts
+// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/hashes/SHAMap/node.ts
namespace Xrpl.Utils.Hashes.ShaMap
{
- public class Node
+ ///
+ /// Abstract base class for SHAMapNode.
+ ///
+ public abstract class Node
+ {
+ ///
+ /// Adds an item to the InnerNode.
+ ///
+ /// Equates to a ledger entry `index`.
+ /// Node to add.
+ public abstract void AddItem(string tag, Node node);
+ ///
+ /// Get the hash of a LeafNode.
+ ///
+ /// Hash of the LeafNode.
+ public abstract string Hash { get; }
+ }
+ public enum NodeType
{
- public Node()
- {
- }
+ INNER = 1,
+ TRANSACTION_NO_METADATA = 2,
+ TRANSACTION_METADATA = 3,
+ ACCOUNT_STATE = 4,
}
}
diff --git a/Xrpl/Utils/Hashes/ShaMap/SHAMap.cs b/Xrpl/Utils/Hashes/ShaMap/SHAMap.cs
index c4b9edec..a3177728 100644
--- a/Xrpl/Utils/Hashes/ShaMap/SHAMap.cs
+++ b/Xrpl/Utils/Hashes/ShaMap/SHAMap.cs
@@ -6,9 +6,26 @@ namespace Xrpl.Utils.Hashes.ShaMap
{
public class SHAMap
{
+ public InnerNode Root { get; set; }
+
+ /// SHAMap tree constructor.
public SHAMap()
{
+ Root = new InnerNode(0);
}
+
+ /// Add an item to the SHAMap.
+ /// @param tag - Index of the Node to add.
+ /// @param data - Data to insert into the tree.
+ /// @param type - Type of the node to add.
+ public void AddItem(string tag, string data, NodeType type)
+ {
+ Root.AddItem(tag, new LeafNode(tag, data, type));
+ }
+
+ /// Get the hash of the SHAMap.
+ /// @returns The hash of the root of the SHAMap.
+ public string Hash => this.Root.Hash;
}
}
diff --git a/Xrpl/Utils/Index.cs b/Xrpl/Utils/Index.cs
new file mode 100644
index 00000000..00f3818a
--- /dev/null
+++ b/Xrpl/Utils/Index.cs
@@ -0,0 +1,66 @@
+using Newtonsoft.Json.Linq;
+
+using System;
+
+using Xrpl.AddressCodec;
+using Xrpl.BinaryCodec;
+using Xrpl.BinaryCodec.Ledger;
+using Xrpl.Keypairs;
+using Xrpl.Models.Subscriptions;
+using Xrpl.Models.Transactions;
+
+//https://github.com/XRPLF/xrpl.js/blob/45963b70356f4609781a6396407e2211fd15bcf1/packages/xrpl/src/utils/index.ts
+
+namespace Xrpl.Utils
+{
+ public static class Utilities
+ {
+ public static bool IsValidSecret(string secret)
+ {
+ try
+ {
+ XrplKeypairs.DeriveKeypair(secret);
+ return true;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+
+ public static string Encode(this TransactionCommon transactionOrLedgerEntry)
+ {
+ return XrplBinaryCodec.Encode(transactionOrLedgerEntry);
+ }
+
+ public static string EncodeForSigning(this TransactionCommon transaction)
+ {
+ return XrplBinaryCodec.EncodeForSigning(transaction);
+ }
+
+ public static string EncodeForSigningClaim(this PaymentChannelClaim paymentChannelClaim)
+ {
+ return XrplBinaryCodec.EncodeForSigningClaim(paymentChannelClaim);
+ }
+
+ public static string EncodeForMultiSigning(this TransactionCommon transaction, string signer)
+ {
+ return XrplBinaryCodec.EncodeForMulitSigning(transaction, signer);
+ }
+
+ public static JToken Decode(string hex)
+ {
+ return XrplBinaryCodec.Decode(hex);
+ }
+
+ public static bool IsValidAddress(string address)
+ {
+ return XrplAddressCodec.IsValidXAddress(address) || XrplCodec.IsValidClassicAddress(address);
+ }
+
+ public static bool HasNextPage(this BaseResponse response)
+ {
+ return response.Result.ContainsKey("marker");
+ }
+ }
+}
diff --git a/Xrpl/Utils/ParseNFTID.cs b/Xrpl/Utils/ParseNFTID.cs
index fb346b5a..9ced9e6f 100644
--- a/Xrpl/Utils/ParseNFTID.cs
+++ b/Xrpl/Utils/ParseNFTID.cs
@@ -1,5 +1,4 @@
using System;
-using System.Reflection.Emit;
using Xrpl.AddressCodec;
using Xrpl.BinaryCodec.Util;
using Xrpl.Client.Exceptions;
@@ -33,12 +32,12 @@ public static class ParseNFTID
/// The scrambled or unscrambled taxon (The XOR is both the encoding and decoding).
/// The account sequence when the token was minted. Used as a psuedorandom seed.
/// The opposite taxon. If the taxon was scrambled it becomes unscrambled, and vice versa.
- public static UInt32 UnscrambleTaxon(UInt32 taxon, UInt32 tokenSeq)
+ public static uint UnscrambleTaxon(uint taxon, uint tokenSeq)
{
- return (UInt32)((taxon ^ (384160001 * tokenSeq + 2459)) % 4294967296);
+ return (uint)((taxon ^ (384160001 * tokenSeq + 2459)) % 4294967296);
}
- public static NFTokenIDData GetNFTokenIDData(string nftokenID)
+ public static NFTokenIDData ParseNFTokenID(this string nftokenID)
{
const int expectedLength = 64;
if (nftokenID.Length != expectedLength)
@@ -47,13 +46,13 @@ public static NFTokenIDData GetNFTokenIDData(string nftokenID)
$", but expected a token with length ${expectedLength}");
}
- UInt32 flags = Convert.ToUInt32(nftokenID.Substring(0, 4), 16);
- UInt32 transferFee = Convert.ToUInt32(nftokenID.Substring(4, 4), 16);
+ uint flags = Convert.ToUInt32(nftokenID.Substring(0, 4), 16);
+ uint transferFee = Convert.ToUInt32(nftokenID.Substring(4, 4), 16);
string scrambledTaxon = nftokenID.Substring(48, 8);
- UInt32 sequence = Convert.ToUInt32(nftokenID.Substring(56, 8), 16);
- UInt32 taxon = UnscrambleTaxon(Convert.ToUInt32(scrambledTaxon, 16), sequence);
+ uint sequence = Convert.ToUInt32(nftokenID.Substring(56, 8), 16);
+ uint taxon = UnscrambleTaxon(Convert.ToUInt32(scrambledTaxon, 16), sequence);
- string issuer = XrplCodec.EncodeAccountID(AddressCodec.Utils.FromHexToBytes(nftokenID.Substring(8, 40)));
+ string issuer = XrplCodec.EncodeAccountID(nftokenID.Substring(8, 40).FromHexToBytes());
return new NFTokenIDData(nftokenID, flags, transferFee, issuer, taxon, sequence);
}
diff --git a/Xrpl/Utils/Quality.cs b/Xrpl/Utils/Quality.cs
index ebd199db..529c172b 100644
--- a/Xrpl/Utils/Quality.cs
+++ b/Xrpl/Utils/Quality.cs
@@ -1,15 +1,11 @@
-
+// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/quality.ts
-// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/quality.ts
-
-//todo DO
namespace Xrpl.Utils
{
public class Quality
{
- public Quality()
- {
- }
+
+ //todo need help with this...
}
}
diff --git a/Xrpl/Utils/SignChannelClaim.cs b/Xrpl/Utils/SignChannelClaim.cs
deleted file mode 100644
index 99572a1f..00000000
--- a/Xrpl/Utils/SignChannelClaim.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/signPaymentChannelClaim.ts
-
-//todo DO
-namespace Xrpl.Utils
-{
- public class SignPaymentChannelClaim
- {
- public SignPaymentChannelClaim()
- {
- }
- }
-}
-
diff --git a/Xrpl/Utils/SignPaymentChannelClaim.cs b/Xrpl/Utils/SignPaymentChannelClaim.cs
new file mode 100644
index 00000000..c6d1c744
--- /dev/null
+++ b/Xrpl/Utils/SignPaymentChannelClaim.cs
@@ -0,0 +1,36 @@
+
+
+// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/signPaymentChannelClaim.ts
+
+//todo DO
+using Xrpl.Keypairs;
+using Xrpl.Models.Transactions;
+
+namespace Xrpl.Utils
+{
+ public static class SignPmntChannelClaim
+ {
+
+ ///
+ /// Sign a payment channel claim.
+ ///
+ /// Channel identifier specified by the paymentChannelClaim.
+ /// Amount specified by the paymentChannelClaim.
+ /// Private Key to sign paymentChannelClaim with.
+ /// True if the channel is valid.
+ public static string SignPaymentChannelClaim(string channel, string amount, string privateKey)
+ {
+
+ var payment = new PaymentChannelClaim
+ {
+ Channel = channel,
+ Amount = XrpConversion.XrpToDrops(amount)
+ };
+
+ var signingData = payment.EncodeForSigningClaim();
+
+ return XrplKeypairs.Sign(signingData, privateKey);
+ }
+ }
+}
+
diff --git a/Xrpl/Utils/StringConversion.cs b/Xrpl/Utils/StringConversion.cs
index f342a9c1..8be82e09 100644
--- a/Xrpl/Utils/StringConversion.cs
+++ b/Xrpl/Utils/StringConversion.cs
@@ -1,6 +1,8 @@
using System;
using System.Globalization;
using System.Text;
+using System.Text.RegularExpressions;
+
using Org.BouncyCastle.Utilities.Encoders;
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/utils/stringConversion.ts
diff --git a/Xrpl/Utils/VerifyPaymentChannelClaim.cs b/Xrpl/Utils/VerifyPaymentChannelClaim.cs
index cf9df4bf..0b82f6d7 100644
--- a/Xrpl/Utils/VerifyPaymentChannelClaim.cs
+++ b/Xrpl/Utils/VerifyPaymentChannelClaim.cs
@@ -4,12 +4,33 @@
//todo DO
+using Xrpl.Keypairs;
+using Xrpl.Models.Transactions;
+
namespace Xrpl.Utils
{
- public class VerifyPaymentChannelClaim
+ public static class VerifyPmntChannelClaim
{
- public VerifyPaymentChannelClaim()
+
+ ///
+ /// Verify the signature of a payment channel claim.
+ ///
+ /// Channel identifier specified by the paymentChannelClaim.
+ /// Amount specified by the paymentChannelClaim.
+ /// Signature produced from signing paymentChannelClaim.
+ /// Public key that signed the paymentChannelClaim.
+ /// True if the channel is valid.
+ /// Utilities
+ public static bool VerifyPaymentChannelClaim(string channel, string amount, string signature, string publicKey)
{
+ var payment = new PaymentChannelClaim
+ {
+ Channel = channel,
+ Amount = XrpConversion.XrpToDrops(amount)
+ };
+
+ var signingData = payment.EncodeForSigningClaim();
+ return XrplKeypairs.Verify(signingData, signature, publicKey);
}
}
}
diff --git a/Xrpl/Utils/XrpConversion.cs b/Xrpl/Utils/XrpConversion.cs
index 6347d82e..aa5409ac 100644
--- a/Xrpl/Utils/XrpConversion.cs
+++ b/Xrpl/Utils/XrpConversion.cs
@@ -94,7 +94,13 @@ public static string DropsToXrp(string dropsToConvert)
* decimal point followed by zeros, e.g. '1.00'.
* Important: specify base BASE_10 to avoid exponential notation, e.g. '1e-7'.
*/
- string drops = BigInteger.Parse(dropsToConvert, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent).ToRadixString(BASE_TEN);
+ string drops = BigInteger.Parse(dropsToConvert, NumberStyles.AllowLeadingSign
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | NumberStyles.AllowExponent
+ | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture).ToRadixString(BASE_TEN);
// check that the value is valid and actually a number
if (!(dropsToConvert is string) && drops != null)
{
@@ -122,7 +128,13 @@ public static string DropsToXrp(string dropsToConvert)
//}
// TODO: SHOULD BE BASE 10
- return ((decimal)BigInteger.Parse(dropsToConvert, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent) / (decimal)new BigInteger(DROPS_PER_XRP)).ToString();
+ return ((decimal)BigInteger.Parse(dropsToConvert, NumberStyles.AllowLeadingSign
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | NumberStyles.AllowExponent
+ | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture) / (decimal)new BigInteger(DROPS_PER_XRP)).ToString();
//return ((decimal)BigInteger.Parse(dropsToConvert, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture) / (decimal)new BigInteger(DROPS_PER_XRP)).ToString("F"+BASE_TEN).TrimEnd('0');
}
@@ -145,7 +157,13 @@ public static string XrpToDrops(string xrpToConvert)
{
// Important: specify base BASE_TEN to avoid exponential notation, e.g. '1e-7'.
// TODO: SHOULD BE BASE 10
- string xrp = decimal.Parse(xrpToConvert, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent).ToString();
+ string xrp = decimal.Parse(xrpToConvert, NumberStyles.AllowLeadingSign
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | NumberStyles.AllowExponent
+ | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture).ToString();
// check that the value is valid and actually a number
if (!(xrpToConvert is string) && xrp != null)
{
@@ -165,7 +183,13 @@ public static string XrpToDrops(string xrpToConvert)
throw new ValidationException($"xrpToDrops: value '{xrp}' has too many decimal places.");
}
// TODO: SHOULD BE BASE 10
- return new BigInteger(decimal.Parse(xrpToConvert, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent) * (decimal)new BigInteger(DROPS_PER_XRP)).ToString();
+ return new BigInteger(decimal.Parse(xrpToConvert, NumberStyles.AllowLeadingSign
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent)
+ | (NumberStyles.AllowLeadingSign & NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | (NumberStyles.AllowExponent & NumberStyles.AllowDecimalPoint)
+ | NumberStyles.AllowExponent
+ | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture) * (decimal)new BigInteger(DROPS_PER_XRP)).ToString();
}
}
}
\ No newline at end of file
diff --git a/Xrpl/Wallet/FundWallet.cs b/Xrpl/Wallet/FundWallet.cs
index 823180d1..475b2a16 100644
--- a/Xrpl/Wallet/FundWallet.cs
+++ b/Xrpl/Wallet/FundWallet.cs
@@ -105,7 +105,7 @@ public static class FaucetNetwork
public static readonly string NFTDevnet = "faucet-nft.ripple.com";
}
- public static async Task FundWallet(XrplClient client, XrplWallet? wallet = null, string? faucetHost = null)
+ public static async Task FundWallet(IXrplClient client, XrplWallet? wallet = null, string? faucetHost = null)
{
//if (!client.IsConnected())
//{
@@ -138,7 +138,7 @@ public static async Task FundWallet(XrplClient client, XrplWallet? walle
public static async Task ReturnPromise(
Dictionary options,
- XrplClient client,
+ IXrplClient client,
double startingBalance,
XrplWallet walletToFund,
string postBody
@@ -161,7 +161,7 @@ string postBody
}
public static Dictionary GetHTTPOptions(
- XrplClient client,
+ IXrplClient client,
byte[] postBody,
string hostname
)
@@ -182,7 +182,7 @@ string hostname
public static async Task OnEnd(
HttpResponseMessage response,
byte[] chunks,
- XrplClient client,
+ IXrplClient client,
double startingBalance,
XrplWallet walletToFund
)
@@ -212,7 +212,7 @@ XrplWallet walletToFund
}
public static async Task ProcessSuccessfulResponse(
- XrplClient client,
+ IXrplClient client,
string body,
double startingBalance,
XrplWallet walletToFund
@@ -267,7 +267,7 @@ await GetUpdatedBalance(
private static double _originalBalance;
private static string _address;
- private static XrplClient _client;
+ private static IXrplClient _client;
private static async void OnTimedEventAsync(Object source, ElapsedEventArgs e)
{
@@ -287,6 +287,10 @@ private static async void OnTimedEventAsync(Object source, ElapsedEventArgs e)
try
{
newBalance = Convert.ToDouble(await _client.GetXrpBalance(_address));
+ }
+ catch (XrplException err)
+ {
+
}
catch (RippleException err)
{
@@ -310,7 +314,7 @@ private static async void OnTimedEventAsync(Object source, ElapsedEventArgs e)
}
public static async Task GetUpdatedBalance(
- XrplClient client,
+ IXrplClient client,
string address,
double originalBalance
)
@@ -330,7 +334,7 @@ double originalBalance
return finalBalance;
}
- public static string GetFaucetHost(XrplClient client)
+ public static string GetFaucetHost(IXrplClient client)
{
string connectionUrl = client.Url();
// 'altnet' for Ripple Testnet server and 'testnet' for XRPL Labs Testnet server
diff --git a/Xrpl/Wallet/XrplWallet.cs b/Xrpl/Wallet/XrplWallet.cs
index 12bdfca9..ac0d3499 100644
--- a/Xrpl/Wallet/XrplWallet.cs
+++ b/Xrpl/Wallet/XrplWallet.cs
@@ -1,4 +1,5 @@
-using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
using System.Collections.Generic;
@@ -6,6 +7,7 @@
using Xrpl.BinaryCodec;
using Xrpl.Client.Exceptions;
using Xrpl.Keypairs;
+using Xrpl.Models.Transactions;
using Xrpl.Utils.Hashes;
// https://github.com/XRPLF/xrpl.js/blob/main/packages/xrpl/src/Wallet/index.ts
@@ -45,7 +47,7 @@ public XrplWallet(string publicKey, string privateKey, string? masterAddress = n
{
this.PublicKey = publicKey;
this.PrivateKey = privateKey;
- this.ClassicAddress = masterAddress != null ? masterAddress : XrplKeypairs.DeriveAddress(publicKey);
+ this.ClassicAddress = masterAddress ?? XrplKeypairs.DeriveAddress(publicKey);
this.Seed = seed;
}
@@ -78,11 +80,23 @@ public static XrplWallet FromSeed(string seed, string? masterAddress = null, str
/// A Wallet derived from an entropy.
public static XrplWallet FromEntropy(byte[] entropy, string? masterAddress = null, string? algorithm = null)
{
- string falgorithm = algorithm != null ? algorithm : XrplWallet.DEFAULT_ALGORITHM;
+ string falgorithm = algorithm ?? XrplWallet.DEFAULT_ALGORITHM;
string seed = XrplKeypairs.GenerateSeed(entropy, falgorithm);
return XrplWallet.DeriveWallet(seed, masterAddress, falgorithm);
}
+ ///
+ /// Creates a Wallet from xumm numbers.
+ ///
+ /// A Wallet from xumm numbers.
+ public static XrplWallet FromXummNumbers(string[] numbers)
+ {
+ byte[] entropy = XummExtension.EntropyFromXummNumbers(numbers);
+ return FromEntropy(entropy);
+ }
+
+
+
///
/// Derive a Wallet from a seed.
///
@@ -132,6 +146,18 @@ public SignatureResult Sign(Dictionary transaction, bool multis
//this.checkTxSerialization(serialized, tx);
return new SignatureResult(serialized, HashLedger.HashSignedTx(serialized));
}
+ ///
+ /// Signs a transaction offline.
+ ///
+ /// A transaction to be signed offline.
+ /// Specify true/false to use multisign or actual address (classic/x-address) to make multisign tx request.
+ ///
+ /// A Wallet derived from the seed.
+ public SignatureResult Sign(ITransactionCommon tx, bool multisign = false, string? signingFor = null)
+ {
+ Dictionary txJson = JsonConvert.DeserializeObject>(tx.ToJson());
+ return Sign(txJson, multisign, signingFor);
+ }
///
/// Verifies a signed transaction offline.
@@ -156,6 +182,14 @@ public string ComputeSignature(Dictionary transaction, string p
string encoded = XrplBinaryCodec.EncodeForSigning(transaction);
return XrplKeypairs.Sign(AddressCodec.Utils.FromHexToBytes(encoded), privateKey);
}
-
+ ///
+ /// Creates a Wallet from xumm numbers.
+ ///
+ /// A Wallet from xumm numbers.
+ public static XrplWallet FromXummNumbers(string[] numbers, string algorithm = "secp256k1")
+ {
+ byte[] entropy = XummExtension.EntropyFromXummNumbers(numbers);
+ return FromEntropy(entropy,null, algorithm);
+ }
}
}
\ No newline at end of file
diff --git a/Xrpl/Wallet/XummExtension.cs b/Xrpl/Wallet/XummExtension.cs
new file mode 100644
index 00000000..f19c8356
--- /dev/null
+++ b/Xrpl/Wallet/XummExtension.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Xrpl.Wallet
+{
+ ///
+ /// xumm from number extensions
+ ///
+ public static class XummExtension
+ {
+ ///
+ /// generate Entropy from xumm numbers
+ ///
+ /// xumm numbers
+ /// byte[] Entropy
+ /// when wrong has wrong digits
+ public static byte[] EntropyFromXummNumbers(string[] numbers)
+ {
+ if (!CheckXummNumbers(numbers))
+ throw new ArgumentException("Wrong numbers");
+
+ var vals = numbers.Select(x => $"0000{int.Parse(x.Substring(0, 5)):X}"[^4..]).ToArray();
+
+ var buffer = new List();
+ foreach (var val in vals)
+ {
+ var v = Enumerable.Range(0, val.Length)
+ .Where(x => x % 2 == 0)
+ .Select(x => Convert.ToByte(val.Substring(x, 2), 16))
+ .ToArray();
+ buffer.AddRange(v);
+
+ }
+ return buffer.ToArray();
+ }
+
+ ///
+ /// xumm numbers validation
+ ///
+ /// xum numbers
+ ///
+ public static bool CheckXummNumbers(string[] numbers) => numbers.Select((n, i) => CheckXummSum(i, n)).All(c => c);
+
+ ///
+ /// xumm validation for part od numbers
+ ///
+ /// numbers position
+ /// xum numbers
+ ///
+ public static bool CheckXummSum(int position, string number)
+ {
+ if (number.Length != 6)
+ return false;
+
+ var checkSum = int.Parse(number[5..]);
+ var value = int.Parse(number[..5]);
+ var sum = value * (position * 2 + 1) % 9;
+ return sum == checkSum;
+ }
+
+ }
+}
diff --git a/Xrpl/Xrpl.csproj b/Xrpl/Xrpl.csproj
index 34fcf2fd..1a5c39e9 100644
--- a/Xrpl/Xrpl.csproj
+++ b/Xrpl/Xrpl.csproj
@@ -2,7 +2,7 @@
- 9.0
+ latest
net6.0
Xrpl
true
@@ -14,7 +14,7 @@
https://github.com/Transia-RnD/XrplCSharp/LICENSE
https://github.com/Transia-RnD/XrplCSharp
XrplCSharp
- 1.0.0
+ 2.0.0
@@ -22,13 +22,12 @@
bin\Debug\net6.0\XrplCSharp.xml
-
+
-