Skip to content

Instantly share code, notes, and snippets.

@hmmftg
Created June 16, 2024 16:01
Show Gist options
  • Save hmmftg/8043c74b1898c935a08d5da0a7b43dbb to your computer and use it in GitHub Desktop.
Save hmmftg/8043c74b1898c935a08d5da0a7b43dbb to your computer and use it in GitHub Desktop.
Atm StateMachine Using XState
import { setup } from "xstate";
export const machine = setup({
types: {
context: {} as {},
events: {} as
| { type: "enter_amount" }
| { type: "enter_national_id" }
| { type: "account_is_valid" }
| { type: "account_is_invalid" }
| { type: "dest_account_is_valid" }
| { type: "dest_account_is_invalid" }
| { type: "select_account_transfer" }
| { type: "select_register_stolen_card" }
| { type: "confirmed" }
| { type: "not_confirmed" }
| { type: "valid_password" }
| { type: "invalid_pin" }
| { type: "successful_account_transfer" }
| { type: "finish_card_less" },
},
}).createMachine({
context: {},
id: "atmMachine",
initial: "idle",
states: {
idle: {
on: {
insert_card: {
target: "card_inserted",
},
cardless_button: {
target: "cardless",
},
},
description:
"The ATM is idle, waiting for a customer to insert their card.",
},
card_inserted: {
on: {
enter_pin: {
target: "pin_entered",
},
eject_card: {
target: "idle",
},
},
description:
"The ATM has detected a card insertion and is prompting for PIN entry.",
},
cardless: {
on: {
select_register_stolen_card: {
target: "register_stolen_card",
},
cancel: {
target: "idle",
},
select_account_transfer: {
target: "request_account_transfer",
},
},
description:
"The user has chosen the cardless option. The ATM prompts for the next action.",
},
pin_entered: {
on: {
pin_valid: {
target: "select_transaction",
},
pin_invalid: {
target: "pin_error",
},
},
description: "The ATM has received the PIN and is verifying it.",
},
register_stolen_card: {
on: {
registration_complete: {
target: "idle",
},
registration_error: {
target: "transaction_error",
},
},
description: "The user is registering a stolen card.",
},
request_account_transfer: {
on: {
enter_national_id: {
target: "select_account",
},
},
description: "user asked for source and dest accounts",
},
select_transaction: {
on: {
select_withdrawal: {
target: "withdrawal",
},
select_balance: {
target: "balance_inquiry",
},
select_deposit: {
target: "deposit",
},
eject_card: {
target: "idle",
},
},
description:
"The PIN is valid. The ATM prompts the user to select a transaction type.",
},
pin_error: {
on: {
reenter_pin: {
target: "card_inserted",
},
eject_card: {
target: "idle",
},
},
description:
"The entered PIN is invalid. The ATM prompts the user to re-enter the PIN or eject the card.",
},
transaction_error: {
on: {
retry: {
target: "select_transaction",
},
eject_card: {
target: "idle",
},
},
description:
"An error occurred during the transaction. The ATM displays an error message.",
},
select_account: {
on: {
account_is_valid: {
target: "enter_destination_account",
},
account_is_invalid: {
target: "transaction_error",
},
},
description: "List of accounts displayed and asked user to select",
},
withdrawal: {
on: {
enter_amount: {
target: "process_withdrawal",
},
cancel: {
target: "select_transaction",
},
},
description:
"The user has selected a withdrawal. The ATM prompts for the amount to withdraw.",
},
balance_inquiry: {
on: {
balance_retrieved: {
target: "display_balance",
},
inquiry_error: {
target: "transaction_error",
},
},
description:
"The user has selected a balance inquiry. The ATM is retrieving the account balance.",
},
deposit: {
on: {
enter_amount: {
target: "process_deposit",
},
cancel: {
target: "select_transaction",
},
},
description:
"The user has selected a deposit. The ATM prompts for the deposit amount.",
},
enter_destination_account: {
on: {
dest_account_is_valid: {
target: "account_transfer",
},
dest_account_is_invalid: {
target: "transaction_error",
},
},
description: "user is asked to enter destination account number",
},
process_withdrawal: {
on: {
withdrawal_success: {
target: "dispense_cash",
},
insufficient_funds: {
target: "insufficient_funds",
},
withdrawal_error: {
target: "transaction_error",
},
},
description: "The ATM is processing the withdrawal request.",
},
display_balance: {
on: {
continue: {
target: "select_transaction",
},
eject_card: {
target: "idle",
},
},
description:
"The ATM displays the retrieved account balance to the user.",
},
process_deposit: {
on: {
deposit_success: {
target: "deposit_complete",
},
deposit_error: {
target: "transaction_error",
},
},
description: "The ATM is processing the deposit request.",
},
account_transfer: {
on: {
enter_amount: {
target: "transfer_confirmation",
},
},
description: "ask user to enter amount",
},
dispense_cash: {
on: {
cash_dispensed: {
target: "transaction_complete",
},
},
description: "The ATM is dispensing cash to the user.",
},
insufficient_funds: {
on: {
retry: {
target: "select_transaction",
},
eject_card: {
target: "idle",
},
},
description:
"The account has insufficient funds for the requested withdrawal amount.",
},
deposit_complete: {
on: {
continue: {
target: "select_transaction",
},
eject_card: {
target: "idle",
},
},
description:
"The deposit transaction is complete. The ATM prompts the user for the next action.",
},
transfer_confirmation: {
on: {
confirmed: {
target: "ask_for_otp_password",
},
not_confirmed: {
target: "transaction_error",
},
},
description: "user confirms operation",
},
transaction_complete: {
on: {
continue: {
target: "select_transaction",
},
eject_card: {
target: "idle",
},
},
description:
"The transaction is complete. The ATM prompts the user for the next action.",
},
ask_for_otp_password: {
on: {
valid_password: {
target: "process_account_transfer",
},
invalid_pin: {
target: "transaction_error",
},
},
},
process_account_transfer: {
on: {
successful_account_transfer: {
target: "account_transfer_complete",
},
},
description: "send transaction request to server",
},
account_transfer_complete: {
on: {
finish_card_less: {
target: "idle",
},
},
},
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment