Skip to content

Commit

Permalink
feat: add ilp rejection packet (error v2)
Browse files Browse the repository at this point in the history
  • Loading branch information
justmoon committed Dec 14, 2017
1 parent 6147ded commit 704f46f
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 7 deletions.
73 changes: 71 additions & 2 deletions packages/ilp-packet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ enum Type {
TYPE_ILQP_BY_DESTINATION_RESPONSE = 7,
TYPE_ILP_ERROR = 8,
TYPE_ILP_FULFILLMENT = 9,
TYPE_ILP_FORWARDED_PAYMENT = 10 // experimental
TYPE_ILP_FORWARDED_PAYMENT = 10, // experimental
TYPE_ILP_REJECTION = 11
}

const serializeEnvelope = (type: number, contents: Buffer) => {
Expand Down Expand Up @@ -117,7 +118,7 @@ const deserializeIlpForwardedPayment = (binary: Buffer): IlpForwardedPayment =>
const reader = Reader.from(contents)

const account = reader.readVarOctetString().toString('ascii')
const data = base64url(reader.readVarOctetString())
const data = bufferToBase64url(reader.readVarOctetString())

// Ignore remaining bytes for extensibility

Expand Down Expand Up @@ -533,6 +534,67 @@ const deserializeIlpFulfillment = (binary: Buffer): IlpFulfillment => {
}
}

interface IlpRejection {
code: string,
triggeredBy: string,
message: string,
data: Buffer
}

const serializeIlpRejection = (json: IlpRejection) => {
const writer = new Writer()

// Convert code to buffer to ensure we are counting bytes, not UTF8 characters
const codeBuffer = Buffer.from(json.code, 'ascii')
if (codeBuffer.length !== ILP_ERROR_CODE_LENGTH) {
throw new Error('ILP error codes must be three bytes long, received: ' + json.code)
}

// code
writer.write(codeBuffer)

// triggeredBy
writer.writeVarOctetString(Buffer.from(json.triggeredBy, 'ascii'))

// message
writer.writeVarOctetString(Buffer.from(json.message, 'utf8'))

// data
writer.writeVarOctetString(json.data)

// extensibility
writer.writeUInt8(0)

return serializeEnvelope(Type.TYPE_ILP_REJECTION, writer.getBuffer())
}

const deserializeIlpRejection = (binary: Buffer): IlpRejection => {
const { type, contents } = deserializeEnvelope(binary)

if (type !== Type.TYPE_ILP_REJECTION) {
throw new Error('Packet has incorrect type')
}

const reader = Reader.from(contents)

const code = reader.read(ILP_ERROR_CODE_LENGTH).toString('ascii')

const triggeredBy = reader.readVarOctetString().toString('ascii')

const message = reader.readVarOctetString().toString('utf8')

const data = reader.readVarOctetString()

// Ignore remaining bytes for extensibility

return {
code,
triggeredBy,
message,
data
}
}

const serializeIlpPacket = (obj: IlpPacket) => {
switch (obj.type) {
case Type.TYPE_ILP_PAYMENT: return serializeIlpPayment(obj.data)
Expand All @@ -545,6 +607,7 @@ const serializeIlpPacket = (obj: IlpPacket) => {
case Type.TYPE_ILP_ERROR: return serializeIlpError(obj.data)
case Type.TYPE_ILP_FULFILLMENT: return serializeIlpFulfillment(obj.data)
case Type.TYPE_ILP_FORWARDED_PAYMENT: return serializeIlpForwardedPayment(obj.data)
case Type.TYPE_ILP_REJECTION: return serializeIlpRejection(obj.data)
default: throw new Error('Object has invalid type')
}
}
Expand Down Expand Up @@ -593,6 +656,10 @@ const deserializeIlpPacket = (binary: Buffer) => {
packet = deserializeIlpForwardedPayment(binary)
typeString = 'ilp_forwarded_payment'
break
case Type.TYPE_ILP_REJECTION:
packet = deserializeIlpRejection(binary)
typeString = 'ilp_rejection'
break
default:
throw new Error('Packet has invalid type')
}
Expand Down Expand Up @@ -625,6 +692,8 @@ module.exports = {
deserializeIlpFulfillment,
serializeIlpForwardedPayment,
deserializeIlpForwardedPayment,
serializeIlpRejection,
deserializeIlpRejection,
serializeIlpPacket,
deserializeIlpPacket
}
4 changes: 0 additions & 4 deletions packages/ilp-packet/src/utils/basic.ts

This file was deleted.

10 changes: 10 additions & 0 deletions packages/ilp-packet/test/data/ilp_rejection/valid/example01.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "example 1",
"binary": "0b424630310e6578616d706c652e75732e626f62276d697373696e672064657374696e6174696f6e2e206c65646765723d6578616d706c652e75732e0600000004104100",
"json": {
"code": "F01",
"triggeredBy": "example.us.bob",
"message": "missing destination. ledger=example.us.",
"data": "AAAABBBB"
}
}
44 changes: 43 additions & 1 deletion packages/ilp-packet/test/parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,42 @@ describe('Parser', function () {
})
})

describe('serializeIlpRejection', function () {
describe('correctly serializes valid ilp rejections', function () {
const validTests = loadTests({ type: 'ilp_rejection' })

for (let test of validTests) {
it(test.name, function () {
const json = test.json

json.data = Buffer.from(json.data, 'base64')

const serialized = Parser.serializeIlpRejection(json)

assert.deepEqual(serialized.toString('hex'), test.binary)
})
}
})
})

describe('deserializeIlpRejection', function () {
describe('correctly parses valid ilp rejections', function () {
const validTests = loadTests({ type: 'ilp_rejection' })

for (let test of validTests) {
it(test.name, function () {
const binary = new Buffer(test.binary, 'hex')

const parsed = Parser.deserializeIlpRejection(binary)

parsed.data = parsed.data.toString('base64')

assert.deepEqual(parsed, test.json)
})
}
})
})

describe('deserializeIlpPacket', function () {
describe('correctly parses valid ilp packets', function () {
testPackets('ilp_payment', Parser.Type.TYPE_ILP_PAYMENT)
Expand All @@ -344,6 +380,9 @@ describe('Parser', function () {
testPackets('ilqp_by_destination_request', Parser.Type.TYPE_ILQP_BY_DESTINATION_REQUEST)
testPackets('ilqp_by_destination_response', Parser.Type.TYPE_ILQP_BY_DESTINATION_RESPONSE)
testPackets('ilp_error', Parser.Type.TYPE_ILP_ERROR)
testPackets('ilp_fulfillment', Parser.Type.TYPE_ILP_FULFILLMENT)
testPackets('ilp_forwarded_payment', Parser.Type.TYPE_ILP_FORWARDED_PAYMENT)
testPackets('ilp_rejection', Parser.Type.TYPE_ILP_REJECTION)

function testPackets (typeString: string, type: number) {
const validTests = loadTests({ type: typeString })
Expand All @@ -358,7 +397,10 @@ describe('Parser', function () {
if (typeString === 'ilp_error') {
parsed.data.triggeredAt = parsed.data.triggeredAt.getTime()
}
assert.deepEqual(parsed, {type, typeString, data: test.json})
if (typeString === 'ilp_rejection') {
parsed.data.data = parsed.data.data.toString('base64')
}
assert.deepEqual(parsed, { type, typeString, data: test.json })
})
}
}
Expand Down

0 comments on commit 704f46f

Please sign in to comment.