get testcase passing

This commit is contained in:
Mayukha Vadari
2022-05-25 17:38:01 -04:00
parent 158cff2be2
commit f717990922
8 changed files with 310 additions and 10 deletions

View File

@@ -2049,12 +2049,12 @@
"NFTokenCreateOffer": 27, "NFTokenCreateOffer": 27,
"NFTokenCancelOffer": 28, "NFTokenCancelOffer": 28,
"NFTokenAcceptOffer": 29, "NFTokenAcceptOffer": 29,
"XchainDoorCreate": 30, "XChainDoorCreate": 30,
"XchainSeqnumCreate": 31, "XChainSeqnumCreate": 31,
"XchainTransfer": 32, "XChainTransfer": 32,
"XchainClaim": 33, "XChainClaim": 33,
"XchainAccountCreate": 34, "XChainAccountCreate": 34,
"XchainAccountClaim": 35, "XChainAccountClaim": 35,
"EnableAmendment": 100, "EnableAmendment": 100,
"SetFee": 101, "SetFee": 101,

View File

@@ -7,7 +7,7 @@ import { Buffer } from 'buffer/'
* BinaryParser is used to compute fields and values from a HexString * BinaryParser is used to compute fields and values from a HexString
*/ */
class BinaryParser { class BinaryParser {
private bytes: Buffer public bytes: Buffer
/** /**
* Initialize bytes to a hex string * Initialize bytes to a hex string

View File

@@ -14,7 +14,7 @@ class Blob extends SerializedType {
* Defines how to read a Blob from a BinaryParser * Defines how to read a Blob from a BinaryParser
* *
* @param parser The binary parser to read the Blob from * @param parser The binary parser to read the Blob from
* @param hint The length of the blob, computed by readVariableLengthLength() and passed in * @param hint The length of the blob, computed by readVariableLength() and passed in
* @returns A Blob object * @returns A Blob object
*/ */
static fromParser(parser: BinaryParser, hint: number): Blob { static fromParser(parser: BinaryParser, hint: number): Blob {

View File

@@ -11,7 +11,9 @@ import { Currency } from './currency'
import { Hash128 } from './hash-128' import { Hash128 } from './hash-128'
import { Hash160 } from './hash-160' import { Hash160 } from './hash-160'
import { Hash256 } from './hash-256' import { Hash256 } from './hash-256'
import { IssuedCurrency } from './issued-currency'
import { PathSet } from './path-set' import { PathSet } from './path-set'
import { Sidechain } from './sidechain'
import { STArray } from './st-array' import { STArray } from './st-array'
import { STObject } from './st-object' import { STObject } from './st-object'
import { UInt16 } from './uint-16' import { UInt16 } from './uint-16'
@@ -28,7 +30,9 @@ const coreTypes = {
Hash128, Hash128,
Hash160, Hash160,
Hash256, Hash256,
IssuedCurrency,
PathSet, PathSet,
Sidechain,
STArray, STArray,
STObject, STObject,
UInt8, UInt8,

View File

@@ -0,0 +1,114 @@
import { BinaryParser } from '../serdes/binary-parser'
import { AccountID } from './account-id'
import { Currency } from './currency'
import { JsonObject, SerializedType } from './serialized-type'
import { Buffer } from 'buffer/'
/**
* Interface for JSON objects that represent amounts
*/
interface IssuedCurrencyObject extends JsonObject {
currency: string
issuer: string
}
/**
* Type guard for AmountObject
*/
function isIssuedCurrencyObject(arg): arg is IssuedCurrencyObject {
const keys = Object.keys(arg).sort()
return keys.length === 2 && keys[0] === 'currency' && keys[1] === 'issuer'
}
/**
* Class for serializing/Deserializing Amounts
*/
class IssuedCurrency extends SerializedType {
static readonly ZERO_ISSUED_CURRENCY: IssuedCurrency = new IssuedCurrency(
Buffer.alloc(20),
)
constructor(bytes: Buffer) {
super(bytes ?? IssuedCurrency.ZERO_ISSUED_CURRENCY.bytes)
}
/**
* Construct an amount from an IOU or string amount
*
* @param value An Amount, object representing an IOU, or a string
* representing an integer amount
* @returns An Amount object
*/
static from<T extends IssuedCurrency | IssuedCurrencyObject | string>(
value: T,
): IssuedCurrency {
if (value instanceof IssuedCurrency) {
return value
}
if (typeof value === 'string') {
IssuedCurrency.assertXrpIsValid(value)
const currency = Currency.from(value).toBytes()
return new IssuedCurrency(currency)
}
if (isIssuedCurrencyObject(value)) {
const currency = Currency.from(value.currency).toBytes()
const issuer = AccountID.from(value.issuer).toBytes()
return new IssuedCurrency(Buffer.concat([currency, issuer]))
}
throw new Error('Invalid type to construct an Amount')
}
/**
* Read an amount from a BinaryParser
*
* @param parser BinaryParser to read the Amount from
* @returns An Amount object
*/
static fromParser(parser: BinaryParser): IssuedCurrency {
const currency = parser.read(20)
if (new Currency(currency).toJSON() === 'XRP') {
return new IssuedCurrency(currency)
}
const currencyAndIssuer = [currency, parser.read(20)]
return new IssuedCurrency(Buffer.concat(currencyAndIssuer))
}
/**
* Get the JSON representation of this Amount
*
* @returns the JSON interpretation of this.bytes
*/
toJSON(): IssuedCurrencyObject | string {
const parser = new BinaryParser(this.toString())
const currency = Currency.fromParser(parser) as Currency
if (currency.toJSON() === 'XRP') {
return currency.toJSON()
}
const issuer = AccountID.fromParser(parser) as AccountID
return {
currency: currency.toJSON(),
issuer: issuer.toJSON(),
}
}
/**
* Validate XRP amount
*
* @param value String representing XRP amount
* @returns void, but will throw if invalid amount
*/
private static assertXrpIsValid(value: string): void {
if (value !== 'XRP') {
throw new Error(`${value} is an illegal amount`)
}
}
}
export { IssuedCurrency, IssuedCurrencyObject }

View File

@@ -0,0 +1,114 @@
import { BinaryParser } from '../serdes/binary-parser'
import { AccountID } from './account-id'
import { JsonObject, SerializedType } from './serialized-type'
import { Buffer } from 'buffer/'
import { IssuedCurrency, IssuedCurrencyObject } from './issued-currency'
/**
* Interface for JSON objects that represent amounts
*/
interface SidechainObject extends JsonObject {
dst_chain_door: string
dst_chain_issue: IssuedCurrencyObject | string
src_chain_door: string
src_chain_issue: IssuedCurrencyObject | string
}
/**
* Type guard for AmountObject
*/
function isSidechainObject(arg): arg is SidechainObject {
const keys = Object.keys(arg).sort()
return (
keys.length === 4 &&
keys[0] === 'dst_chain_door' &&
keys[1] === 'dst_chain_issue' &&
keys[2] === 'src_chain_door' &&
keys[3] === 'src_chain_issue'
)
}
/**
* Class for serializing/Deserializing Amounts
*/
class Sidechain extends SerializedType {
static readonly ZERO_SIDECHAIN: Sidechain = new Sidechain(Buffer.alloc(80))
constructor(bytes: Buffer) {
super(bytes ?? Sidechain.ZERO_SIDECHAIN.bytes)
}
/**
* Construct an amount from an IOU or string amount
*
* @param value An Amount, object representing an IOU, or a string
* representing an integer amount
* @returns An Amount object
*/
static from<T extends Sidechain | SidechainObject>(value: T): Sidechain {
if (value instanceof Sidechain) {
return value
}
if (isSidechainObject(value)) {
const dst_chain_door = AccountID.from(value.dst_chain_door).toBytes()
const dst_chain_issue = IssuedCurrency.from(
value.dst_chain_issue,
).toBytes()
const src_chain_door = AccountID.from(value.src_chain_door).toBytes()
const src_chain_issue = IssuedCurrency.from(
value.src_chain_issue,
).toBytes()
return new Sidechain(
Buffer.concat([
dst_chain_door,
dst_chain_issue,
src_chain_door,
src_chain_issue,
]),
)
}
throw new Error('Invalid type to construct a Sidechain')
}
/**
* Read an amount from a BinaryParser
*
* @param parser BinaryParser to read the Amount from
* @returns An Amount object
*/
static fromParser(parser: BinaryParser): Sidechain {
const bytes: Array<Buffer> = []
bytes.push(parser.read(AccountID.width))
bytes.push(IssuedCurrency.fromParser(parser).toBytes())
bytes.push(parser.read(AccountID.width))
bytes.push(IssuedCurrency.fromParser(parser).toBytes())
return new Sidechain(Buffer.concat(bytes))
}
/**
* Get the JSON representation of this Amount
*
* @returns the JSON interpretation of this.bytes
*/
toJSON(): SidechainObject {
const parser = new BinaryParser(this.toString())
const dst_chain_door = AccountID.fromParser(parser) as AccountID
const dst_chain_issue = IssuedCurrency.fromParser(parser)
const src_chain_door = AccountID.fromParser(parser) as AccountID
const src_chain_issue = IssuedCurrency.fromParser(parser)
return {
dst_chain_door: dst_chain_door.toJSON(),
dst_chain_issue: dst_chain_issue.toJSON(),
src_chain_door: src_chain_door.toJSON(),
src_chain_issue: src_chain_issue.toJSON(),
}
}
}
export { Sidechain, SidechainObject }

View File

@@ -105,6 +105,7 @@ let json_omitted = {
} }
const NegativeUNL = require('./fixtures/negative-unl.json') const NegativeUNL = require('./fixtures/negative-unl.json')
const XChainDoorCreate = require('./fixtures/xchain-door-create.json')
function bytesListTest() { function bytesListTest() {
const list = new BytesList() const list = new BytesList()
@@ -220,7 +221,7 @@ function PaymentChannelTest() {
}) })
} }
function NegativeUNLTest() { function negativeUNLTest() {
test('can serialize NegativeUNL', () => { test('can serialize NegativeUNL', () => {
expect(encode(NegativeUNL.tx)).toEqual(NegativeUNL.binary) expect(encode(NegativeUNL.tx)).toEqual(NegativeUNL.binary)
}) })
@@ -229,6 +230,15 @@ function NegativeUNLTest() {
}) })
} }
function sidechainTest() {
test('can serialize XChainDoorCreate', () => {
expect(encode(XChainDoorCreate.tx)).toEqual(XChainDoorCreate.binary)
})
test('can deserialize XChainDoorCreate', () => {
expect(decode(XChainDoorCreate.binary)).toEqual(XChainDoorCreate.tx)
})
}
function omitUndefinedTest() { function omitUndefinedTest() {
test('omits fields with undefined value', () => { test('omits fields with undefined value', () => {
let encodedOmitted = encode(json_omitted) let encodedOmitted = encode(json_omitted)
@@ -282,7 +292,8 @@ describe('Binary Serialization', function () {
describe('SignerListSet', SignerListSetTest) describe('SignerListSet', SignerListSetTest)
describe('Escrow', EscrowTest) describe('Escrow', EscrowTest)
describe('PaymentChannel', PaymentChannelTest) describe('PaymentChannel', PaymentChannelTest)
describe('NegativeUNLTest', NegativeUNLTest) describe('NegativeUNLTest', negativeUNLTest)
describe('SidechainTest', sidechainTest)
describe('OmitUndefined', omitUndefinedTest) describe('OmitUndefined', omitUndefinedTest)
describe('TicketTest', ticketTest) describe('TicketTest', ticketTest)
describe('NFToken', nfTokenTest) describe('NFToken', nfTokenTest)

View File

@@ -0,0 +1,57 @@
{
"binary": "12001E22800000002023000000048114C48CAD01682D7A86296EF14523074D4852C02EA9F4EB130001811474A41942D90FDD8E4E8BB25A7E91843CFEDB9A5DE1EB1300018114C287E75E44FEB7AF3537173BB3A866A652C91502E1EB1300018114F5B6BA5BA9F91592A4B607E0397E47A298B95EA2E1EB13000181145720A5ABFA7D844BD615F4E62FA7C963E85B0C7DE1EB1300018114B7521887260F712472A8E5775EE6234042641C0CE1F10118CC86E58C9B58D4CF71CB8C1B41F21BB290CE13D4000000000000000000000000555344000000000027B6C49755570AD538DDD42EE417A4708F17EF76C48CAD01682D7A86296EF14523074D4852C02EA90000000000000000000000000000000000000000",
"tx": {
"Account" : "rJvExveLEL4jNDEeLKCVdxaSCN9cEBnEQC",
"Flags" : 2147483648,
"Sidechain" :
{
"dst_chain_door" : "rKeSSvHvaMZJp9ykaxutVwkhZgWuWMLnQt",
"dst_chain_issue" : {
"currency" : "USD",
"issuer" : "rhczJR49YsdxwtYTPvxeSc1Jjr7R748cHv"
},
"src_chain_door" : "rJvExveLEL4jNDEeLKCVdxaSCN9cEBnEQC",
"src_chain_issue" : "XRP"
},
"SignerEntries" :
[
{
"SignerEntry" :
{
"Account" : "rBdjyperRHKTzdxnZhyN94MpjN2aknRX8G",
"SignerWeight" : 1
}
},
{
"SignerEntry" :
{
"Account" : "rJj2ty2MDGu7dtm1bvZMA5KuhzreNL2HHo",
"SignerWeight" : 1
}
},
{
"SignerEntry" :
{
"Account" : "rPQDTwG7tWYNzqjytf8YCYX6hZemGG9TTh",
"SignerWeight" : 1
}
},
{
"SignerEntry" :
{
"Account" : "r3AguhaYj2enNDz37mzJNskxcQKb3sAYjE",
"SignerWeight" : 1
}
},
{
"SignerEntry" :
{
"Account" : "rH5KrD1ocKBWq3Mf7WGy8tTtEi84M1uwGm",
"SignerWeight" : 1
}
}
],
"SignerQuorum" : 4,
"TransactionType" : "XChainDoorCreate"
}
}