Transfer currency

When you use the @moneypot/hub server, this is already handled for you.

However, knowing how it works can help you debug potential issues related to transfers.

One of the core features of the MoneyPot casino API is that you can transfer currency between holders (users and controllers).

Transfer status

Transfers can move between these states:

  • COMPLETED: (Terminal) The transfer is settled and money was moved between two holder accounts.
  • PENDING: (Initial) The transfer hasn’t moved any money yet until the sender calls completeTransfer(id).
  • UNCLAIMED: (Initial) An expirable transfer. Funds have been deducted from the sender (user), but the receiver (controller) must call claimTransfer(id) before expiration or before the user cancels the transfer.
  • EXPIRED: (Terminal) An UNCLAIMED transfer that wasn’t claimed in time by receiver. Funds have been returned to sender.
  • CANCELED: (Terminal) An UNCLAIMED or PENDING transfer where the sender called cancelTransfer(id).
stateDiagram-v2
  [*] --> PENDING: Controller creates transfer to user
  [*] --> UNCLAIMED: User creates transfer to experience

  PENDING --> COMPLETED: Controller calls completeTransfer()
  PENDING --> CANCELED: Controller calls cancelTransfer()

  UNCLAIMED --> COMPLETED: Controller calls claimTransfer()
  UNCLAIMED --> EXPIRED: Time expires
  UNCLAIMED --> CANCELED: User calls cancelTransfer()

Receiving user transfers through an experience

When a user wants to play an experience, they use the transferCurrencyToExperience mutation which starts a transfer to the experience’s underlying controller.

Here is the process:

  1. The funds are deducted from the user’s account immediately
  2. An UNCLAIMED transfer is created with a very short expiration (one minute)

Then one of these things can happen:

  1. The user calls cancelTransfer(id) and the transfer state becomes CANCELED
  2. The transfer expires and its state becomes EXPIRED
  3. The receiving Controller calls claimTransfer(id), their balance gets credited, and the transfer state becomes COMPLETED

The controller is responsible for polling the Casino API to watch for incoming UNCLAIMED transfers.

You must ensure that the claimTransfer(id) request to the origin MoneyPot casino succeeds before crediting users in your own database.

Otherwise, you will credit users for money that you never received.

A deeper look at funds movement

Most of the complexity in the MoneyPot ecosystem comes from the decentralized nature of a MoneyPot casino, all the experiences, and any number of hub servers underlying those experiences.

User -> Experience transfers (“Put”)

When a user wants to play an experience, they “put” money into the experience by creating an UNCLAIMED transfer to the experience’s underlying controller.

The user’s balance on MoneyPot is immediately deducted so that they can’t double-spend those funds.

  • If the unclaimed transfer expires, the user’s funds are refunded to them.
  • If the unclaimed transfer is canceled (by the user), the user’s funds are refunded to them.
  • If the unclaimed transfer is claimed (by the controller), then the user’s funds are credited to the controller’s balance.

Experience -> User transfers (“Take”)

When a user wants to take funds out of an experience, they use the “take” form to create a take request.

The hub server scans for take requests and turns them into PENDING transfers on MoneyPot.

When hub creates a PENDING transfer, they deduct the user’s funds in the hub database so that the user cannot double-spend those funds on hub. However, no funds are moved on the MoneyPot side until completeTransfer(id) is called by the controller.

The transfer will stay in the PENDING state until a successful completeTransfer(id) is called by the controller or if the controller calls cancelTransfer(id).