This commit is contained in:
hatim boufnichel 2022-11-09 21:34:53 +01:00
parent 9c8d201a10
commit 947cf34ff4
20 changed files with 789 additions and 603 deletions

View file

@ -2,4 +2,10 @@ LND_ADDRESS=
LND_CERT_PATH=
LND_MACAROON_PATH=
DATABASE_FILE=db.sqlite
JWT_SECRET=bigsecrethere
JWT_SECRET=bigsecrethere
LIMIT_FEE_RATE_MILLISATS=6
LIMIT_FEE_FIXED_SATS=100
SERVICE_FEE_INCOMING_TX_PERCENT=0
SERVICE_FEE_OUTGOING_TX_PERCENT=0
SERVICE_FEE_INCOMING_INVOICE_PERCENT=0
SERVICE_FEE_OUTGOING_INVOICE_PERCENT=0

View file

@ -1,5 +1,5 @@
([]*main.Method) (len=11 cap=16) {
(*main.Method)(0xc0002886e0)({
(*main.Method)(0xc0002ba730)({
in: (main.MethodMessage) {
name: (string) (len=5) "Empty",
hasZeroFields: (bool) true
@ -9,8 +9,8 @@
name: (string) (len=5) "Empty",
hasZeroFields: (bool) true
},
opts: (*main.methodOptions)(0xc0003cc420)({
authType: (*main.supportedAuth)(0xc000379fb0)({
opts: (*main.methodOptions)(0xc0003fc4e0)({
authType: (*main.supportedAuth)(0xc00040c030)({
id: (string) (len=5) "guest",
name: (string) (len=5) "Guest",
encrypted: (bool) false,
@ -25,7 +25,7 @@
query: ([]string) <nil>
})
}),
(*main.Method)(0xc000288730)({
(*main.Method)(0xc0002ba780)({
in: (main.MethodMessage) {
name: (string) (len=25) "EncryptionExchangeRequest",
hasZeroFields: (bool) false
@ -35,8 +35,8 @@
name: (string) (len=5) "Empty",
hasZeroFields: (bool) true
},
opts: (*main.methodOptions)(0xc0003cc5a0)({
authType: (*main.supportedAuth)(0xc0003d60c0)({
opts: (*main.methodOptions)(0xc0003fc660)({
authType: (*main.supportedAuth)(0xc00040c120)({
id: (string) (len=5) "guest",
name: (string) (len=5) "Guest",
encrypted: (bool) false,
@ -51,7 +51,7 @@
query: ([]string) <nil>
})
}),
(*main.Method)(0xc000288780)({
(*main.Method)(0xc0002ba7d0)({
in: (main.MethodMessage) {
name: (string) (len=17) "LndGetInfoRequest",
hasZeroFields: (bool) false
@ -61,8 +61,8 @@
name: (string) (len=18) "LndGetInfoResponse",
hasZeroFields: (bool) false
},
opts: (*main.methodOptions)(0xc0003cc720)({
authType: (*main.supportedAuth)(0xc0003d6180)({
opts: (*main.methodOptions)(0xc0003fc7e0)({
authType: (*main.supportedAuth)(0xc00040c1e0)({
id: (string) (len=5) "admin",
name: (string) (len=5) "Admin",
encrypted: (bool) true,
@ -78,7 +78,7 @@
query: ([]string) <nil>
})
}),
(*main.Method)(0xc0002887d0)({
(*main.Method)(0xc0002ba820)({
in: (main.MethodMessage) {
name: (string) (len=14) "AddUserRequest",
hasZeroFields: (bool) false
@ -88,8 +88,8 @@
name: (string) (len=15) "AddUserResponse",
hasZeroFields: (bool) false
},
opts: (*main.methodOptions)(0xc0003cc8a0)({
authType: (*main.supportedAuth)(0xc0003d6240)({
opts: (*main.methodOptions)(0xc0003fc960)({
authType: (*main.supportedAuth)(0xc00040c2a0)({
id: (string) (len=5) "guest",
name: (string) (len=5) "Guest",
encrypted: (bool) false,
@ -104,7 +104,7 @@
query: ([]string) <nil>
})
}),
(*main.Method)(0xc000288820)({
(*main.Method)(0xc0002ba870)({
in: (main.MethodMessage) {
name: (string) (len=15) "AuthUserRequest",
hasZeroFields: (bool) false
@ -114,8 +114,8 @@
name: (string) (len=16) "AuthUserResponse",
hasZeroFields: (bool) false
},
opts: (*main.methodOptions)(0xc0003cca20)({
authType: (*main.supportedAuth)(0xc0003d6300)({
opts: (*main.methodOptions)(0xc0003fcae0)({
authType: (*main.supportedAuth)(0xc00040c360)({
id: (string) (len=5) "guest",
name: (string) (len=5) "Guest",
encrypted: (bool) false,
@ -130,7 +130,7 @@
query: ([]string) <nil>
})
}),
(*main.Method)(0xc0002888c0)({
(*main.Method)(0xc0002ba910)({
in: (main.MethodMessage) {
name: (string) (len=17) "NewAddressRequest",
hasZeroFields: (bool) false
@ -140,8 +140,8 @@
name: (string) (len=18) "NewAddressResponse",
hasZeroFields: (bool) false
},
opts: (*main.methodOptions)(0xc0003ccba0)({
authType: (*main.supportedAuth)(0xc0003d63c0)({
opts: (*main.methodOptions)(0xc0003fcc60)({
authType: (*main.supportedAuth)(0xc00040c420)({
id: (string) (len=4) "user",
name: (string) (len=4) "User",
encrypted: (bool) false,
@ -157,7 +157,7 @@
query: ([]string) <nil>
})
}),
(*main.Method)(0xc000288960)({
(*main.Method)(0xc0002ba9b0)({
in: (main.MethodMessage) {
name: (string) (len=17) "PayAddressRequest",
hasZeroFields: (bool) false
@ -167,8 +167,8 @@
name: (string) (len=18) "PayAddressResponse",
hasZeroFields: (bool) false
},
opts: (*main.methodOptions)(0xc0003ccd20)({
authType: (*main.supportedAuth)(0xc0003d6480)({
opts: (*main.methodOptions)(0xc0003fcde0)({
authType: (*main.supportedAuth)(0xc00040c4e0)({
id: (string) (len=4) "user",
name: (string) (len=4) "User",
encrypted: (bool) false,
@ -184,7 +184,7 @@
query: ([]string) <nil>
})
}),
(*main.Method)(0xc000288a00)({
(*main.Method)(0xc0002baa50)({
in: (main.MethodMessage) {
name: (string) (len=17) "NewInvoiceRequest",
hasZeroFields: (bool) false
@ -194,8 +194,8 @@
name: (string) (len=18) "NewInvoiceResponse",
hasZeroFields: (bool) false
},
opts: (*main.methodOptions)(0xc0003ccea0)({
authType: (*main.supportedAuth)(0xc0003d6540)({
opts: (*main.methodOptions)(0xc0003fcf60)({
authType: (*main.supportedAuth)(0xc00040c5a0)({
id: (string) (len=4) "user",
name: (string) (len=4) "User",
encrypted: (bool) false,
@ -211,7 +211,7 @@
query: ([]string) <nil>
})
}),
(*main.Method)(0xc000288aa0)({
(*main.Method)(0xc0002baaf0)({
in: (main.MethodMessage) {
name: (string) (len=17) "PayInvoiceRequest",
hasZeroFields: (bool) false
@ -221,8 +221,8 @@
name: (string) (len=18) "PayInvoiceResponse",
hasZeroFields: (bool) false
},
opts: (*main.methodOptions)(0xc0003cd020)({
authType: (*main.supportedAuth)(0xc0003d6600)({
opts: (*main.methodOptions)(0xc0003fd0e0)({
authType: (*main.supportedAuth)(0xc00040c660)({
id: (string) (len=4) "user",
name: (string) (len=4) "User",
encrypted: (bool) false,
@ -238,7 +238,7 @@
query: ([]string) <nil>
})
}),
(*main.Method)(0xc000288b40)({
(*main.Method)(0xc0002bab90)({
in: (main.MethodMessage) {
name: (string) (len=18) "OpenChannelRequest",
hasZeroFields: (bool) false
@ -248,8 +248,8 @@
name: (string) (len=19) "OpenChannelResponse",
hasZeroFields: (bool) false
},
opts: (*main.methodOptions)(0xc0003cd1a0)({
authType: (*main.supportedAuth)(0xc0003d66c0)({
opts: (*main.methodOptions)(0xc0003fd260)({
authType: (*main.supportedAuth)(0xc00040c720)({
id: (string) (len=4) "user",
name: (string) (len=4) "User",
encrypted: (bool) false,
@ -265,7 +265,7 @@
query: ([]string) <nil>
})
}),
(*main.Method)(0xc000288b90)({
(*main.Method)(0xc0002babe0)({
in: (main.MethodMessage) {
name: (string) (len=5) "Empty",
hasZeroFields: (bool) true
@ -275,8 +275,8 @@
name: (string) (len=27) "GetOpenChannelLNURLResponse",
hasZeroFields: (bool) false
},
opts: (*main.methodOptions)(0xc0003cd320)({
authType: (*main.supportedAuth)(0xc0003d6780)({
opts: (*main.methodOptions)(0xc0003fd3e0)({
authType: (*main.supportedAuth)(0xc00040c7e0)({
id: (string) (len=4) "user",
name: (string) (len=4) "User",
encrypted: (bool) false,
@ -295,7 +295,7 @@
}
([]*main.Enum) (len=1 cap=1) {
(*main.Enum)(0xc000379860)({
(*main.Enum)(0xc0003cf8c0)({
name: (string) (len=11) "AddressType",
values: ([]main.EnumValue) (len=3 cap=4) {
(main.EnumValue) {
@ -315,86 +315,11 @@
}
(map[string]*main.Message) (len=19) {
(string) (len=17) "LndGetInfoRequest": (*main.Message)(0xc000215140)({
fullName: (string) (len=17) "LndGetInfoRequest",
name: (string) (len=17) "LndGetInfoRequest",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc000379320)({
name: (string) (len=7) "node_id",
kind: (string) (len=5) "int64",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=18) "LndGetInfoResponse": (*main.Message)(0xc000215180)({
fullName: (string) (len=18) "LndGetInfoResponse",
name: (string) (len=18) "LndGetInfoResponse",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc000379350)({
name: (string) (len=5) "alias",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=17) "NewAddressRequest": (*main.Message)(0xc0002151c0)({
fullName: (string) (len=17) "NewAddressRequest",
name: (string) (len=17) "NewAddressRequest",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc000379380)({
name: (string) (len=12) "address_type",
kind: (string) (len=11) "AddressType",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) true,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=17) "NewInvoiceRequest": (*main.Message)(0xc0002152c0)({
fullName: (string) (len=17) "NewInvoiceRequest",
name: (string) (len=17) "NewInvoiceRequest",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc000379470)({
name: (string) (len=11) "amount_sats",
kind: (string) (len=5) "int64",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=18) "PayInvoiceResponse": (*main.Message)(0xc000215380)({
fullName: (string) (len=18) "PayInvoiceResponse",
name: (string) (len=18) "PayInvoiceResponse",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc000379530)({
name: (string) (len=8) "preimage",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=19) "OpenChannelResponse": (*main.Message)(0xc000215400)({
(string) (len=19) "OpenChannelResponse": (*main.Message)(0xc000249440)({
fullName: (string) (len=19) "OpenChannelResponse",
name: (string) (len=19) "OpenChannelResponse",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc000379620)({
(*main.Field)(0xc0003cf680)({
name: (string) (len=10) "channel_id",
kind: (string) (len=6) "string",
isMap: (bool) false,
@ -405,89 +330,11 @@
})
}
}),
(string) (len=18) "PayAddressResponse": (*main.Message)(0xc000215280)({
fullName: (string) (len=18) "PayAddressResponse",
name: (string) (len=18) "PayAddressResponse",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc000379440)({
name: (string) (len=5) "tx_id",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=17) "PayInvoiceRequest": (*main.Message)(0xc000215340)({
fullName: (string) (len=17) "PayInvoiceRequest",
name: (string) (len=17) "PayInvoiceRequest",
fields: ([]*main.Field) (len=2 cap=2) {
(*main.Field)(0xc0003794d0)({
name: (string) (len=7) "invoice",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc000379500)({
name: (string) (len=6) "amount",
kind: (string) (len=5) "int64",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=25) "EncryptionExchangeRequest": (*main.Message)(0xc000215100)({
fullName: (string) (len=25) "EncryptionExchangeRequest",
name: (string) (len=25) "EncryptionExchangeRequest",
fields: ([]*main.Field) (len=2 cap=2) {
(*main.Field)(0xc0003792c0)({
name: (string) (len=10) "public_key",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003792f0)({
name: (string) (len=9) "device_id",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=18) "NewAddressResponse": (*main.Message)(0xc000215200)({
fullName: (string) (len=18) "NewAddressResponse",
name: (string) (len=18) "NewAddressResponse",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc0003793b0)({
name: (string) (len=7) "address",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=27) "GetOpenChannelLNURLResponse": (*main.Message)(0xc000215440)({
(string) (len=27) "GetOpenChannelLNURLResponse": (*main.Message)(0xc000249480)({
fullName: (string) (len=27) "GetOpenChannelLNURLResponse",
name: (string) (len=27) "GetOpenChannelLNURLResponse",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc000379650)({
(*main.Field)(0xc0003cf6b0)({
name: (string) (len=5) "lnurl",
kind: (string) (len=6) "string",
isMap: (bool) false,
@ -498,44 +345,11 @@
})
}
}),
(string) (len=14) "AddUserRequest": (*main.Message)(0xc000215480)({
fullName: (string) (len=14) "AddUserRequest",
name: (string) (len=14) "AddUserRequest",
fields: ([]*main.Field) (len=3 cap=4) {
(*main.Field)(0xc000379680)({
name: (string) (len=12) "callback_url",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003796b0)({
name: (string) (len=4) "name",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003796e0)({
name: (string) (len=6) "secret",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=15) "AddUserResponse": (*main.Message)(0xc0002154c0)({
(string) (len=15) "AddUserResponse": (*main.Message)(0xc000249500)({
fullName: (string) (len=15) "AddUserResponse",
name: (string) (len=15) "AddUserResponse",
fields: ([]*main.Field) (len=2 cap=2) {
(*main.Field)(0xc000379710)({
(*main.Field)(0xc0003cf770)({
name: (string) (len=7) "user_id",
kind: (string) (len=6) "string",
isMap: (bool) false,
@ -544,7 +358,7 @@
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc000379740)({
(*main.Field)(0xc0003cf7a0)({
name: (string) (len=10) "auth_token",
kind: (string) (len=6) "string",
isMap: (bool) false,
@ -555,12 +369,12 @@
})
}
}),
(string) (len=15) "AuthUserRequest": (*main.Message)(0xc000215500)({
fullName: (string) (len=15) "AuthUserRequest",
name: (string) (len=15) "AuthUserRequest",
(string) (len=25) "EncryptionExchangeRequest": (*main.Message)(0xc000249140)({
fullName: (string) (len=25) "EncryptionExchangeRequest",
name: (string) (len=25) "EncryptionExchangeRequest",
fields: ([]*main.Field) (len=2 cap=2) {
(*main.Field)(0xc000379770)({
name: (string) (len=4) "name",
(*main.Field)(0xc0003cf2f0)({
name: (string) (len=10) "public_key",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
@ -568,8 +382,8 @@
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003797a0)({
name: (string) (len=6) "secret",
(*main.Field)(0xc0003cf320)({
name: (string) (len=9) "device_id",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
@ -579,64 +393,11 @@
})
}
}),
(string) (len=16) "AuthUserResponse": (*main.Message)(0xc000215540)({
fullName: (string) (len=16) "AuthUserResponse",
name: (string) (len=16) "AuthUserResponse",
fields: ([]*main.Field) (len=2 cap=2) {
(*main.Field)(0xc0003797d0)({
name: (string) (len=7) "user_id",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc000379800)({
name: (string) (len=10) "auth_token",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=5) "Empty": (*main.Message)(0xc0002150c0)({
fullName: (string) (len=5) "Empty",
name: (string) (len=5) "Empty",
fields: ([]*main.Field) <nil>
}),
(string) (len=17) "PayAddressRequest": (*main.Message)(0xc000215240)({
fullName: (string) (len=17) "PayAddressRequest",
name: (string) (len=17) "PayAddressRequest",
fields: ([]*main.Field) (len=2 cap=2) {
(*main.Field)(0xc0003793e0)({
name: (string) (len=7) "address",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc000379410)({
name: (string) (len=10) "amout_sats",
kind: (string) (len=5) "int64",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=18) "NewInvoiceResponse": (*main.Message)(0xc000215300)({
(string) (len=18) "NewInvoiceResponse": (*main.Message)(0xc000249340)({
fullName: (string) (len=18) "NewInvoiceResponse",
name: (string) (len=18) "NewInvoiceResponse",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc0003794a0)({
(*main.Field)(0xc0003cf500)({
name: (string) (len=7) "invoice",
kind: (string) (len=6) "string",
isMap: (bool) false,
@ -647,11 +408,95 @@
})
}
}),
(string) (len=18) "OpenChannelRequest": (*main.Message)(0xc0002153c0)({
(string) (len=18) "PayInvoiceResponse": (*main.Message)(0xc0002493c0)({
fullName: (string) (len=18) "PayInvoiceResponse",
name: (string) (len=18) "PayInvoiceResponse",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc0003cf590)({
name: (string) (len=8) "preimage",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=15) "AuthUserRequest": (*main.Message)(0xc000249540)({
fullName: (string) (len=15) "AuthUserRequest",
name: (string) (len=15) "AuthUserRequest",
fields: ([]*main.Field) (len=2 cap=2) {
(*main.Field)(0xc0003cf7d0)({
name: (string) (len=4) "name",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003cf800)({
name: (string) (len=6) "secret",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=18) "LndGetInfoResponse": (*main.Message)(0xc0002491c0)({
fullName: (string) (len=18) "LndGetInfoResponse",
name: (string) (len=18) "LndGetInfoResponse",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc0003cf380)({
name: (string) (len=5) "alias",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=17) "NewAddressRequest": (*main.Message)(0xc000249200)({
fullName: (string) (len=17) "NewAddressRequest",
name: (string) (len=17) "NewAddressRequest",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc0003cf3b0)({
name: (string) (len=12) "address_type",
kind: (string) (len=11) "AddressType",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) true,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=17) "NewInvoiceRequest": (*main.Message)(0xc000249300)({
fullName: (string) (len=17) "NewInvoiceRequest",
name: (string) (len=17) "NewInvoiceRequest",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc0003cf4d0)({
name: (string) (len=11) "amount_sats",
kind: (string) (len=5) "int64",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=18) "OpenChannelRequest": (*main.Message)(0xc000249400)({
fullName: (string) (len=18) "OpenChannelRequest",
name: (string) (len=18) "OpenChannelRequest",
fields: ([]*main.Field) (len=4 cap=4) {
(*main.Field)(0xc000379560)({
(*main.Field)(0xc0003cf5c0)({
name: (string) (len=11) "destination",
kind: (string) (len=6) "string",
isMap: (bool) false,
@ -660,7 +505,7 @@
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc000379590)({
(*main.Field)(0xc0003cf5f0)({
name: (string) (len=14) "funding_amount",
kind: (string) (len=5) "int64",
isMap: (bool) false,
@ -669,7 +514,7 @@
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003795c0)({
(*main.Field)(0xc0003cf620)({
name: (string) (len=11) "push_amount",
kind: (string) (len=5) "int64",
isMap: (bool) false,
@ -678,7 +523,7 @@
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003795f0)({
(*main.Field)(0xc0003cf650)({
name: (string) (len=13) "close_address",
kind: (string) (len=6) "string",
isMap: (bool) false,
@ -688,6 +533,170 @@
isOptional: (bool) false
})
}
}),
(string) (len=14) "AddUserRequest": (*main.Message)(0xc0002494c0)({
fullName: (string) (len=14) "AddUserRequest",
name: (string) (len=14) "AddUserRequest",
fields: ([]*main.Field) (len=3 cap=4) {
(*main.Field)(0xc0003cf6e0)({
name: (string) (len=12) "callback_url",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003cf710)({
name: (string) (len=4) "name",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003cf740)({
name: (string) (len=6) "secret",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=16) "AuthUserResponse": (*main.Message)(0xc000249580)({
fullName: (string) (len=16) "AuthUserResponse",
name: (string) (len=16) "AuthUserResponse",
fields: ([]*main.Field) (len=2 cap=2) {
(*main.Field)(0xc0003cf830)({
name: (string) (len=7) "user_id",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003cf860)({
name: (string) (len=10) "auth_token",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=5) "Empty": (*main.Message)(0xc000249100)({
fullName: (string) (len=5) "Empty",
name: (string) (len=5) "Empty",
fields: ([]*main.Field) <nil>
}),
(string) (len=17) "LndGetInfoRequest": (*main.Message)(0xc000249180)({
fullName: (string) (len=17) "LndGetInfoRequest",
name: (string) (len=17) "LndGetInfoRequest",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc0003cf350)({
name: (string) (len=7) "node_id",
kind: (string) (len=5) "int64",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=18) "NewAddressResponse": (*main.Message)(0xc000249240)({
fullName: (string) (len=18) "NewAddressResponse",
name: (string) (len=18) "NewAddressResponse",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc0003cf3e0)({
name: (string) (len=7) "address",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=17) "PayAddressRequest": (*main.Message)(0xc000249280)({
fullName: (string) (len=17) "PayAddressRequest",
name: (string) (len=17) "PayAddressRequest",
fields: ([]*main.Field) (len=3 cap=4) {
(*main.Field)(0xc0003cf410)({
name: (string) (len=7) "address",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003cf440)({
name: (string) (len=10) "amout_sats",
kind: (string) (len=5) "int64",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003cf470)({
name: (string) (len=11) "target_conf",
kind: (string) (len=5) "int64",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=18) "PayAddressResponse": (*main.Message)(0xc0002492c0)({
fullName: (string) (len=18) "PayAddressResponse",
name: (string) (len=18) "PayAddressResponse",
fields: ([]*main.Field) (len=1 cap=1) {
(*main.Field)(0xc0003cf4a0)({
name: (string) (len=5) "tx_id",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
}),
(string) (len=17) "PayInvoiceRequest": (*main.Message)(0xc000249380)({
fullName: (string) (len=17) "PayInvoiceRequest",
name: (string) (len=17) "PayInvoiceRequest",
fields: ([]*main.Field) (len=2 cap=2) {
(*main.Field)(0xc0003cf530)({
name: (string) (len=7) "invoice",
kind: (string) (len=6) "string",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
}),
(*main.Field)(0xc0003cf560)({
name: (string) (len=6) "amount",
kind: (string) (len=5) "int64",
isMap: (bool) false,
isArray: (bool) false,
isEnum: (bool) false,
isMessage: (bool) false,
isOptional: (bool) false
})
}
})
}

View file

@ -106,15 +106,53 @@ export const EmptyValidate = (o?: Empty, opts: EmptyOptions = {}, path: string =
return null
}
export type LndGetInfoRequest = {
node_id: number
}
export const LndGetInfoRequestOptionalFields: [] = []
export type LndGetInfoRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
node_id_CustomCheck?: (v: number) => boolean
}
export const LndGetInfoRequestValidate = (o?: LndGetInfoRequest, opts: LndGetInfoRequestOptions = {}, path: string = 'LndGetInfoRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.node_id !== 'number') return new Error(`${path}.node_id: is not a number`)
if (opts.node_id_CustomCheck && !opts.node_id_CustomCheck(o.node_id)) return new Error(`${path}.node_id: custom check failed`)
return null
}
export type NewAddressResponse = {
address: string
}
export const NewAddressResponseOptionalFields: [] = []
export type NewAddressResponseOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
address_CustomCheck?: (v: string) => boolean
}
export const NewAddressResponseValidate = (o?: NewAddressResponse, opts: NewAddressResponseOptions = {}, path: string = 'NewAddressResponse::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.address !== 'string') return new Error(`${path}.address: is not a string`)
if (opts.address_CustomCheck && !opts.address_CustomCheck(o.address)) return new Error(`${path}.address: custom check failed`)
return null
}
export type PayAddressRequest = {
address: string
amout_sats: number
target_conf: number
}
export const PayAddressRequestOptionalFields: [] = []
export type PayAddressRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
address_CustomCheck?: (v: string) => boolean
amout_sats_CustomCheck?: (v: number) => boolean
target_conf_CustomCheck?: (v: number) => boolean
}
export const PayAddressRequestValidate = (o?: PayAddressRequest, opts: PayAddressRequestOptions = {}, path: string = 'PayAddressRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
@ -126,56 +164,49 @@ export const PayAddressRequestValidate = (o?: PayAddressRequest, opts: PayAddres
if (typeof o.amout_sats !== 'number') return new Error(`${path}.amout_sats: is not a number`)
if (opts.amout_sats_CustomCheck && !opts.amout_sats_CustomCheck(o.amout_sats)) return new Error(`${path}.amout_sats: custom check failed`)
if (typeof o.target_conf !== 'number') return new Error(`${path}.target_conf: is not a number`)
if (opts.target_conf_CustomCheck && !opts.target_conf_CustomCheck(o.target_conf)) return new Error(`${path}.target_conf: custom check failed`)
return null
}
export type NewInvoiceResponse = {
invoice: string
export type PayAddressResponse = {
tx_id: string
}
export const NewInvoiceResponseOptionalFields: [] = []
export type NewInvoiceResponseOptions = OptionsBaseMessage & {
export const PayAddressResponseOptionalFields: [] = []
export type PayAddressResponseOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
tx_id_CustomCheck?: (v: string) => boolean
}
export const PayAddressResponseValidate = (o?: PayAddressResponse, opts: PayAddressResponseOptions = {}, path: string = 'PayAddressResponse::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.tx_id !== 'string') return new Error(`${path}.tx_id: is not a string`)
if (opts.tx_id_CustomCheck && !opts.tx_id_CustomCheck(o.tx_id)) return new Error(`${path}.tx_id: custom check failed`)
return null
}
export type PayInvoiceRequest = {
invoice: string
amount: number
}
export const PayInvoiceRequestOptionalFields: [] = []
export type PayInvoiceRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
invoice_CustomCheck?: (v: string) => boolean
amount_CustomCheck?: (v: number) => boolean
}
export const NewInvoiceResponseValidate = (o?: NewInvoiceResponse, opts: NewInvoiceResponseOptions = {}, path: string = 'NewInvoiceResponse::root.'): Error | null => {
export const PayInvoiceRequestValidate = (o?: PayInvoiceRequest, opts: PayInvoiceRequestOptions = {}, path: string = 'PayInvoiceRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.invoice !== 'string') return new Error(`${path}.invoice: is not a string`)
if (opts.invoice_CustomCheck && !opts.invoice_CustomCheck(o.invoice)) return new Error(`${path}.invoice: custom check failed`)
return null
}
export type OpenChannelRequest = {
destination: string
funding_amount: number
push_amount: number
close_address: string
}
export const OpenChannelRequestOptionalFields: [] = []
export type OpenChannelRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
destination_CustomCheck?: (v: string) => boolean
funding_amount_CustomCheck?: (v: number) => boolean
push_amount_CustomCheck?: (v: number) => boolean
close_address_CustomCheck?: (v: string) => boolean
}
export const OpenChannelRequestValidate = (o?: OpenChannelRequest, opts: OpenChannelRequestOptions = {}, path: string = 'OpenChannelRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.destination !== 'string') return new Error(`${path}.destination: is not a string`)
if (opts.destination_CustomCheck && !opts.destination_CustomCheck(o.destination)) return new Error(`${path}.destination: custom check failed`)
if (typeof o.funding_amount !== 'number') return new Error(`${path}.funding_amount: is not a number`)
if (opts.funding_amount_CustomCheck && !opts.funding_amount_CustomCheck(o.funding_amount)) return new Error(`${path}.funding_amount: custom check failed`)
if (typeof o.push_amount !== 'number') return new Error(`${path}.push_amount: is not a number`)
if (opts.push_amount_CustomCheck && !opts.push_amount_CustomCheck(o.push_amount)) return new Error(`${path}.push_amount: custom check failed`)
if (typeof o.close_address !== 'string') return new Error(`${path}.close_address: is not a string`)
if (opts.close_address_CustomCheck && !opts.close_address_CustomCheck(o.close_address)) return new Error(`${path}.close_address: custom check failed`)
if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`)
if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`)
return null
}
@ -198,20 +229,125 @@ export const OpenChannelResponseValidate = (o?: OpenChannelResponse, opts: OpenC
return null
}
export type LndGetInfoRequest = {
node_id: number
export type GetOpenChannelLNURLResponse = {
lnurl: string
}
export const LndGetInfoRequestOptionalFields: [] = []
export type LndGetInfoRequestOptions = OptionsBaseMessage & {
export const GetOpenChannelLNURLResponseOptionalFields: [] = []
export type GetOpenChannelLNURLResponseOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
node_id_CustomCheck?: (v: number) => boolean
lnurl_CustomCheck?: (v: string) => boolean
}
export const LndGetInfoRequestValidate = (o?: LndGetInfoRequest, opts: LndGetInfoRequestOptions = {}, path: string = 'LndGetInfoRequest::root.'): Error | null => {
export const GetOpenChannelLNURLResponseValidate = (o?: GetOpenChannelLNURLResponse, opts: GetOpenChannelLNURLResponseOptions = {}, path: string = 'GetOpenChannelLNURLResponse::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.node_id !== 'number') return new Error(`${path}.node_id: is not a number`)
if (opts.node_id_CustomCheck && !opts.node_id_CustomCheck(o.node_id)) return new Error(`${path}.node_id: custom check failed`)
if (typeof o.lnurl !== 'string') return new Error(`${path}.lnurl: is not a string`)
if (opts.lnurl_CustomCheck && !opts.lnurl_CustomCheck(o.lnurl)) return new Error(`${path}.lnurl: custom check failed`)
return null
}
export type AddUserResponse = {
user_id: string
auth_token: string
}
export const AddUserResponseOptionalFields: [] = []
export type AddUserResponseOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
user_id_CustomCheck?: (v: string) => boolean
auth_token_CustomCheck?: (v: string) => boolean
}
export const AddUserResponseValidate = (o?: AddUserResponse, opts: AddUserResponseOptions = {}, path: string = 'AddUserResponse::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.user_id !== 'string') return new Error(`${path}.user_id: is not a string`)
if (opts.user_id_CustomCheck && !opts.user_id_CustomCheck(o.user_id)) return new Error(`${path}.user_id: custom check failed`)
if (typeof o.auth_token !== 'string') return new Error(`${path}.auth_token: is not a string`)
if (opts.auth_token_CustomCheck && !opts.auth_token_CustomCheck(o.auth_token)) return new Error(`${path}.auth_token: custom check failed`)
return null
}
export type EncryptionExchangeRequest = {
public_key: string
device_id: string
}
export const EncryptionExchangeRequestOptionalFields: [] = []
export type EncryptionExchangeRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
public_key_CustomCheck?: (v: string) => boolean
device_id_CustomCheck?: (v: string) => boolean
}
export const EncryptionExchangeRequestValidate = (o?: EncryptionExchangeRequest, opts: EncryptionExchangeRequestOptions = {}, path: string = 'EncryptionExchangeRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.public_key !== 'string') return new Error(`${path}.public_key: is not a string`)
if (opts.public_key_CustomCheck && !opts.public_key_CustomCheck(o.public_key)) return new Error(`${path}.public_key: custom check failed`)
if (typeof o.device_id !== 'string') return new Error(`${path}.device_id: is not a string`)
if (opts.device_id_CustomCheck && !opts.device_id_CustomCheck(o.device_id)) return new Error(`${path}.device_id: custom check failed`)
return null
}
export type NewInvoiceResponse = {
invoice: string
}
export const NewInvoiceResponseOptionalFields: [] = []
export type NewInvoiceResponseOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
invoice_CustomCheck?: (v: string) => boolean
}
export const NewInvoiceResponseValidate = (o?: NewInvoiceResponse, opts: NewInvoiceResponseOptions = {}, path: string = 'NewInvoiceResponse::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.invoice !== 'string') return new Error(`${path}.invoice: is not a string`)
if (opts.invoice_CustomCheck && !opts.invoice_CustomCheck(o.invoice)) return new Error(`${path}.invoice: custom check failed`)
return null
}
export type PayInvoiceResponse = {
preimage: string
}
export const PayInvoiceResponseOptionalFields: [] = []
export type PayInvoiceResponseOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
preimage_CustomCheck?: (v: string) => boolean
}
export const PayInvoiceResponseValidate = (o?: PayInvoiceResponse, opts: PayInvoiceResponseOptions = {}, path: string = 'PayInvoiceResponse::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.preimage !== 'string') return new Error(`${path}.preimage: is not a string`)
if (opts.preimage_CustomCheck && !opts.preimage_CustomCheck(o.preimage)) return new Error(`${path}.preimage: custom check failed`)
return null
}
export type AuthUserRequest = {
name: string
secret: string
}
export const AuthUserRequestOptionalFields: [] = []
export type AuthUserRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
name_CustomCheck?: (v: string) => boolean
secret_CustomCheck?: (v: string) => boolean
}
export const AuthUserRequestValidate = (o?: AuthUserRequest, opts: AuthUserRequestOptions = {}, path: string = 'AuthUserRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.name !== 'string') return new Error(`${path}.name: is not a string`)
if (opts.name_CustomCheck && !opts.name_CustomCheck(o.name)) return new Error(`${path}.name: custom check failed`)
if (typeof o.secret !== 'string') return new Error(`${path}.secret: is not a string`)
if (opts.secret_CustomCheck && !opts.secret_CustomCheck(o.secret)) return new Error(`${path}.secret: custom check failed`)
return null
}
@ -270,79 +406,58 @@ export const NewInvoiceRequestValidate = (o?: NewInvoiceRequest, opts: NewInvoic
return null
}
export type PayInvoiceResponse = {
preimage: string
export type OpenChannelRequest = {
destination: string
funding_amount: number
push_amount: number
close_address: string
}
export const PayInvoiceResponseOptionalFields: [] = []
export type PayInvoiceResponseOptions = OptionsBaseMessage & {
export const OpenChannelRequestOptionalFields: [] = []
export type OpenChannelRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
preimage_CustomCheck?: (v: string) => boolean
destination_CustomCheck?: (v: string) => boolean
funding_amount_CustomCheck?: (v: number) => boolean
push_amount_CustomCheck?: (v: number) => boolean
close_address_CustomCheck?: (v: string) => boolean
}
export const PayInvoiceResponseValidate = (o?: PayInvoiceResponse, opts: PayInvoiceResponseOptions = {}, path: string = 'PayInvoiceResponse::root.'): Error | null => {
export const OpenChannelRequestValidate = (o?: OpenChannelRequest, opts: OpenChannelRequestOptions = {}, path: string = 'OpenChannelRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.preimage !== 'string') return new Error(`${path}.preimage: is not a string`)
if (opts.preimage_CustomCheck && !opts.preimage_CustomCheck(o.preimage)) return new Error(`${path}.preimage: custom check failed`)
if (typeof o.destination !== 'string') return new Error(`${path}.destination: is not a string`)
if (opts.destination_CustomCheck && !opts.destination_CustomCheck(o.destination)) return new Error(`${path}.destination: custom check failed`)
if (typeof o.funding_amount !== 'number') return new Error(`${path}.funding_amount: is not a number`)
if (opts.funding_amount_CustomCheck && !opts.funding_amount_CustomCheck(o.funding_amount)) return new Error(`${path}.funding_amount: custom check failed`)
if (typeof o.push_amount !== 'number') return new Error(`${path}.push_amount: is not a number`)
if (opts.push_amount_CustomCheck && !opts.push_amount_CustomCheck(o.push_amount)) return new Error(`${path}.push_amount: custom check failed`)
if (typeof o.close_address !== 'string') return new Error(`${path}.close_address: is not a string`)
if (opts.close_address_CustomCheck && !opts.close_address_CustomCheck(o.close_address)) return new Error(`${path}.close_address: custom check failed`)
return null
}
export type PayAddressResponse = {
tx_id: string
}
export const PayAddressResponseOptionalFields: [] = []
export type PayAddressResponseOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
tx_id_CustomCheck?: (v: string) => boolean
}
export const PayAddressResponseValidate = (o?: PayAddressResponse, opts: PayAddressResponseOptions = {}, path: string = 'PayAddressResponse::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.tx_id !== 'string') return new Error(`${path}.tx_id: is not a string`)
if (opts.tx_id_CustomCheck && !opts.tx_id_CustomCheck(o.tx_id)) return new Error(`${path}.tx_id: custom check failed`)
return null
}
export type PayInvoiceRequest = {
invoice: string
amount: number
}
export const PayInvoiceRequestOptionalFields: [] = []
export type PayInvoiceRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
invoice_CustomCheck?: (v: string) => boolean
amount_CustomCheck?: (v: number) => boolean
}
export const PayInvoiceRequestValidate = (o?: PayInvoiceRequest, opts: PayInvoiceRequestOptions = {}, path: string = 'PayInvoiceRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.invoice !== 'string') return new Error(`${path}.invoice: is not a string`)
if (opts.invoice_CustomCheck && !opts.invoice_CustomCheck(o.invoice)) return new Error(`${path}.invoice: custom check failed`)
if (typeof o.amount !== 'number') return new Error(`${path}.amount: is not a number`)
if (opts.amount_CustomCheck && !opts.amount_CustomCheck(o.amount)) return new Error(`${path}.amount: custom check failed`)
return null
}
export type AuthUserRequest = {
export type AddUserRequest = {
callback_url: string
name: string
secret: string
}
export const AuthUserRequestOptionalFields: [] = []
export type AuthUserRequestOptions = OptionsBaseMessage & {
export const AddUserRequestOptionalFields: [] = []
export type AddUserRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
callback_url_CustomCheck?: (v: string) => boolean
name_CustomCheck?: (v: string) => boolean
secret_CustomCheck?: (v: string) => boolean
}
export const AuthUserRequestValidate = (o?: AuthUserRequest, opts: AuthUserRequestOptions = {}, path: string = 'AuthUserRequest::root.'): Error | null => {
export const AddUserRequestValidate = (o?: AddUserRequest, opts: AddUserRequestOptions = {}, path: string = 'AddUserRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.callback_url !== 'string') return new Error(`${path}.callback_url: is not a string`)
if (opts.callback_url_CustomCheck && !opts.callback_url_CustomCheck(o.callback_url)) return new Error(`${path}.callback_url: custom check failed`)
if (typeof o.name !== 'string') return new Error(`${path}.name: is not a string`)
if (opts.name_CustomCheck && !opts.name_CustomCheck(o.name)) return new Error(`${path}.name: custom check failed`)
@ -375,113 +490,3 @@ export const AuthUserResponseValidate = (o?: AuthUserResponse, opts: AuthUserRes
return null
}
export type EncryptionExchangeRequest = {
public_key: string
device_id: string
}
export const EncryptionExchangeRequestOptionalFields: [] = []
export type EncryptionExchangeRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
public_key_CustomCheck?: (v: string) => boolean
device_id_CustomCheck?: (v: string) => boolean
}
export const EncryptionExchangeRequestValidate = (o?: EncryptionExchangeRequest, opts: EncryptionExchangeRequestOptions = {}, path: string = 'EncryptionExchangeRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.public_key !== 'string') return new Error(`${path}.public_key: is not a string`)
if (opts.public_key_CustomCheck && !opts.public_key_CustomCheck(o.public_key)) return new Error(`${path}.public_key: custom check failed`)
if (typeof o.device_id !== 'string') return new Error(`${path}.device_id: is not a string`)
if (opts.device_id_CustomCheck && !opts.device_id_CustomCheck(o.device_id)) return new Error(`${path}.device_id: custom check failed`)
return null
}
export type NewAddressResponse = {
address: string
}
export const NewAddressResponseOptionalFields: [] = []
export type NewAddressResponseOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
address_CustomCheck?: (v: string) => boolean
}
export const NewAddressResponseValidate = (o?: NewAddressResponse, opts: NewAddressResponseOptions = {}, path: string = 'NewAddressResponse::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.address !== 'string') return new Error(`${path}.address: is not a string`)
if (opts.address_CustomCheck && !opts.address_CustomCheck(o.address)) return new Error(`${path}.address: custom check failed`)
return null
}
export type GetOpenChannelLNURLResponse = {
lnurl: string
}
export const GetOpenChannelLNURLResponseOptionalFields: [] = []
export type GetOpenChannelLNURLResponseOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
lnurl_CustomCheck?: (v: string) => boolean
}
export const GetOpenChannelLNURLResponseValidate = (o?: GetOpenChannelLNURLResponse, opts: GetOpenChannelLNURLResponseOptions = {}, path: string = 'GetOpenChannelLNURLResponse::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.lnurl !== 'string') return new Error(`${path}.lnurl: is not a string`)
if (opts.lnurl_CustomCheck && !opts.lnurl_CustomCheck(o.lnurl)) return new Error(`${path}.lnurl: custom check failed`)
return null
}
export type AddUserRequest = {
callback_url: string
name: string
secret: string
}
export const AddUserRequestOptionalFields: [] = []
export type AddUserRequestOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
callback_url_CustomCheck?: (v: string) => boolean
name_CustomCheck?: (v: string) => boolean
secret_CustomCheck?: (v: string) => boolean
}
export const AddUserRequestValidate = (o?: AddUserRequest, opts: AddUserRequestOptions = {}, path: string = 'AddUserRequest::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.callback_url !== 'string') return new Error(`${path}.callback_url: is not a string`)
if (opts.callback_url_CustomCheck && !opts.callback_url_CustomCheck(o.callback_url)) return new Error(`${path}.callback_url: custom check failed`)
if (typeof o.name !== 'string') return new Error(`${path}.name: is not a string`)
if (opts.name_CustomCheck && !opts.name_CustomCheck(o.name)) return new Error(`${path}.name: custom check failed`)
if (typeof o.secret !== 'string') return new Error(`${path}.secret: is not a string`)
if (opts.secret_CustomCheck && !opts.secret_CustomCheck(o.secret)) return new Error(`${path}.secret: custom check failed`)
return null
}
export type AddUserResponse = {
user_id: string
auth_token: string
}
export const AddUserResponseOptionalFields: [] = []
export type AddUserResponseOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
user_id_CustomCheck?: (v: string) => boolean
auth_token_CustomCheck?: (v: string) => boolean
}
export const AddUserResponseValidate = (o?: AddUserResponse, opts: AddUserResponseOptions = {}, path: string = 'AddUserResponse::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.user_id !== 'string') return new Error(`${path}.user_id: is not a string`)
if (opts.user_id_CustomCheck && !opts.user_id_CustomCheck(o.user_id)) return new Error(`${path}.user_id: custom check failed`)
if (typeof o.auth_token !== 'string') return new Error(`${path}.auth_token: is not a string`)
if (opts.auth_token_CustomCheck && !opts.auth_token_CustomCheck(o.auth_token)) return new Error(`${path}.auth_token: custom check failed`)
return null
}

View file

@ -33,6 +33,7 @@ message NewAddressResponse{
message PayAddressRequest{
string address = 1;
int64 amout_sats = 2;
int64 target_conf = 3;
}
message PayAddressResponse{

View file

@ -21,13 +21,14 @@ export class ServerTestSuite {
encryptCallback: async (b) => b,
deviceId: "device0"
})
mainHandler = new Main(LoadMainSettingsFromEnv()) // TODO - test env file
mainHandler = new Main(LoadMainSettingsFromEnv(true)) // TODO - test env file
server = NewServer(GetServerMethods(this.mainHandler), { ...serverOptions(this.mainHandler), throwErrors: true })
@BeforeAll()
async startServer() {
await this.mainHandler.storage.Connect()
await this.mainHandler.lnd.Warmup()
this.server.Listen(testPort)
}
@AfterAll()

View file

@ -0,0 +1,12 @@
export const EnvMustBeNonEmptyString = (name: string): string => {
const env = process.env[name]
if (!env) throw new Error(`${name} ENV must be non empty`)
return env
}
export const EnvMustBeInteger = (name: string): number => {
const env = EnvMustBeNonEmptyString(name)
if (isNaN(+env) || !Number.isInteger(+env)) {
throw new Error(`${name} ENV must be an integer number`);
}
return +env
}

View file

@ -6,8 +6,9 @@ import * as Types from '../../../proto/autogenerated/ts/types';
export class LndTestSuite {
lnd: LndHandler
@BeforeAll()
createLnd() {
this.lnd = new LndHandler(LoadLndSettingsFromEnv())
async createLnd() {
this.lnd = new LndHandler(LoadLndSettingsFromEnv(true), console.log, console.log)
await this.lnd.Warmup()
}
@AfterAll()
stopStreams() {
@ -27,6 +28,11 @@ export class LndTestSuite {
const res = await this.lnd.NewInvoice(1000)
console.log(res)
}
@FTest()
async estimateFees() {
const res = await this.lnd.EstimateChainFees("bcrt1qajzzx453x9fx5gtlyax8zrsennckrw3syd2llt", 1000, 100)
console.log(res)
}
@Test()
async openChannel() {

View file

@ -10,41 +10,23 @@ import { GetInfoResponse, AddressType, NewAddressResponse, AddInvoiceResponse, I
import { OpenChannelReq } from './openChannelReq';
import { AddInvoiceReq } from './addInvoiceReq';
import { PayInvoiceReq } from './payInvoiceReq';
import { SendCoinsReq } from './sendCoinsReq';
import { EnvMustBeInteger, EnvMustBeNonEmptyString } from '../helpers/envParser';
const DeadLineMetadata = (deadline = 10 * 1000) => ({ deadline: Date.now() + deadline })
export type LndSettings = {
lndAddr: string
lndCertPath: string
lndMacaroonPath: string
walletAccount: string
feeRateLimit: number
feeFixedLimit: number
}
export const LoadLndSettingsFromEnv = (test = false): LndSettings => {
const lndAddr = process.env.LND_ADDRESS;
const lndCertPath = process.env.LND_CERT_PATH;
const lndMacaroonPath = process.env.LND_MACAROON_PATH;
if (!lndAddr) throw new Error(`missing env for LND_ADDRESS`)
if (!lndCertPath) throw new Error(`missing env for LND_CERT_PATH`)
if (!lndMacaroonPath) throw new Error(`missing env for LND_MACAROON_PATH`)
if (!process.env.LIMIT_FEE_RATE_MILLISATS) {
throw new Error(`missing env for LIMIT_FEE_RATE_MILLISATS`)
}
if (isNaN(+process.env.LIMIT_FEE_RATE_MILLISATS) || !Number.isInteger(+process.env.LIMIT_FEE_RATE_MILLISATS)) {
throw new Error("LIMIT_FEE_RATE_MILLISATS must be an integer number");
}
if (!process.env.LIMIT_FEE_FIXED_SATS) {
throw new Error(`missing env for LIMIT_FEE_FIXED_SATS`)
}
if (isNaN(+process.env.LIMIT_FEE_FIXED_SATS) || !Number.isInteger(+process.env.LIMIT_FEE_FIXED_SATS)) {
throw new Error("LIMIT_FEE_FIXED_SATS must be an integer number");
}
const feeRateLimit = +process.env.LIMIT_FEE_RATE_MILLISATS / 1000
const feeFixedLimit = +process.env.LIMIT_FEE_FIXED_SATS
const walletAccount = process.env.LND_WALLET_ACCOUNT || ""
return { lndAddr, lndCertPath, lndMacaroonPath, walletAccount, feeRateLimit, feeFixedLimit }
const lndAddr = EnvMustBeNonEmptyString("LND_ADDRESS")
const lndCertPath = EnvMustBeNonEmptyString("LND_CERT_PATH")
const lndMacaroonPath = EnvMustBeNonEmptyString("LND_MACAROON_PATH")
const feeRateLimit = EnvMustBeInteger("LIMIT_FEE_RATE_MILLISATS") / 1000
const feeFixedLimit = EnvMustBeInteger("LIMIT_FEE_FIXED_SATS")
return { lndAddr, lndCertPath, lndMacaroonPath, feeRateLimit, feeFixedLimit }
}
type TxOutput = {
hash: string
@ -102,7 +84,7 @@ export default class {
}
SubscribeAddressPaid() {
const stream = this.lightning.subscribeTransactions({
account: this.settings.walletAccount,
account: "",
endHeight: 0,
startHeight: this.latestKnownBlockHeigh,
}, { abort: this.abortController.signal })
@ -154,7 +136,7 @@ export default class {
default:
throw new Error("unknown address type " + addressType)
}
const res = await this.lightning.newAddress({ account: this.settings.walletAccount, type: lndAddressType }, DeadLineMetadata())
const res = await this.lightning.newAddress({ account: "", type: lndAddressType }, DeadLineMetadata())
return res.response
}
@ -193,6 +175,22 @@ export default class {
})
}
async EstimateChainFees(address: string, amount: number, targetConf: number) {
const res = await this.lightning.estimateFee({
addrToAmount: { [address]: BigInt(amount) },
minConfs: 1,
spendUnconfirmed: false,
targetConf: targetConf
})
return res.response
}
async PayAddress(address: string, amount: number, satPerVByte: number, label = "") {
this.checkReady()
const res = await this.lightning.sendCoins(SendCoinsReq(address, amount, satPerVByte, label), DeadLineMetadata())
return res.response
}
async OpenChannel(destination: string, closeAddress: string, fundingAmount: number, pushSats: number): Promise<string> {
this.checkReady()
@ -201,6 +199,7 @@ export default class {
const stream = this.lightning.openChannel(req, { abort: abortController.signal })
return new Promise((res, rej) => {
stream.responses.onMessage(message => {
switch (message.update.oneofKind) {
case 'chanPending':
abortController.abort()

View file

@ -11,6 +11,7 @@ export const OpenChannelReq = (destination: string, closeAddress: string, fundin
minConfs: 0, // TBD
baseFee: 0n, // TBD
feeRate: 0n, // TBD
targetConf: 0,
zeroConf: false,
maxLocalCsv: 0,
remoteCsvDelay: 0,
@ -19,7 +20,6 @@ export const OpenChannelReq = (destination: string, closeAddress: string, fundin
remoteChanReserveSat: 0n,
remoteMaxHtlcs: 0,
remoteMaxValueInFlightMsat: 0n,
targetConf: 0,
useBaseFee: false,
useFeeRate: false,

View file

@ -0,0 +1,13 @@
import { SendCoinsRequest } from "../../../proto/lnd/lightning";
export const SendCoinsReq = (address: string, amount: number, satPerVByte: number, label = ""): SendCoinsRequest => ({
addr: address,
amount: BigInt(amount),
label: label,
satPerVbyte: BigInt(satPerVByte),
targetConf: 0,
minConfs: 1,
sendAll: false,
spendUnconfirmed: false,
satPerByte: 0n
})

View file

@ -2,20 +2,34 @@ import jwt from 'jsonwebtoken'
import Storage, { LoadStorageSettingsFromEnv, StorageSettings } from '../storage'
import * as Types from '../../../proto/autogenerated/ts/types'
import LND, { AddressPaidCb, InvoicePaidCb, LndSettings, LoadLndSettingsFromEnv } from '../lnd'
import { EnvMustBeInteger, EnvMustBeNonEmptyString } from '../helpers/envParser'
export type MainSettings = {
storageSettings: StorageSettings,
lndSettings: LndSettings,
jwtSecret: string
incomingTxFee: number
outgoingTxFee: number
incomingInvoiceFee: number
outgoingInvoiceFee: number
}
export const LoadMainSettingsFromEnv = (test = false): MainSettings => {
const jwtSecret = process.env.JWT_SECRET;
if (!jwtSecret) throw new Error(`missing env for JWT_SECRET`)
return {
lndSettings: LoadLndSettingsFromEnv(test),
storageSettings: LoadStorageSettingsFromEnv(test),
jwtSecret
jwtSecret: EnvMustBeNonEmptyString("JWT_SECRET"),
incomingTxFee: EnvMustBeInteger("SERVICE_FEE_INCOMING_TX_PERCENT") / 100,
outgoingTxFee: EnvMustBeInteger("SERVICE_FEE_OUTGOING_TX_PERCENT") / 100,
incomingInvoiceFee: EnvMustBeInteger("SERVICE_FEE_INCOMING_INVOICE_PERCENT") / 100,
outgoingInvoiceFee: EnvMustBeInteger("SERVICE_FEE_OUTGOING_INVOICE_PERCENT") / 100,
}
}
enum ActionType {
INCOMING_TX = "INCOMING_TX",
OUTGOING_TX = "OUTGOING_TX",
INCOMING_INVOICE = "INCOMING_INVOICE",
OUTGOING_INVOICE = "OUTGOING_INVOICE"
}
export default class {
storage: Storage
lnd: LND
@ -25,12 +39,27 @@ export default class {
this.storage = new Storage(settings.storageSettings)
this.lnd = new LND(settings.lndSettings, this.addressPaidCb, this.invoicePaidCb)
}
getServiceFee(action: ActionType, amount: number): number {
switch (action) {
case ActionType.INCOMING_TX:
return Math.ceil(this.settings.incomingTxFee * amount)
case ActionType.OUTGOING_TX:
return Math.ceil(this.settings.outgoingTxFee * amount)
case ActionType.INCOMING_INVOICE:
return Math.ceil(this.settings.incomingInvoiceFee * amount)
case ActionType.OUTGOING_INVOICE:
return Math.ceil(this.settings.outgoingInvoiceFee * amount)
default:
throw new Error("Unknown service action type")
}
}
addressPaidCb: AddressPaidCb = (txOutput, address, amount) => {
this.storage.StartTransaction(async tx => {
const userAddress = await this.storage.GetAddressOwner(address, tx)
if (!userAddress) { return }
const fee = this.getServiceFee(ActionType.INCOMING_TX, amount)
// This call will fail if the transaction is already registered
const addedTx = await this.storage.AddAddressTransaction(address, txOutput.hash, txOutput.index, amount)
const addedTx = await this.storage.AddAddressReceivingTransaction(userAddress, txOutput.hash, txOutput.index, amount, fee, tx)
await this.storage.IncrementUserBalance(userAddress.user.user_id, addedTx.amount, tx)
})
}
@ -38,9 +67,10 @@ export default class {
this.storage.StartTransaction(async tx => {
const userInvoice = await this.storage.GetInvoiceOwner(paymentRequest, tx)
if (!userInvoice || userInvoice.paid) { return }
const fee = this.getServiceFee(ActionType.INCOMING_INVOICE, amount)
// This call will fail if the invoice is already registered
await this.storage.FlagInvoiceAsPaid(userInvoice.serial_id, amount, tx)
await this.storage.IncrementUserBalance(userInvoice.user.user_id, amount)
await this.storage.FlagInvoiceAsPaid(userInvoice, amount, fee, tx)
await this.storage.IncrementUserBalance(userInvoice.user.user_id, amount, tx)
})
}
SignUserToken(userId: string): string {
@ -76,21 +106,55 @@ export default class {
}
}
async lockUserWithMinBalance(userId: string, minBalance: number) {
return this.storage.StartTransaction(async tx => {
const user = await this.storage.GetUser(userId, tx)
if (user.balance_sats < minBalance) {
throw new Error("insufficient balance")
}
// this call will fail if the user is already locked
await this.storage.LockUser(userId, tx)
})
}
async PayInvoice(userId: string, req: Types.PayInvoiceRequest): Promise<Types.PayInvoiceResponse> {
const decoded = await this.lnd.DecodeInvoice(req.invoice)
const payAmount = Number(decoded.numSatoshis)
const feeLimit = this.lnd.GetFeeLimitAmount(payAmount)
const decrement = payAmount + feeLimit
// this call will fail if the user balance is not enough
await this.storage.DecrementUserBalance(userId, decrement)
try {
await this.lnd.PayInvoice(req.invoice, req.amount, feeLimit)
} catch (e) {
await this.storage.IncrementUserBalance(userId, decrement)
throw e
if (decoded.numSatoshis !== 0n && req.amount !== 0) {
throw new Error("invoice has value, do not provide amount the the request")
}
if (decoded.numSatoshis === 0n && req.amount === 0) {
throw new Error("invoice has no value, an amount must be provided in the request")
}
const payAmount = req.amount !== 0 ? req.amount : Number(decoded.numSatoshis)
const serviceFee = this.getServiceFee(ActionType.OUTGOING_INVOICE, payAmount)
const totalAmountToDecrement = payAmount + serviceFee
const routingFeeLimit = this.lnd.GetFeeLimitAmount(payAmount)
await this.lockUserWithMinBalance(userId, totalAmountToDecrement + routingFeeLimit)
const payment = await this.lnd.PayInvoice(req.invoice, req.amount, routingFeeLimit)
await this.storage.DecrementUserBalance(userId, totalAmountToDecrement + Number(payment.feeSat))
await this.storage.UnlockUser(userId)
await this.storage.AddUserInvoicePayment(userId, req.invoice, payAmount, Number(payment.feeSat), serviceFee)
return {
preimage: payment.paymentPreimage
}
}
async PayAddress(userId: string, req: Types.PayAddressRequest): Promise<Types.PayAddressResponse> {
const estimate = await this.lnd.EstimateChainFees(req.address, req.amout_sats, req.target_conf)
const satPerVByte = Number(estimate.satPerVbyte)
const chainFees = Number(estimate.feeSat)
const total = req.amout_sats + chainFees
const serviceFee = this.getServiceFee(ActionType.OUTGOING_INVOICE, req.amout_sats)
await this.lockUserWithMinBalance(userId, total + serviceFee)
const payment = await this.lnd.PayAddress(req.address, req.amout_sats, satPerVByte)
await this.storage.DecrementUserBalance(userId, total + serviceFee)
await this.storage.UnlockUser(userId)
await this.storage.AddUserTransactionPayment(userId, req.address, payment.txid, 0, req.amout_sats, chainFees, serviceFee)
return {
tx_id: payment.txid
}
await this.storage.AddUserPayment(userId, req.invoice,)
}
async OpenChannel(userId: string, req: Types.OpenChannelRequest): Promise<Types.OpenChannelResponse> { throw new Error("WIP") }

View file

@ -33,7 +33,13 @@ export default (mainHandler: Main): Types.ServerMethods => {
return mainHandler.NewAddress(ctx.user_id, req)
},
PayAddress: async (ctx: Types.UserContext, req: Types.PayAddressRequest): Promise<Types.PayAddressResponse> => {
throw new Error("unimplemented")
const err = Types.PayAddressRequestValidate(req, {
address_CustomCheck: addr => addr !== '',
amout_sats_CustomCheck: amt => amt > 0,
target_conf_CustomCheck: target => target > 0
})
if (err != null) throw new Error(err.message)
return mainHandler.PayAddress(ctx.user_id, req)
},
NewInvoice: async (ctx: Types.UserContext, req: Types.NewInvoiceRequest): Promise<Types.NewInvoiceResponse> => {
throw new Error("unimplemented")

View file

@ -1,24 +1,24 @@
import "reflect-metadata"
import { DataSource } from "typeorm"
import { AddressTransaction } from "./entity/AddressTransaction"
import { AddressReceivingTransaction } from "./entity/AddressReceivingTransaction"
import { User } from "./entity/User"
import { UserAddress } from "./entity/UserAddress"
import { UserInvoice } from "./entity/UserInvoice"
import { UserPayment } from "./entity/UserPayment"
import { UserReceivingAddress } from "./entity/UserReceivingAddress"
import { UserReceivingInvoice } from "./entity/UserReceivingInvoice"
import { UserInvoicePayment } from "./entity/UserInvoicePayment"
import { EnvMustBeNonEmptyString } from "../helpers/envParser"
import { UserTransactionPayment } from "./entity/UserTransactionPayment"
export type DbSettings = {
databaseFile: string
}
export const LoadDbSettingsFromEnv = (test = false): DbSettings => {
const databaseFile = process.env.DATABASE_FILE
if (!databaseFile) throw new Error(`missing env for DATABASE_FILE`)
return { databaseFile: test ? ":memory:" : databaseFile }
return { databaseFile: test ? ":memory:" : EnvMustBeNonEmptyString("DATABASE_FILE") }
}
export default async (settings: DbSettings) => {
return new DataSource({
type: "sqlite",
database: settings.databaseFile,
//logging: true,
entities: [User, UserInvoice, UserAddress, AddressTransaction, UserPayment],
entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment],
synchronize: true
}).initialize()
}

View file

@ -0,0 +1,26 @@
import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne } from "typeorm"
import { User } from "./User"
import { UserReceivingAddress } from "./UserReceivingAddress"
@Entity()
@Index("address_transaction_unique", ["tx_hash", "output_index"], { unique: true })
export class AddressReceivingTransaction {
@PrimaryGeneratedColumn()
serial_id: number
@ManyToOne(type => UserReceivingAddress)
user_address: UserReceivingAddress
@Column()
tx_hash: string
@Column()
output_index: number
@Column()
amount: number
@Column()
service_fee: number
}

View file

@ -1,7 +1,6 @@
import { Entity, PrimaryGeneratedColumn, Column, Index, Check } from "typeorm"
@Entity()
@Check(`"balance_sats" >= 0`)
export class User {
@PrimaryGeneratedColumn()

View file

@ -2,7 +2,7 @@ import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne } from
import { User } from "./User"
@Entity()
export class UserPayment {
export class UserInvoicePayment {
@PrimaryGeneratedColumn()
serial_id: number
@ -16,4 +16,10 @@ export class UserPayment {
@Column()
amount: number
@Column()
routing_fees: number
@Column()
service_fees: number
}

View file

@ -2,7 +2,7 @@ import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne } from
import { User } from "./User"
@Entity()
export class UserAddress {
export class UserReceivingAddress {
@PrimaryGeneratedColumn()
serial_id: number

View file

@ -2,7 +2,7 @@ import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne } from
import { User } from "./User"
@Entity()
export class UserInvoice {
export class UserReceivingInvoice {
@PrimaryGeneratedColumn()
serial_id: number
@ -22,4 +22,7 @@ export class UserInvoice {
@Column({ default: 0 })
settle_amount: number
@Column()
service_fee: number
}

View file

@ -1,16 +1,18 @@
import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne } from "typeorm"
import { User } from "./User"
import { UserAddress } from "./UserAddress"
@Entity()
@Index("address_transaction_unique", ["tx_hash", "output_index"], { unique: true })
export class AddressTransaction {
export class UserTransactionPayment {
@PrimaryGeneratedColumn()
serial_id: number
@ManyToOne(type => UserAddress)
user_address: UserAddress
@ManyToOne(type => User)
user: User
@Column()
address: string
@Column()
tx_hash: string
@ -20,4 +22,10 @@ export class AddressTransaction {
@Column()
amount: number
@Column()
chain_fees: number
@Column()
service_fees: number
}

View file

@ -2,10 +2,11 @@ import { DataSource, EntityManager } from "typeorm"
import crypto from 'crypto';
import NewDB, { DbSettings, LoadDbSettingsFromEnv } from "./db"
import { User } from "./entity/User"
import { UserAddress } from "./entity/UserAddress";
import { UserInvoice } from "./entity/UserInvoice";
import { AddressTransaction } from "./entity/AddressTransaction";
import { UserPayment } from "./entity/UserPayment";
import { UserReceivingAddress } from "./entity/UserReceivingAddress";
import { UserReceivingInvoice } from "./entity/UserReceivingInvoice";
import { AddressReceivingTransaction } from "./entity/AddressReceivingTransaction";
import { UserInvoicePayment } from "./entity/UserInvoicePayment";
import { UserTransactionPayment } from "./entity/UserTransactionPayment";
export type StorageSettings = {
dbSettings: DbSettings
}
@ -23,7 +24,7 @@ export default class {
this.DB = await NewDB(this.settings.dbSettings)
}
StartTransaction(exec: (entityManager: EntityManager) => Promise<void>) {
this.DB.transaction(exec)
return this.DB.transaction(exec)
}
async AddUser(name: string, callbackUrl: string, secret: string, entityManager = this.DB): Promise<User> {
const newUser = entityManager.getRepository(User).create({
@ -49,72 +50,93 @@ export default class {
return user
}
async AddAddressTransaction(address: string, txHash: string, outputIndex: number, amount: number, entityManager = this.DB) {
const newAddressTransaction = entityManager.getRepository(AddressTransaction).create({
user_address: { address: address },
async AddAddressReceivingTransaction(address: UserReceivingAddress, txHash: string, outputIndex: number, amount: number, serviceFee: number, entityManager = this.DB) {
const newAddressTransaction = entityManager.getRepository(AddressReceivingTransaction).create({
user_address: address,
tx_hash: txHash,
output_index: outputIndex,
amount: amount
amount: amount,
service_fee: serviceFee
})
return entityManager.getRepository(AddressTransaction).save(newAddressTransaction)
return entityManager.getRepository(AddressReceivingTransaction).save(newAddressTransaction)
}
async AddUserAddress(userId: string, address: string, callbackUrl = "", entityManager = this.DB): Promise<UserAddress> {
const newUserAddress = entityManager.getRepository(UserAddress).create({
async AddUserAddress(userId: string, address: string, callbackUrl = "", entityManager = this.DB): Promise<UserReceivingAddress> {
const newUserAddress = entityManager.getRepository(UserReceivingAddress).create({
address,
callbackUrl,
user: { user_id: userId }
user: await this.GetUser(userId, entityManager)
})
return entityManager.getRepository(UserAddress).save(newUserAddress)
return entityManager.getRepository(UserReceivingAddress).save(newUserAddress)
}
async FlagInvoiceAsPaid(invoiceSerialId: number, amount: number, entityManager = this.DB) {
return entityManager.getRepository(UserInvoice).update(invoiceSerialId, { paid: true, settle_amount: amount })
async FlagInvoiceAsPaid(invoice: UserReceivingInvoice, amount: number, serviceFee: number, entityManager = this.DB) {
return entityManager.getRepository(UserReceivingInvoice).update(invoice.serial_id, { paid: true, settle_amount: amount, service_fee: serviceFee })
}
async AddUserInvoice(userId: string, invoice: string, callbackUrl = "", entityManager = this.DB): Promise<UserInvoice> {
const newUserInvoice = entityManager.getRepository(UserInvoice).create({
async AddUserInvoice(userId: string, invoice: string, callbackUrl = "", entityManager = this.DB): Promise<UserReceivingInvoice> {
const newUserInvoice = entityManager.getRepository(UserReceivingInvoice).create({
invoice: invoice,
callbackUrl,
user: { user_id: userId }
user: await this.GetUser(userId, entityManager)
})
return entityManager.getRepository(UserInvoice).save(newUserInvoice)
return entityManager.getRepository(UserReceivingInvoice).save(newUserInvoice)
}
async GetAddressOwner(address: string, entityManager = this.DB): Promise<UserAddress | null> {
return entityManager.getRepository(UserAddress).findOne({
async GetAddressOwner(address: string, entityManager = this.DB): Promise<UserReceivingAddress | null> {
return entityManager.getRepository(UserReceivingAddress).findOne({
where: {
address
}
})
}
async GetInvoiceOwner(paymentRequest: string, entityManager = this.DB): Promise<UserInvoice | null> {
return entityManager.getRepository(UserInvoice).findOne({
async GetInvoiceOwner(paymentRequest: string, entityManager = this.DB): Promise<UserReceivingInvoice | null> {
return entityManager.getRepository(UserReceivingInvoice).findOne({
where: {
invoice: paymentRequest
}
})
}
async AddUserPayment(userId: string, invoice: string, amount: number, entityManager = this.DB): Promise<UserPayment> {
const newPayment = entityManager.getRepository(UserPayment).create({
user: { user_id: userId },
async AddUserInvoicePayment(userId: string, invoice: string, amount: number, routingFees: number, serviceFees: number, entityManager = this.DB): Promise<UserInvoicePayment> {
const newPayment = entityManager.getRepository(UserInvoicePayment).create({
user: await this.GetUser(userId),
amount,
invoice
invoice,
routing_fees: routingFees,
service_fees: serviceFees
})
return entityManager.getRepository(UserPayment).save(newPayment)
return entityManager.getRepository(UserInvoicePayment).save(newPayment)
}
LockUser(userId: string, entityManager = this.DB) {
return entityManager.getRepository(User).update({
async AddUserTransactionPayment(userId: string, address: string, txHash: string, txOutput: number, amount: number, chainFees: number, serviceFees: number, entityManager = this.DB): Promise<UserTransactionPayment> {
const newTx = entityManager.getRepository(UserTransactionPayment).create({
user: await this.GetUser(userId),
address,
amount,
chain_fees: chainFees,
output_index: txOutput,
tx_hash: txHash,
service_fees: serviceFees
})
return entityManager.getRepository(UserTransactionPayment).save(newTx)
}
async LockUser(userId: string, entityManager = this.DB) {
const res = await entityManager.getRepository(User).update({
user_id: userId
}, { locked: true })
if (!res.affected) {
throw new Error("unaffected user lock for " + userId) // TODO: fix logs doxing
}
}
UnlockUser(userId: string, entityManager = this.DB) {
return entityManager.getRepository(User).update({
async UnlockUser(userId: string, entityManager = this.DB) {
const res = await entityManager.getRepository(User).update({
user_id: userId
}, { locked: false })
if (!res.affected) {
throw new Error("unaffected user unlock for " + userId) // TODO: fix logs doxing
}
}
async IncrementUserBalance(userId: string, increment: number, entityManager = this.DB) {
const res = await entityManager.getRepository(User).increment({