Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/features/buy/buy-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ type CreateBuyStoreProps = {
account: CashuAccount;
amount: Money;
description?: string;
receiveType: 'BUY';
}) => Promise<CashuReceiveQuote>;
createSparkReceiveQuote: (params: {
account: SparkAccount;
amount: Money;
description?: string;
receiveType: 'BUY';
}) => Promise<SparkReceiveQuote>;
};

Expand Down Expand Up @@ -72,6 +74,7 @@ export const createBuyStore = ({
account,
amount,
description: 'Pay to Agicash',
receiveType: 'BUY',
});
quote = {
id: cashuQuote.id,
Expand All @@ -84,6 +87,7 @@ export const createBuyStore = ({
account,
amount,
description: 'Pay to Agicash',
receiveType: 'BUY',
});
quote = {
id: sparkQuote.id,
Expand Down
32 changes: 18 additions & 14 deletions app/features/receive/cashu-receive-quote-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,15 @@ export type CreateQuoteBaseParams = {
/**
* Type of the receive.
* - LIGHTNING - The money is received via a regular lightning payment.
* - BUY - A purchase of bitcoin. The receive quote is created by the buyer, who pays the Lightning invoice through an external payment method.
* - TRANSFER - An internal transfer between accounts. The receive quote is created and paid automatically by the app.
* - CASHU_TOKEN - The money is received as a cashu token. The proofs will be melted
* from the account they originated from to pay the request for this receive quote.
*/
receiveType: 'LIGHTNING' | 'CASHU_TOKEN';
receiveType: 'LIGHTNING' | 'BUY' | 'TRANSFER' | 'CASHU_TOKEN';
} & (
| {
receiveType: 'LIGHTNING';
receiveType: 'LIGHTNING' | 'BUY' | 'TRANSFER';
}
| {
receiveType: 'CASHU_TOKEN';
Expand Down Expand Up @@ -176,7 +178,7 @@ export type RepositoryCreateQuoteParams = {
totalFee: Money;
} & (
| {
receiveType: 'LIGHTNING';
receiveType: 'LIGHTNING' | 'BUY' | 'TRANSFER';
}
| {
receiveType: 'CASHU_TOKEN';
Expand Down Expand Up @@ -282,16 +284,16 @@ export async function getLightningQuote(
* For CASHU_TOKEN type quotes, the expiry is the earler of the mint quote expiry and the melt quote expiry.
*/
export function computeQuoteExpiry(params: CreateQuoteBaseParams): string {
if (params.receiveType === 'LIGHTNING') {
return params.lightningQuote.expiresAt;
if (params.receiveType === 'CASHU_TOKEN') {
return new Date(
Math.min(
new Date(params.lightningQuote.expiresAt).getTime(),
new Date(params.meltQuoteExpiresAt).getTime(),
),
).toISOString();
}

return new Date(
Math.min(
new Date(params.lightningQuote.expiresAt).getTime(),
new Date(params.meltQuoteExpiresAt).getTime(),
),
).toISOString();
return params.lightningQuote.expiresAt;
}

/**
Expand All @@ -304,9 +306,11 @@ export function computeTotalFee(params: CreateQuoteBaseParams): Money {
params.lightningQuote.mintingFee ??
Money.zero(params.lightningQuote.amount.currency);

if (params.receiveType === 'LIGHTNING') {
return mintingFee;
if (params.receiveType === 'CASHU_TOKEN') {
return mintingFee
.add(params.cashuReceiveFee)
.add(params.lightningFeeReserve);
}

return mintingFee.add(params.cashuReceiveFee).add(params.lightningFeeReserve);
return mintingFee;
}
10 changes: 8 additions & 2 deletions app/features/receive/cashu-receive-quote-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type CreateProps = {
account: CashuAccount;
amount: Money;
description?: string;
receiveType?: 'LIGHTNING' | 'BUY';
};
class CashuReceiveQuoteCache {
// Query that tracks the "active" cashu receive quote. Active one is the one that user created in current browser session.
Expand Down Expand Up @@ -154,7 +155,12 @@ export function useCreateCashuReceiveQuote() {
scope: {
id: 'create-cashu-receive-quote',
},
mutationFn: async ({ account, amount, description }: CreateProps) => {
mutationFn: async ({
account,
amount,
description,
receiveType = 'LIGHTNING',
}: CreateProps) => {
const lightningQuote = await cashuReceiveQuoteService.getLightningQuote({
wallet: account.wallet,
amount,
Expand All @@ -164,7 +170,7 @@ export function useCreateCashuReceiveQuote() {
return cashuReceiveQuoteService.createReceiveQuote({
userId,
account,
receiveType: 'LIGHTNING',
receiveType,
lightningQuote,
});
},
Expand Down
6 changes: 4 additions & 2 deletions app/features/receive/cashu-receive-quote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,11 @@ const CashuReceiveQuoteBaseSchema = z.object({
const CashuReceiveQuoteLightningTypeSchema = z.object({
/**
* Type of the receive.
* LIGHTNING - The money is received via Lightning.
* LIGHTNING - The money is received via a regular lightning payment.
* BUY - A purchase of bitcoin. The receive quote is created by the buyer, who pays the Lightning invoice through an external payment method.
* TRANSFER - An internal transfer between accounts. The receive quote is created and paid automatically by the app.
*/
type: z.literal('LIGHTNING'),
type: z.enum(['LIGHTNING', 'BUY', 'TRANSFER']),
});

const CashuReceiveQuoteCashuTokenTypeSchema = z.object({
Expand Down
40 changes: 22 additions & 18 deletions app/features/receive/spark-receive-quote-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ export type CreateQuoteBaseParams = {
| {
/**
* Type of the receive.
* LIGHTNING - Standard lightning receive.
* LIGHTNING - The money is received via a regular lightning payment.
* BUY - A purchase of bitcoin. The receive quote is created by the buyer, who pays the Lightning invoice through an external payment method.
* TRANSFER - An internal transfer between accounts. The receive quote is created and paid automatically by the app.
*/
receiveType: 'LIGHTNING';
receiveType: 'LIGHTNING' | 'BUY' | 'TRANSFER';
}
| {
/**
Expand Down Expand Up @@ -165,9 +167,11 @@ export type RepositoryCreateQuoteParams = {
| {
/**
* Type of the receive.
* LIGHTNING - Standard lightning receive.
* LIGHTNING - The money is received via a regular lightning payment.
* BUY - A purchase of bitcoin. The receive quote is created by the buyer, who pays the Lightning invoice through an external payment method.
* TRANSFER - An internal transfer between accounts. The receive quote is created and paid automatically by the app.
*/
receiveType: 'LIGHTNING';
receiveType: 'LIGHTNING' | 'BUY' | 'TRANSFER';
}
| {
/**
Expand Down Expand Up @@ -256,16 +260,16 @@ export async function getLightningQuote({
* For CASHU_TOKEN type, returns the earlier of lightning and melt quote expiry.
*/
export function computeQuoteExpiry(params: CreateQuoteBaseParams): string {
if (params.receiveType === 'LIGHTNING') {
return params.lightningQuote.invoice.expiresAt;
if (params.receiveType === 'CASHU_TOKEN') {
return new Date(
Math.min(
new Date(params.lightningQuote.invoice.expiresAt).getTime(),
new Date(params.meltQuoteExpiresAt).getTime(),
),
).toISOString();
}

return new Date(
Math.min(
new Date(params.lightningQuote.invoice.expiresAt).getTime(),
new Date(params.meltQuoteExpiresAt).getTime(),
),
).toISOString();
return params.lightningQuote.invoice.expiresAt;
}

/**
Expand All @@ -279,12 +283,12 @@ export function getAmountAndFee(params: CreateQuoteBaseParams): {
} {
const amount = moneyFromSparkAmount(params.lightningQuote.invoice.amount);

if (params.receiveType === 'LIGHTNING') {
return { amount, totalFee: Money.zero(amount.currency) };
if (params.receiveType === 'CASHU_TOKEN') {
return {
amount,
totalFee: params.cashuReceiveFee.add(params.lightningFeeReserve),
};
}

return {
amount,
totalFee: params.cashuReceiveFee.add(params.lightningFeeReserve),
};
return { amount, totalFee: Money.zero(amount.currency) };
}
7 changes: 6 additions & 1 deletion app/features/receive/spark-receive-quote-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@ type CreateProps = {
* Description to include in the Lightning invoice memo.
*/
description?: string;
/**
* Type of the receive. Defaults to 'LIGHTNING'.
*/
receiveType?: 'LIGHTNING' | 'BUY';
};

/**
Expand All @@ -292,6 +296,7 @@ export function useCreateSparkReceiveQuote() {
amount,
receiverIdentityPubkey,
description,
receiveType = 'LIGHTNING',
}: CreateProps) => {
const lightningQuote = await getLightningQuote({
wallet: account.wallet,
Expand All @@ -304,7 +309,7 @@ export function useCreateSparkReceiveQuote() {
userId,
account,
lightningQuote,
receiveType: 'LIGHTNING',
receiveType,
});
},
onSuccess: (data) => {
Expand Down
2 changes: 1 addition & 1 deletion app/features/receive/spark-receive-quote-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class SparkReceiveQuoteService {

return this.repository.create({
...baseParams,
receiveType: 'LIGHTNING',
receiveType: params.receiveType,
});
}

Expand Down
6 changes: 4 additions & 2 deletions app/features/receive/spark-receive-quote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,11 @@ const SparkReceiveQuoteBaseSchema = z.object({
const SparkReceiveQuoteLightningTypeSchema = z.object({
/**
* Type of the receive.
* LIGHTNING - The money is received via regular Lightning flow. User provides the lightning invoice to the payer who then pays the invoice.
* LIGHTNING - The money is received via a regular lightning payment.
* BUY - A purchase of bitcoin. The receive quote is created by the buyer, who pays the Lightning invoice through an external payment method.
* TRANSFER - An internal transfer between accounts. The receive quote is created and paid automatically by the app.
*/
type: z.literal('LIGHTNING'),
type: z.enum(['LIGHTNING', 'BUY', 'TRANSFER']),
});

const SparkReceiveQuoteCashuTokenTypeSchema = z.object({
Expand Down
2 changes: 2 additions & 0 deletions app/features/transactions/transaction-enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const TransactionTypeSchema = z.enum([
'CASHU_LIGHTNING',
'CASHU_TOKEN',
'SPARK_LIGHTNING',
'BUY',
'TRANSFER',
]);

export type TransactionType = z.infer<typeof TransactionTypeSchema>;
Expand Down
19 changes: 15 additions & 4 deletions supabase/database.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1612,7 +1612,7 @@ export type Database = {
| "FAILED"
| "REVERSED"
currency: "BTC" | "USD"
receive_quote_type: "LIGHTNING" | "CASHU_TOKEN"
receive_quote_type: "LIGHTNING" | "CASHU_TOKEN" | "TRANSFER" | "BUY"
spark_receive_quote_state: "UNPAID" | "EXPIRED" | "PAID" | "FAILED"
spark_send_quote_state: "UNPAID" | "PENDING" | "COMPLETED" | "FAILED"
transaction_direction: "SEND" | "RECEIVE"
Expand All @@ -1622,7 +1622,12 @@ export type Database = {
| "COMPLETED"
| "FAILED"
| "REVERSED"
transaction_type: "CASHU_LIGHTNING" | "CASHU_TOKEN" | "SPARK_LIGHTNING"
transaction_type:
| "CASHU_LIGHTNING"
| "CASHU_TOKEN"
| "SPARK_LIGHTNING"
| "TRANSFER"
| "BUY"
}
CompositeTypes: {
account_input: {
Expand Down Expand Up @@ -1900,7 +1905,7 @@ export const Constants = {
"REVERSED",
],
currency: ["BTC", "USD"],
receive_quote_type: ["LIGHTNING", "CASHU_TOKEN"],
receive_quote_type: ["LIGHTNING", "CASHU_TOKEN", "TRANSFER", "BUY"],
spark_receive_quote_state: ["UNPAID", "EXPIRED", "PAID", "FAILED"],
spark_send_quote_state: ["UNPAID", "PENDING", "COMPLETED", "FAILED"],
transaction_direction: ["SEND", "RECEIVE"],
Expand All @@ -1911,7 +1916,13 @@ export const Constants = {
"FAILED",
"REVERSED",
],
transaction_type: ["CASHU_LIGHTNING", "CASHU_TOKEN", "SPARK_LIGHTNING"],
transaction_type: [
"CASHU_LIGHTNING",
"CASHU_TOKEN",
"SPARK_LIGHTNING",
"TRANSFER",
"BUY",
],
},
},
} as const
Expand Down
Loading