diff --git a/src/lib/components/messaging/ChatPreview.svelte b/src/lib/components/messaging/ChatPreview.svelte
index 638969165..b4d0ade60 100644
--- a/src/lib/components/messaging/ChatPreview.svelte
+++ b/src/lib/components/messaging/ChatPreview.svelte
@@ -34,7 +34,6 @@
$: user = chat.typing_indicator.users().map(u => {
return $lookupUsers[u]
})
- $: self = get(Store.state.user)
let timeago = getTimeAgo(chat.last_message_at)
const dispatch = createEventDispatcher()
let ownId = get(Store.state.user)
@@ -57,9 +56,11 @@
? $_("message_previews.coin_requested", { values: { username: sendingUserDetails.name, amount: amountPreview } })
: $_("message_previews.request_sent", { values: { amount: amountPreview } })
} catch (error) {
+ console.log(chat.last_message_preview)
return "Invalid message format"
}
- } else if (chat.last_message_preview.startsWith(PaymentRequestsEnum.Reject)) {
+ }
+ if (chat.last_message_preview.startsWith(PaymentRequestsEnum.Reject)) {
try {
const sendingUserId = ConversationStore.getMessage(chat.id, chat.last_message_id)?.details.origin
const sendingUserDetails = get(Store.getUser(sendingUserId!))
@@ -69,6 +70,35 @@
return $_("message_previews.coin_canceled")
}
} catch (error) {
+ console.log(chat.last_message_preview)
+ return "Invalid message format"
+ }
+ }
+ if (chat.last_message_preview.startsWith(PaymentRequestsEnum.Send)) {
+ try {
+ const sendingUserId = ConversationStore.getMessage(chat.id, chat.last_message_id)?.details.origin
+ const sendingUserDetails = get(Store.getUser(sendingUserId!))
+ const jsonStartIndex = chat.last_message_preview.indexOf("{")
+ if (jsonStartIndex === -1) {
+ console.error("No JSON found in last_message_preview:", chat.last_message_preview)
+ return "Invalid message format"
+ }
+ const jsonPart = chat.last_message_preview.slice(jsonStartIndex)
+ let parsedMessage
+ try {
+ parsedMessage = JSON.parse(jsonPart)
+ } catch (error) {
+ console.error("Error parsing JSON:", error, chat.last_message_preview)
+ return "Invalid message format"
+ }
+ const amountWei = parsedMessage.details.amount
+ if (sendingUserDetails.key !== ownId.key) {
+ return `${sendingUserDetails.name} sent you ${amountWei}`
+ } else {
+ return `You sent ${amountWei} to ${sendingUserDetails.name}`
+ }
+ } catch (error) {
+ console.error("Error in PaymentRequestsEnum.Send condition:", error)
return "Invalid message format"
}
}
diff --git a/src/lib/components/wallet/CreateTransaction.svelte b/src/lib/components/wallet/CreateTransaction.svelte
index d962117ac..0a4a86050 100644
--- a/src/lib/components/wallet/CreateTransaction.svelte
+++ b/src/lib/components/wallet/CreateTransaction.svelte
@@ -2,52 +2,107 @@
import Button from "$lib/elements/Button.svelte"
import { ConversationStore } from "$lib/state/conversation"
import { Store } from "$lib/state/Store"
- import { AssetType, shortenAddr, Transfer, wallet, type Asset } from "$lib/utils/Wallet"
+ import { AssetType, getValidPaymentRequest, shortenAddr, Transfer, wallet, type Asset } from "$lib/utils/Wallet"
import { RaygunStoreInstance } from "$lib/wasm/RaygunStore"
import { get } from "svelte/store"
import { _ } from "svelte-i18n"
- import { Select } from "$lib/elements"
+ import { Icon, Input, Label, Select, Text } from "$lib/elements"
+ import { Appearance, PaymentRequestsEnum, Shape, Size } from "$lib/enums"
export let onClose
-
+ enum ViewMode {
+ None = "",
+ Send = "send",
+ Receive = "receive",
+ QRScanner = "send",
+ SendFunds = "SendFunds",
+ }
let transfer = new Transfer()
-
+ let sendCoin = ViewMode.None
+ let initialSelect = "Select an asset"
async function sendMessage(text: string) {
- let chat = get(Store.state.activeChat)
- let txt = text.split("\n")
- let result = await RaygunStoreInstance.send(chat.id, txt, [])
- result.onSuccess(res => {
- ConversationStore.addPendingMessages(chat.id, res.message, txt)
- })
+ if (sendCoin === ViewMode.Send) {
+ let chat = get(Store.state.activeChat)
+ let txt = text.split("\n")
+ let whatReturned = await getValidPaymentRequest(txt[0])?.execute()
+ if (whatReturned !== undefined) {
+ let result = await RaygunStoreInstance.send(chat.id, txt, [])
+ result.onSuccess(res => {
+ ConversationStore.addPendingMessages(chat.id, res.message, txt)
+ })
+ }
+ }
+ if (sendCoin === ViewMode.Receive) {
+ let chat = get(Store.state.activeChat)
+ let txt = text.split("\n")
+ let result = await RaygunStoreInstance.send(chat.id, txt, [])
+ result.onSuccess(res => {
+ console.log(txt)
+ ConversationStore.addPendingMessages(chat.id, res.message, txt)
+ })
+ }
}
let inputAmount = ""
-
function onInputAmount() {
- //remove any input that is not a number or a dot
+ isAmountTouched = true
+ console.log(transfer.asset.kind)
inputAmount = inputAmount.replace(/[^0-9.]/g, "")
- //if there is more than 1 dot, only keep the first one
if (inputAmount.split(".").length > 2) {
- let i = inputAmount.indexOf(".")
- inputAmount = inputAmount.substring(0, i + 1) + inputAmount.substring(i + 1, inputAmount.length).replace(".", "")
+ const i = inputAmount.indexOf(".")
+ inputAmount = inputAmount.substring(0, i + 1) + inputAmount.substring(i + 1).replace(".", "")
}
- //convert string amount to bigint
- wallet.toBigIntAmount(transfer.asset, inputAmount).then(amount => {
- transfer.amount = amount
- wallet.toAmountPreviewString(transfer.asset, transfer.amount).then(amountPreview => {
- transfer.amountPreview = amountPreview
+ const decimalPlaces = 18 // Max decimals for the asset type
+ const parts = inputAmount.split(".")
+ if (parts[1] && parts[1].length > decimalPlaces) {
+ inputAmount = parts[0] + "." + parts[1].substring(0, decimalPlaces)
+ }
+
+ isValidAmount = /^[0-9]+(\.[0-9]+)?$/.test(inputAmount)
+
+ if (isValidAmount) {
+ wallet.toBigIntAmount(transfer.asset, inputAmount).then(amount => {
+ transfer.amount = amount
+ wallet.toAmountPreviewString(transfer.asset, transfer.amount).then(amountPreview => {
+ transfer.amountPreview = amountPreview
+ })
})
- })
+ }
}
+
+ let addressInput = ""
+ let isValidAddress = false
+ let isAddressTouched = false
+ let isValidAmount = false
+ let isAmountTouched = false
+ function onAddressInput() {
+ isAddressTouched = true
+
+ const bitcoinRegex = /^(1|3|bc1|tb1)[a-zA-HJ-NP-Z0-9]{25,62}$/
+ const ethereumRegex = /^0x[a-fA-F0-9]{40}$/
+
+ isValidAddress = bitcoinRegex.test(addressInput) || ethereumRegex.test(addressInput)
+
+ if (isValidAddress) {
+ transfer.toAddress = addressInput
+ }
+ }
+
onInputAmount()
function onChangeAssetKind() {
transfer.asset.id = ""
transfer.amount = BigInt(0)
onInputAmount()
- wallet.myAddress(transfer.asset).then(address => {
- transfer.toAddress = address
- })
+ if (sendCoin !== ViewMode.Send) {
+ wallet.myAddress(transfer.asset).then(address => {
+ transfer.toAddress = address
+ })
+ } else {
+ wallet.myAddress(transfer.asset).then(address => {
+ transfer.toAddress = addressInput
+ })
+ }
}
onChangeAssetKind()
@@ -56,21 +111,146 @@
}
-
-
{$_("payments.assetType") + ":"}
- {#if needsAssetId()}
-
{$_("payments.assetId") + ":"}
- {/if}
-
{transfer.amountPreview}
-
{$_("payments.amount") + ":"}
- {#if transfer.toAddress !== ""}
-
{$_("payments.receiving_to")}: {shortenAddr(transfer.toAddress, 6)}
- {/if}
+
+
+ Transfer Funds
+
+
+
+
+
+ {#if sendCoin === ViewMode.Send}
+
+
+
+
+ {#if transfer.asset.kind !== initialSelect}
+
+
+
+
+ {#if isAddressTouched && !isValidAddress}
+ Invalid wallet address.
+ {/if}
+
+
+ {/if}
-
+ {#if isValidAddress && addressInput !== ""}
+
+
+
+ {#if isAmountTouched && !isValidAmount && inputAmount.length > 1}
+ Invalid amount format.
+ {/if}
+
+ {/if}
+
+ {#if needsAssetId()}
+
+ {$_("payments.assetId") + ":"}
+
+
+ {/if}
+
+ {#if isValidAddress && isValidAmount}
+
+
+
+ {/if}
+ {:else if sendCoin === ViewMode.Receive}
+
+
+ {#if transfer.toAddress !== ""}
+
+
+
+
+
+ {/if}
+
+ {#if needsAssetId()}
+
{$_("payments.assetId") + ":"}
+ {/if}
+
+
+
+ {/if}
+
+
diff --git a/src/lib/enums/icons.ts b/src/lib/enums/icons.ts
index f5cf38f9f..9980f7d5c 100644
--- a/src/lib/enums/icons.ts
+++ b/src/lib/enums/icons.ts
@@ -15,6 +15,18 @@ export const enum Shape {
Boot = `
`,
ID = `
`,
Details = `
`,
+ QRCodeScan = `
`,
+ QRCode = `
+
+
+
+
+
+
+
+
+
+
`,
Tag = `
`,
Shield = `
`,
Popout = `
`,
diff --git a/src/lib/enums/index.ts b/src/lib/enums/index.ts
index 6255ea875..2f3d69874 100644
--- a/src/lib/enums/index.ts
+++ b/src/lib/enums/index.ts
@@ -23,6 +23,7 @@ export enum Color {
export enum PaymentRequestsEnum {
Reject = "/reject",
Request = "/request",
+ Send = "/send",
}
export enum Format {
diff --git a/src/lib/lang/en.json b/src/lib/lang/en.json
index fd5e378bb..0372753aa 100644
--- a/src/lib/lang/en.json
+++ b/src/lib/lang/en.json
@@ -209,6 +209,7 @@
"payments": {
"send": "Send",
"receive": "Receive",
+ "type": "Type",
"receiving_to": "Receiving to",
"sendCoin": "Send Coin",
"amount": "Amount",
@@ -217,15 +218,25 @@
"note": "Note",
"date": "Date",
"decline": "Decline",
+ "enter_address": "Enter Address",
+ "address": "Address",
+ "create_transaction": "Create Transaction",
"create": "Create Payment Request",
+ "decline_payment": "Decline Payment",
+ "sent_request": "Sent Request",
+ "canceled_request": "Canceled Request",
"declinePayment": "Decline Payment",
"sentRequest": "Request has been sent",
"cancel_request": "Cancel Request",
"canceledRequest": "Canceled Request",
"network": "Network",
- "paymentDeclined": "Payment Canceled",
- "youCanceledRequest": "You Canceled Payment Request",
- "declinedPayment": "{user} Canceled Payment",
+ "payment_success": "Payment Success",
+ "payment_declined": "Payment Declined",
+ "you_canceled_request": "You Canceled Payment Request",
+ "payment_canceled": "Payment Canceled",
+ "declined_payment": "{user} Canceled Payment",
+ "recievedPayment": "{user} Sent You {amount}",
+ "sentPayment": "You Sent {amount}",
"assetType": "Asset type",
"assetName": "Asset name",
"assetId": "Asset Id",
diff --git a/src/lib/utils/Wallet.ts b/src/lib/utils/Wallet.ts
index e18f9ae1d..a577ea140 100644
--- a/src/lib/utils/Wallet.ts
+++ b/src/lib/utils/Wallet.ts
@@ -1,6 +1,8 @@
import Wallet, { AddressPurpose, AddressType, RpcErrorCode } from "sats-connect"
import { ethers } from "ethers"
import { log } from "./Logger"
+import { PaymentRequestsEnum } from "$lib/enums"
+import type { MessageType } from "warp-wasm"
export type Account = {
address: string
@@ -361,7 +363,7 @@ async function ethToBigIntAmount(amount: string): Promise
{
}
async function ethTransfer(ethWallet: EthWallet, amount: bigint, toAddress: string) {
- let tx = await ethWallet.signer.sendTransaction({
+ return await ethWallet.signer.sendTransaction({
to: toAddress,
value: amount,
})
@@ -488,33 +490,45 @@ export class Transfer {
toCmdString(): string {
let transfer = JSON.stringify(this, (k, v) => (k === "amount" && typeof v === "bigint" ? v.toString() : v))
+ console.log(transfer)
return `/request ${transfer}`
}
toRejectString(id: string) {
- let transfer = JSON.stringify(this, (k, v) => (k === "amount" && typeof v === "bigint" ? v.toString() : v))
- return `/reject ${id}`
+ const transfer = JSON.stringify(this, (key, value) => (key === "amount" && typeof value === "bigint" ? value.toString() : value))
+ return `/reject ${id} {"details":${transfer}}`
}
- toDisplayString(): string {
- let id = this.asset.id === "n/a" ? "" : this.asset.id
- return `Send ${this.amountPreview} to ${shortenAddr(this.toAddress, 6)}`
+ toDisplayString(kind: string, amount: string, toAddress: string, messageId?: string): string {
+ const transfer = JSON.stringify(this, (key, value) => (key === "amount" && typeof value === "bigint" ? value.toString() : value))
+ const message = {
+ kind,
+ details: {
+ amount,
+ toAddress,
+ messageID: messageId,
+ transfer: JSON.parse(transfer),
+ },
+ }
+ return `/send ${JSON.stringify(message)}`
}
async execute() {
if (this.isValid()) {
- await wallet.transfer(this.asset, this.amount, this.toAddress)
+ let verifyTansfer = await wallet.transfer(this.asset, this.amount, this.toAddress)
+ if (verifyTansfer === undefined) {
+ return false
+ } else {
+ return true
+ }
}
}
}
export function getValidPaymentRequest(msg: string, msgId?: string): Transfer | undefined {
- let requestCmd = "/request"
- let rejectCmd = "/reject"
-
- if (msg.startsWith(requestCmd)) {
- let json = msg.substring(requestCmd.length, msg.length).trim()
- let transfer = new Transfer()
+ let transfer = new Transfer()
+ if (msg.startsWith(PaymentRequestsEnum.Request)) {
+ let json = msg.substring(PaymentRequestsEnum.Request.length, msg.length).trim()
try {
let parsed = JSON.parse(json, (k, v) => (k === "amount" && typeof v === "string" ? BigInt(v) : v))
transfer.asset = parsed.asset
@@ -527,9 +541,8 @@ export function getValidPaymentRequest(msg: string, msgId?: string): Transfer |
if (transfer.asset.kind !== AssetType.None && transfer.isValid()) {
return transfer
}
- } else if (msg.startsWith(rejectCmd)) {
- let json = msg.substring(rejectCmd.length, msg.length).trim()
- let transfer = new Transfer()
+ } else if (msg.startsWith(PaymentRequestsEnum.Reject)) {
+ let json = msg.substring(PaymentRequestsEnum.Reject.length, msg.length).trim()
if (json.startsWith("{")) {
try {
@@ -539,16 +552,53 @@ export function getValidPaymentRequest(msg: string, msgId?: string): Transfer |
transfer.toAddress = parsed.toAddress
transfer.amountPreview = parsed.amountPreview
} catch (err) {
- console.log("Parse Failed", err)
+ console.error("Parse Failed", err)
}
} else {
- console.log("Reject message is not JSON, possibly an ID or UUID:", json)
+ console.error("Reject message is not JSON, possibly an ID or UUID:", json)
return undefined
}
if (transfer.asset.kind !== AssetType.None && transfer.isValid()) {
return transfer
}
+ } else if (msg.startsWith(PaymentRequestsEnum.Send)) {
+ let json = msg.substring(PaymentRequestsEnum.Send.length).trim()
+ let jsonStartIndex = json.indexOf("{")
+ if (jsonStartIndex !== -1) {
+ json = json.substring(jsonStartIndex).trim()
+ try {
+ let parsed = JSON.parse(json, (key, value) => {
+ if (key === "amount" && typeof value === "string") {
+ if (/^\d+(\.\d+)?$/.test(value)) {
+ return BigInt(Math.round(Number(value) * 1e18))
+ }
+ }
+ return value
+ })
+ const details = parsed.details || {}
+ transfer.asset = details.asset && typeof details.asset === "object" ? details.asset : { kind: details.asset || "Unknown" }
+
+ transfer.amount = details.amount ? BigInt(Math.round(Number(details.amount) * 1e18)) : BigInt(0)
+
+ transfer.amountPreview = details.amount ? `${(Number(details.amount) / 1e18).toFixed(18)} ETH` : ""
+
+ transfer.toAddress = details.toAddress || ""
+ } catch (err) {
+ console.error("Parse Failed", err, "JSON Input:", json)
+ return undefined
+ }
+ } else {
+ console.error("Send message is not JSON:", json)
+ return undefined
+ }
+
+ if (transfer.asset && transfer.asset.kind !== undefined && transfer.asset.kind !== AssetType.None && transfer.isValid()) {
+ return transfer
+ } else {
+ console.error("Invalid transfer object:", transfer)
+ return undefined
+ }
}
return undefined
diff --git a/src/routes/chat/+page.svelte b/src/routes/chat/+page.svelte
index ab6f31ecc..cf503a0fb 100644
--- a/src/routes/chat/+page.svelte
+++ b/src/routes/chat/+page.svelte
@@ -38,6 +38,7 @@
import BrowseFiles from "../files/BrowseFiles.svelte"
import AttachmentRenderer from "$lib/components/messaging/AttachmentRenderer.svelte"
import ShareFile from "$lib/components/files/ShareFile.svelte"
+ import { StateEffect } from "@codemirror/state"
import { ToastMessage } from "$lib/state/ui/toast"
import AddMembers from "$lib/components/group/AddMembers.svelte"
@@ -129,25 +130,50 @@
}
function sanitizePaymentRequest(message: string, sender: string): string {
- // Match and extract "kind", "amountPreview", and "toAddress" from the input string
const kindMatch = message.match(/"kind":"(.*?)"/)
const amountPreviewMatch = message.match(/"amountPreview":"(.*?)"/)
- // const toAddressMatch = message.match(/"toAddress":"(.*?)"/)
-
- // Extract the values from the match results, defaulting to an empty string if not found
const kind = kindMatch ? kindMatch[1] : ""
let amountPreview = amountPreviewMatch ? amountPreviewMatch[1] : ""
- // const toAddress = toAddressMatch ? toAddressMatch[1] : ""
-
- // Remove any extra occurrence of the currency symbol in `amountPreview`
if (amountPreview.includes(kind)) {
amountPreview = amountPreview.replace(kind, "").trim()
}
amountPreview = amountPreview.replace(/(\.\d*?[1-9])0+$|\.0*$/, "$1")
- // Return the formatted string
- return `Send ${amountPreview} ${kind}`
+ const result = `Send ${amountPreview} ${kind}`
+ return result
}
+ $: sanitizePaymentSent = (() => {
+ const sendingUserId = ConversationStore.getMessage($activeChat.id, $activeChat.last_message_id)?.details.origin
+ const sendingUserDetails = get(Store.getUser(sendingUserId!))
+ const jsonStartIndex = $activeChat.last_message_preview.indexOf("{")
+ if (jsonStartIndex === -1) {
+ console.error("No JSON found in last_message_preview:", $activeChat.last_message_preview)
+ return "Invalid message format"
+ }
+ const jsonPart = $activeChat.last_message_preview.slice(jsonStartIndex)
+ let parsedMessage
+ try {
+ parsedMessage = JSON.parse(jsonPart)
+ } catch (error) {
+ console.error("Error parsing JSON:", error, $activeChat.last_message_preview)
+ return "Invalid message format"
+ }
+ console.log(parsedMessage)
+ if (parsedMessage.details) {
+ if (sendingUserDetails.key !== $own_user.key) {
+ return `${sendingUserDetails.name} sent you ${parsedMessage.details.amount}`
+ } else {
+ return `You sent ${parsedMessage.details.amount} to ${sendingUserDetails.name}`
+ }
+ } else {
+ if (sendingUserDetails.key !== $own_user.key) {
+ return `${sendingUserDetails.name} sent you ${parsedMessage.amount}`
+ } else {
+ return `You sent ${parsedMessage.amount} to ${sendingUserDetails.name}`
+ }
+ }
+ })()
+
function addFilesToUpload(selected: File[]) {
let files: [File?, string?][] = []
for (let file of selected) {
@@ -302,24 +328,20 @@
$: rejectedPayments = Store.state.paymentTracker
- async function sendPaymentMessage(message: MessageType, paymentType: string) {
+ async function sendPaymentMessage(message: MessageType, line: string, paymentType: string) {
let transfer = new Transfer()
let chat = get(Store.state.activeChat)
- let rejectTransfer = transfer.toRejectString(message.id)
- let txt = rejectTransfer.split("\n")
- if (paymentType === "result") {
+ if (paymentType === PaymentRequestsEnum.Request) {
+ let rejectTranfser = transfer.toCmdString()
+ let txt = rejectTranfser.split("\n")
let result = await RaygunStoreInstance.send(chat.id, txt, [])
result.onSuccess(res => {
- if (getValidPaymentRequest(message.text[0])) {
- getValidPaymentRequest(message.text[0])?.execute()
- }
Store.state.paymentTracker.update(payments => {
const alreadyRejected = payments.some(payment => payment.messageId === message.id)
-
if (!alreadyRejected) {
return [...payments, { messageId: message.id, senderId: message.details.origin, rejectedPayment: false }]
} else {
- console.log(`MessageId ${message.id} is already in the rejected payments list`)
+ console.error(`MessageId ${message.id} is already in the rejected payments list`)
return payments
}
})
@@ -328,6 +350,8 @@
})
}
if (paymentType === PaymentRequestsEnum.Reject) {
+ let rejectTranfser = transfer.toRejectString(message.id)
+ let txt = rejectTranfser.split("\n")
let result = await RaygunStoreInstance.send(chat.id, txt, [])
result.onSuccess(res => {
Store.state.paymentTracker.update(payments => {
@@ -336,7 +360,7 @@
if (!alreadyRejected) {
return [...payments, { messageId: message.id, senderId: message.details.origin, rejectedPayment: true }]
} else {
- console.log(`MessageId ${message.id} is already in the rejected payments list`)
+ console.error(`MessageId ${message.id} is already in the rejected payments list`)
return payments
}
})
@@ -344,6 +368,80 @@
ConversationStore.addPendingMessages(chat.id, res.message, txt)
})
}
+ if (paymentType === PaymentRequestsEnum.Send) {
+ try {
+ const jsonStartIndex = message.text[0].indexOf("{")
+ if (jsonStartIndex === -1) {
+ throw new Error("No JSON part found in message")
+ }
+ const jsonPart = message.text[0].slice(jsonStartIndex)
+ const paymentDetails = JSON.parse(jsonPart)
+ const kind = paymentDetails.asset?.kind || "unknown"
+ const amount = paymentDetails.amountPreview || "0"
+ const toAddress = paymentDetails.toAddress || "0"
+ const formattedMessage = transfer.toDisplayString(kind, amount, toAddress, message.id)
+
+ let chat = get(Store.state.activeChat)
+ let txt = formattedMessage.split("\n")
+
+ let walletSuccess = await getValidPaymentRequest(line, message.id)?.execute()
+ if (walletSuccess) {
+ let result = await RaygunStoreInstance.send(chat.id, txt, [])
+ result.onSuccess(res => {
+ Store.state.paymentTracker.update(payments => {
+ const alreadyRejected = payments.some(payment => payment.messageId === message.id)
+
+ if (!alreadyRejected) {
+ return [...payments, { messageId: message.id, senderId: message.details.origin, rejectedPayment: false }]
+ } else {
+ console.error(`MessageId ${message.id} is already in the rejected payments list`)
+ return payments
+ }
+ })
+ ConversationStore.addPendingMessages(chat.id, res.message, txt)
+ })
+ } else {
+ let rejectTranfser = transfer.toRejectString(message.id)
+ let txt = rejectTranfser.split("\n")
+ let result = await RaygunStoreInstance.send(chat.id, txt, [])
+ result.onSuccess(res => {
+ Store.state.paymentTracker.update(payments => {
+ const alreadyRejected = payments.some(payment => payment.messageId === message.id)
+
+ if (!alreadyRejected) {
+ return [...payments, { messageId: message.id, senderId: message.details.origin, rejectedPayment: true }]
+ } else {
+ console.error(`MessageId ${message.id} is already in the rejected payments list`)
+ return payments
+ }
+ })
+ transfer.toRejectString(message.id)
+ ConversationStore.addPendingMessages(chat.id, res.message, txt)
+ })
+ Store.addToastNotification(new ToastMessage("", "Error extracting payment details or sending message:", 4, undefined, Appearance.Warning))
+ }
+ } catch (error) {
+ let rejectTranfser = transfer.toRejectString(message.id)
+ let txt = rejectTranfser.split("\n")
+ let result = await RaygunStoreInstance.send(chat.id, txt, [])
+ result.onSuccess(res => {
+ Store.state.paymentTracker.update(payments => {
+ const alreadyRejected = payments.some(payment => payment.messageId === message.id)
+
+ if (!alreadyRejected) {
+ return [...payments, { messageId: message.id, senderId: message.details.origin, rejectedPayment: true }]
+ } else {
+ console.error(`MessageId ${message.id} is already in the rejected payments list`)
+ return payments
+ }
+ })
+ transfer.toRejectString(message.id)
+ ConversationStore.addPendingMessages(chat.id, res.message, txt)
+ })
+ Store.addToastNotification(new ToastMessage("", "Error extracting payment details or sending message:", 4, undefined, Appearance.Warning))
+ console.error("Error extracting payment details or sending message:", error)
+ }
+ }
}
let activeCallInProgress = false
@@ -372,13 +470,30 @@
}
}, 500)
})
-
+ $: sanitizePaymentSent
function checkForActiveRequest(message: MessageType, messageLine: string) {
- const idMatch = messageLine.match(/^\/reject\s([a-f0-9-]{36})$/)
- if (idMatch) {
- const messageId = idMatch[1]
+ const rejectidMatch = messageLine.match(/^\/reject\s([a-f0-9-]{36})(?:\s|$)/)
+ const sendidMatch = messageLine.match(/^\/send\s.*"messageID":"([a-f0-9-]{36})"/)
+ if (rejectidMatch) {
+ const messageId = rejectidMatch[1]
+ let wasAdded = false
+ Store.state.paymentTracker.update(payments => {
+ const alreadyRejected = payments.some(payment => payment.messageId === messageId)
+
+ if (!alreadyRejected) {
+ wasAdded = true
+ return [...payments, { messageId, senderId: message.details.origin, rejectedPayment: true }]
+ }
+ return payments
+ })
+ return wasAdded
+ }
+
+ if (sendidMatch) {
+ const messageId = sendidMatch[1]
let wasAdded = false
+
Store.state.paymentTracker.update(payments => {
const alreadyRejected = payments.some(payment => payment.messageId === messageId)
@@ -391,6 +506,7 @@
return wasAdded
}
+
return false
}
@@ -425,7 +541,6 @@
if (group.details.at > $activeChat.last_view_date) {
unreads.push(group)
} else {
- // Individual messages in a group can still be new since messages are grouped each min
let [readMessages, unreadsMessages] = splitMessages(group)
if (unreadsMessages.length > 0) {
unreads.push({
@@ -819,13 +934,21 @@
{#each message.text as line}
{#if line.startsWith(PaymentRequestsEnum.Reject)}
{#if !checkForActiveRequest(message, line)}
- {#if $own_user.key !== message.details.origin}
+ {#if $own_user.key === message.details.origin}
+
+ {:else}
- {:else}
-
+ {/if}
+ {/if}
+ {:else if line.startsWith(PaymentRequestsEnum.Send)}
+ {#if !checkForActiveRequest(message, line)}
+ {#if $own_user.key !== message.details.origin}
+ {sanitizePaymentSent}
+ {:else if $own_user.key === message.details.origin}
+ {sanitizePaymentSent}
{/if}
{/if}
{:else if getValidPaymentRequest(line) !== undefined}
@@ -836,39 +959,41 @@
hook="text-chat-message"
class="send_coin"
text={sanitizePaymentRequest(line, resolved.name)}
- on:click={async () => getValidPaymentRequest(line, message.id)?.execute()}>
+ on:click={async () => {
+ sendPaymentMessage(message, line, PaymentRequestsEnum.Send)
+ }}>
- {:else if !checkForActiveRequest(message, line)}
+ {:else if !checkForActiveRequest(message, line) && !$rejectedPayments.some(payment => payment.messageId === message.id)}
{:else}
{/if}
- {:else if $own_user.key === message.details.origin && !checkForActiveRequest(message, line)}
-
+ {:else if !line.startsWith(PaymentRequestsEnum.Send) && $rejectedPayments.some(payment => payment.messageId === message.id && !payment.rejectedPayment)}
+
{:else}
-
+
{/if}
{:else if !line.includes(tempCDN)}
@@ -1046,7 +1171,6 @@
{/if}
{#if contentAsideOpen}
-