Skip to content

Open-loop & Closed-loop Wallets

Every member holds two wallets, and they do different jobs:

  • The open-loop wallet is for the outside world: paying any QRIS merchant, sending to a bank account, cashing out to an e-wallet.
  • The closed-loop wallet is for everything inside the member’s organisation: saving goals, saving circles, dues, financing, investments, takaful, donations, and transfers to other members of the same organisation.

The member can move money between the two at any time, in either direction, at no charge.

Open-loopClosed-loop
Indonesian appDompet DigitalSaldo Moria (Kantong Utama)
English appE-WalletSaldo Moria (Main Pocket)

An organisation can rename “Saldo Moria” to its own name. Its members then see “Saldo” followed by that name.

Open-loop walletClosed-loop wallet
Where the money sitsAn account at Moria’s payment provider, opened in the member’s own name and operated by Moria on their behalfThe member’s balance in Moria’s ledger. The cash behind it sits in the organisation’s own account at the payment provider
Tied to an organisationNo. One account per member, the same in every organisation they belong toYes. Each organisation has its own account, never pooled with another organisation, and a member of two organisations has a separate balance in each
Money inTop-up by bank virtual account, a transfer from the closed-loop wallet, a partner transferTop-up by bank virtual account, a transfer from the open-loop wallet, a partner transfer
Money outQRIS payment to any merchant, transfer to a bank account, cash-out to DANA, OVO, ShopeePay or GoPayPaying for the organisation’s products, transfer to another member of the same organisation
Can money leave the organisationYes, that is its purposeOnly by first moving it to the member’s own open-loop wallet
Member PINRequired for every payment or transfer outRequired for transfers to other members and to the open-loop wallet

Top-up, bank transfer and e-wallet cash-out on the open-loop wallet start at IDR 10,000. Fees on open-loop payments out are set per payment method for the partner or organisation. Moving money between the two wallets is free.

flowchart LR
    subgraph Provider["Moria's payment provider"]
        direction TB
        MA["Member's own account<br/>(one per member)"]
        OA["Organisation's account<br/>(one per organisation)"]
    end
    subgraph Ledger["Moria ledger"]
        direction TB
        P1["Member A's Saldo Moria"]
        P2["Member B's Saldo Moria"]
    end
    DD(["Open-loop wallet<br/>Dompet Digital"]) --> MA
    P1 -. backed by .-> OA
    P2 -. backed by .-> OA

    classDef step fill:#E8E1FF,stroke:#3C2C96,stroke-width:1.5px,color:#1E1B4B;
    classDef done fill:#FDF8E8,stroke:#3C2C96,stroke-width:2px,color:#1E1B4B;
    class MA,OA,P1,P2 step;
    class DD done;

The open-loop wallet is a real account of its own, so its balance is whatever the provider holds in it. A closed-loop balance is a share of the organisation’s account, and Moria’s ledger records how much of it belongs to each member. That is why closed-loop money moves between members of one organisation instantly and without a fee, and why it cannot be spent outside the organisation directly.

The member moves money from the app, in either direction. The provider moves the cash between the organisation’s account and the member’s own account, and the ledger follows.

sequenceDiagram
    autonumber
    actor M as Member
    participant App as Moria app
    participant L as Moria ledger
    participant Prov as Payment provider

    M->>App: Move to Dompet Digital (amount, PIN)
    App->>Prov: Transfer organisation account to member account
    Prov-->>App: Confirmed
    App->>L: Update Saldo Moria
    App-->>M: Both balances updated

The opposite direction works the same way, from the member’s account to the organisation’s account, then a credit to Saldo Moria. Neither direction charges a fee.

flowchart TD
    A([Member wants to pay]) --> B{Who receives it?}
    B -->|Any QRIS merchant| O[Open-loop wallet]
    B -->|A bank account| O
    B -->|DANA, OVO, ShopeePay, GoPay| O
    B -->|Saving goal, circle, dues,<br/>financing, investment,<br/>takaful, donation| C[Closed-loop wallet]
    B -->|Another member of the<br/>same organisation| C
    O --> D([Paid])
    C --> D
    C -. not enough balance .-> X[Move money from the<br/>open-loop wallet first]

    classDef step fill:#E8E1FF,stroke:#3C2C96,stroke-width:1.5px,color:#1E1B4B;
    classDef gate fill:#FFF3D0,stroke:#F4BE27,stroke-width:1.5px,color:#8B5A00;
    classDef done fill:#FDF8E8,stroke:#3C2C96,stroke-width:2px,color:#1E1B4B;
    class O,C,X step;
    class B gate;
    class A,D done;

A withdrawal from a product, for example a saving goal, returns to the closed-loop wallet. To take it to a bank, the member moves it to the open-loop wallet first.

When a partner provisions a member, both wallets are prepared for them:

WalletWhen it is ready
Closed-loopIn the provisioning call itself
Open-loopFor a new member, shortly after the provisioning call, not in the same call. A member who already had a Moria account keeps the open-loop wallet they had; if they never opened one, it is opened the first time they use it

An open_loop transfer to a member whose open-loop wallet is not active yet is refused with STATE_MEMBER_WALLET_NOT_READY. Retry a little later, or send to closed_loop.

A partner using the payment gateway can move part of its balance straight into a member’s wallet. The transfer names the wallet with wallet: open_loop (the default) or closed_loop. No fee is charged and the member does not need to approve it, because money only goes in.

sequenceDiagram
    autonumber
    participant Partner as Partner system
    participant API as Moria API
    participant Prov as Payment provider
    actor M as Member

    Partner->>API: Transfer to member (wallet open_loop)
    API->>API: Check transfers are on and the balance covers it
    API->>API: Set the amount aside from the partner balance
    API->>Prov: Partner account to member's own account
    Prov-->>API: Confirmed
    API-->>Partner: succeeded
    API-->>Partner: Webhook member.transfer.succeeded
    API-->>M: App notification, Dompet Digital credited
sequenceDiagram
    autonumber
    participant Partner as Partner system
    participant API as Moria API
    participant Prov as Payment provider
    participant L as Moria ledger
    actor M as Member

    Partner->>API: Transfer to member (wallet closed_loop)
    API->>API: Check transfers are on and the balance covers it
    API->>API: Set the amount aside from the partner balance
    API->>Prov: Partner account to the organisation's account
    Prov-->>API: Confirmed
    API->>L: Credit the member's Saldo Moria
    API-->>Partner: succeeded
    API-->>Partner: Webhook member.transfer.succeeded
    API-->>M: App notification, Saldo Moria credited

Both flows normally finish within the request. If the provider does not answer clearly in time, the transfer answers pending. Moria keeps checking it in the background, and it ends as succeeded or failed, with the matching webhook. While a transfer is pending, nothing has been added to the member’s wallet yet, and the partner’s balance stays set aside. A failed transfer returns the amount to the partner’s balance.

Send toWhen the member will
open_loopSpend the money outside the organisation: QRIS merchants, bank transfers, e-wallets
closed_loopUse the money inside the organisation: savings, dues, financing, takaful, or sending to colleagues

The member can move the money to the other wallet later, so the choice is about convenience, not a lock-in.

Both wallets hold the member’s own money under Wadiah safe-keeping. Neither earns nor charges interest. Moving between them is free; fees on payments out of the open-loop wallet are transparent service charges, not riba.