@@ -20,11 +20,12 @@ import {
2020 ConnectionMaxStreamIdFrame ,
2121 StreamMaxDataFrame ,
2222 StreamDataBlockedFrame ,
23+ StreamReceiptFrame ,
2324 ConnectionMaxDataFrame ,
2425 ConnectionDataBlockedFrame ,
2526 StreamMoneyBlockedFrame
2627} from './packet'
27- import { Reader } from 'oer-utils'
28+ import { Reader , Writer } from 'oer-utils'
2829import { CongestionController } from './util/congestion'
2930import { Plugin } from './util/plugin-interface'
3031import {
@@ -38,6 +39,7 @@ import {
3839} from './util/long'
3940import * as Long from 'long'
4041import Rational from './util/rational'
42+ import { createReceipt , RECEIPT_VERSION } from './util/receipt'
4143import { v4 as uuid } from 'uuid'
4244
4345const RETRY_DELAY_START = 100
@@ -65,6 +67,10 @@ export interface ConnectionOpts {
6567 enablePadding ?: boolean ,
6668 /** User-specified connection identifier that was passed into [`generateAddressAndSecret`]{@link Server#generateAddressAndSecret} */
6769 connectionTag ?: string ,
70+ /** User-specified receipt nonce that was passed into [`generateAddressAndSecret`]{@link Server#generateAddressAndSecret} */
71+ receiptNonce ?: Buffer ,
72+ /** User-specified receipt secret that was passed into [`generateAddressAndSecret`]{@link Server#generateAddressAndSecret} */
73+ receiptSecret ?: Buffer ,
6874 /** Maximum number of streams the other entity can have open at once. Defaults to 10 */
6975 maxRemoteStreams ?: number ,
7076 /** Number of bytes each connection can have in the buffer. Defaults to 65534 */
@@ -147,6 +153,8 @@ function defaultGetExpiry (): Date {
147153export class Connection extends EventEmitter {
148154 /** Application identifier for a certain connection */
149155 readonly connectionTag ?: string
156+ protected readonly _receiptNonce ?: Buffer
157+ protected readonly _receiptSecret ?: Buffer
150158
151159 protected connectionId : string
152160 protected plugin : Plugin
@@ -221,6 +229,11 @@ export class Connection extends EventEmitter {
221229 this . allowableReceiveExtra = Rational . fromNumber ( 1.01 , true )
222230 this . enablePadding = ! ! opts . enablePadding
223231 this . connectionTag = opts . connectionTag
232+ if ( ! opts . receiptNonce !== ! opts . receiptSecret ) {
233+ throw new Error ( 'receiptNonce and receiptSecret must accompany each other' )
234+ }
235+ this . _receiptNonce = opts . receiptNonce
236+ this . _receiptSecret = opts . receiptSecret
224237 this . maxStreamId = 2 * ( opts . maxRemoteStreams || DEFAULT_MAX_REMOTE_STREAMS )
225238 this . maxBufferedData = opts . connectionBufferSize || MAX_DATA_SIZE * 2
226239 this . minExchangeRatePrecision = opts . minExchangeRatePrecision || DEFAULT_MINIMUM_EXCHANGE_RATE_PRECISION
@@ -681,8 +694,22 @@ export class Connection extends EventEmitter {
681694 }
682695
683696 // Add incoming amounts to each stream
697+ const totalsReceived : Map < number , string > = new Map ( )
684698 for ( let { stream, amount } of amountsToReceive ) {
685699 stream . _addToIncoming ( amount , prepare )
700+ totalsReceived . set ( stream . id , stream . totalReceived )
701+ }
702+
703+ // Add receipt frame(s)
704+ if ( this . _receiptNonce && this . _receiptSecret ) {
705+ for ( let [ streamId , totalReceived ] of totalsReceived ) {
706+ responseFrames . push ( new StreamReceiptFrame ( streamId , createReceipt ( {
707+ nonce : this . _receiptNonce ,
708+ streamId,
709+ totalReceived,
710+ secret : this . _receiptSecret
711+ } ) ) )
712+ }
686713 }
687714
688715 // TODO make sure the queued frames aren't too big
@@ -1142,6 +1169,17 @@ export class Connection extends EventEmitter {
11421169 }
11431170
11441171 if ( responsePacket . ilpPacketType === IlpPacketType . Fulfill ) {
1172+ for ( let frame of responsePacket . frames ) {
1173+ if ( frame . type === FrameType . StreamReceipt ) {
1174+ const stream = this . streams . get ( frame . streamId . toNumber ( ) )
1175+ if ( stream ) {
1176+ stream . _setReceipt ( frame . receipt )
1177+ } else {
1178+ this . log . debug ( 'received receipt for unknown stream %d: %h' , frame . streamId , frame . receipt )
1179+ }
1180+ }
1181+ }
1182+
11451183 for ( let stream of streamsSentFrom ) {
11461184 stream . _executeHold ( requestPacket . sequence . toString ( ) )
11471185 }
@@ -1158,7 +1196,7 @@ export class Connection extends EventEmitter {
11581196 }
11591197
11601198 /**
1161- * (Internal) Send volly of test packests to find the exchange rate, its precision, and potential other amounts to try.
1199+ * (Internal) Send volley of test packets to find the exchange rate, its precision, and potential other amounts to try.
11621200 * @private
11631201 */
11641202 protected async sendTestPacketVolley ( testPacketAmounts : number [ ] ) : Promise < any > {
0 commit comments