diff --git a/package.json b/package.json index 618d2c9..edd28b1 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "license": "ISC", "dependencies": { "@drift-labs/sdk": "^2.86.0-beta.0", + "@solana/actions": "^1.1.2", "@solana/spl-token": "^0.4.7", "@solana/web3.js": "^1.94.0", "compression": "^1.7.4", diff --git a/src/routes/index.ts b/src/routes/index.ts index 6501b9e..e6f5a08 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -1,9 +1,9 @@ import express, { Request, Response } from 'express'; -import { - ActionsSpecGetResponse, - ActionsSpecPostResponse, - ActionsSpecErrorResponse, -} from '../types/solana-actions'; +import { + ActionError, + ActionGetResponse, + ActionPostResponse, +} from '@solana/actions'; import { Connection, PublicKey, @@ -150,7 +150,7 @@ router.get('/blinks/deposit', async (req: Request, res: Response) => { const queryParams = new URLSearchParams(queryParamsObject).toString(); - const links: ActionsSpecGetResponse['links'] = { + const links: ActionGetResponse['links'] = { actions: [ { href: `${HOST}/transactions/deposit?${queryParams}&amount={${amountQuery}}`, @@ -164,8 +164,8 @@ router.get('/blinks/deposit', async (req: Request, res: Response) => { }, ], }; - - const response: ActionsSpecGetResponse = { + + const response: ActionGetResponse = { icon, label, title, @@ -181,7 +181,7 @@ router.get('/blinks/deposit', async (req: Request, res: Response) => { router.post('/transactions/deposit', async (req: Request, res: Response) => { const returnErrorResponse = (message: string) => { - return res.status(400).json({ message } as ActionsSpecErrorResponse); + return res.status(400).json({ message } as ActionError); }; const utmObject = req.query.utm_source @@ -333,7 +333,7 @@ router.post('/transactions/deposit', async (req: Request, res: Response) => { ); } - const actionResponse: ActionsSpecPostResponse = { + const actionResponse: ActionPostResponse = { transaction: uint8ArrayToBase64(txn.serialize()), message: `Successfully deposited ${token}. Visit ${DRIFT_MAIN_APP_URL} to view your deposit.`, }; diff --git a/src/types/solana-actions.ts b/src/types/solana-actions.ts deleted file mode 100644 index 41ce45b..0000000 --- a/src/types/solana-actions.ts +++ /dev/null @@ -1,63 +0,0 @@ -// Following types are obtained from https://github.com/dialectlabs/actions/blob/main/spec/actions-spec.ts - -interface SolanaPaySpecGetResponse { - label: string; - icon: string; -} - -interface SolanaPaySpecPostRequestBody { - account: string; // transaction signer public key -} - -interface SolanaPaySpecPostResponse { - transaction: string; // base64-encoded serialized transaction - message?: string; // the nature of the transaction response e.g. the name of an item being purchased - redirect?: string; // redirect URL after the transaction is successful -} - -export interface ActionsSpecGetResponse extends SolanaPaySpecGetResponse { - icon: string; // image - label: string; // button text - title: string; - description: string; - disabled?: boolean; // allows to model invalid state of the action e.g. nft sold out - links?: { - // linked actions inspired by HAL https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-11 - actions: LinkedAction[]; - }; - // optional error indication for non-fatal errors, if present client should display it to the user - // doesn't prevent client from interpreting the action or displaying it to the user - // e.g. can be used together with 'disabled' to display the reason e.g. business constraint failure - error?: ActionError; -} - -export type ActionsSpecPostResponse = SolanaPaySpecPostResponse; - -// Linked action inspired by HAL https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-11 -export interface LinkedAction { - href: string; // solana pay/actions get/post url - label: string; // button text - // optional parameters for the action, e.g. input fields, inspired by OpenAPI - // enforcing single parameter for now for simplicity and determenistic client UIs - // can be extended to multiple inputs w/o breaking change by switching to Parameter[] - // note: there are no use-cases for multiple parameters atm, e.g. farcaster frames also have just single input - parameters?: [Parameter]; -} - -export interface Parameter { - name: string; // parameter name in url - label?: string; // input placeholder -} - -// No changes -export type ActionsSpecPostRequestBody = SolanaPaySpecPostRequestBody; - -// A common error data structure that should be used in all responses for error indication, -// can be used in both GET and POST and extended with additional fields if needed -export interface ActionError { - message: string; -} - -// Error response that can be used in both GET and POST for non 200 status codes -// interoperable with: https://github.com/anza-xyz/solana-pay/blob/master/SPEC1.1.md#error-handling -export type ActionsSpecErrorResponse = ActionError; diff --git a/yarn.lock b/yarn.lock index c39be8c..20510a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -254,7 +254,7 @@ snake-case "^3.0.4" spok "^1.4.3" -"@noble/curves@^1.0.0", "@noble/curves@^1.4.0": +"@noble/curves@^1.0.0", "@noble/curves@^1.4.0", "@noble/curves@^1.4.2": version "1.4.2" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== @@ -421,6 +421,18 @@ bs58 "^5.0.0" jito-ts "^3.0.1" +"@solana/actions@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@solana/actions/-/actions-1.1.2.tgz#3b4716e167c1def9e3a00a1f5ad78caffa633dc7" + integrity sha512-VXGkDSvVd/rRb10iQ2MLRUPXG8LsxsbV052x8Hdzr4nR827sxzNFDCDST7vo9knVsQWiJ/IChok8aiqRJVM83A== + dependencies: + "@solana/qr-code-styling" "^1.6.0" + "@solana/web3.js" "^1.61.0" + bs58 "^5.0.0" + cross-fetch "^3.1.5" + js-base64 "^3.7.2" + tweetnacl "^1.0.3" + "@solana/buffer-layout-utils@^0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@solana/buffer-layout-utils/-/buffer-layout-utils-0.2.0.tgz#b45a6cab3293a2eb7597cceb474f229889d875ca" @@ -498,6 +510,13 @@ "@solana/codecs-core" "2.0.0-preview.2" "@solana/codecs-numbers" "2.0.0-preview.2" +"@solana/qr-code-styling@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@solana/qr-code-styling/-/qr-code-styling-1.6.0.tgz#8693bae79ace4b81135e032ee0b60f1ad739c3ef" + integrity sha512-KyBmyFKPxQPhUkP0jjnxV2ZeF1R1guTD8Hrd0YvHvMnhtrNEoEEdv4Jpp4W0GN4qCGG2KYOM5d3TgoLD+CNf9Q== + dependencies: + qrcode-generator "^1.4.3" + "@solana/spl-token-group@^0.0.3": version "0.0.3" resolved "https://registry.yarnpkg.com/@solana/spl-token-group/-/spl-token-group-0.0.3.tgz#e47b0db49cd17c166101cc7650d50a9ee80cba13" @@ -605,6 +624,27 @@ rpc-websockets "^9.0.2" superstruct "^1.0.4" +"@solana/web3.js@^1.61.0": + version "1.95.0" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.95.0.tgz#9cf08383e7dcba212a73d78349cf9b25bc34764f" + integrity sha512-iHwJ/HcWrF9qbnI1ctwI1UXHJ0vZXRpnt+lI5UcQIk8WvJNuQ5gV06icxzM6B7ojUES85Q1/FM4jZ49UQ8yZZQ== + dependencies: + "@babel/runtime" "^7.24.7" + "@noble/curves" "^1.4.2" + "@noble/hashes" "^1.4.0" + "@solana/buffer-layout" "^4.0.1" + agentkeepalive "^4.5.0" + bigint-buffer "^1.1.5" + bn.js "^5.2.1" + borsh "^0.7.0" + bs58 "^4.0.1" + buffer "6.0.3" + fast-stable-stringify "^1.0.0" + jayson "^4.1.0" + node-fetch "^2.7.0" + rpc-websockets "^9.0.2" + superstruct "^2.0.2" + "@solana/web3.js@~1.77.3": version "1.77.4" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.77.4.tgz#aad8c44a02ced319493308ef765a2b36a9e9fa8c" @@ -2093,6 +2133,11 @@ jito-ts@^3.0.1: node-fetch "^2.6.7" superstruct "^1.0.3" +js-base64@^3.7.2: + version "3.7.7" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.7.tgz#e51b84bf78fbf5702b9541e2cb7bfcb893b43e79" + integrity sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw== + js-sha256@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" @@ -2485,6 +2530,11 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== +qrcode-generator@^1.4.3: + version "1.4.4" + resolved "https://registry.yarnpkg.com/qrcode-generator/-/qrcode-generator-1.4.4.tgz#63f771224854759329a99048806a53ed278740e7" + integrity sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw== + qs@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -2822,6 +2872,11 @@ superstruct@^1.0.3, superstruct@^1.0.4: resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== +superstruct@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54" + integrity sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -2925,6 +2980,11 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"