@buildonspark/spark-sdk 0.1.44 → 0.1.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/{RequestLightningSendInput-BxbCtwpV.d.cts → RequestLightningSendInput-2cSh_In4.d.cts} +1 -1
  3. package/dist/{RequestLightningSendInput-RGel43ks.d.ts → RequestLightningSendInput-CN6BNg_g.d.ts} +1 -1
  4. package/dist/address/index.cjs +2 -2
  5. package/dist/address/index.d.cts +2 -2
  6. package/dist/address/index.d.ts +2 -2
  7. package/dist/address/index.js +2 -2
  8. package/dist/{chunk-EKFD62HN.js → chunk-4EMV7HHW.js} +2 -1
  9. package/dist/{chunk-4Q2ZDYYU.js → chunk-BGGEVUJK.js} +1157 -208
  10. package/dist/{chunk-CIZNCBKE.js → chunk-C2S227QR.js} +648 -45
  11. package/dist/{chunk-WPTRVD2V.js → chunk-DXR2PXJU.js} +15 -15
  12. package/dist/{chunk-NBCNYDWJ.js → chunk-HHNQ3ZHC.js} +2 -2
  13. package/dist/{chunk-DAXGVPVM.js → chunk-HSCLBJEL.js} +2 -2
  14. package/dist/{chunk-6AFUC5M2.js → chunk-HWJWKEIU.js} +8 -2
  15. package/dist/{chunk-A2ZLMH6I.js → chunk-JB64OQES.js} +259 -327
  16. package/dist/{chunk-KEKGSH7B.js → chunk-KMUMFYFX.js} +3 -3
  17. package/dist/chunk-LHRD2WT6.js +2374 -0
  18. package/dist/{chunk-HTMXTJRK.js → chunk-N5VZVCGJ.js} +4 -4
  19. package/dist/{chunk-SQKXGAIR.js → chunk-NTFKFRQ2.js} +1 -1
  20. package/dist/{chunk-K4BJARWM.js → chunk-OBFKIEMP.js} +1 -1
  21. package/dist/{chunk-UBT6EDVJ.js → chunk-OFCJFZ4I.js} +1 -1
  22. package/dist/{chunk-XX4RRWOX.js → chunk-UXDODSDT.js} +8 -10
  23. package/dist/graphql/objects/index.d.cts +5 -4
  24. package/dist/graphql/objects/index.d.ts +5 -4
  25. package/dist/index-CKL5DodV.d.cts +214 -0
  26. package/dist/index-COm59SPw.d.ts +214 -0
  27. package/dist/index.cjs +4026 -1315
  28. package/dist/index.d.cts +764 -19
  29. package/dist/index.d.ts +764 -19
  30. package/dist/index.js +23 -27
  31. package/dist/index.node.cjs +4026 -1319
  32. package/dist/index.node.d.cts +10 -8
  33. package/dist/index.node.d.ts +10 -8
  34. package/dist/index.node.js +23 -31
  35. package/dist/native/index.cjs +4027 -1316
  36. package/dist/native/index.d.cts +281 -85
  37. package/dist/native/index.d.ts +281 -85
  38. package/dist/native/index.js +4018 -1307
  39. package/dist/{network-CfxLnaot.d.cts → network-Css46DAz.d.cts} +1 -1
  40. package/dist/{network-CroCOQ0B.d.ts → network-hynb7iTZ.d.ts} +1 -1
  41. package/dist/proto/lrc20.cjs +222 -19
  42. package/dist/proto/lrc20.d.cts +1 -1
  43. package/dist/proto/lrc20.d.ts +1 -1
  44. package/dist/proto/lrc20.js +2 -2
  45. package/dist/proto/spark.cjs +1154 -205
  46. package/dist/proto/spark.d.cts +1 -1
  47. package/dist/proto/spark.d.ts +1 -1
  48. package/dist/proto/spark.js +3 -1
  49. package/dist/proto/spark_token.cjs +1377 -58
  50. package/dist/proto/spark_token.d.cts +153 -15
  51. package/dist/proto/spark_token.d.ts +153 -15
  52. package/dist/proto/spark_token.js +40 -4
  53. package/dist/{sdk-types-CTbTdDbE.d.ts → sdk-types-CKBsylfW.d.ts} +1 -1
  54. package/dist/{sdk-types-BeCBoozO.d.cts → sdk-types-Ct8xmN7l.d.cts} +1 -1
  55. package/dist/services/config.cjs +2 -2
  56. package/dist/services/config.d.cts +5 -4
  57. package/dist/services/config.d.ts +5 -4
  58. package/dist/services/config.js +6 -6
  59. package/dist/services/connection.cjs +2438 -262
  60. package/dist/services/connection.d.cts +5 -4
  61. package/dist/services/connection.d.ts +5 -4
  62. package/dist/services/connection.js +4 -4
  63. package/dist/services/index.cjs +5937 -3154
  64. package/dist/services/index.d.cts +7 -6
  65. package/dist/services/index.d.ts +7 -6
  66. package/dist/services/index.js +17 -15
  67. package/dist/services/lrc-connection.cjs +223 -20
  68. package/dist/services/lrc-connection.d.cts +5 -4
  69. package/dist/services/lrc-connection.d.ts +5 -4
  70. package/dist/services/lrc-connection.js +4 -4
  71. package/dist/services/token-transactions.cjs +840 -236
  72. package/dist/services/token-transactions.d.cts +25 -7
  73. package/dist/services/token-transactions.d.ts +25 -7
  74. package/dist/services/token-transactions.js +5 -4
  75. package/dist/services/wallet-config.cjs +3 -1
  76. package/dist/services/wallet-config.d.cts +7 -5
  77. package/dist/services/wallet-config.d.ts +7 -5
  78. package/dist/services/wallet-config.js +3 -1
  79. package/dist/signer/signer.cjs +1 -1
  80. package/dist/signer/signer.d.cts +3 -2
  81. package/dist/signer/signer.d.ts +3 -2
  82. package/dist/signer/signer.js +2 -2
  83. package/dist/{signer-D7vfYik9.d.ts → signer-BP6F__oR.d.cts} +2 -6
  84. package/dist/{signer-DaY8c60s.d.cts → signer-BVZJXcq7.d.ts} +2 -6
  85. package/dist/{spark-C4ZrsgjC.d.cts → spark-DbzGfse6.d.cts} +93 -15
  86. package/dist/{spark-C4ZrsgjC.d.ts → spark-DbzGfse6.d.ts} +93 -15
  87. package/dist/spark_bindings/native/index.cjs +183 -0
  88. package/dist/spark_bindings/native/index.d.cts +14 -0
  89. package/dist/spark_bindings/native/index.d.ts +14 -0
  90. package/dist/spark_bindings/native/index.js +141 -0
  91. package/dist/spark_bindings/wasm/index.cjs +1093 -0
  92. package/dist/spark_bindings/wasm/index.d.cts +47 -0
  93. package/dist/spark_bindings/wasm/index.d.ts +47 -0
  94. package/dist/{chunk-K4C4W5FC.js → spark_bindings/wasm/index.js} +7 -6
  95. package/dist/types/index.cjs +1156 -208
  96. package/dist/types/index.d.cts +5 -4
  97. package/dist/types/index.d.ts +5 -4
  98. package/dist/types/index.js +2 -2
  99. package/dist/types-C-Rp0Oo7.d.cts +46 -0
  100. package/dist/types-C-Rp0Oo7.d.ts +46 -0
  101. package/dist/utils/index.cjs +65 -13
  102. package/dist/utils/index.d.cts +14 -134
  103. package/dist/utils/index.d.ts +14 -134
  104. package/dist/utils/index.js +13 -13
  105. package/package.json +22 -2
  106. package/src/index.node.ts +0 -1
  107. package/src/index.ts +0 -1
  108. package/src/native/index.ts +1 -2
  109. package/src/proto/common.ts +5 -5
  110. package/src/proto/google/protobuf/descriptor.ts +34 -34
  111. package/src/proto/google/protobuf/duration.ts +2 -2
  112. package/src/proto/google/protobuf/empty.ts +2 -2
  113. package/src/proto/google/protobuf/timestamp.ts +2 -2
  114. package/src/proto/mock.ts +4 -4
  115. package/src/proto/spark.ts +1452 -185
  116. package/src/proto/spark_authn.ts +7 -7
  117. package/src/proto/spark_token.ts +1668 -105
  118. package/src/proto/validate/validate.ts +24 -24
  119. package/src/services/bolt11-spark.ts +62 -187
  120. package/src/services/coop-exit.ts +3 -0
  121. package/src/services/lrc20.ts +1 -1
  122. package/src/services/token-transactions.ts +197 -9
  123. package/src/services/transfer.ts +22 -0
  124. package/src/services/tree-creation.ts +13 -0
  125. package/src/services/wallet-config.ts +2 -2
  126. package/src/spark-wallet/spark-wallet.node.ts +0 -4
  127. package/src/spark-wallet/spark-wallet.ts +76 -108
  128. package/src/spark-wallet/types.ts +39 -3
  129. package/src/tests/bolt11-spark.test.ts +7 -15
  130. package/src/tests/integration/ssp/coop-exit.test.ts +7 -7
  131. package/src/tests/integration/swap.test.ts +453 -433
  132. package/src/tests/integration/transfer.test.ts +261 -248
  133. package/src/tests/token-identifier.test.ts +54 -0
  134. package/src/tests/tokens.test.ts +218 -23
  135. package/src/utils/token-hashing.ts +320 -44
  136. package/src/utils/token-identifier.ts +88 -0
  137. package/src/utils/token-transaction-validation.ts +350 -5
  138. package/src/utils/token-transactions.ts +12 -8
  139. package/src/utils/transaction.ts +0 -6
  140. package/dist/chunk-B3AMIGJG.js +0 -1073
  141. package/dist/index-CZmDdSts.d.cts +0 -829
  142. package/dist/index-ClIRO_3y.d.ts +0 -829
  143. package/dist/wasm-7OWFHDMS.js +0 -21
@@ -1,6 +1,6 @@
1
1
  // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
2
  // versions:
3
- // protoc-gen-ts_proto v2.7.2
3
+ // protoc-gen-ts_proto v2.7.5
4
4
  // protoc v5.29.3
5
5
  // source: validate/validate.proto
6
6
 
@@ -1337,7 +1337,7 @@ export const FieldRules: MessageFns<FieldRules> = {
1337
1337
 
1338
1338
  decode(input: BinaryReader | Uint8Array, length?: number): FieldRules {
1339
1339
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
1340
- let end = length === undefined ? reader.len : reader.pos + length;
1340
+ const end = length === undefined ? reader.len : reader.pos + length;
1341
1341
  const message = createBaseFieldRules();
1342
1342
  while (reader.pos < end) {
1343
1343
  const tag = reader.uint32();
@@ -1806,7 +1806,7 @@ export const FloatRules: MessageFns<FloatRules> = {
1806
1806
 
1807
1807
  decode(input: BinaryReader | Uint8Array, length?: number): FloatRules {
1808
1808
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
1809
- let end = length === undefined ? reader.len : reader.pos + length;
1809
+ const end = length === undefined ? reader.len : reader.pos + length;
1810
1810
  const message = createBaseFloatRules();
1811
1811
  while (reader.pos < end) {
1812
1812
  const tag = reader.uint32();
@@ -2002,7 +2002,7 @@ export const DoubleRules: MessageFns<DoubleRules> = {
2002
2002
 
2003
2003
  decode(input: BinaryReader | Uint8Array, length?: number): DoubleRules {
2004
2004
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
2005
- let end = length === undefined ? reader.len : reader.pos + length;
2005
+ const end = length === undefined ? reader.len : reader.pos + length;
2006
2006
  const message = createBaseDoubleRules();
2007
2007
  while (reader.pos < end) {
2008
2008
  const tag = reader.uint32();
@@ -2198,7 +2198,7 @@ export const Int32Rules: MessageFns<Int32Rules> = {
2198
2198
 
2199
2199
  decode(input: BinaryReader | Uint8Array, length?: number): Int32Rules {
2200
2200
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
2201
- let end = length === undefined ? reader.len : reader.pos + length;
2201
+ const end = length === undefined ? reader.len : reader.pos + length;
2202
2202
  const message = createBaseInt32Rules();
2203
2203
  while (reader.pos < end) {
2204
2204
  const tag = reader.uint32();
@@ -2394,7 +2394,7 @@ export const Int64Rules: MessageFns<Int64Rules> = {
2394
2394
 
2395
2395
  decode(input: BinaryReader | Uint8Array, length?: number): Int64Rules {
2396
2396
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
2397
- let end = length === undefined ? reader.len : reader.pos + length;
2397
+ const end = length === undefined ? reader.len : reader.pos + length;
2398
2398
  const message = createBaseInt64Rules();
2399
2399
  while (reader.pos < end) {
2400
2400
  const tag = reader.uint32();
@@ -2590,7 +2590,7 @@ export const UInt32Rules: MessageFns<UInt32Rules> = {
2590
2590
 
2591
2591
  decode(input: BinaryReader | Uint8Array, length?: number): UInt32Rules {
2592
2592
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
2593
- let end = length === undefined ? reader.len : reader.pos + length;
2593
+ const end = length === undefined ? reader.len : reader.pos + length;
2594
2594
  const message = createBaseUInt32Rules();
2595
2595
  while (reader.pos < end) {
2596
2596
  const tag = reader.uint32();
@@ -2786,7 +2786,7 @@ export const UInt64Rules: MessageFns<UInt64Rules> = {
2786
2786
 
2787
2787
  decode(input: BinaryReader | Uint8Array, length?: number): UInt64Rules {
2788
2788
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
2789
- let end = length === undefined ? reader.len : reader.pos + length;
2789
+ const end = length === undefined ? reader.len : reader.pos + length;
2790
2790
  const message = createBaseUInt64Rules();
2791
2791
  while (reader.pos < end) {
2792
2792
  const tag = reader.uint32();
@@ -2982,7 +2982,7 @@ export const SInt32Rules: MessageFns<SInt32Rules> = {
2982
2982
 
2983
2983
  decode(input: BinaryReader | Uint8Array, length?: number): SInt32Rules {
2984
2984
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
2985
- let end = length === undefined ? reader.len : reader.pos + length;
2985
+ const end = length === undefined ? reader.len : reader.pos + length;
2986
2986
  const message = createBaseSInt32Rules();
2987
2987
  while (reader.pos < end) {
2988
2988
  const tag = reader.uint32();
@@ -3178,7 +3178,7 @@ export const SInt64Rules: MessageFns<SInt64Rules> = {
3178
3178
 
3179
3179
  decode(input: BinaryReader | Uint8Array, length?: number): SInt64Rules {
3180
3180
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
3181
- let end = length === undefined ? reader.len : reader.pos + length;
3181
+ const end = length === undefined ? reader.len : reader.pos + length;
3182
3182
  const message = createBaseSInt64Rules();
3183
3183
  while (reader.pos < end) {
3184
3184
  const tag = reader.uint32();
@@ -3374,7 +3374,7 @@ export const Fixed32Rules: MessageFns<Fixed32Rules> = {
3374
3374
 
3375
3375
  decode(input: BinaryReader | Uint8Array, length?: number): Fixed32Rules {
3376
3376
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
3377
- let end = length === undefined ? reader.len : reader.pos + length;
3377
+ const end = length === undefined ? reader.len : reader.pos + length;
3378
3378
  const message = createBaseFixed32Rules();
3379
3379
  while (reader.pos < end) {
3380
3380
  const tag = reader.uint32();
@@ -3570,7 +3570,7 @@ export const Fixed64Rules: MessageFns<Fixed64Rules> = {
3570
3570
 
3571
3571
  decode(input: BinaryReader | Uint8Array, length?: number): Fixed64Rules {
3572
3572
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
3573
- let end = length === undefined ? reader.len : reader.pos + length;
3573
+ const end = length === undefined ? reader.len : reader.pos + length;
3574
3574
  const message = createBaseFixed64Rules();
3575
3575
  while (reader.pos < end) {
3576
3576
  const tag = reader.uint32();
@@ -3766,7 +3766,7 @@ export const SFixed32Rules: MessageFns<SFixed32Rules> = {
3766
3766
 
3767
3767
  decode(input: BinaryReader | Uint8Array, length?: number): SFixed32Rules {
3768
3768
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
3769
- let end = length === undefined ? reader.len : reader.pos + length;
3769
+ const end = length === undefined ? reader.len : reader.pos + length;
3770
3770
  const message = createBaseSFixed32Rules();
3771
3771
  while (reader.pos < end) {
3772
3772
  const tag = reader.uint32();
@@ -3962,7 +3962,7 @@ export const SFixed64Rules: MessageFns<SFixed64Rules> = {
3962
3962
 
3963
3963
  decode(input: BinaryReader | Uint8Array, length?: number): SFixed64Rules {
3964
3964
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
3965
- let end = length === undefined ? reader.len : reader.pos + length;
3965
+ const end = length === undefined ? reader.len : reader.pos + length;
3966
3966
  const message = createBaseSFixed64Rules();
3967
3967
  while (reader.pos < end) {
3968
3968
  const tag = reader.uint32();
@@ -4133,7 +4133,7 @@ export const BoolRules: MessageFns<BoolRules> = {
4133
4133
 
4134
4134
  decode(input: BinaryReader | Uint8Array, length?: number): BoolRules {
4135
4135
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
4136
- let end = length === undefined ? reader.len : reader.pos + length;
4136
+ const end = length === undefined ? reader.len : reader.pos + length;
4137
4137
  const message = createBaseBoolRules();
4138
4138
  while (reader.pos < end) {
4139
4139
  const tag = reader.uint32();
@@ -4286,7 +4286,7 @@ export const StringRules: MessageFns<StringRules> = {
4286
4286
 
4287
4287
  decode(input: BinaryReader | Uint8Array, length?: number): StringRules {
4288
4288
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
4289
- let end = length === undefined ? reader.len : reader.pos + length;
4289
+ const end = length === undefined ? reader.len : reader.pos + length;
4290
4290
  const message = createBaseStringRules();
4291
4291
  while (reader.pos < end) {
4292
4292
  const tag = reader.uint32();
@@ -4779,7 +4779,7 @@ export const BytesRules: MessageFns<BytesRules> = {
4779
4779
 
4780
4780
  decode(input: BinaryReader | Uint8Array, length?: number): BytesRules {
4781
4781
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
4782
- let end = length === undefined ? reader.len : reader.pos + length;
4782
+ const end = length === undefined ? reader.len : reader.pos + length;
4783
4783
  const message = createBaseBytesRules();
4784
4784
  while (reader.pos < end) {
4785
4785
  const tag = reader.uint32();
@@ -5040,7 +5040,7 @@ export const EnumRules: MessageFns<EnumRules> = {
5040
5040
 
5041
5041
  decode(input: BinaryReader | Uint8Array, length?: number): EnumRules {
5042
5042
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
5043
- let end = length === undefined ? reader.len : reader.pos + length;
5043
+ const end = length === undefined ? reader.len : reader.pos + length;
5044
5044
  const message = createBaseEnumRules();
5045
5045
  while (reader.pos < end) {
5046
5046
  const tag = reader.uint32();
@@ -5162,7 +5162,7 @@ export const MessageRules: MessageFns<MessageRules> = {
5162
5162
 
5163
5163
  decode(input: BinaryReader | Uint8Array, length?: number): MessageRules {
5164
5164
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
5165
- let end = length === undefined ? reader.len : reader.pos + length;
5165
+ const end = length === undefined ? reader.len : reader.pos + length;
5166
5166
  const message = createBaseMessageRules();
5167
5167
  while (reader.pos < end) {
5168
5168
  const tag = reader.uint32();
@@ -5247,7 +5247,7 @@ export const RepeatedRules: MessageFns<RepeatedRules> = {
5247
5247
 
5248
5248
  decode(input: BinaryReader | Uint8Array, length?: number): RepeatedRules {
5249
5249
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
5250
- let end = length === undefined ? reader.len : reader.pos + length;
5250
+ const end = length === undefined ? reader.len : reader.pos + length;
5251
5251
  const message = createBaseRepeatedRules();
5252
5252
  while (reader.pos < end) {
5253
5253
  const tag = reader.uint32();
@@ -5376,7 +5376,7 @@ export const MapRules: MessageFns<MapRules> = {
5376
5376
 
5377
5377
  decode(input: BinaryReader | Uint8Array, length?: number): MapRules {
5378
5378
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
5379
- let end = length === undefined ? reader.len : reader.pos + length;
5379
+ const end = length === undefined ? reader.len : reader.pos + length;
5380
5380
  const message = createBaseMapRules();
5381
5381
  while (reader.pos < end) {
5382
5382
  const tag = reader.uint32();
@@ -5511,7 +5511,7 @@ export const AnyRules: MessageFns<AnyRules> = {
5511
5511
 
5512
5512
  decode(input: BinaryReader | Uint8Array, length?: number): AnyRules {
5513
5513
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
5514
- let end = length === undefined ? reader.len : reader.pos + length;
5514
+ const end = length === undefined ? reader.len : reader.pos + length;
5515
5515
  const message = createBaseAnyRules();
5516
5516
  while (reader.pos < end) {
5517
5517
  const tag = reader.uint32();
@@ -5627,7 +5627,7 @@ export const DurationRules: MessageFns<DurationRules> = {
5627
5627
 
5628
5628
  decode(input: BinaryReader | Uint8Array, length?: number): DurationRules {
5629
5629
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
5630
- let end = length === undefined ? reader.len : reader.pos + length;
5630
+ const end = length === undefined ? reader.len : reader.pos + length;
5631
5631
  const message = createBaseDurationRules();
5632
5632
  while (reader.pos < end) {
5633
5633
  const tag = reader.uint32();
@@ -5814,7 +5814,7 @@ export const TimestampRules: MessageFns<TimestampRules> = {
5814
5814
 
5815
5815
  decode(input: BinaryReader | Uint8Array, length?: number): TimestampRules {
5816
5816
  const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
5817
- let end = length === undefined ? reader.len : reader.pos + length;
5817
+ const end = length === undefined ? reader.len : reader.pos + length;
5818
5818
  const message = createBaseTimestampRules();
5819
5819
  while (reader.pos < end) {
5820
5820
  const tag = reader.uint32();
@@ -1,9 +1,29 @@
1
- import { bech32 } from "@scure/base";
2
- import { sha256 } from "@noble/hashes/sha2";
3
- import { secp256k1 } from "@noble/curves/secp256k1";
1
+ import { decode } from "light-bolt11-decoder";
2
+
4
3
  import { Network } from "../utils/network.js";
5
4
  import { ValidationError } from "../errors/index.js";
6
5
 
6
+ // Invoice section interface
7
+ interface Section {
8
+ name: string;
9
+ letters: string;
10
+ value?: any;
11
+ tag?: string;
12
+ }
13
+
14
+ interface RouteHint {
15
+ pubkey: string;
16
+ short_channel_id: string;
17
+ fee_base_msat: number;
18
+ fee_proportional_millionths: number;
19
+ cltv_expiry_delta: number;
20
+ }
21
+
22
+ const RECEIVER_IDENTITY_PUBLIC_KEY_SHORT_CHANNEL_ID = "f42400f424000001";
23
+ const PAYMENT_HASH_NAME = "payment_hash";
24
+ const AMOUNT_MSATS_NAME = "amount";
25
+ const PAYMENT_SECRET_NAME = "payment_secret";
26
+
7
27
  interface DecodedInvoice {
8
28
  amountMSats: bigint | null;
9
29
  fallbackAddress: string | undefined;
@@ -11,103 +31,57 @@ interface DecodedInvoice {
11
31
  }
12
32
 
13
33
  export function decodeInvoice(invoice: string): DecodedInvoice {
14
- const { words, prefix } = bech32.decode(
15
- invoice as `${string}1${string}`,
16
- 1_000,
17
- );
18
- verifySignature(words, prefix);
19
-
20
- const amountMSats = extractMillisatoshiAmountFromInvoice(invoice);
21
-
22
- let fallbackAddress: string | undefined = undefined;
23
- let paymentHash: string | undefined = undefined;
24
- let paymentSecret: string | undefined = undefined;
25
-
26
- // TLV data lives between the timestamp and the signature+recovery words
27
- let i = 7;
28
- const tlvEnd = words.length - 105;
29
- while (i + 2 < tlvEnd) {
30
- const tag = words[i];
31
- const len1 = words[i + 1];
32
- const len2 = words[i + 2];
33
- if (len1 === undefined || len2 === undefined) {
34
- console.log("No length word");
35
- break;
34
+ const decodedInvoice = decode(invoice);
35
+ const network = getNetworkFromInvoice(invoice);
36
+
37
+ if (network === null) {
38
+ throw new ValidationError("Invalid network found in invoice: " + invoice);
39
+ }
40
+
41
+ let paymentSection: Section | undefined;
42
+ let routeHints: RouteHint[][] = [];
43
+ let amountSection: Section | undefined;
44
+ let paymentSecretSection: Section | undefined;
45
+ let fallbackAddress: string | undefined;
46
+
47
+ for (const section of decodedInvoice.sections) {
48
+ if (section.name === PAYMENT_HASH_NAME) {
49
+ paymentSection = section;
36
50
  }
37
- const len = (len1 << 5) + len2;
38
- const start = i + 3;
39
- const end = start + len;
40
-
41
- if (tag === 1) {
42
- // payment hash (tag 'p (1)')
43
- const hashWords = words.slice(start, end);
44
- const hashBytes = bech32WordsToBytes(hashWords);
45
- if (hashBytes.length === 32) {
46
- paymentHash = Buffer.from(hashBytes).toString("hex");
47
- }
48
- } else if (tag === 9) {
49
- // fallback address (tag 'f (9)')
50
- const verWord = words[start]; // 1st word = version (5-bit)
51
- if (verWord !== 31) {
52
- console.warn("Not our custom version-31");
53
- i = end;
54
- continue;
55
- }
51
+ if (section.name === AMOUNT_MSATS_NAME) {
52
+ amountSection = section;
53
+ }
54
+ if (section.name === PAYMENT_SECRET_NAME) {
55
+ paymentSecretSection = section;
56
+ }
57
+ }
56
58
 
57
- const payloadWords = words.slice(start + 1, end);
58
- const payloadBytes = bech32WordsToBytes(payloadWords);
59
-
60
- fallbackAddress = Buffer.from(payloadBytes).toString("hex");
61
- } else if (tag === 16) {
62
- // Payment secret (tag 's (16)') - should be 32 bytes (52 words)
63
- if (len !== 52) {
64
- throw new ValidationError("Invalid payment secret length", {
65
- field: "paymentSecret",
66
- value: len,
67
- expected: "52 words (32 bytes for 256-bit secret)",
68
- });
69
- }
59
+ routeHints = decodedInvoice.route_hints;
70
60
 
71
- const secretWords = words.slice(start, end);
72
- const secretBytes = bech32WordsToBytes(secretWords);
61
+ const amountMSats = amountSection?.value ? BigInt(amountSection.value) : null;
62
+ const paymentHash = paymentSection?.value as string;
73
63
 
74
- if (secretBytes.length !== 32) {
75
- throw new ValidationError("Invalid payment secret size", {
76
- field: "paymentSecret",
77
- value: secretBytes.length,
78
- expected: "32 bytes (256 bits)",
79
- });
64
+ for (const routeHintArray of routeHints) {
65
+ for (const routeHint of routeHintArray) {
66
+ if (
67
+ routeHint.short_channel_id ===
68
+ RECEIVER_IDENTITY_PUBLIC_KEY_SHORT_CHANNEL_ID
69
+ ) {
70
+ fallbackAddress = routeHint.pubkey;
80
71
  }
81
-
82
- paymentSecret = Buffer.from(secretBytes).toString("hex");
83
72
  }
84
- i = end; // next TLV
85
73
  }
74
+
86
75
  if (paymentHash === undefined) {
87
76
  throw new ValidationError("No payment hash found in invoice: " + invoice);
88
77
  }
89
- if (paymentSecret === undefined) {
78
+ if (paymentSecretSection?.value === undefined) {
90
79
  throw new ValidationError(
91
80
  "Invalid payment secret found in invoice: " + invoice,
92
81
  );
93
82
  }
94
- return { amountMSats, fallbackAddress, paymentHash };
95
- }
96
83
 
97
- function bech32WordsToBytes(words: number[]): Uint8Array {
98
- let acc = 0,
99
- bits = 0;
100
- const out: number[] = [];
101
- for (const w of words) {
102
- if (w < 0 || w > 31) throw new Error(`bad word ${w}`);
103
- acc = (acc << 5) | w;
104
- bits += 5;
105
- while (bits >= 8) {
106
- bits -= 8;
107
- out.push((acc >> bits) & 0xff);
108
- }
109
- }
110
- return new Uint8Array(out);
84
+ return { amountMSats, fallbackAddress, paymentHash };
111
85
  }
112
86
 
113
87
  export function getNetworkFromInvoice(invoice: string): Network | null {
@@ -120,109 +94,10 @@ export function getNetworkFromInvoice(invoice: string): Network | null {
120
94
  return null;
121
95
  }
122
96
 
123
- function extractMillisatoshiAmountFromInvoice(invoice: string): bigint | null {
124
- const match = invoice.match(/^ln[a-z]+(\d+)([a-z]?)1/);
125
- if (!match) return null;
126
-
127
- const [, amount, multiplier] = match;
128
- if (!amount) return null;
129
-
130
- const value = BigInt(amount);
131
- const MILLISATS_PER_BTC = 100_000_000_000n;
132
-
133
- const divisors = {
134
- m: 1_000n,
135
- u: 1_000_000n,
136
- n: 1_000_000_000n,
137
- p: 10_000_000_000_000n,
138
- };
139
-
140
- if (multiplier) {
141
- // Validate multiplier is valid
142
- if (!(multiplier in divisors)) {
143
- throw new ValidationError(`Invalid multiplier: ${multiplier}`, {
144
- field: "multiplier",
145
- value: multiplier,
146
- expected: "valid bolt11 multiplier: m, u, n, p",
147
- });
148
- }
149
-
150
- const divisor = divisors[multiplier as keyof typeof divisors];
151
-
152
- // Check if division results in fractional millisatoshis
153
- if ((value * MILLISATS_PER_BTC) % divisor !== 0n) {
154
- throw new ValidationError("Invalid submillisatoshi precision", {
155
- field: "amount",
156
- value: `${amount}${multiplier}`,
157
- expected: "amount must result in whole millisatoshis",
158
- });
159
- }
160
-
161
- return (value * MILLISATS_PER_BTC) / divisor;
162
- } else {
163
- return value * MILLISATS_PER_BTC;
164
- }
165
- }
166
-
167
- export function hasSparkHeader(bytes: Uint8Array): boolean {
168
- if (bytes.length < 3) {
169
- return false;
170
- }
171
-
172
- return (
173
- bytes[0] === 0x53 && // 'S'
174
- bytes[1] === 0x50 && // 'P'
175
- bytes[2] === 0x4b // 'K'
176
- );
177
- }
178
-
179
97
  export function isValidSparkFallback(bytes: Uint8Array): boolean {
180
- // should be 36 bytes (3-byte SPK header + 33-byte identity public key)
181
- if (bytes.length !== 36) {
98
+ // 33-byte identity public key
99
+ if (bytes.length !== 33) {
182
100
  return false;
183
101
  }
184
- return hasSparkHeader(bytes);
185
- }
186
-
187
- function verifySignature(words: number[], prefix: string) {
188
- if (words.length < 104) {
189
- throw new ValidationError("Invoice too short for signature");
190
- }
191
-
192
- const signatureStart = words.length - 104;
193
- const signatureEnd = words.length - 1;
194
-
195
- const hrp = prefix;
196
- const hrpBytes = new TextEncoder().encode(hrp);
197
-
198
- const dataWords = words.slice(0, signatureStart);
199
- const dataBytes = bech32WordsToBytes(dataWords);
200
-
201
- const sigWords = words.slice(signatureStart, signatureEnd);
202
- const sigBytes = bech32WordsToBytes(sigWords);
203
- if (sigBytes.length !== 64) {
204
- throw new ValidationError("Invalid signature length");
205
- }
206
-
207
- const recoveryId = words[words.length - 1];
208
- if (recoveryId === undefined) {
209
- throw new ValidationError("Missing recovery ID in signature");
210
- }
211
-
212
- const messageBytes = new Uint8Array(hrpBytes.length + dataBytes.length);
213
- messageBytes.set(hrpBytes, 0);
214
- messageBytes.set(dataBytes, hrpBytes.length);
215
-
216
- const messageHash = sha256(messageBytes);
217
-
218
- try {
219
- const signature =
220
- secp256k1.Signature.fromCompact(sigBytes).addRecoveryBit(recoveryId);
221
-
222
- signature.recoverPublicKey(messageHash);
223
- } catch (error) {
224
- throw new ValidationError(
225
- `Invalid BOLT11 signature: ${(error as Error).message}`,
226
- );
227
- }
102
+ return true;
228
103
  }
@@ -156,6 +156,9 @@ export class CoopExitService extends BaseTransferService {
156
156
  rawTx: refundTx.toBytes(),
157
157
  signingNonceCommitment: signingNonceCommitment,
158
158
  },
159
+ // TODO: Add direct refund signature
160
+ directRefundTxSigningJob: undefined,
161
+ directFromCpfpRefundTxSigningJob: undefined,
159
162
  };
160
163
 
161
164
  signingJobs.push(signingJob);
@@ -19,7 +19,7 @@ export async function broadcastL1Withdrawal(
19
19
  ({ output, previousTransactionHash, previousTransactionVout }) => {
20
20
  return {
21
21
  amount: bytesToNumberBE(output!.tokenAmount),
22
- tokenPubkey: bytesToHex(output!.tokenPublicKey),
22
+ tokenPubkey: bytesToHex(output!.tokenPublicKey!),
23
23
  sats: WITHDRAW_BOND_SATS,
24
24
  cltvOutputLocktime: WITHDRAW_RELATIVE_BLOCK_LOCKTIME,
25
25
  revocationKey: bytesToHex(output!.revocationCommitment!),