Comparing version 1.2.0 to 1.2.1
@@ -15,4 +15,5 @@ const {bech32} = require('bech32'); | ||
encoded: <Payment Request Details Hex String> | ||
mtokens: <Millitokens Number String> | ||
[mtokens]: <Millitokens Number String> | ||
network: <Network Name String> | ||
words: <Words Count Number> | ||
} | ||
@@ -28,3 +29,3 @@ | ||
*/ | ||
module.exports = ({encoded, mtokens, network}) => { | ||
module.exports = ({encoded, mtokens, network, words}) => { | ||
if (!isHex(encoded)) { | ||
@@ -34,6 +35,2 @@ throw new Error('ExpectedHexEncodedPaymentRequestDataToDecodeRequest'); | ||
if (!mtokens) { | ||
throw new Error('ExpectedAmountToDecodeByteEncodedRequest'); | ||
} | ||
if (!network) { | ||
@@ -43,2 +40,7 @@ throw new Error('ExpectedNetworkToDecodeByteEncodedRequest'); | ||
if (!words) { | ||
throw new Error('ExpectedWordsCountToDecodeByteEncodedRequest'); | ||
} | ||
// Lookup the BOLT 11 network prefix for the request | ||
const currencyPrefix = keys(currencyCodes) | ||
@@ -52,6 +54,9 @@ .map(code => ({code, network: currencyCodes[code]})) | ||
// Before the encoded data is a network code and the amount | ||
const prefix = `ln${currencyPrefix.code}${mtokensAsHrp({mtokens}).hrp}`; | ||
const words = bech32.toWords(hexAsBuffer(encoded)); | ||
return {request: bech32.encode(prefix, words, limit)}; | ||
// The data of the request is encoded in 5 bit words ie bech32 | ||
const fiveBit = bech32.toWords(hexAsBuffer(encoded)).slice(Number(), words); | ||
return {request: bech32.encode(prefix, fiveBit, limit)}; | ||
}; |
const {bech32} = require('bech32'); | ||
const decodePrefix = require('./decode_prefix'); | ||
const hrpAsTokens = require('./hrp_as_tokens'); | ||
const hrpAsMtokens = require('./hrp_as_mtokens'); | ||
const wordsAsBuffer = require('./words_as_buffer'); | ||
@@ -11,3 +11,2 @@ | ||
const maxRequestLength = Number.MAX_SAFE_INTEGER; | ||
const trim = true; | ||
@@ -28,2 +27,3 @@ /** Derive bytes for payment request details | ||
network: <Network Name String> | ||
words: <Word Length Number> | ||
} | ||
@@ -44,7 +44,9 @@ */ | ||
const {mtokens} = hrpAsTokens({amount, units}); | ||
// Decode the request amount millitokens requested amount | ||
const {mtokens} = hrpAsMtokens({amount, units}); | ||
const encoded = bufferAsHex(wordsAsBuffer({trim, words})); | ||
// Encode the words as binary data in a hex string | ||
const encoded = bufferAsHex(wordsAsBuffer({words})); | ||
return {encoded, mtokens, network}; | ||
return {encoded, network, mtokens, words: words.length}; | ||
}; |
@@ -16,6 +16,2 @@ { | ||
{ | ||
"letter": "p", | ||
"value": "10" | ||
}, | ||
{ | ||
"letter": "u", | ||
@@ -22,0 +18,0 @@ "value": "100000" |
@@ -27,2 +27,3 @@ const {createHash} = require('crypto'); | ||
const {sha256} = crypto; | ||
const tokensAsMtokens = n => !n ? '0' : (BigInt(n) * BigInt(1e3)).toString(); | ||
@@ -94,3 +95,3 @@ /** Create an unsigned payment request | ||
const createdAtWords = numberAsWords({number: floor(createdAt)}).words; | ||
const mtokens = args.mtokens || args.tokens * mtokPerTok; | ||
const mtokens = args.mtokens || tokensAsMtokens(args.tokens); | ||
@@ -97,0 +98,0 @@ const hrp = `ln${currencyPrefix.code}${mtokensAsHrp({mtokens}).hrp}`; |
const {multipliers} = require('./conf/multipliers'); | ||
const isEmpty = n => !n || n === '0'; | ||
const isNumeric = n => /^\d+$/.test(n); | ||
const asPico = amount => (amount * BigInt(10)).toString() + 'p'; | ||
const isString = n => typeof n === 'string'; | ||
/** Get Tokens as the Human Readable Part of a BOLT11 payment request | ||
@@ -9,3 +14,6 @@ | ||
@returns via cbk | ||
@throws | ||
<Error> | ||
@returns | ||
{ | ||
@@ -16,8 +24,18 @@ hrp: <Human Readable Part String> | ||
module.exports = ({mtokens}) => { | ||
if (!mtokens) { | ||
return {hrp: ''}; | ||
// Exit early when there are no mtokens | ||
if (isEmpty(mtokens)) { | ||
return {hrp: String()}; | ||
} | ||
if (!isString(mtokens)) { | ||
throw new Error('ExpectedStringValueToConvertMtokensToHrp'); | ||
} | ||
if (!isNumeric(mtokens)) { | ||
throw new Error('ExpectedNumericStringValueToConvertMtokensToHrp'); | ||
} | ||
const amount = BigInt(mtokens); | ||
// Map the amount into multiplier representations and select the shortest | ||
const [hrp] = multipliers | ||
@@ -29,3 +47,8 @@ .map(({letter, value}) => ({letter, value: BigInt(value)})) | ||
// The smallest amounts do not have any multiplier | ||
if (!hrp) { | ||
return {hrp: asPico(amount)}; | ||
} | ||
return {hrp}; | ||
}; |
@@ -6,3 +6,3 @@ const {bech32} = require('bech32'); | ||
const fieldAsDetails = require('./field_as_details'); | ||
const hrpAsTokens = require('./hrp_as_tokens'); | ||
const hrpAsMtokens = require('./hrp_as_mtokens'); | ||
const requestDetails = require('./request_details'); | ||
@@ -93,3 +93,3 @@ const signatureFromWords = require('./signature_from_words'); | ||
})), | ||
mtokens: hrpAsTokens({amount, units}).mtokens, | ||
mtokens: hrpAsMtokens({amount, units}).mtokens, | ||
timestamp: wordsAsNumber({words: timestampWords}) * msPerSec, | ||
@@ -96,0 +96,0 @@ }); |
# Versions | ||
## 1.2.1 | ||
Fix issues with millitoken value invoices and add additional test coverage for sub-token requests. | ||
- `byteDecodeRequest`: Fix decoding issue, add required word count argument | ||
- `byteEncodeRequest`: Return word count with encoding | ||
## 1.2.0 | ||
@@ -4,0 +11,0 @@ |
@@ -7,4 +7,4 @@ { | ||
"dependencies": { | ||
"bolt07": "1.7.2", | ||
"bolt09": "0.1.4", | ||
"bolt07": "1.7.3", | ||
"bolt09": "0.1.5", | ||
"bech32": "2.0.0", | ||
@@ -17,3 +17,3 @@ "bitcoinjs-lib": "5.2.0", | ||
"devDependencies": { | ||
"tap": "15.0.2" | ||
"tap": "15.0.9" | ||
}, | ||
@@ -40,3 +40,3 @@ "engines": { | ||
}, | ||
"version": "1.2.0" | ||
"version": "1.2.1" | ||
} |
@@ -14,4 +14,5 @@ # Invoices | ||
encoded: <Payment Request Details Hex String> | ||
mtokens: <Millitokens Number String> | ||
[mtokens]: <Millitokens Number String> | ||
network: <Network Name String> | ||
words: <Words Count Number> | ||
} | ||
@@ -56,2 +57,3 @@ | ||
network: <Network Name String> | ||
words: <Word Length Number> | ||
} | ||
@@ -58,0 +60,0 @@ |
@@ -7,5 +7,6 @@ const {test} = require('tap'); | ||
const args = { | ||
encoded: '0b675c0ac10d388683237d00319b98b8c56c7325aaee5728c2ec02506fcd790d8406bcbd6d3a81a1ea932b0b21d1023b637b130b61021b93cb83a37b1bab93932b731bc902932b3bab630ba34b7b73001120dfa2ed0f3bee3252b6132a943032fe0158340b6784a5a9b2b018ec3ed2ee3fa8a0b8102e27747c432917543ea7476b2d43a33d6a55198d0f3fc4a89b2e5c8bd0', | ||
encoded: '0b25fe64410d00004080c1014181c20240004080c1014181c20240004080c1014181c202404081a1fa83632b0b9b29031b7b739b4b232b91039bab83837b93a34b733903a3434b990383937b532b1ba038ec6891345e204145be8a3a99de38e98a39d6a569434e1845c8af7205afcfcc7f425fcd1463e93c32881ead0d6e356d467ec8c02553f9aab15e5738b11f127f00', | ||
mtokens: '150000', | ||
network: 'testnet', | ||
words: 232, | ||
}; | ||
@@ -25,7 +26,2 @@ | ||
{ | ||
args: makeArgs({mtokens: undefined}), | ||
description: 'Millitokens is required', | ||
error: 'ExpectedAmountToDecodeByteEncodedRequest', | ||
}, | ||
{ | ||
args: makeArgs({network: undefined}), | ||
@@ -44,3 +40,3 @@ description: 'Network is required', | ||
expected: { | ||
request: 'lntb1500n1pdn4czkpp5ugdqer05qrrxuchrzkcue94th9w2xzasp9qm7d0yxcgp4uh4kn4qdpa2fjkzep6yprkcmmzv9kzqsmj09c8gmmrw4e8yetwvdujq5n9va6kcct5d9hkucqzysdlghdpua7uvjjkcfj49psxtlqzkp5pdncffdfk2cp3mp76thrl29qhqgzufm503pjj96586n5w6edgw3n66j4rxxs707y4zdjuhyt6quatqte', | ||
request: 'lntb1500n1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqz03uuk', | ||
}, | ||
@@ -47,0 +43,0 @@ }, |
const {test} = require('tap'); | ||
const {byteDecodeRequest} = require('./../../'); | ||
const {byteEncodeRequest} = require('./../../'); | ||
const {parsePaymentRequest} = require('./../../'); | ||
@@ -18,11 +20,48 @@ const tests = [ | ||
args: { | ||
request: 'lntb1500n1pdn4czkpp5ugdqer05qrrxuchrzkcue94th9w2xzasp9qm7d0yxcgp4uh4kn4qdpa2fjkzep6yprkcmmzv9kzqsmj09c8gmmrw4e8yetwvdujq5n9va6kcct5d9hkucqzysdlghdpua7uvjjkcfj49psxtlqzkp5pdncffdfk2cp3mp76thrl29qhqgzufm503pjj96586n5w6edgw3n66j4rxxs707y4zdjuhyt6qqe5weu4', | ||
request: 'lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx2ctnv5sxxmmwwd5kgetjypeh2ursdae8g6twvus8g6rfwvs8qun0dfjkxaq8rkx3yf5tcsyz3d73gafnh3cax9rn449d9p5uxz9ezhhypd0elx87sjle52x86fux2ypatgddc6k63n7erqz25le42c4u4ecky03ylcqca784w', | ||
}, | ||
description: 'Byte encode a payment request', | ||
expected: { | ||
encoded: '0b675c0ac10d388683237d00319b98b8c56c7325aaee5728c2ec02506fcd790d8406bcbd6d3a81a1ea932b0b21d1023b637b130b61021b93cb83a37b1bab93932b731bc902932b3bab630ba34b7b73001120dfa2ed0f3bee3252b6132a943032fe0158340b6784a5a9b2b018ec3ed2ee3fa8a0b8102e27747c432917543ea7476b2d43a33d6a55198d0f3fc4a89b2e5c8bd0', | ||
mtokens: '150000', | ||
network: 'testnet', | ||
encoded: '0b25fe64410d00004080c1014181c20240004080c1014181c20240004080c1014181c202404081a1fa83632b0b9b29031b7b739b4b232b91039bab83837b93a34b733903a3434b990383937b532b1ba038ec6891345e204145be8a3a99de38e98a39d6a569434e1845c8af7205afcfcc7f425fcd1463e93c32881ead0d6e356d467ec8c02553f9aab15e5738b11f127f00', | ||
mtokens: undefined, | ||
network: 'bitcoin', | ||
words: 232, | ||
}, | ||
}, | ||
{ | ||
args: { | ||
request: 'lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdq5xysxxatsyp3k7enxv4jsxqzpuaztrnwngzn3kdzw5hydlzf03qdgm2hdq27cqv3agm2awhz5se903vruatfhq77w3ls4evs3ch9zw97j25emudupq63nyw24cg27h2rspfj9srp', | ||
}, | ||
description: 'Byte encode a payment request with an amount', | ||
expected: { | ||
encoded: '0b25fe64410d00004080c1014181c20240004080c1014181c20240004080c1014181c202404081a0a189031bab81031b7b33332b2818020f3a258e6e9a0538d9a2752e46fc497c40d46d576815ec0191ea36aebae2a43257c583e7569b83de747f0ae5908e2e5138be92a99df1bc08351991caae10af5d438040', | ||
mtokens: '250000000', | ||
network: 'bitcoin', | ||
words: 194, | ||
}, | ||
}, | ||
{ | ||
args: { | ||
request: 'lnbc2500u1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpquwpc4curk03c9wlrswe78q4eyqc7d8d0xqzpuyk0sg5g70me25alkluzd2x62aysf2pyy8edtjeevuv4p2d5p76r4zkmneet7uvyakky2zr4cusd45tftc9c5fh0nnqpnl2jfll544esqchsrny', | ||
}, | ||
description: 'Byte encode a payment request with an amount', | ||
expected: { | ||
encoded: '0b25fe64410d00004080c1014181c20240004080c1014181c20240004080c1014181c202404081a1071c1c571c1d9f1c15df1c1d9f1c15c9018f34ed798020f0967c114479fbcaa9dfdbfc13546d2ba482541210f96ae59cb38ca854da07da1d456dcf395fb8c276d622843ae3906d68b4af05c51377ce600cfea927ffa56b9800', | ||
mtokens: '250000000', | ||
network: 'bitcoin', | ||
words: 206, | ||
}, | ||
}, | ||
{ | ||
args: { | ||
request: 'lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqscc6gd6ql3jrc5yzme8v4ntcewwz5cnw92tz0pc8qcuufvq7khhr8wpald05e92xw006sq94mg8v2ndf4sefvf9sygkshp5zfem29trqq2yxxz7', | ||
}, | ||
description: 'Byte encode a payment request with a desc hash', | ||
expected: { | ||
encoded: '0b25fe64410d00004080c1014181c20240004080c1014181c20240004080c1014181c202404082e1a1c92db7b3f161a001b7689049eea2701b46f8db7513629edf2408fac7eaedc608631a43740fc643c5082de4ecacd78cb9c2a626e2a962787070639c4b01eb5ee33b83dfb5f4c954673dfa800b5da0ec54da9ac329624b0222d0b86824e76a2ac60000', | ||
mtokens: '2000000000', | ||
network: 'bitcoin', | ||
words: 221, | ||
}, | ||
}, | ||
]; | ||
@@ -37,2 +76,8 @@ | ||
const {request} = byteDecodeRequest(details); | ||
const original = parsePaymentRequest({request: args.request}); | ||
const decoded = parsePaymentRequest({request}) | ||
strictSame(original, decoded, 'Original payment details preserved'); | ||
strictSame(details, expected, 'Got expected byte encoding'); | ||
@@ -39,0 +84,0 @@ } |
@@ -7,2 +7,17 @@ const {test} = require('tap'); | ||
{ | ||
args: {mtokens: '1'}, | ||
description: 'The smallest possible', | ||
expected: '10p', | ||
}, | ||
{ | ||
args: {mtokens: '10'}, | ||
description: 'Test smaller than a nano', | ||
expected: '100p', | ||
}, | ||
{ | ||
args: {mtokens: '100'}, | ||
description: 'Test smaller than a token', | ||
expected: '1n', | ||
}, | ||
{ | ||
args: {mtokens: '1000'}, description: 'Test nano tokens', expected: '10n', | ||
@@ -17,5 +32,2 @@ }, | ||
{ | ||
args: {mtokens: '1', description: 'Test pico', expected: '10p'}, | ||
}, | ||
{ | ||
args: {mtokens: '100000000'}, description: 'Test milli', expected: '1m', | ||
@@ -22,0 +34,0 @@ }, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
98245
54
2514
203
+ Addedbolt07@1.7.3(transitive)
+ Addedbolt09@0.1.5(transitive)
+ Addedcipher-base@1.0.6(transitive)
- Removedbolt07@1.7.2(transitive)
- Removedbolt09@0.1.4(transitive)
- Removedcipher-base@1.0.5(transitive)
Updatedbolt07@1.7.3
Updatedbolt09@0.1.5