From 08b227200b83af7212b4a15b40085445f1e789fc Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Fri, 14 Apr 2023 13:18:05 +0700 Subject: [PATCH] Sell resources endpoint and postgres function --- .gitignore | 1 + README.md | 12 +---- sql/procedures.sql | 54 +++++++++++++++++++ sql/queries.sql | 40 -------------- src/app/page.tsx | 26 +++++---- .../[userId]/{bank-account.ts => account.ts} | 22 ++++---- test-endpoints.restclient | 18 ++++++- 7 files changed, 102 insertions(+), 71 deletions(-) delete mode 100644 sql/queries.sql rename src/pages/api/user/[userId]/{bank-account.ts => account.ts} (67%) diff --git a/.gitignore b/.gitignore index 01ce800..6a97f6f 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ database.db .env /sql/create-users.sql /.dir-locals.el +sql/queries.sql diff --git a/README.md b/README.md index 8484a31..4d45c11 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,5 @@ DB_DATABASE= ## API Endpoints -POST `/user/login` check if user exists -GET `/user/USER_ID/stakes` get stake event -POST `/user/USER_ID/stakes/claim` claim stake -POST `/user/USER_ID/stakes/start` start stake -GET `/user/USER_ID/bank-account` get balance -PUT `/user/USER_ID/bank-account` sell resource -GET `/user/USER_ID/inventory-items` get inventory items -POST `/user/USER_ID/inventory-items` buy item -GET `/user/USER_ID/staking-sources` get staking sources -POST `/user/USER_ID/staking-sources` create staking source +Refer to ~test-endpoints.restclient~ for an up-to-date list of endpoints. If you want to use this to +actually query the endpoints, it's not too hard to setup with Emacs. diff --git a/sql/procedures.sql b/sql/procedures.sql index a106323..de74458 100644 --- a/sql/procedures.sql +++ b/sql/procedures.sql @@ -54,6 +54,60 @@ begin end; $$ language plpgsql; + +create or replace function sell_resources( + p_user_id uuid, + p_resources jsonb +) +returns table ( + "resourceName" text, + "resourceAmount" integer, + "returnAmount" integer, + "saleResult" text +) +as $$ +declare + resource jsonb; + resource_name text; + resource_amount integer; + return_amount integer; + resource_sell_factor real; + sale_result text; +begin + for resource in select * from jsonb_array_elements(p_resources) + loop + resource_name := resource ->> 'resourceType'; + resource_amount := (resource ->> 'resourceAmount')::integer; + sale_result := null; + + begin + update resource_account + set balance = balance - resource_amount + where user_id = p_user_id and resource_id = ( + select id from resource where name = resource_name + ); + exception + when others then + sale_result := 'Error: Insufficient amount'; + end; + + if sale_result is null then + select value into resource_sell_factor + from game_constants + where key = resource_name || 'ToMoonbucks'; + + update bank_account + set balance = balance + resource_amount * resource_sell_factor + where user_id = p_user_id + returning resource_amount * resource_sell_factor into return_amount; + + sale_result := 'Success'; + end if; + return query select resource_name, resource_amount, return_amount, sale_result; + end loop; +end; +$$ language plpgsql; + create or replace function clear_user_data(p_user_id uuid) returns void as $$ diff --git a/sql/queries.sql b/sql/queries.sql deleted file mode 100644 index a2a8d4a..0000000 --- a/sql/queries.sql +++ /dev/null @@ -1,40 +0,0 @@ -select * from users; - -select * from resource; - -select * from resource_account; - -select * from bank_account; - -select * from resource_account -join users on resource_account.user_id = users.id -join resource on resource.id = resource_account.resource_id -where users.name = 'Harry'; - -update bank_account -set balance = 2000 -from users -where bank_account.user_id = users.id and name = 'Joe'; - -select * from staking_source; -select * from resource_well; - -select * from inventory_item; - -select * from upgrade_event; - -delete from upgrade_event; - -update inventory_item set tier = 0; - -select * from staking_event; - -update staking_event set created_at = '2023-03-30 05:05:39.696926+00' -where id = 'e53ef75e-fbb8-453f-a55c-758683bb0bb4'; - -select * from claim_event; - -delete from claim_event; - -alter table store_item alter column price type integer using price::integer; - diff --git a/src/app/page.tsx b/src/app/page.tsx index a83ed66..785be4e 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -75,7 +75,7 @@ export default function Home() { }; const fetchBankAccount = async () => { - const response = await fetch(`/api/user/${userId}/bank-account`); + const response = await fetch(`/api/user/${userId}/account`); const bankAccount = await response.json(); setBankAccount(bankAccount); }; @@ -171,17 +171,27 @@ export default function Home() { } }; - // TODO Joe create sql const sellResource = async (pairs: IConversionPair[]) => { - console.log("Selling resource"); - const response = await fetch(`/api/user/${userId}/bank-account`, { + const response = await fetch(`/api/user/${userId}/account`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ pairs: pairs, }), }); - return await response.json(); + + if (!response.ok) { + const error = await response.text(); + setNotification({ message: error, type: "Error" }); + } + if (response.status == 200) { + const data = await response.json(); + setNotification({ + message: `You've received ${data[0].returnAmount} $MoonBucks`, + type: "Success", + }); + fetchBankAccount(); + } }; const buyStoreItem = async (storeItemId: number) => { @@ -293,10 +303,6 @@ export default function Home() { } }; - const handleSetLightBox = () => { - setLightBoxIsActive(!lightBoxIsActive); - }; - const handleCloseNotification = () => { setNotification(null); }; @@ -316,7 +322,7 @@ export default function Home() { if (isLoading) { return

Loading...

; } - console.log(stakingSources); + return ( <> diff --git a/src/pages/api/user/[userId]/bank-account.ts b/src/pages/api/user/[userId]/account.ts similarity index 67% rename from src/pages/api/user/[userId]/bank-account.ts rename to src/pages/api/user/[userId]/account.ts index 369236e..7d8f213 100644 --- a/src/pages/api/user/[userId]/bank-account.ts +++ b/src/pages/api/user/[userId]/account.ts @@ -8,9 +8,9 @@ export default async function handler( res: NextApiResponse ) { try { + const db = postgresConnection; if (req.method === "GET") { const { userId } = req.query; - const db = postgresConnection; if (!checkIfValidUUID(userId)) { return res.status(400).json({error: "Invalid UUID for user id"}); @@ -23,19 +23,21 @@ export default async function handler( } else { return res.status(400).json({error: "Could not find accounts for user"}); } - } - if (req.method === "PUT") { - // sell resource - // payload userId, key:resourceName/value:amount + } else if (req.method === "PUT") { + const { userId } = req.query; - // an array of IConversionPairs const { pairs } = req.body; - // check they have appropriate amount of each resource - // increment balance - // decrement resources + + const result = await db.query("select * from sell_resources($1, $2)", [userId, JSON.stringify(pairs)]); + if (result.rowCount > 0) { + return res.status(200).json(result.rows); + } else { + return res.status(400).json({error: "Could not find accounts for user"}); + } + } } catch (error) { - res.status(500).json(error); + res.status(500).json(error.message); } } diff --git a/test-endpoints.restclient b/test-endpoints.restclient index 3836ec2..5a1b745 100644 --- a/test-endpoints.restclient +++ b/test-endpoints.restclient @@ -17,9 +17,25 @@ POST http://localhost:3000/api/user/login { "wallet" : "Wallet12345678" } # Get bank account -GET http://localhost:3000/api/user/:user_id/bank-account +GET http://localhost:3000/api/user/:user_id/account :headers +# Sell a resource +PUT http://localhost:3000/api/user/:user_id/account +:headers +{ + "pairs": [ + { + "resourceType": "Sollux", + "resourceAmount": 100 + }, + { + "resourceType": "Novafor", + "resourceAmount": 100 + } + ] +} + # Clear user data POST http://localhost:3000/api/user/:user_id/clear-data :headers