product qr
This commit is contained in:
parent
38241a3266
commit
8b7ab71078
18 changed files with 1752 additions and 1263 deletions
|
|
@ -18,6 +18,18 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [UserInfo](#UserInfo)
|
- output: [UserInfo](#UserInfo)
|
||||||
|
|
||||||
|
- AddProduct
|
||||||
|
- auth type: __User__
|
||||||
|
- input: [AddProductRequest](#AddProductRequest)
|
||||||
|
- output: [Product](#Product)
|
||||||
|
|
||||||
|
- NewProductInvoice
|
||||||
|
- auth type: __User__
|
||||||
|
- the request url __query__ can take the following string items:
|
||||||
|
- id
|
||||||
|
- This methods has an __empty__ __request__ body
|
||||||
|
- output: [NewInvoiceResponse](#NewInvoiceResponse)
|
||||||
|
|
||||||
- GetUserOperations
|
- GetUserOperations
|
||||||
- auth type: __User__
|
- auth type: __User__
|
||||||
- input: [GetUserOperationsRequest](#GetUserOperationsRequest)
|
- input: [GetUserOperationsRequest](#GetUserOperationsRequest)
|
||||||
|
|
@ -126,6 +138,22 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- This methods has an __empty__ __request__ body
|
- This methods has an __empty__ __request__ body
|
||||||
- output: [UserInfo](#UserInfo)
|
- output: [UserInfo](#UserInfo)
|
||||||
|
|
||||||
|
- AddProduct
|
||||||
|
- auth type: __User__
|
||||||
|
- http method: __post__
|
||||||
|
- http route: __/api/user/product/add__
|
||||||
|
- input: [AddProductRequest](#AddProductRequest)
|
||||||
|
- output: [Product](#Product)
|
||||||
|
|
||||||
|
- NewProductInvoice
|
||||||
|
- auth type: __User__
|
||||||
|
- http method: __get__
|
||||||
|
- http route: __/api/user/product/get/invoice__
|
||||||
|
- the request url __query__ can take the following string items:
|
||||||
|
- id
|
||||||
|
- This methods has an __empty__ __request__ body
|
||||||
|
- output: [NewInvoiceResponse](#NewInvoiceResponse)
|
||||||
|
|
||||||
- GetUserOperations
|
- GetUserOperations
|
||||||
- auth type: __User__
|
- auth type: __User__
|
||||||
- http method: __post__
|
- http method: __post__
|
||||||
|
|
@ -232,15 +260,78 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
## Messages
|
## Messages
|
||||||
### The content of requests and response from the methods
|
### The content of requests and response from the methods
|
||||||
|
|
||||||
|
### OpenChannelResponse
|
||||||
|
- __channelId__: _string_
|
||||||
|
|
||||||
|
### UserInfo
|
||||||
|
- __userId__: _string_
|
||||||
|
- __balance__: _number_
|
||||||
|
|
||||||
|
### GetUserOperationsRequest
|
||||||
|
- __latestIncomingInvoice__: _number_
|
||||||
|
- __latestOutgoingInvoice__: _number_
|
||||||
|
- __latestIncomingTx__: _number_
|
||||||
|
- __latestOutgoingTx__: _number_
|
||||||
|
|
||||||
|
### AddProductRequest
|
||||||
|
- __name__: _string_
|
||||||
|
- __price_sats__: _number_
|
||||||
|
|
||||||
|
### Product
|
||||||
|
- __id__: _string_
|
||||||
|
- __name__: _string_
|
||||||
|
- __price_sats__: _number_
|
||||||
|
|
||||||
|
### EncryptionExchangeRequest
|
||||||
|
- __publicKey__: _string_
|
||||||
|
- __deviceId__: _string_
|
||||||
|
|
||||||
|
### NewInvoiceRequest
|
||||||
|
- __amountSats__: _number_
|
||||||
|
- __memo__: _string_
|
||||||
|
|
||||||
|
### PayInvoiceResponse
|
||||||
|
- __preimage__: _string_
|
||||||
|
|
||||||
|
### HandleLnurlPayResponse
|
||||||
|
- __pr__: _string_
|
||||||
|
- __routes__: ARRAY of: _[Empty](#Empty)_
|
||||||
|
|
||||||
|
### AuthUserRequest
|
||||||
|
- __name__: _string_
|
||||||
|
- __secret__: _string_
|
||||||
|
|
||||||
|
### UserOperations
|
||||||
|
- __fromIndex__: _number_
|
||||||
|
- __toIndex__: _number_
|
||||||
|
- __operations__: ARRAY of: _[UserOperation](#UserOperation)_
|
||||||
|
|
||||||
|
### PayAddressRequest
|
||||||
|
- __address__: _string_
|
||||||
|
- __amoutSats__: _number_
|
||||||
|
- __targetConf__: _number_
|
||||||
|
|
||||||
|
### OpenChannelRequest
|
||||||
|
- __destination__: _string_
|
||||||
|
- __fundingAmount__: _number_
|
||||||
|
- __pushAmount__: _number_
|
||||||
|
- __closeAddress__: _string_
|
||||||
|
|
||||||
|
### LnurlLinkResponse
|
||||||
|
- __lnurl__: _string_
|
||||||
|
- __k1__: _string_
|
||||||
|
|
||||||
### Empty
|
### Empty
|
||||||
|
|
||||||
|
### NewInvoiceResponse
|
||||||
|
- __invoice__: _string_
|
||||||
|
|
||||||
### DecodeInvoiceRequest
|
### DecodeInvoiceRequest
|
||||||
- __invoice__: _string_
|
- __invoice__: _string_
|
||||||
|
|
||||||
### AddUserRequest
|
### AuthUserResponse
|
||||||
- __callbackUrl__: _string_
|
- __userId__: _string_
|
||||||
- __name__: _string_
|
- __authToken__: _string_
|
||||||
- __secret__: _string_
|
|
||||||
|
|
||||||
### GetUserOperationsResponse
|
### GetUserOperationsResponse
|
||||||
- __latestOutgoingInvoiceOperations__: _[UserOperations](#UserOperations)_
|
- __latestOutgoingInvoiceOperations__: _[UserOperations](#UserOperations)_
|
||||||
|
|
@ -248,8 +339,15 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __latestOutgoingTxOperations__: _[UserOperations](#UserOperations)_
|
- __latestOutgoingTxOperations__: _[UserOperations](#UserOperations)_
|
||||||
- __latestIncomingTxOperations__: _[UserOperations](#UserOperations)_
|
- __latestIncomingTxOperations__: _[UserOperations](#UserOperations)_
|
||||||
|
|
||||||
### PayAddressResponse
|
### LndGetInfoRequest
|
||||||
- __txId__: _string_
|
- __nodeId__: _number_
|
||||||
|
|
||||||
|
### LndGetInfoResponse
|
||||||
|
- __alias__: _string_
|
||||||
|
|
||||||
|
### AddUserResponse
|
||||||
|
- __userId__: _string_
|
||||||
|
- __authToken__: _string_
|
||||||
|
|
||||||
### LnurlWithdrawInfoResponse
|
### LnurlWithdrawInfoResponse
|
||||||
- __tag__: _string_
|
- __tag__: _string_
|
||||||
|
|
@ -261,21 +359,13 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __balanceCheck__: _string_
|
- __balanceCheck__: _string_
|
||||||
- __payLink__: _string_
|
- __payLink__: _string_
|
||||||
|
|
||||||
### UserInfo
|
### GetProductBuyLinkResponse
|
||||||
- __userId__: _string_
|
- __link__: _string_
|
||||||
- __balance__: _number_
|
|
||||||
|
|
||||||
### NewAddressResponse
|
### AddUserRequest
|
||||||
- __address__: _string_
|
- __callbackUrl__: _string_
|
||||||
|
- __name__: _string_
|
||||||
### PayAddressRequest
|
- __secret__: _string_
|
||||||
- __address__: _string_
|
|
||||||
- __amoutSats__: _number_
|
|
||||||
- __targetConf__: _number_
|
|
||||||
|
|
||||||
### HandleLnurlPayResponse
|
|
||||||
- __pr__: _string_
|
|
||||||
- __routes__: ARRAY of: _[Empty](#Empty)_
|
|
||||||
|
|
||||||
### UserOperation
|
### UserOperation
|
||||||
- __paidAtUnix__: _number_
|
- __paidAtUnix__: _number_
|
||||||
|
|
@ -283,25 +373,21 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __inbound__: _boolean_
|
- __inbound__: _boolean_
|
||||||
- __amount__: _number_
|
- __amount__: _number_
|
||||||
|
|
||||||
### DecodeInvoiceResponse
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### AddUserResponse
|
|
||||||
- __userId__: _string_
|
|
||||||
- __authToken__: _string_
|
|
||||||
|
|
||||||
### NewInvoiceResponse
|
|
||||||
- __invoice__: _string_
|
|
||||||
|
|
||||||
### PayInvoiceResponse
|
|
||||||
- __preimage__: _string_
|
|
||||||
|
|
||||||
### NewAddressRequest
|
### NewAddressRequest
|
||||||
- __addressType__: _[AddressType](#AddressType)_
|
- __addressType__: _[AddressType](#AddressType)_
|
||||||
|
|
||||||
### LnurlLinkResponse
|
### NewAddressResponse
|
||||||
- __lnurl__: _string_
|
- __address__: _string_
|
||||||
- __k1__: _string_
|
|
||||||
|
### PayInvoiceRequest
|
||||||
|
- __invoice__: _string_
|
||||||
|
- __amount__: _number_
|
||||||
|
|
||||||
|
### PayAddressResponse
|
||||||
|
- __txId__: _string_
|
||||||
|
|
||||||
|
### DecodeInvoiceResponse
|
||||||
|
- __amount__: _number_
|
||||||
|
|
||||||
### LnurlPayInfoResponse
|
### LnurlPayInfoResponse
|
||||||
- __tag__: _string_
|
- __tag__: _string_
|
||||||
|
|
@ -309,52 +395,6 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
- __maxSendable__: _number_
|
- __maxSendable__: _number_
|
||||||
- __minSendable__: _number_
|
- __minSendable__: _number_
|
||||||
- __metadata__: _string_
|
- __metadata__: _string_
|
||||||
|
|
||||||
### GetUserOperationsRequest
|
|
||||||
- __latestIncomingInvoice__: _number_
|
|
||||||
- __latestOutgoingInvoice__: _number_
|
|
||||||
- __latestIncomingTx__: _number_
|
|
||||||
- __latestOutgoingTx__: _number_
|
|
||||||
|
|
||||||
### AuthUserResponse
|
|
||||||
- __userId__: _string_
|
|
||||||
- __authToken__: _string_
|
|
||||||
|
|
||||||
### EncryptionExchangeRequest
|
|
||||||
- __publicKey__: _string_
|
|
||||||
- __deviceId__: _string_
|
|
||||||
|
|
||||||
### LndGetInfoRequest
|
|
||||||
- __nodeId__: _number_
|
|
||||||
|
|
||||||
### LndGetInfoResponse
|
|
||||||
- __alias__: _string_
|
|
||||||
|
|
||||||
### PayInvoiceRequest
|
|
||||||
- __invoice__: _string_
|
|
||||||
- __amount__: _number_
|
|
||||||
|
|
||||||
### OpenChannelRequest
|
|
||||||
- __destination__: _string_
|
|
||||||
- __fundingAmount__: _number_
|
|
||||||
- __pushAmount__: _number_
|
|
||||||
- __closeAddress__: _string_
|
|
||||||
|
|
||||||
### OpenChannelResponse
|
|
||||||
- __channelId__: _string_
|
|
||||||
|
|
||||||
### AuthUserRequest
|
|
||||||
- __name__: _string_
|
|
||||||
- __secret__: _string_
|
|
||||||
|
|
||||||
### UserOperations
|
|
||||||
- __fromIndex__: _number_
|
|
||||||
- __toIndex__: _number_
|
|
||||||
- __operations__: ARRAY of: _[UserOperation](#UserOperation)_
|
|
||||||
|
|
||||||
### NewInvoiceRequest
|
|
||||||
- __amountSats__: _number_
|
|
||||||
- __memo__: _string_
|
|
||||||
## Enums
|
## Enums
|
||||||
### The enumerators used in the messages
|
### The enumerators used in the messages
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -105,6 +105,31 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
|
||||||
res.json({status: 'OK', ...response})
|
res.json({status: 'OK', ...response})
|
||||||
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e }
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e }
|
||||||
})
|
})
|
||||||
|
if (!opts.allowNotImplementedMethods && !methods.AddProduct) throw new Error('method: AddProduct is not implemented')
|
||||||
|
app.post('/api/user/product/add', async (req, res) => {
|
||||||
|
try {
|
||||||
|
if (!methods.AddProduct) throw new Error('method: AddProduct is not implemented')
|
||||||
|
const authContext = await opts.UserAuthGuard(req.headers['authorization'])
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.AddProductRequestValidate(request)
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger)
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.AddProduct({ ...authContext, ...query, ...params }, request)
|
||||||
|
res.json({status: 'OK', ...response})
|
||||||
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e }
|
||||||
|
})
|
||||||
|
if (!opts.allowNotImplementedMethods && !methods.NewProductInvoice) throw new Error('method: NewProductInvoice is not implemented')
|
||||||
|
app.get('/api/user/product/get/invoice', async (req, res) => {
|
||||||
|
try {
|
||||||
|
if (!methods.NewProductInvoice) throw new Error('method: NewProductInvoice is not implemented')
|
||||||
|
const authContext = await opts.UserAuthGuard(req.headers['authorization'])
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.NewProductInvoice({ ...authContext, ...query, ...params })
|
||||||
|
res.json({status: 'OK', ...response})
|
||||||
|
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e }
|
||||||
|
})
|
||||||
if (!opts.allowNotImplementedMethods && !methods.GetUserOperations) throw new Error('method: GetUserOperations is not implemented')
|
if (!opts.allowNotImplementedMethods && !methods.GetUserOperations) throw new Error('method: GetUserOperations is not implemented')
|
||||||
app.post('/api/user/operations', async (req, res) => {
|
app.post('/api/user/operations', async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,36 @@ export default (params: ClientParams) => ({
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
AddProduct: async (request: Types.AddProductRequest): Promise<ResultError | ({ status: 'OK' }& Types.Product)> => {
|
||||||
|
const auth = await params.retrieveUserAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
||||||
|
let finalRoute = '/api/user/product/add'
|
||||||
|
const { data } = await axios.post(params.baseUrl + finalRoute, request, { headers: { 'authorization': auth } })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.ProductValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
NewProductInvoice: async (query: Types.NewProductInvoice_Query): Promise<ResultError | ({ status: 'OK' }& Types.NewInvoiceResponse)> => {
|
||||||
|
const auth = await params.retrieveUserAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
||||||
|
let finalRoute = '/api/user/product/get/invoice'
|
||||||
|
const q = (new URLSearchParams(query)).toString()
|
||||||
|
finalRoute = finalRoute + (q === '' ? '' : '?' + q)
|
||||||
|
const { data } = await axios.get(params.baseUrl + finalRoute, { headers: { 'authorization': auth } })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.NewInvoiceResponseValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
GetUserOperations: async (request: Types.GetUserOperationsRequest): Promise<ResultError | ({ status: 'OK' }& Types.GetUserOperationsResponse)> => {
|
GetUserOperations: async (request: Types.GetUserOperationsRequest): Promise<ResultError | ({ status: 'OK' }& Types.GetUserOperationsResponse)> => {
|
||||||
const auth = await params.retrieveUserAuth()
|
const auth = await params.retrieveUserAuth()
|
||||||
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
if (auth === null) throw new Error('retrieveUserAuth() returned null')
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,36 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
|
||||||
}
|
}
|
||||||
return { status: 'ERROR', reason: 'invalid response' }
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
},
|
},
|
||||||
|
AddProduct: async (request: Types.AddProductRequest): Promise<ResultError | ({ status: 'OK' }& Types.Product)> => {
|
||||||
|
const auth = await params.retrieveNostrUserAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.body = request
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'AddProduct',authIdentifier:auth, ...nostrRequest })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.ProductValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
|
NewProductInvoice: async (query: Types.NewProductInvoice_Query): Promise<ResultError | ({ status: 'OK' }& Types.NewInvoiceResponse)> => {
|
||||||
|
const auth = await params.retrieveNostrUserAuth()
|
||||||
|
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||||
|
const nostrRequest: NostrRequest = {}
|
||||||
|
nostrRequest.query = query
|
||||||
|
const data = await send(params.pubDestination, {rpcName:'NewProductInvoice',authIdentifier:auth, ...nostrRequest })
|
||||||
|
if (data.status === 'ERROR' && typeof data.reason === 'string') return data
|
||||||
|
if (data.status === 'OK') {
|
||||||
|
const result = data
|
||||||
|
if(!params.checkResult) return { status: 'OK', ...result }
|
||||||
|
const error = Types.NewInvoiceResponseValidate(result)
|
||||||
|
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
|
||||||
|
}
|
||||||
|
return { status: 'ERROR', reason: 'invalid response' }
|
||||||
|
},
|
||||||
GetUserOperations: async (request: Types.GetUserOperationsRequest): Promise<ResultError | ({ status: 'OK' }& Types.GetUserOperationsResponse)> => {
|
GetUserOperations: async (request: Types.GetUserOperationsRequest): Promise<ResultError | ({ status: 'OK' }& Types.GetUserOperationsResponse)> => {
|
||||||
const auth = await params.retrieveNostrUserAuth()
|
const auth = await params.retrieveNostrUserAuth()
|
||||||
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,29 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
|
||||||
res({status: 'OK', ...response})
|
res({status: 'OK', ...response})
|
||||||
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e }
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e }
|
||||||
break
|
break
|
||||||
|
case 'AddProduct':
|
||||||
|
try {
|
||||||
|
if (!methods.AddProduct) throw new Error('method: AddProduct is not implemented')
|
||||||
|
const authContext = await opts.NostrUserAuthGuard(req.authIdentifier)
|
||||||
|
const request = req.body
|
||||||
|
const error = Types.AddProductRequestValidate(request)
|
||||||
|
if (error !== null) return logErrorAndReturnResponse(error, 'invalid request body', res, logger)
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.AddProduct({ ...authContext, ...query, ...params }, request)
|
||||||
|
res({status: 'OK', ...response})
|
||||||
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e }
|
||||||
|
break
|
||||||
|
case 'NewProductInvoice':
|
||||||
|
try {
|
||||||
|
if (!methods.NewProductInvoice) throw new Error('method: NewProductInvoice is not implemented')
|
||||||
|
const authContext = await opts.NostrUserAuthGuard(req.authIdentifier)
|
||||||
|
const query = req.query
|
||||||
|
const params = req.params
|
||||||
|
const response = await methods.NewProductInvoice({ ...authContext, ...query, ...params })
|
||||||
|
res({status: 'OK', ...response})
|
||||||
|
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger); if (opts.throwErrors) throw e }
|
||||||
|
break
|
||||||
case 'GetUserOperations':
|
case 'GetUserOperations':
|
||||||
try {
|
try {
|
||||||
if (!methods.GetUserOperations) throw new Error('method: GetUserOperations is not implemented')
|
if (!methods.GetUserOperations) throw new Error('method: GetUserOperations is not implemented')
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -78,7 +78,6 @@ service LightningPub {
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
option (http_route) = "/api/lnd/getinfo";
|
option (http_route) = "/api/lnd/getinfo";
|
||||||
};
|
};
|
||||||
|
|
||||||
rpc AddUser(structs.AddUserRequest)returns (structs.AddUserResponse){
|
rpc AddUser(structs.AddUserRequest)returns (structs.AddUserResponse){
|
||||||
option (auth_type) = "Guest";
|
option (auth_type) = "Guest";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
|
|
@ -96,6 +95,19 @@ service LightningPub {
|
||||||
option (nostr) = true;
|
option (nostr) = true;
|
||||||
}
|
}
|
||||||
// USER
|
// USER
|
||||||
|
rpc AddProduct(structs.AddProductRequest) returns (structs.Product){
|
||||||
|
option (auth_type) = "User";
|
||||||
|
option (http_method) = "post";
|
||||||
|
option (http_route) = "/api/user/product/add";
|
||||||
|
option (nostr) = true;
|
||||||
|
};
|
||||||
|
rpc NewProductInvoice(structs.Empty) returns (structs.NewInvoiceResponse){
|
||||||
|
option (auth_type) = "User";
|
||||||
|
option (http_method) = "get";
|
||||||
|
option (http_route) = "/api/user/product/get/invoice";
|
||||||
|
option (query) = {items: ["id"]};
|
||||||
|
option (nostr) = true;
|
||||||
|
};
|
||||||
rpc GetUserOperations(structs.GetUserOperationsRequest) returns (structs.GetUserOperationsResponse) {
|
rpc GetUserOperations(structs.GetUserOperationsRequest) returns (structs.GetUserOperationsResponse) {
|
||||||
option (auth_type) = "User";
|
option (auth_type) = "User";
|
||||||
option (http_method) = "post";
|
option (http_method) = "post";
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ message NewInvoiceResponse{
|
||||||
string invoice = 1;
|
string invoice = 1;
|
||||||
}
|
}
|
||||||
message DecodeInvoiceRequest{
|
message DecodeInvoiceRequest{
|
||||||
string invoice=1;
|
string invoice = 1;
|
||||||
}
|
}
|
||||||
message DecodeInvoiceResponse{
|
message DecodeInvoiceResponse{
|
||||||
int64 amount=1;
|
int64 amount=1;
|
||||||
|
|
@ -153,3 +153,18 @@ message GetUserOperationsResponse{
|
||||||
UserOperations latestOutgoingTxOperations=3;
|
UserOperations latestOutgoingTxOperations=3;
|
||||||
UserOperations latestIncomingTxOperations=4;
|
UserOperations latestIncomingTxOperations=4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AddProductRequest {
|
||||||
|
string name = 1;
|
||||||
|
int64 price_sats = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Product {
|
||||||
|
string id = 1;
|
||||||
|
string name = 2;
|
||||||
|
int64 price_sats = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetProductBuyLinkResponse {
|
||||||
|
string link = 1;
|
||||||
|
}
|
||||||
|
|
@ -5,17 +5,8 @@ import * as Types from '../../../proto/autogenerated/ts/types.js'
|
||||||
import LND, { AddressPaidCb, InvoicePaidCb, LndSettings, LoadLndSettingsFromEnv } from '../lnd/index.js'
|
import LND, { AddressPaidCb, InvoicePaidCb, LndSettings, LoadLndSettingsFromEnv } from '../lnd/index.js'
|
||||||
import { EnvMustBeInteger, EnvMustBeNonEmptyString } from '../helpers/envParser.js'
|
import { EnvMustBeInteger, EnvMustBeNonEmptyString } from '../helpers/envParser.js'
|
||||||
import { UserReceivingInvoice } from '../storage/entity/UserReceivingInvoice.js'
|
import { UserReceivingInvoice } from '../storage/entity/UserReceivingInvoice.js'
|
||||||
import { Type } from 'typescript'
|
import ProductManager from './product.js'
|
||||||
export type MainSettings = {
|
import { MainSettings } from './settings.js'
|
||||||
storageSettings: StorageSettings,
|
|
||||||
lndSettings: LndSettings,
|
|
||||||
jwtSecret: string
|
|
||||||
incomingTxFee: number
|
|
||||||
outgoingTxFee: number
|
|
||||||
incomingInvoiceFee: number
|
|
||||||
outgoingInvoiceFee: number
|
|
||||||
serviceUrl: string
|
|
||||||
}
|
|
||||||
export const LoadMainSettingsFromEnv = (test = false): MainSettings => {
|
export const LoadMainSettingsFromEnv = (test = false): MainSettings => {
|
||||||
return {
|
return {
|
||||||
lndSettings: LoadLndSettingsFromEnv(test),
|
lndSettings: LoadLndSettingsFromEnv(test),
|
||||||
|
|
@ -47,10 +38,12 @@ export default class {
|
||||||
lnd: LND
|
lnd: LND
|
||||||
settings: MainSettings
|
settings: MainSettings
|
||||||
userOperationsSub: UserOperationsSub | null = null
|
userOperationsSub: UserOperationsSub | null = null
|
||||||
|
productManager: ProductManager
|
||||||
constructor(settings: MainSettings) {
|
constructor(settings: MainSettings) {
|
||||||
this.settings = settings
|
this.settings = settings
|
||||||
this.storage = new Storage(settings.storageSettings)
|
this.storage = new Storage(settings.storageSettings)
|
||||||
this.lnd = new LND(settings.lndSettings, this.addressPaidCb, this.invoicePaidCb)
|
this.lnd = new LND(settings.lndSettings, this.addressPaidCb, this.invoicePaidCb)
|
||||||
|
this.productManager = new ProductManager(this.storage, this.lnd, this.settings)
|
||||||
}
|
}
|
||||||
getServiceFee(action: Types.UserOperationType, amount: number): number {
|
getServiceFee(action: Types.UserOperationType, amount: number): number {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
|
@ -119,8 +112,9 @@ export default class {
|
||||||
}
|
}
|
||||||
|
|
||||||
async NewInvoice(userId: string, req: Types.NewInvoiceRequest): Promise<Types.NewInvoiceResponse> {
|
async NewInvoice(userId: string, req: Types.NewInvoiceRequest): Promise<Types.NewInvoiceResponse> {
|
||||||
|
const user = await this.storage.GetUser(userId)
|
||||||
const res = await this.lnd.NewInvoice(req.amountSats, req.memo)
|
const res = await this.lnd.NewInvoice(req.amountSats, req.memo)
|
||||||
const userInvoice = await this.storage.AddUserInvoice(userId, res.paymentRequest)
|
const userInvoice = await this.storage.AddUserInvoice(user, res.paymentRequest)
|
||||||
return {
|
return {
|
||||||
invoice: userInvoice.invoice
|
invoice: userInvoice.invoice
|
||||||
}
|
}
|
||||||
|
|
|
||||||
36
src/services/main/product.ts
Normal file
36
src/services/main/product.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import Storage from '../storage/index.js'
|
||||||
|
import * as Types from '../../../proto/autogenerated/ts/types.js'
|
||||||
|
import LND from '../lnd/index.js'
|
||||||
|
|
||||||
|
import { MainSettings } from './settings.js'
|
||||||
|
|
||||||
|
export default class {
|
||||||
|
|
||||||
|
storage: Storage
|
||||||
|
settings: MainSettings
|
||||||
|
lnd: LND
|
||||||
|
constructor(storage: Storage, lnd: LND, settings: MainSettings) {
|
||||||
|
this.storage = storage
|
||||||
|
this.settings = settings
|
||||||
|
this.lnd = lnd
|
||||||
|
}
|
||||||
|
|
||||||
|
async AddProduct(userId: string, req: Types.AddProductRequest): Promise<Types.Product> {
|
||||||
|
const user = await this.storage.GetUser(userId)
|
||||||
|
const newProduct = await this.storage.productStorage.AddProduct(req.name, req.price_sats, user)
|
||||||
|
return {
|
||||||
|
id: newProduct.product_id,
|
||||||
|
name: newProduct.name,
|
||||||
|
price_sats: newProduct.price_sats,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async NewProductInvoice(id: string): Promise<Types.NewInvoiceResponse> {
|
||||||
|
const product = await this.storage.productStorage.GetProduct(id)
|
||||||
|
const newInvoice = await this.lnd.NewInvoice(product.price_sats, product.name)
|
||||||
|
await this.storage.AddUserInvoice(product.owner, newInvoice.paymentRequest, product)
|
||||||
|
return {
|
||||||
|
invoice: newInvoice.paymentRequest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/services/main/settings.ts
Normal file
12
src/services/main/settings.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { StorageSettings } from '../storage/index.js'
|
||||||
|
import { LndSettings } from '../lnd/index.js'
|
||||||
|
export type MainSettings = {
|
||||||
|
storageSettings: StorageSettings,
|
||||||
|
lndSettings: LndSettings,
|
||||||
|
jwtSecret: string
|
||||||
|
incomingTxFee: number
|
||||||
|
outgoingTxFee: number
|
||||||
|
incomingInvoiceFee: number
|
||||||
|
outgoingInvoiceFee: number
|
||||||
|
serviceUrl: string
|
||||||
|
}
|
||||||
|
|
@ -90,8 +90,17 @@ export default (mainHandler: Main): Types.ServerMethods => {
|
||||||
}
|
}
|
||||||
return mainHandler.HandleLnurlPay(ctx.k1, +ctx.amount)
|
return mainHandler.HandleLnurlPay(ctx.k1, +ctx.amount)
|
||||||
},
|
},
|
||||||
|
AddProduct: async (ctx, req) => {
|
||||||
|
return mainHandler.productManager.AddProduct(ctx.user_id, req)
|
||||||
|
},
|
||||||
|
NewProductInvoice: async (ctx) => {
|
||||||
|
if (!ctx.id) {
|
||||||
|
throw new Error("product id must be non empty")
|
||||||
|
}
|
||||||
|
return mainHandler.productManager.NewProductInvoice(ctx.id)
|
||||||
|
},
|
||||||
GetLNURLChannelLink: async (ctx) => {
|
GetLNURLChannelLink: async (ctx) => {
|
||||||
throw new Error("unimplemented")
|
throw new Error("unimplemented")
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,6 +10,7 @@ import { UserTransactionPayment } from "./entity/UserTransactionPayment.js"
|
||||||
import { UserNostrAuth } from "./entity/UserNostrAuth.js"
|
import { UserNostrAuth } from "./entity/UserNostrAuth.js"
|
||||||
import { UserBasicAuth } from "./entity/UserBasicAuth.js"
|
import { UserBasicAuth } from "./entity/UserBasicAuth.js"
|
||||||
import { UserEphemeralKey } from "./entity/UserEphemeralKey.js"
|
import { UserEphemeralKey } from "./entity/UserEphemeralKey.js"
|
||||||
|
import { Product } from "./entity/Product.js"
|
||||||
export type DbSettings = {
|
export type DbSettings = {
|
||||||
databaseFile: string
|
databaseFile: string
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +22,7 @@ export default async (settings: DbSettings) => {
|
||||||
type: "sqlite",
|
type: "sqlite",
|
||||||
database: settings.databaseFile,
|
database: settings.databaseFile,
|
||||||
//logging: true,
|
//logging: true,
|
||||||
entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment, UserNostrAuth, UserBasicAuth, UserEphemeralKey],
|
entities: [User, UserReceivingInvoice, UserReceivingAddress, AddressReceivingTransaction, UserInvoicePayment, UserTransactionPayment, UserNostrAuth, UserBasicAuth, UserEphemeralKey, Product],
|
||||||
synchronize: true
|
synchronize: true
|
||||||
}).initialize()
|
}).initialize()
|
||||||
}
|
}
|
||||||
18
src/services/storage/entity/Product.ts
Normal file
18
src/services/storage/entity/Product.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm"
|
||||||
|
import { User } from "./User.js"
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class Product {
|
||||||
|
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
product_id: string
|
||||||
|
|
||||||
|
@ManyToOne(type => User, { eager: true })
|
||||||
|
owner: User
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
name: string
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
price_sats: number
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn } from "typeorm"
|
import { Entity, PrimaryGeneratedColumn, Column, Index, Check, ManyToOne, JoinColumn } from "typeorm"
|
||||||
|
import { Product } from "./Product.js"
|
||||||
import { User } from "./User.js"
|
import { User } from "./User.js"
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
|
|
@ -26,4 +27,7 @@ export class UserReceivingInvoice {
|
||||||
|
|
||||||
@Column({ default: 0 })
|
@Column({ default: 0 })
|
||||||
service_fee: number
|
service_fee: number
|
||||||
|
|
||||||
|
@ManyToOne(type => Product, { eager: true })
|
||||||
|
product: Product | null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ import { UserTransactionPayment } from "./entity/UserTransactionPayment.js";
|
||||||
import { UserNostrAuth } from "./entity/UserNostrAuth.js";
|
import { UserNostrAuth } from "./entity/UserNostrAuth.js";
|
||||||
import { UserBasicAuth } from "./entity/UserBasicAuth.js";
|
import { UserBasicAuth } from "./entity/UserBasicAuth.js";
|
||||||
import { EphemeralKeyType, UserEphemeralKey } from "./entity/UserEphemeralKey.js";
|
import { EphemeralKeyType, UserEphemeralKey } from "./entity/UserEphemeralKey.js";
|
||||||
|
import ProductStorage from './productStorage.js'
|
||||||
|
import { Product } from "./entity/Product.js";
|
||||||
export type StorageSettings = {
|
export type StorageSettings = {
|
||||||
dbSettings: DbSettings
|
dbSettings: DbSettings
|
||||||
}
|
}
|
||||||
|
|
@ -20,11 +22,13 @@ export const LoadStorageSettingsFromEnv = (test = false): StorageSettings => {
|
||||||
export default class {
|
export default class {
|
||||||
DB: DataSource | EntityManager
|
DB: DataSource | EntityManager
|
||||||
settings: StorageSettings
|
settings: StorageSettings
|
||||||
|
productStorage: ProductStorage
|
||||||
constructor(settings: StorageSettings) {
|
constructor(settings: StorageSettings) {
|
||||||
this.settings = settings
|
this.settings = settings
|
||||||
}
|
}
|
||||||
async Connect() {
|
async Connect() {
|
||||||
this.DB = await NewDB(this.settings.dbSettings)
|
this.DB = await NewDB(this.settings.dbSettings)
|
||||||
|
this.productStorage = new ProductStorage(this.DB)
|
||||||
}
|
}
|
||||||
StartTransaction(exec: (entityManager: EntityManager) => Promise<void>) {
|
StartTransaction(exec: (entityManager: EntityManager) => Promise<void>) {
|
||||||
return this.DB.transaction(exec)
|
return this.DB.transaction(exec)
|
||||||
|
|
@ -134,11 +138,12 @@ export default class {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async AddUserInvoice(userId: string, invoice: string, callbackUrl = "", entityManager = this.DB): Promise<UserReceivingInvoice> {
|
async AddUserInvoice(user: User, invoice: string, product?: Product, callbackUrl = "", entityManager = this.DB): Promise<UserReceivingInvoice> {
|
||||||
const newUserInvoice = entityManager.getRepository(UserReceivingInvoice).create({
|
const newUserInvoice = entityManager.getRepository(UserReceivingInvoice).create({
|
||||||
invoice: invoice,
|
invoice: invoice,
|
||||||
callbackUrl,
|
callbackUrl,
|
||||||
user: await this.GetUser(userId, entityManager)
|
user: user,
|
||||||
|
product: product
|
||||||
})
|
})
|
||||||
return entityManager.getRepository(UserReceivingInvoice).save(newUserInvoice)
|
return entityManager.getRepository(UserReceivingInvoice).save(newUserInvoice)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
23
src/services/storage/productStorage.ts
Normal file
23
src/services/storage/productStorage.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { DataSource, EntityManager } from "typeorm"
|
||||||
|
import { Product } from "./entity/Product.js"
|
||||||
|
import { User } from "./entity/User.js"
|
||||||
|
export default class {
|
||||||
|
DB: DataSource | EntityManager
|
||||||
|
constructor(DB: DataSource | EntityManager) {
|
||||||
|
this.DB = DB
|
||||||
|
}
|
||||||
|
async AddProduct(name: string, priceSats: number, user: User, entityManager = this.DB): Promise<Product> {
|
||||||
|
const newProduct = entityManager.getRepository(Product).create({
|
||||||
|
name: name, price_sats: priceSats, owner: user
|
||||||
|
})
|
||||||
|
return entityManager.getRepository(Product).save(newProduct)
|
||||||
|
}
|
||||||
|
|
||||||
|
async GetProduct(id: string, entityManager = this.DB): Promise<Product> {
|
||||||
|
const product = await entityManager.getRepository(Product).findOne({ where: { product_id: id } })
|
||||||
|
if (!product) {
|
||||||
|
throw new Error("product not found")
|
||||||
|
}
|
||||||
|
return product
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue