Merge pull request #835 from shocknet/clink-exp-and-desc
clink exp and desc
This commit is contained in:
commit
f3d7041bd3
10 changed files with 31 additions and 16 deletions
8
package-lock.json
generated
8
package-lock.json
generated
|
|
@ -13,7 +13,7 @@
|
||||||
"@protobuf-ts/grpc-transport": "^2.9.4",
|
"@protobuf-ts/grpc-transport": "^2.9.4",
|
||||||
"@protobuf-ts/plugin": "^2.5.0",
|
"@protobuf-ts/plugin": "^2.5.0",
|
||||||
"@protobuf-ts/runtime": "^2.5.0",
|
"@protobuf-ts/runtime": "^2.5.0",
|
||||||
"@shocknet/clink-sdk": "^1.3.1",
|
"@shocknet/clink-sdk": "^1.4.0",
|
||||||
"@stablelib/xchacha20": "^1.0.1",
|
"@stablelib/xchacha20": "^1.0.1",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/node": "^17.0.31",
|
"@types/node": "^17.0.31",
|
||||||
|
|
@ -686,9 +686,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@shocknet/clink-sdk": {
|
"node_modules/@shocknet/clink-sdk": {
|
||||||
"version": "1.3.1",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@shocknet/clink-sdk/-/clink-sdk-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@shocknet/clink-sdk/-/clink-sdk-1.4.0.tgz",
|
||||||
"integrity": "sha512-jQtiB6jHN8ApuyTjmf6xB1b+53O2tSkAUsIQtctEopJL3xq4xLgmIKce+tTefr6BYQJtzSd2lAiumiT4KLxSrw==",
|
"integrity": "sha512-J0PWE8CVRJrFF1Zi/UhChhvOrlmDj7LRJTpR6rbHlFPmjC5TGIW6891tVWWv+JmUR0jzez9QHFrHnc8DgIJYCQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@noble/hashes": "^1.8.0",
|
"@noble/hashes": "^1.8.0",
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
"@protobuf-ts/grpc-transport": "^2.9.4",
|
"@protobuf-ts/grpc-transport": "^2.9.4",
|
||||||
"@protobuf-ts/plugin": "^2.5.0",
|
"@protobuf-ts/plugin": "^2.5.0",
|
||||||
"@protobuf-ts/runtime": "^2.5.0",
|
"@protobuf-ts/runtime": "^2.5.0",
|
||||||
"@shocknet/clink-sdk": "^1.3.1",
|
"@shocknet/clink-sdk": "^1.4.0",
|
||||||
"@stablelib/xchacha20": "^1.0.1",
|
"@stablelib/xchacha20": "^1.0.1",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/node": "^17.0.31",
|
"@types/node": "^17.0.31",
|
||||||
|
|
|
||||||
|
|
@ -1393,6 +1393,7 @@ The nostr server will send back a message response, and inside the body there wi
|
||||||
|
|
||||||
### NewInvoiceRequest
|
### NewInvoiceRequest
|
||||||
- __amountSats__: _number_
|
- __amountSats__: _number_
|
||||||
|
- __expiry__: _number_ *this field is optional
|
||||||
- __memo__: _string_
|
- __memo__: _string_
|
||||||
- __zap__: _string_ *this field is optional
|
- __zap__: _string_ *this field is optional
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -466,6 +466,7 @@ type NewAddressResponse struct {
|
||||||
}
|
}
|
||||||
type NewInvoiceRequest struct {
|
type NewInvoiceRequest struct {
|
||||||
Amountsats int64 `json:"amountSats"`
|
Amountsats int64 `json:"amountSats"`
|
||||||
|
Expiry int64 `json:"expiry"`
|
||||||
Memo string `json:"memo"`
|
Memo string `json:"memo"`
|
||||||
Zap string `json:"zap"`
|
Zap string `json:"zap"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2743,14 +2743,16 @@ export const NewAddressResponseValidate = (o?: NewAddressResponse, opts: NewAddr
|
||||||
|
|
||||||
export type NewInvoiceRequest = {
|
export type NewInvoiceRequest = {
|
||||||
amountSats: number
|
amountSats: number
|
||||||
|
expiry?: number
|
||||||
memo: string
|
memo: string
|
||||||
zap?: string
|
zap?: string
|
||||||
}
|
}
|
||||||
export type NewInvoiceRequestOptionalField = 'zap'
|
export type NewInvoiceRequestOptionalField = 'expiry' | 'zap'
|
||||||
export const NewInvoiceRequestOptionalFields: NewInvoiceRequestOptionalField[] = ['zap']
|
export const NewInvoiceRequestOptionalFields: NewInvoiceRequestOptionalField[] = ['expiry', 'zap']
|
||||||
export type NewInvoiceRequestOptions = OptionsBaseMessage & {
|
export type NewInvoiceRequestOptions = OptionsBaseMessage & {
|
||||||
checkOptionalsAreSet?: NewInvoiceRequestOptionalField[]
|
checkOptionalsAreSet?: NewInvoiceRequestOptionalField[]
|
||||||
amountSats_CustomCheck?: (v: number) => boolean
|
amountSats_CustomCheck?: (v: number) => boolean
|
||||||
|
expiry_CustomCheck?: (v?: number) => boolean
|
||||||
memo_CustomCheck?: (v: string) => boolean
|
memo_CustomCheck?: (v: string) => boolean
|
||||||
zap_CustomCheck?: (v?: string) => boolean
|
zap_CustomCheck?: (v?: string) => boolean
|
||||||
}
|
}
|
||||||
|
|
@ -2761,6 +2763,9 @@ export const NewInvoiceRequestValidate = (o?: NewInvoiceRequest, opts: NewInvoic
|
||||||
if (typeof o.amountSats !== 'number') return new Error(`${path}.amountSats: is not a number`)
|
if (typeof o.amountSats !== 'number') return new Error(`${path}.amountSats: is not a number`)
|
||||||
if (opts.amountSats_CustomCheck && !opts.amountSats_CustomCheck(o.amountSats)) return new Error(`${path}.amountSats: custom check failed`)
|
if (opts.amountSats_CustomCheck && !opts.amountSats_CustomCheck(o.amountSats)) return new Error(`${path}.amountSats: custom check failed`)
|
||||||
|
|
||||||
|
if ((o.expiry || opts.allOptionalsAreSet || opts.checkOptionalsAreSet?.includes('expiry')) && typeof o.expiry !== 'number') return new Error(`${path}.expiry: is not a number`)
|
||||||
|
if (opts.expiry_CustomCheck && !opts.expiry_CustomCheck(o.expiry)) return new Error(`${path}.expiry: custom check failed`)
|
||||||
|
|
||||||
if (typeof o.memo !== 'string') return new Error(`${path}.memo: is not a string`)
|
if (typeof o.memo !== 'string') return new Error(`${path}.memo: is not a string`)
|
||||||
if (opts.memo_CustomCheck && !opts.memo_CustomCheck(o.memo)) return new Error(`${path}.memo: custom check failed`)
|
if (opts.memo_CustomCheck && !opts.memo_CustomCheck(o.memo)) return new Error(`${path}.memo: custom check failed`)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -379,7 +379,6 @@ message AddAppUserInvoiceRequest {
|
||||||
optional string offer_string = 6;
|
optional string offer_string = 6;
|
||||||
optional bool rejectUnauthorized = 7;
|
optional bool rejectUnauthorized = 7;
|
||||||
optional string token = 8;
|
optional string token = 8;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetAppUserRequest {
|
message GetAppUserRequest {
|
||||||
|
|
@ -450,6 +449,7 @@ message NewInvoiceRequest{
|
||||||
int64 amountSats = 1;
|
int64 amountSats = 1;
|
||||||
string memo = 2;
|
string memo = 2;
|
||||||
optional string zap = 3;
|
optional string zap = 3;
|
||||||
|
optional int64 expiry = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message NewInvoiceResponse{
|
message NewInvoiceResponse{
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,8 @@ export default class {
|
||||||
|
|
||||||
async NewInvoice(value: number, memo: string, expiry: number, { useProvider, from }: TxActionOptions): Promise<Invoice> {
|
async NewInvoice(value: number, memo: string, expiry: number, { useProvider, from }: TxActionOptions): Promise<Invoice> {
|
||||||
if (useProvider) {
|
if (useProvider) {
|
||||||
const invoice = await this.liquidProvider.AddInvoice(value, memo, from)
|
console.log("using provider")
|
||||||
|
const invoice = await this.liquidProvider.AddInvoice(value, memo, from, expiry)
|
||||||
const providerDst = this.liquidProvider.GetProviderDestination()
|
const providerDst = this.liquidProvider.GetProviderDestination()
|
||||||
return { payRequest: invoice, providerDst }
|
return { payRequest: invoice, providerDst }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -195,8 +195,9 @@ export default class {
|
||||||
if (req.invoice_req.zap) {
|
if (req.invoice_req.zap) {
|
||||||
zapInfo = this.paymentManager.validateZapEvent(req.invoice_req.zap, req.invoice_req.amountSats)
|
zapInfo = this.paymentManager.validateZapEvent(req.invoice_req.zap, req.invoice_req.amountSats)
|
||||||
}
|
}
|
||||||
|
const expiry = req.invoice_req.expiry ? Math.min(req.invoice_req.expiry, defaultInvoiceExpiry) : defaultInvoiceExpiry
|
||||||
const opts: InboundOptionals = {
|
const opts: InboundOptionals = {
|
||||||
callbackUrl: cbUrl, expiry: defaultInvoiceExpiry, expectedPayer: payer.user, linkedApplication: app, zapInfo,
|
callbackUrl: cbUrl, expiry: expiry, expectedPayer: payer.user, linkedApplication: app, zapInfo,
|
||||||
offerId: req.offer_string, payerData: req.payer_data?.data, rejectUnauthorized: req.rejectUnauthorized,
|
offerId: req.offer_string, payerData: req.payer_data?.data, rejectUnauthorized: req.rejectUnauthorized,
|
||||||
token: req.token
|
token: req.token
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,12 +165,12 @@ export class LiquidityProvider {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
AddInvoice = async (amount: number, memo: string, from: 'user' | 'system') => {
|
AddInvoice = async (amount: number, memo: string, from: 'user' | 'system', expiry: number) => {
|
||||||
try {
|
try {
|
||||||
if (!this.ready) {
|
if (!this.ready) {
|
||||||
throw new Error("liquidity provider is not ready yet")
|
throw new Error("liquidity provider is not ready yet")
|
||||||
}
|
}
|
||||||
const res = await this.client.NewInvoice({ amountSats: amount, memo })
|
const res = await this.client.NewInvoice({ amountSats: amount, memo, expiry })
|
||||||
if (res.status === 'ERROR') {
|
if (res.status === 'ERROR') {
|
||||||
this.log("error creating invoice", res.reason)
|
this.log("error creating invoice", res.reason)
|
||||||
throw new Error(res.reason)
|
throw new Error(res.reason)
|
||||||
|
|
|
||||||
|
|
@ -195,14 +195,14 @@ export class OfferManager {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
async HandleDefaultUserOffer(offerReq: NofferData, appId: string, remote: number): Promise<{ success: true, invoice: string } | { success: false, code: number, max: number }> {
|
async HandleDefaultUserOffer(offerReq: NofferData, appId: string, remote: number, { memo, expiry }: { memo?: string, expiry?: number }): Promise<{ success: true, invoice: string } | { success: false, code: number, max: number }> {
|
||||||
const { amount_sats: amount, offer } = offerReq
|
const { amount_sats: amount, offer } = offerReq
|
||||||
if (!amount || isNaN(amount) || amount < 10 || amount > remote) {
|
if (!amount || isNaN(amount) || amount < 10 || amount > remote) {
|
||||||
return { success: false, code: 5, max: remote }
|
return { success: false, code: 5, max: remote }
|
||||||
}
|
}
|
||||||
const res = await this.applicationManager.AddAppUserInvoice(appId, {
|
const res = await this.applicationManager.AddAppUserInvoice(appId, {
|
||||||
http_callback_url: "", payer_identifier: offer, receiver_identifier: offer,
|
http_callback_url: "", payer_identifier: offer, receiver_identifier: offer,
|
||||||
invoice_req: { amountSats: amount, memo: "Default NIP-69 Offer", zap: offerReq.zap },
|
invoice_req: { amountSats: amount, memo: memo ||"Default NIP-69 Offer", zap: offerReq.zap, expiry },
|
||||||
offer_string: 'offer'
|
offer_string: 'offer'
|
||||||
})
|
})
|
||||||
return { success: true, invoice: res.invoice }
|
return { success: true, invoice: res.invoice }
|
||||||
|
|
@ -211,8 +211,10 @@ export class OfferManager {
|
||||||
async HandleUserOffer(offerReq: NofferData, appId: string, remote: number): Promise<{ success: true, invoice: string } | { success: false, code: number, max: number }> {
|
async HandleUserOffer(offerReq: NofferData, appId: string, remote: number): Promise<{ success: true, invoice: string } | { success: false, code: number, max: number }> {
|
||||||
const { amount_sats: amount, offer } = offerReq
|
const { amount_sats: amount, offer } = offerReq
|
||||||
const userOffer = await this.storage.offerStorage.GetOffer(offer)
|
const userOffer = await this.storage.offerStorage.GetOffer(offer)
|
||||||
|
const expiry = offerReq.expires_in_seconds ? offerReq.expires_in_seconds : undefined
|
||||||
|
|
||||||
if (!userOffer) {
|
if (!userOffer) {
|
||||||
return this.HandleDefaultUserOffer(offerReq, appId, remote)
|
return this.HandleDefaultUserOffer(offerReq, appId, remote, { memo: offerReq.description, expiry })
|
||||||
}
|
}
|
||||||
if (userOffer.app_user_id === userOffer.offer_id) {
|
if (userOffer.app_user_id === userOffer.offer_id) {
|
||||||
if (userOffer.price_sats !== 0 || userOffer.payer_data) {
|
if (userOffer.price_sats !== 0 || userOffer.payer_data) {
|
||||||
|
|
@ -234,9 +236,13 @@ export class OfferManager {
|
||||||
this.logger("Invalid expected data", validated || {})
|
this.logger("Invalid expected data", validated || {})
|
||||||
return { success: false, code: 1, max: remote }
|
return { success: false, code: 1, max: remote }
|
||||||
}
|
}
|
||||||
|
if (offerReq.description && (typeof offerReq.description !== 'string' || offerReq.description.length > 100)) {
|
||||||
|
return { success: false, code: 1, max: remote }
|
||||||
|
}
|
||||||
|
const memo = offerReq.description || userOffer.label
|
||||||
const res = await this.applicationManager.AddAppUserInvoice(appId, {
|
const res = await this.applicationManager.AddAppUserInvoice(appId, {
|
||||||
http_callback_url: userOffer.callback_url, payer_identifier: userOffer.app_user_id, receiver_identifier: userOffer.app_user_id,
|
http_callback_url: userOffer.callback_url, payer_identifier: userOffer.app_user_id, receiver_identifier: userOffer.app_user_id,
|
||||||
invoice_req: { amountSats: amt, memo: userOffer.label, zap: offerReq.zap },
|
invoice_req: { amountSats: amt, memo, zap: offerReq.zap, expiry },
|
||||||
payer_data: validated ? { data: validated } : undefined,
|
payer_data: validated ? { data: validated } : undefined,
|
||||||
offer_string: offer,
|
offer_string: offer,
|
||||||
rejectUnauthorized: userOffer.rejectUnauthorized,
|
rejectUnauthorized: userOffer.rejectUnauthorized,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue