UNPKG

3.54 kBPlain TextView Raw
1import * as IlpPacket from 'ilp-packet'
2import { create as createLogger } from '../common/log'
3const log = createLogger('ilp-prepare')
4import reduct = require('reduct')
5
6import Accounts from '../services/accounts'
7import RouteBuilder from '../services/route-builder'
8import RateBackend from '../services/rate-backend'
9import PeerProtocolController from '../controllers/peer-protocol'
10import EchoController from '../controllers/echo'
11
12const PEER_PROTOCOL_PREFIX = 'peer.'
13
14export default class IlpPrepareController {
15 private accounts: Accounts
16 private routeBuilder: RouteBuilder
17 private backend: RateBackend
18 private peerProtocolController: PeerProtocolController
19 private echoController: EchoController
20
21 constructor (deps: reduct.Injector) {
22 this.accounts = deps(Accounts)
23 this.routeBuilder = deps(RouteBuilder)
24 this.backend = deps(RateBackend)
25 this.peerProtocolController = deps(PeerProtocolController)
26 this.echoController = deps(EchoController)
27 }
28
29 async sendData (
30 packet: Buffer,
31 sourceAccount: string,
32 outbound: (data: Buffer, accountId: string) => Promise<Buffer>
33 ) {
34 const parsedPacket = IlpPacket.deserializeIlpPrepare(packet)
35 const { amount, executionCondition, destination, expiresAt } = parsedPacket
36
37 log.trace('handling ilp prepare. sourceAccount=%s destination=%s amount=%s condition=%s expiry=%s packet=%s', sourceAccount, destination, amount, executionCondition.toString('base64'), expiresAt.toISOString(), packet.toString('base64'))
38
39 if (destination.startsWith(PEER_PROTOCOL_PREFIX)) {
40 return this.peerProtocolController.handle(packet, sourceAccount, { parsedPacket })
41 } else if (destination === this.accounts.getOwnAddress()) {
42 return this.echoController.handle(packet, sourceAccount, { parsedPacket, outbound })
43 }
44
45 const { nextHop, nextHopPacket } = await this.routeBuilder.getNextHopPacket(sourceAccount, parsedPacket)
46
47 log.trace('sending outbound ilp prepare. destination=%s amount=%s', destination, nextHopPacket.amount)
48 const result = await outbound(IlpPacket.serializeIlpPrepare(nextHopPacket), nextHop)
49
50 this.backend.submitPacket({
51 sourceAccount: sourceAccount,
52 sourceAmount: amount,
53 destinationAccount: nextHop,
54 destinationAmount: nextHopPacket.amount,
55 parsedPacket,
56 result
57 }).catch(err => {
58 const errInfo = (err && typeof err === 'object' && err.stack) ? err.stack : String(err)
59 log.error('error while submitting packet to backend. error=%s', errInfo)
60 })
61
62 if (result[0] === IlpPacket.Type.TYPE_ILP_FULFILL) {
63 log.trace('got fulfillment. cond=%s nextHop=%s amount=%s', executionCondition.slice(0, 6).toString('base64'), nextHop, nextHopPacket.amount)
64
65 this.backend.submitPayment({
66 sourceAccount: sourceAccount,
67 sourceAmount: amount,
68 destinationAccount: nextHop,
69 destinationAmount: nextHopPacket.amount
70 })
71 .catch(err => {
72 const errInfo = (err && typeof err === 'object' && err.stack) ? err.stack : String(err)
73 log.error('error while submitting payment to backend. error=%s', errInfo)
74 })
75 } else if (result[0] === IlpPacket.Type.TYPE_ILP_REJECT) {
76 const parsed = IlpPacket.deserializeIlpReject(result)
77
78 log.trace('got rejection. cond=%s nextHop=%s amount=%s code=%s triggeredBy=%s message=%s', executionCondition.slice(0, 6).toString('base64'), nextHop, nextHopPacket.amount, parsed.code, parsed.triggeredBy, parsed.message)
79 }
80
81 return result
82 }
83}