diff --git a/interface/public/images/logo.png b/interface/public/images/logo.png new file mode 100644 index 0000000..b04b168 Binary files /dev/null and b/interface/public/images/logo.png differ diff --git a/interface/src/components/AccountSelector.js b/interface/src/components/AccountSelector.js index 91c6bb1..2a2bb2c 100644 --- a/interface/src/components/AccountSelector.js +++ b/interface/src/components/AccountSelector.js @@ -12,7 +12,6 @@ import { } from "semantic-ui-react"; import { useSubstrate, useSubstrateState } from "../substrate-lib"; -import { formatAmount } from "../utils"; const CHROME_EXT_URL = "https://chrome.google.com/webstore/detail/polkadot%7Bjs%7D-extension/mopnmbcafieddcagagdcbnhejhlodfdd"; @@ -63,10 +62,7 @@ function Main(props) { > - + {!currentAccount ? ( @@ -121,7 +117,7 @@ function BalanceAnnotation(props) { currentAccount && api.query.system .account(acctAddr(currentAccount), (balance) => - setAccountBalance(balance.data.free) + setAccountBalance(balance.data.free.toHuman()) ) .then((unsub) => (unsubscribe = unsub)) .catch(console.error); @@ -132,7 +128,7 @@ function BalanceAnnotation(props) { return currentAccount ? ( ) : null; } diff --git a/interface/src/components/Checkout.js b/interface/src/components/Checkout.js index d88eec6..4db8d9e 100644 --- a/interface/src/components/Checkout.js +++ b/interface/src/components/Checkout.js @@ -4,16 +4,27 @@ import Tabs from "react-bootstrap/Tabs"; import Cards from "react-credit-cards"; import toast, { Toaster } from "react-hot-toast"; +import { web3FromSource } from "@polkadot/extension-dapp"; +import { hexToU8a } from "@polkadot/util"; import "react-credit-cards/es/styles-compiled.css"; +import { useNavigate } from "react-router-dom"; +import { Loader } from "semantic-ui-react"; +import { ss58ToHex, useSubstrateState } from "../substrate-lib"; import { - formatCreditCardNumber, formatCVC, + formatCreditCardNumber, formatExpirationDate, } from "../utils"; +const MERCHANT = + "0xecd07df8b5fdd6c13e776c4720b325423d5c2449520266ca11dfd1735e28f572"; + const Checkout = () => { + const { api, currentAccount, keyring } = useSubstrateState(); + const navigate = useNavigate(); const [quantity, setQuantity] = useState(1); const [amount, setAmount] = useState(0); + const [loading, setLoading] = useState(false); const [cardDetails, setCardDetails] = useState({ cvc: "", @@ -57,7 +68,7 @@ const Checkout = () => { // TODO: Call your backend to create the Checkout session. console.log("cardDetails", cardDetails); - fetch(`${process.env.MODE === "dev" ? "" : "http://0.0.0.0:3000"}/pos/`, { + fetch(`${process.env.MODE === "dev" ? "" : "http://0.0.0.0:3001"}/pos/`, { method: "POST", headers: { "Content-Type": "application/json", @@ -76,154 +87,219 @@ const Checkout = () => { // go back to dashboard if approved if (data.status) { toast.success("Payment confirmed!"); - window.location.href = "/"; + navigate("/dashboard"); } else { toast.error("Transaction failed: " + data.message); } }); }; + const initiateTransfer = async () => { + const { + meta: { source, isInjected }, + } = currentAccount; + + const tx = api.tx.iso8583.initiateTransfer( + currentAccount.publicKey, + hexToU8a(MERCHANT), + amount + ); + + if (isInjected) { + const injector = await web3FromSource(source); + + const hash = await tx.signAndSend(currentAccount.address, { + signer: injector.signer, + }); + toast.success("Transfer initiated with hash " + hash.toHex()); + } else { + // get it from dev accounts + console.log("account", currentAccount.address); + let signer = keyring.getPair(currentAccount.address); + const hash = await tx.signAndSend(signer); + toast.success("Transfer initiated with hash " + hash.toHex()); + } + + setLoading(true); + + // wait for `ProcessedTransaction` event + // navigate to dashboard + api.query.system.events((events) => { + events.forEach((record) => { + // Extract the phase, event and the event types + const { event } = record; + + // Show what we are busy with + console.log(`\t${event.section}:${event.method}})`); + + if ( + event.section === "iso8583" && + event.method === "ProcessedTransaction" + ) { + const data = event.data.toJSON(); + if ( + ss58ToHex(data[0].from) === ss58ToHex(currentAccount.address) && + ss58ToHex(data[0].to) === MERCHANT.substring(2) + ) { + toast.success("Payment confirmed!"); + setLoading(false); + navigate("/"); + } + } + }); + }); + }; return ( -
- -
-
-
-

Random photo

-

Purchase an original photo

-
- Random asset from Picsum + <> + +
+
+ +
+
+

Random photo

+

Purchase an original photo

+
+ Random asset from Picsum +
-
-
-
- - - + + +
+

Number of copies (max 10)

+ + -
-

Number of copies (max 10)

+ +
+
+
+
+ + +
+
+ - - -
-
-
-
- - -
-
- - -
-
- -
-
- -
-
-
+ +
-
+
-
- -
- -
- +
+
+ +
+
+ +
+
+ +
+ +
+ +
-
- + - -
-
- + +
+
+ +
-
- - -
+ + + +
- + ); }; diff --git a/interface/src/components/Dashboard.js b/interface/src/components/Dashboard.js index 8cfcffe..2bcffd4 100644 --- a/interface/src/components/Dashboard.js +++ b/interface/src/components/Dashboard.js @@ -6,7 +6,6 @@ import toast, { Toaster } from "react-hot-toast"; import { Link, useNavigate } from "react-router-dom"; import { Button, Grid, Label, Table } from "semantic-ui-react"; import { u8aToHexCompact, useSubstrateState } from "../substrate-lib"; -import { formatAmount } from "../utils"; const Dashboard = ({ state }) => { const { apiState, currentAccount } = useSubstrateState(); @@ -49,18 +48,18 @@ const Dashboard = ({ state }) => { const DEV_MODE = process.env.MODE === "dev"; const onReverse = async (hash, amount) => { - fetch(`${DEV_MODE ? "" : "http://0.0.0.0:3000"}/reverse`, { + fetch(`${DEV_MODE ? "" : "http://0.0.0.0:3001"}/reverse`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ - cardNumber: currentAccount.card_number, + cardNumber: bankAccount.card_number, cardExpiration: - currentAccount.card_expiration_date.slice(5, 7) + + bankAccount.card_expiration_date.slice(5, 7) + "/" + - currentAccount.card_expiration_date.slice(2, 4), - cvv: currentAccount.card_cvv, + bankAccount.card_expiration_date.slice(2, 4), + cvv: bankAccount.card_cvv, amount: amount.toString(), txHash: hash, }), @@ -139,9 +138,7 @@ const Dashboard = ({ state }) => { {bankAccount?.card_expiration_date?.slice(0, 7)} - - ${formatAmount(bankAccount.balance)} - + ${bankAccount.balance} { {transaction.reversed.toString()} - - ${formatAmount(transaction.amount)} - + ${transaction.amount} {currentAccount.id === transaction.from ? "Credit" @@ -236,6 +231,7 @@ const Dashboard = ({ state }) => { onClick={() => onReverse(transaction.hash, transaction.amount) } + disabled={transaction.reversed} > Revert Transaction diff --git a/interface/src/substrate-lib/SubstrateContext.js b/interface/src/substrate-lib/SubstrateContext.js index fcccff0..d6e046e 100644 --- a/interface/src/substrate-lib/SubstrateContext.js +++ b/interface/src/substrate-lib/SubstrateContext.js @@ -98,7 +98,7 @@ const loadAccounts = (state, dispatch) => { const asyncLoadAccounts = async () => { try { - await web3Enable("iso8583-chain"); + await web3Enable("polkadot-js"); let allAccounts = await web3Accounts(); allAccounts = allAccounts.map(({ address, meta }) => ({ diff --git a/interface/src/substrate-lib/index.js b/interface/src/substrate-lib/index.js index a05999e..9aaf297 100644 --- a/interface/src/substrate-lib/index.js +++ b/interface/src/substrate-lib/index.js @@ -7,24 +7,24 @@ import { } from "./SubstrateContext"; export { SubstrateContextProvider, useSubstrate, useSubstrateState }; -const _utils = { - paramConversion: { - num: [ - "Compact", - "BalanceOf", - "u8", - "u16", - "u32", - "u64", - "u128", - "i8", - "i16", - "i32", - "i64", - "i128", - ], - }, -}; +// const _utils = { +// paramConversion: { +// num: [ +// "Compact", +// "BalanceOf", +// "u8", +// "u16", +// "u32", +// "u64", +// "u128", +// "i8", +// "i16", +// "i32", +// "i64", +// "i128", +// ], +// }, +// }; export function u8aToHexCompact(data) { return u8aToHex(data).substring(2); diff --git a/payment-processor/src/server.ts b/payment-processor/src/server.ts index 20e0643..6e147ce 100644 --- a/payment-processor/src/server.ts +++ b/payment-processor/src/server.ts @@ -227,8 +227,8 @@ export default class Server { accountId, }: RequestBody = body; - let isReversal = txHash !== null; - let registerOnChainAccount = accountId !== null; + let isReversal = !!txHash; + let registerOnChainAccount = !!accountId; console.log("registerOnChainAccount", registerOnChainAccount, accountId); diff --git a/pcidss/oracle/src/tests/register.rs b/pcidss/oracle/src/tests/register.rs index 4c2fcf8..9a7efa1 100644 --- a/pcidss/oracle/src/tests/register.rs +++ b/pcidss/oracle/src/tests/register.rs @@ -47,5 +47,8 @@ async fn test_register() { let charlie_account = get_bank_account_by_card_number(&api, &CHARLIE.1).await; - assert_eq!(charlie_account.account_id, Some(CHARLIE.4.trim_start_matches("0x").to_string())); + assert_eq!( + charlie_account.account_id, + Some(CHARLIE.4.unwrap().trim_start_matches("0x").to_string()) + ); }