DEV Community

Daniel Ioni
Daniel Ioni

Posted on

πŸš€ MyZubster β€” Dev Update: Tari payout integration

Today we made a major step forward in the MyZubster Gateway β†’ Tari network integration, focusing on the infrastructure required to move MYZ withdrawals from a simulated development flow toward real on-chain Tari payouts.

This was not just a configuration change. We went deep into the Tari codebase, traced the wallet transaction flow, identified the correct API layer, inspected the protobuf definitions, verified the transaction types, and prepared the environment required to build and run the Tari wallet.

Here’s a detailed breakdown of what was done today.

πŸ—οΈ 1. Auditing the Existing MyZubster Payout Service

We started from the existing:

MyZubsterGateway/tari_payout.js

The current service already provides the basic payout abstraction:

transferToAddress()
transfer IDs
user IDs
destination addresses
payout amounts
transfer status
transaction IDs
failure handling
user transfer history

The service also includes a development simulation mode.

Previously, if a real Tari wallet was not configured, the system generated a simulated transaction ID such as:

tari_tx_sim_...

This was useful during development, but it obviously cannot be used for actual withdrawals.

The important discovery was that the current implementation attempted to communicate with Tari using:

POST /transfer

through Axios.

That assumption needed to be validated against the actual Tari wallet implementation.

πŸ” 2. Going Directly Into the Tari Source Code

Instead of guessing how the wallet works, we inspected the Tari repository directly.

We located the relevant applications:

applications/minotari_console_wallet
applications/minotari_node
applications/minotari_mcp_wallet
applications/minotari_mcp_node

The most important component for our use case is:

applications/minotari_console_wallet

This is the wallet application responsible for handling outgoing transactions.

From there, we traced the wallet's gRPC implementation.

⚑ 3. Identifying the Real Wallet API: gRPC

One of the biggest findings today was that the Tari wallet exposes its transaction functionality through gRPC.

The relevant implementation is:

applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs

We found the wallet server implementation and, more importantly, the actual:

Transfer

RPC.

The corresponding protobuf definition is located at:

applications/minotari_app_grpc/proto/wallet.proto

This gives us the actual contract between the MyZubster Gateway and the Tari wallet.

So the architecture is being changed conceptually from:

MyZubster
↓
HTTP /transfer
↓
Tari

to:

MyZubster
↓
gRPC TransferRequest
↓
Tari Console Wallet
↓
Tari Network

This is a much more accurate integration with the Tari wallet we're actually running.

πŸ“‘ 4. Inspecting TransferRequest

We found the actual protobuf definition:

message TransferRequest {
repeated PaymentRecipient recipients = 1;
bool single_tx = 2;
}

This is important because it confirms that Tari supports sending funds to one or multiple recipients through the wallet API.

The actual recipient object is:

message PaymentRecipient {
string address = 1;
uint64 amount = 2;
uint64 fee_per_gram = 3;
PaymentType payment_type = 5;
bytes raw_payment_id = 6;
UserPaymentId user_payment_id = 7;
}

This gives us everything required for the MyZubster withdrawal flow:

destination Tari address
amount
fee configuration
payment type
optional payment metadata
πŸ’° 5. Confirming Tari's Unit of Account

Another important implementation detail we verified today is the amount denomination.

The Tari protobuf explicitly defines:

amount

as a value in microTari.

Therefore:

1 Tari = 1,000,000 microTari

This is particularly important for MyZubster because the Gateway currently works with MYZ amounts.

The conversion layer therefore needs to be explicit and deterministic rather than relying on implicit floating-point conversion.

For example:

1 MYZ β†’ 1,000,000 microTari

assuming the MyZubster economic model defines MYZ with that exact Tari-denominated conversion.

This will be handled carefully in the final payout implementation to avoid rounding or precision problems.

πŸ” 6. Investigating Tari Payment Types

We also inspected the supported payment types.

Tari currently exposes:

STANDARD_MIMBLEWIMBLE = 0
ONE_SIDED = 1
ONE_SIDED_TO_STEALTH_ADDRESS = 2

The wallet implementation showed that the newer one-sided stealth mechanism is directly supported by the transaction service.

We found code paths such as:

send_one_sided_transaction(...)

and:

send_one_sided_to_stealth_address_transaction(...)

This is important because a MyZubster withdrawal does not require an interactive sender/receiver transaction flow.

For the production payout system, we'll be able to select the appropriate Tari payment mechanism based on the address and wallet requirements.

🧠 7. Inspecting the Actual Transfer Implementation

We went further than simply finding the protobuf.

We inspected the actual Rust implementation around the wallet's transfer() method.

The wallet:

receives the gRPC request;
validates the Tari address;
processes the recipient;
validates the payment type;
constructs the payment ID;
calls the appropriate transaction service;
obtains the transaction ID;
performs broadcast/confirmation handling;
returns a TransferResult.

This is extremely useful because it means the Gateway doesn't need to reproduce Tari's transaction construction logic.

The Tari wallet remains responsible for:

UTXO selection
transaction construction
fees
signing
transaction service interaction
broadcasting

The MyZubster Gateway should remain responsible for:

withdrawal validation
user/account balance management
payout authorization
transaction tracking
business logic
reconciliation

That separation is exactly what we want.

πŸ“‹ 8. Understanding TransferResult

We also inspected the response structure:

message TransferResult {
string address = 1;
uint64 transaction_id = 2;
bool is_success = 3;
string failure_message = 4;
TransactionInfo transaction_info = 5;
}

This gives us a much better foundation for the MyZubster payout state machine.

Instead of simply assuming:

HTTP 200 = payout successful

we can distinguish between:

requested
↓
wallet accepted
↓
transaction created
↓
broadcast
↓
confirmed
↓
completed

and failure states.

This is particularly important for financial operations.

πŸ” 9. Investigating gRPC Authentication

We also traced Tari's gRPC authentication implementation.

The relevant type is:

GrpcAuthentication

located in:

base_layer/common_types/src/grpc_authentication.rs

The wallet configuration exposes:

grpc_authentication

and the gRPC server creates:

ServerAuthenticationInterceptor

before accepting requests.

We also found the console wallet configuration example:

gRPC authentication method

grpc_authentication = { username = "admin", password = "xxxx" }

This means the final Gateway integration must not blindly expose the wallet's gRPC endpoint.

Authentication needs to be configured deliberately, especially if the Gateway and wallet are not isolated on the same private host/network.

🌐 10. Identifying the gRPC Endpoint

We traced how the console wallet obtains its gRPC listener address.

The wallet accepts:

MINOTARI_WALLET_GRPC_ADDRESS

and the configuration eventually reaches:

run_grpc(...)

where the address is converted and passed into:

serve_with_shutdown(...)

The configuration examples point to:

18143

for the console wallet gRPC interface.

So our intended local architecture is:

MyZubster Gateway
β”‚
β”‚ gRPC
β–Ό
127.0.0.1:18143
β”‚
β–Ό
Minotari Console Wallet

This keeps the wallet API local rather than unnecessarily exposing it publicly.

πŸ¦€ 11. Preparing the Tari Build Environment

The server did not initially have the Rust toolchain installed.

We installed Rust using rustup.

The environment now reports:

rustc 1.97.1
cargo 1.97.1

We then attempted to build:

minotari_console_wallet

using:

cargo build -p minotari_console_wallet --release
πŸ”§ 12. Resolving the Missing C Toolchain

The first compilation attempt revealed another environment issue:

error: linker x86_64-linux-gnu-gcc not found

This wasn't a Tari source-code problem.

The machine simply didn't have the required system compiler/linker available.

We installed the necessary build tooling and verified:

/usr/bin/gcc
/usr/bin/x86_64-linux-gnu-gcc

with:

gcc 13.3.0

The correct cross-target linker is now available.

πŸ“¦ 13. Tari Dependencies Successfully Downloaded

After fixing the build environment, Cargo was able to resolve and download the Tari dependency tree.

The build downloaded more than:

600 crates

with approximately:

57 MB

of Rust dependencies.

This included major components such as:

tonic
hyper
libc
sqlite
git2
hickory
zerocopy

and many others required by the Tari ecosystem.

The build is now progressing through the actual compilation stage.

πŸ§ͺ 14. Current Build Status

The current command is:

cargo build -p minotari_console_wallet --release

The initial failure caused by the missing linker has been addressed.

The next milestone is obtaining:

target/release/minotari_console_wallet

Once that binary exists, we can move from source-code investigation into actual runtime testing.

πŸ”Œ 15. Next Phase: Live gRPC Testing

The next phase will be to start the console wallet with gRPC enabled and verify:

127.0.0.1:18143

is listening.

We'll then test the actual Transfer RPC independently from MyZubster.

The goal is to prove this path first:

gRPC client
↓
TransferRequest
↓
Tari Wallet
↓
TransferResult

before connecting the production withdrawal system.

This gives us a much safer development process.

πŸ’Έ 16. Next Phase: Rebuilding tari_payout.js

Once the wallet RPC is proven, we'll update the MyZubster Gateway.

The current concept:

axios.post(${TARI_WALLET_URL}/transfer, ...)

will be replaced with a proper Tari gRPC client.

The Gateway will construct a request equivalent to:

TransferRequest
└── PaymentRecipient
β”œβ”€β”€ address
β”œβ”€β”€ amount
β”œβ”€β”€ fee_per_gram
β”œβ”€β”€ payment_type
└── payment_id

The response will then be mapped into MyZubster's internal payout state.

🧾 17. Improving Transaction Tracking

The existing MyZubster service already has a useful foundation:

transferId
userId
address
amount
status
createdAt
txId
networkTxId

We'll preserve that architecture while making the transaction ID come from the real Tari wallet.

The eventual lifecycle will look more like:

pending
↓
submitted
↓
sent
↓
broadcast
↓
confirmed
↓
completed

with explicit failure handling.

This is significantly safer than treating the initial RPC response as proof that the transaction has permanently settled.

πŸ›‘οΈ 18. Production Safety

Another important principle from today's work is that real withdrawals should not be enabled simply because the RPC call works.

Before production payouts, we'll need to validate:

Tari wallet connectivity
wallet synchronization
available balance
correct network
destination address validation
amount conversion
fee handling
transaction IDs
broadcast status
confirmation handling
duplicate withdrawal protection
failure/retry behavior
authentication
wallet endpoint exposure
logging and reconciliation

Financial transaction infrastructure needs these checks before moving from development to production.

🎯 The Architecture We're Building

The final architecture is shaping up as:

                MYZUBSTER
                    β”‚
                    β–Ό
          Withdrawal Request
                    β”‚
                    β–Ό
          MyZubster Gateway
                    β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚                   β”‚
          β–Ό                   β–Ό
   Balance / Ledger      Payout Service
                              β”‚
                              β–Ό
                       Tari gRPC Client
                              β”‚
                              β–Ό
                 Minotari Console Wallet
                          :18143
                              β”‚
                              β–Ό
                     Tari Transaction
                              β”‚
                              β–Ό
                        Tari Network
                              β”‚
                              β–Ό
                          Recipient
Enter fullscreen mode Exit fullscreen mode

This gives us a clean separation between the MyZubster business layer and the Tari blockchain layer.

πŸš€ What Comes Next

The immediate priorities are:

  1. Finish the Tari wallet compilation

cargo build -p minotari_console_wallet --release

  1. Start the wallet

with the correct network and gRPC configuration.

  1. Verify gRPC

127.0.0.1:18143

  1. Execute a controlled test transaction

using the actual TransferRequest.

  1. Implement the Node.js gRPC client

inside tari_payout.js.

  1. Connect it to MyZubster withdrawals.

  2. Add robust transaction state and confirmation tracking.

πŸ”₯ Summary

Today was primarily about understanding the real Tari architecture and building the correct foundation, rather than rushing directly into production transactions.

We moved from an assumed REST integration to the actual Tari wallet gRPC architecture, traced the transaction implementation down to the Rust wallet service, identified the protobuf contract, verified payment types and microTari denomination, investigated authentication, identified the wallet gRPC endpoint, and prepared the server with the Rust and C build toolchains required to compile Tari.

The result is a much clearer and more reliable path toward real MYZ β†’ Tari withdrawals.

The next major milestone is simple:

Get the Tari wallet running, connect to gRPC, execute the first controlled real transfer, and then wire that transaction path into the MyZubster Gateway.

MyZubster Γ— Tari β€” real blockchain payouts are getting closer. πŸš€

MyZubster #Tari #Blockchain #Crypto #Web3 #Rust #NodeJS #GRPC #Payments #Fintech #DevUpdate #OpenSource #BlockchainDevelopment #CryptoInfrastructure #Engineering

Top comments (0)