{"id":15172221,"url":"https://github.com/laugharne/ssf_s6_exo","last_synced_at":"2026-01-24T05:35:09.068Z","repository":{"id":255311089,"uuid":"844428827","full_name":"Laugharne/ssf_s6_exo","owner":"Laugharne","description":"Build a Point-Of-Sale Web UI for adding products and checking out with Solana Pay. The payment confirmation should be displayed after checkout.","archived":false,"fork":false,"pushed_at":"2024-09-13T05:46:33.000Z","size":3695,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-19T05:42:26.144Z","etag":null,"topics":["fellowship","solana","solana-pay","summer","typescript","web3js"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Laugharne.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-19T08:38:16.000Z","updated_at":"2024-09-13T05:46:36.000Z","dependencies_parsed_at":"2024-08-29T08:18:22.124Z","dependency_job_id":"096636b9-1a4c-4dbd-823d-e81ef671b72e","html_url":"https://github.com/Laugharne/ssf_s6_exo","commit_stats":{"total_commits":9,"total_committers":1,"mean_commits":9.0,"dds":0.0,"last_synced_commit":"91229cbafe70f0ac1773196ed29cedaf2a486aa1"},"previous_names":["laugharne/ssf_s6_exo"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Laugharne%2Fssf_s6_exo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Laugharne%2Fssf_s6_exo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Laugharne%2Fssf_s6_exo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Laugharne%2Fssf_s6_exo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Laugharne","download_url":"https://codeload.github.com/Laugharne/ssf_s6_exo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239605124,"owners_count":19666998,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fellowship","solana","solana-pay","summer","typescript","web3js"],"created_at":"2024-09-27T09:42:43.980Z","updated_at":"2025-11-13T08:30:16.268Z","avatar_url":"https://github.com/Laugharne.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Solana Pay Point-Of-Sale\n\n![](assets/2024-08-24-14-30-12.png)\n\n\nBuild a **Point-Of-Sale Web UI** for adding products and checking out with **Solana Pay**. The payment confirmation should be displayed after checkout.\n\n\n\u003e Not being a \"front-end\" developer, I started from a robust [existing base](https://github.com/anza-xyz/solana-pay/tree/master/examples/point-of-sale) as framework to help me, in order to minimize the NextJS development time and focus mainly on understanding **Solana Pay** itself. It will be used as a model for future developement.\n\n\n--------\n\n**TABLE OF CONTENTS**\n\n\n\u003c!-- TOC --\u003e\n\n- [Solana Pay Point-Of-Sale](#solana-pay-point-of-sale)\n\t- [Installation](#installation)\n\t- [Usage with screenshots](#usage-with-screenshots)\n\t\t- [On Web UI](#on-web-ui)\n\t\t- [On Mobile phone](#on-mobile-phone)\n\t\t- [Transaction details](#transaction-details)\n\t- [Overview of application](#overview-of-application)\n\t\t- [\"QRCode.tsx\"](#qrcodetsx)\n\t\t\t- [Payment URL](#payment-url)\n\t\t\t- [QR Code generation](#qr-code-generation)\n\t\t\t- [Rendering the component](#rendering-the-component)\n\t\t- [\"index.ts\"](#indexts)\n\t\t\t- [Code overview](#code-overview)\n\t\t\t- [GET handler](#get-handler)\n\t\t\t- [POST handler](#post-handler)\n\t\t\t- [Main handler](#main-handler)\n\t\t- [\"PaymentProvider.tsx\"](#paymentprovidertsx)\n\t\t\t- [Code overview](#code-overview)\n\t\t\t- [Transaction URL Construction - encodeURL](#transaction-url-construction---encodeurl)\n\t\t\t- [Creating and Sending the Transaction](#creating-and-sending-the-transaction)\n\t\t\t- [Waiting for transaction confirmation](#waiting-for-transaction-confirmation)\n\t- [Resources](#resources)\n\n\u003c!-- /TOC --\u003e\n\n\n\n--------\n\n\n## Installation\n\n**Clone the repo:**\n\n```bash\ngit clone https://github.com/Laugharne/ssf_s6_exo.git\n```\n\n**Install dependencies:**\n\n```bash\nnpm install\n```\n\n**Starting a local dev server:**\n\n```bash\nnpm run dev\n```\n\n**Starting a local proxy:**\n\nIn an other terminal (_same path_) run the server who handles responses and transactions.\n\n```bash\nnpm run proxy\n```\n\n**Local URL:**\n\n[` https://localhost:3001?recipient=26BLvEsyA6n1eVDyV8U4g78V47M7v6PQ4QHmedV12mz5\u0026label=Solana+Summer+Pizza `](https://localhost:3001?recipient=26BLvEsyA6n1eVDyV8U4g78V47M7v6PQ4QHmedV12mz5\u0026label=Solana+Summer+Pizza)\n\nYou need **two wallets** to use the app\n1. One to interact with the app. (_You can use Phantom or any other wallet that supports Solana._)\n2. And another wallet serving as the shop's cash register.\n\nBoth need to be funded with SOL, one for payments and the other to facilitate transactions.\n\n\n\n## Usage with screenshots\n\nThe final goal of the exercise being simply to complete a transaction with Solana Pay, I didn't bother to implement a dynamic conversion from Euros to SOL or to make a payment in USDC. The conversion rate is therefore **hard-coded** into the code!\n\nThe application is utilizing the mainnet for this occasion, as **the devnet has been notably unstable in recent days!**\n\nTo use the application, please ensure you have enough SOL in your wallets.\n\n\n### On Web UI\n\n![](assets/2024-08-26-11-21-55.png)\n\nI have just selected the **\"Special ONE\" pizza** for the demo !\n\n![](assets/2024-08-26-11-22-09.png)\n\nIt costs only **0.0069981 SOL**\n\n![](assets/2024-08-26-11-22-21.png)\n\nThe **QR-Code** generated for ths transaction is:\n\n![](assets/2024-08-26-11-22-36.png)\n\n\n### On Mobile phone\n\nAfter scanning the QR-Code with the **Phantom** app of the **mobile phone**, we will see how much it will cost (_fee included_)\n\n![](assets/phone1.png)\n\nConfimation of the transaction\n\n![](assets/phone2.png)\n\nTransaction listed on the recent **activity list**...\n\n![](assets/phone3.png)\n\n\n### Transaction details\n\n- [Solscan](https://solscan.io/tx/4ARWs3xBhpTmTS1NLKhCM4nxyYC5uq9RND6JNVAGqjAWsjpHH1hXAB9yucMEMAHYDrGGfmcrbWtM9A5XSxN6FWqq)\n- [Solana Explorer](https://solana.fm/tx/4ARWs3xBhpTmTS1NLKhCM4nxyYC5uq9RND6JNVAGqjAWsjpHH1hXAB9yucMEMAHYDrGGfmcrbWtM9A5XSxN6FWqq?cluster=mainnet-alpha)\n\n\n## Overview of application\n\nOverall, the transaction process with Solana Pay involves several steps, including generating a transaction request URL, retrieving the label and icon for the transaction, creating a transfer transaction, signing the transaction with the wallet, and submitting the transaction to the Solana network.\n\n![](assets/2024-08-25-14-21-41.png)\n\nThis overview connects with the code examples provided in **several source files** and Solana Pay implementation, illustrating how each element contributes to the overall payment process.\n\n\n### \"QRCode.tsx\"\n\n\u003e src/client/components/contexts/QRCode.tsx\n\nThis `QRCode` component is designed to display dynamically a **QR code** based on a **payment URL**.\n\n\n**Imports needed:**\n\n```typescript\nimport { createQROptions } from '@solana/pay';\nimport QRCodeStyling from '@solana/qr-code-styling';\n```\n\n#### Payment URL\n\n```typescript\nconst { url } = usePayment();\n```\nThis hook retrieves the necessary payment data, specifically the payment URL (`url`), which is used to generate the **QR code**.\n\n\n#### QR Code generation\n\n**QR Code options**\n\n```typescript\nconst [size, setSize] = useState(() =\u003e\n    typeof window === 'undefined' ? 400 : Math.min(window.screen.availWidth - 48, 400)\n);\n```\nThe state `size` represents the size of the QR code. If the code is executed server-side (`typeof window === 'undefined'`), the default size is set to 400 pixels. Otherwise, it calculates the size based on the available screen width (`window.screen.availWidth`), minus 48 pixels, with a maximum of 400 pixels.\n\n```typescript\nconst options = useMemo(() =\u003e createQROptions(url, size, 'transparent', '#2a2a2a'), [url, size]);\n```\nThe QR code options, generated by `createQROptions()`, are recalculated only when the payment URL (`url`) or the size (`size`) changes. This optimizes performance by avoiding unnecessary recalculations.\n\n\n**QR Code instance**\n\n```typescript\nconst qr = useMemo(() =\u003e new QRCodeStyling(), []);\n```\nThis library allows the creation of customized QR codes. `useMemo` ensures that the `QRCodeStyling` instance is only created once (on the first render).\n\n\n#### Rendering the component\n\n```typescript\nuseEffect(() =\u003e qr.update(options), [qr, options]);\n```\nWhenever the **QR code options** change (_due to changes in the URL or size_), the **QR code instance** is updated with the new options.\n\n```typescript\nconst ref = useRef\u003cHTMLDivElement\u003e(null);\n```\nThis reference is used to directly access a DOM element (`div`) where the **QR code** will be rendered.\n\n```typescript\nuseEffect(() =\u003e {\n    if (ref.current) {\n        qr.append(ref.current);\n    }\n}, [ref, qr]);\n```\nOnce the `ref` to the `div` is set (_not null_), the QR code is appended to this DOM element using the `append()` method.\n\n```typescript\nreturn \u003cdiv ref={ref} className={css.root} /\u003e;\n```\nThe component returns a simple `div` with a reference (`ref`) and a CSS class. This `div` is where the QR code will be rendered.\n\n\n### \"index.ts\"\n\n\u003e src/server/api/index.tsx\n\n#### Code overview\n\nThis code defines an API route in a Next.js application that interacts with the Solana blockchain using Solana Pay.\n\nThe route handles both `GET` and `POST` requests for this two  functionalities:\n1. Serving metadata about the payment (_like a label and icon_).\n2. Creating a Solana transaction for a payment request.\n\nThis API route is designed to facilitate payments on the Solana blockchain using Solana Pay. It provides a way to fetch metadata about a payment request via a `GET` request and to create a payment transaction via a `POST` request.\n\n#### GET handler\n\nThe `get` function handles `GET` requests and returns metadata for the payment request.\n\n```typescript\ninterface GetResponse {\n    label: string;\n    icon : string;\n}\n\nconst get: NextApiHandler\u003cGetResponse\u003e = async (request, response) =\u003e {\n    const label = request.query.label;\n    if (!label) throw new Error('missing label');\n    if (typeof label !== 'string') throw new Error('invalid label');\n\n    const icon = `https://${request.headers.host}/solana-pay-logo.svg`;\n\n    response.status(200).send({\n        label,\n        icon,\n    });\n};\n```\n\n#### POST handler\n\nThe `post` function handles `POST` requests to create a Solana transaction.\n\n**Input Validation**: The function validates several parameters from the query string (`recipient`, `amount`, `spl-token`, `reference`, `memo`, and `message`) and the request body (`account`).\n\n**Transaction creation**:\n\n- **`createTransfer`**: A transaction is created using the `createTransfer` function, which constructs a transfer operation on the Solana blockchain with the provided parameters (e.g., recipient, amount, SPL token, reference, and memo).\n```typescript\nlet transaction = await createTransfer(connection, account, {\n    recipient,\n    amount,\n    splToken,\n    reference,\n    memo,\n});\n```\n- **Serialization**: The transaction is serialized and deserialized to ensure consistent ordering of account keys, which is important for signature verification.\n\n```typescript\ntransaction = Transaction.from(\n    transaction.serialize({\n        verifySignatures    : false,\n        requireAllSignatures: false,\n    })\n);\n```\n- **Response**: The serialized transaction is converted to a base64 string and returned to the client along with an optional message.\n```typescript\nconst serialized = transaction.serialize({\n    verifySignatures    : false,\n    requireAllSignatures: false,\n});\nconst base64 = serialized.toString('base64');\n\nresponse.status(200).send({ transaction: base64, message });\n```\n\n#### Main handler\n\nThe `index` function serves as the main API handler.\n\n```typescript\nconst index: NextApiHandler\u003cGetResponse | PostResponse\u003e = async (request, response) =\u003e {\n    await cors(request, response);\n    await rateLimit(request, response);\n\n    if (request.method === 'GET') return get(request, response);\n    if (request.method === 'POST') return post(request, response);\n\n    throw new Error(`Unexpected method ${request.method}`);\n};\n```\n\n- **Middleware Execution**: Runs CORS and rate-limiting middleware to ensure that the API is accessed appropriately and to prevent abuse.\n- **Request Routing**: Depending on the HTTP method, it delegates the request to the appropriate handler.\n\n\n### \"PaymentProvider.tsx\"\n\n\u003e src/client/components/sections/QRCode.tsx\n\n#### Code overview\n\n- **Connection to Solana**: Interaction with the blockchain is enabled via the `connection` object.\n- **Wallet Integration**: User transactions are facilitated through their connected wallet.\n- **Transaction Management**: The code handles the entire lifecycle of a transaction, from creation to finalization.\n- **Real-time Monitoring**: The system continuously checks for transaction confirmations and validates them to ensure the payment process is secure and accurate.\n\n\n#### Transaction URL Construction - `encodeURL()`\n\n```typescript\nconst url = useMemo(() =\u003e {\n    // ...\n    // URL generation logic based on whether a link is provided\n    // ...\n}, [link, recipient, amount, splToken, reference, label, message, memo]);\n```\nThis memoized function constructs the **payment URL**, which encodes all the necessary payment details.\n\n**`encodeURL()`:**\n\nLet’s delve into the `encodeURL()`. This function plays a critical role in **generating the payment URL**, which encodes all the necessary details for the transaction.\n\nThe `encodeURL()` function is part of the S**olana Pay SDK**. Its primary role is to take the payment parameters (like the recipient, amount, SPL token, etc...) and encode them into a URL format that can be shared or used to initiate a payment.\n\nThis URL can be processed by **wallets** or **payment gateways** to complete the transaction.\n\n`encodeURL()` is used inside a `useMemo` hook to generate a **payment URL**:\n\nThe code checks if a `link` is provided:\n- If `link` exist The URL is built using the provided link as a base, and additional payment parameters (like `recipient`, `amount`, etc...) are appended as query parameters.\n- Else The URL is constructed from scratch using the provided payment parameters.\n\n```typescript\nconst url = useMemo(() =\u003e {\n    if (link) {\n        const url = new URL(String(link));\n\n        url.searchParams.append('recipient', recipient.toBase58());\n\n        if (amount) {\n            url.searchParams.append('amount', amount.toFixed(amount.decimalPlaces() ?? 0));\n        }\n\n        if (splToken) {\n            url.searchParams.append('spl-token', splToken.toBase58());\n        }\n\n        if (reference) {\n            url.searchParams.append('reference', reference.toBase58());\n        }\n\n        if (memo) {\n            url.searchParams.append('memo', memo);\n        }\n\n        if (label) {\n            url.searchParams.append('label', label);\n        }\n\n        if (message) {\n            url.searchParams.append('message', message);\n        }\n\n        return encodeURL({ link: url });\n    } else {\n        return encodeURL({\n            recipient,\n            amount,\n            splToken,\n            reference,\n            label,\n            message,\n            memo,\n        });\n    }\n}, [link, recipient, amount, splToken, reference, label, message, memo]);\n```\n\n**Payment Parameters**:\n\n- The `recipient` public key is encoded in the URL. This key specifies where the payment is sent.\n- If an `amount` is specified, it is encoded in the URL, rounded to the appropriate number of decimal places.\n- If the payment involves an `SPL token`, its public key is included.\n- A `reference` public key that can be used to track the payment is added to the URL.\n- An optional `memo` field is included, which can hold a note or other small pieces of data.\n- The `label` and `message` fields can include metadata about the payment, like a label for the transaction or a message to the recipient.\n\n**This URL can be shared or scanned**.\n\nAnd a wallet can use it to automatically fill in the details for the payment.\n\n\n#### Creating and Sending the Transaction\n\n```typescript\nuseEffect(() =\u003e {\n    if (status === PaymentStatus.Pending \u0026\u0026 connectWallet \u0026\u0026 publicKey) {\n        let changed = false;\n\n        const run = async () =\u003e {\n            try {\n                const request = parseURL(url);\n                let transaction: Transaction;\n\n                if ('link' in request) {\n                    const { link } = request;\n                    transaction = await fetchTransaction(connection, publicKey, link);\n                } else {\n                    const { recipient, amount, splToken, reference, memo } = request;\n                    if (!amount) return;\n\n                    transaction = await createTransfer(connection, publicKey, {\n                        recipient,\n                        amount,\n                        splToken,\n                        reference,\n                        memo,\n                    });\n                }\n\n                if (!changed) {\n                    await sendTransaction(transaction, connection);\n                }\n            } catch (error) {\n                console.error(error);\n                timeout = setTimeout(run, 5000);\n            }\n        };\n        let timeout = setTimeout(run, 0);\n\n        return () =\u003e {\n            changed = true;\n            clearTimeout(timeout);\n        };\n    }\n}, [status, connectWallet, publicKey, url, connection, sendTransaction]);\n```\nThis `useEffect` handles the creation and sending of the transaction. Depending on whether a `link` is provided or not, the transaction is either fetched from a link or created with the provided details (recipient, amount, etc...).\n\nThen the transaction is sent using the connected wallet’s `sendTransaction()` method.\n\n\n#### Waiting for transaction confirmation\n\n```typescript\nuseEffect(() =\u003e {\n    if (status === PaymentStatus.Pending \u0026\u0026 reference \u0026\u0026 !signature) {\n        const interval = setInterval(async () =\u003e {\n            try {\n                const foundSignature = await findReference(connection, reference);\n                setSignature(foundSignature.signature);\n                setStatus(PaymentStatus.Confirmed);\n            } catch (error) {\n                if (!(error instanceof FindReferenceError)) console.error(error);\n            }\n        }, 250);\n        return () =\u003e clearInterval(interval);\n    }\n}, [status, reference, signature, connection]);\n```\nThis effect continuously polls the blockchain to find a signature for the transaction. Once the transaction is found and confirmed, the status is updated to `Confirmed`.\n\n\n**Transaction validation**\n\n```typescript\nuseEffect(() =\u003e {\n    if (status === PaymentStatus.Confirmed \u0026\u0026 signature \u0026\u0026 amount) {\n        const run = async () =\u003e {\n            try {\n                await validateTransfer(connection, signature, {\n                    recipient,\n                    amount,\n                    splToken,\n                    reference,\n                });\n                setStatus(PaymentStatus.Valid);\n            } catch (error) {\n                console.warn(error);\n                setTimeout(run, 250); // Retry on failure\n            }\n        };\n        run();\n    }\n}, [status, signature, amount, connection, recipient, splToken, reference]);\n```\nOnce a transaction is confirmed, this effect validates the transaction details against what was expected. If the validation is successful, the status is updated to `Valid`.\n\n**Payment status**\n\nSee `PaymentStatus` in `src/client/hooks/usePayment.ts`\n\n```typescript\nexport enum PaymentStatus {\n    New       = 'New',\n    Pending   = 'Pending',\n    Confirmed = 'Confirmed',\n    Valid     = 'Valid',\n    Invalid   = 'Invalid',\n    Finalized = 'Finalized',\n}\n```\n\n\n\n\n**Confirmations**\n\n```typescript\n    useEffect(() =\u003e {\n        if (!(status === PaymentStatus.Valid \u0026\u0026 signature)) return;\n        let changed = false;\n\n        const interval = setInterval(async () =\u003e {\n            try {\n                const response = await connection.getSignatureStatus(signature);\n                const status   = response.value;\n                if (!status) return;\n                if (status.err) throw status.err;\n\n                if (!changed) {\n                    const confirmations = (status.confirmations || 0) as Confirmations;\n                    setConfirmations(confirmations);\n\n                    if (confirmations \u003e= requiredConfirmations || status.confirmationStatus === 'finalized') {\n                        clearInterval(interval);\n                        setStatus(PaymentStatus.Finalized);\n                    }\n                }\n            } catch (error: any) {\n                console.log(error);\n            }\n        }, 250);\n\n        return () =\u003e {\n            changed = true;\n            clearInterval(interval);\n        };\n    }, [status, signature, connection, requiredConfirmations]);\n```\n\nThis effect monitors the transaction confirmations. It checks if the transaction has reached the required number of confirmations to be considered finalized. Once finalized, the status is updated accordingly.\n\n\n\n## Resources\n\n**Introduction:**\n- [Solana Pay explained in 100 seconds - YouTube](https://www.youtube.com/watch?v=nV6Y8nXS5-U)\n- [A decentralized, permissionless, and open-source payments protocol | Solana Pay](https://solanapay.com/fr)\n- [Solana Pay | Solana](https://solana.com/developers/courses/solana-pay/solana-pay)\n\n**Quicknode:**\n- [What is Solana Pay and How to Use It](https://www.quicknode.com/guides/solana-development/solana-pay/getting-started-with-solana-pay)\n- [How to Use Solana Pay with Custom Solana Programs](https://www.quicknode.com/guides/solana-development/solana-pay/beyond-pay-custom-programs)\n\n**Anza:**\n- [GitHub - anza-xyz/solana-pay: A new standard for decentralized payments.](https://github.com/anza-xyz/solana-pay)\n- [solana-pay/examples/point-of-sale at master · anza-xyz/solana-pay · GitHub](https://github.com/anza-xyz/solana-pay/tree/master/examples/point-of-sale)\n- [app.solanapay.com/](https://app.solanapay.com/new?recipient=GvHeR432g7MjN9uKyX3Dzg66TqwrEWgANLnnFZXMeyyj\u0026label=Solana+Pay)\n- [A simple guide on how to set up Solana Pay's POS system on Devnet - DEV Community](https://dev.to/tunkunmi/a-simple-guide-on-how-to-set-up-solana-pays-pos-system-on-devnet-1jhl)\n- [Solana Storefront with Solana Pay - YouTube](https://www.youtube.com/watch?v=TBQA29217Kk)\n\n**Python:**\n- [GitHub - Solana-Workshops/storefront-solana-pay: A storefront build with Solana Pay!](https://github.com/Solana-Workshops/storefront-solana-pay)\n- [Solana Workshop: SolanaPay Storefront - YouTube](https://www.youtube.com/watch?v=jG-uJqDMpCY)\n\n**Misc:**\n- [Create a transaction request | Solana Pay Docs](https://docs.solanapay.com/core/transaction-request/merchant-integration)\n- [crates.io: Rust Package Registry](https://crates.io/crates/solana-pay)\n- [solana_pay - Rust](https://docs.rs/solana-pay/latest/solana_pay/)\n- [anchor - Integrating Solana Pay with Rust Code - Solana Stack Exchange](https://solana.stackexchange.com/questions/75/integrating-solana-pay-with-rust-code)\n- [GitHub - 256hax/solana-anchor-react-minimal-example: Solana, Anchor, Metaplex, React Minimal Example. Out of the Box, easy to start!](https://github.com/256hax/solana-anchor-react-minimal-example)\n- [blockchain - Make a Solana program pay for the transaction - Stack Overflow](https://stackoverflow.com/questions/72790319/make-a-solana-program-pay-for-the-transaction)\n- [Solana Pay: Simplify your Transaction Requests [Solana Tutorial] - May 11th '23 - YouTube](https://www.youtube.com/watch?v=8mIBeDMgTDc)\n\n--------\n\n![](assets/julie.png)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaugharne%2Fssf_s6_exo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flaugharne%2Fssf_s6_exo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaugharne%2Fssf_s6_exo/lists"}