Passive (debit) transaction service?

Hi, I am pretty new to blockchain technology, and I had an idea that it would be nice if clients had to pay fees to use a server api or website. But I have a hard time figuring out how this should be implemented in detail, so I am asking here if someone could help me.

The idea is to have a server expose an API, that is guarded by a fee collector, i.e. the server has a wallet and clients have to pay a fee to that wallet before their requests get accepted. This should also work for websockets, where each processed message sent between client and server should incur a fee.
The client should be able to use a browser wallet to automatically pay the fee while using the website without any interaction (if configured) and with as little overhead as possible.

I imagine this to be implemented in a way as the server sending clients it’s wallet address and something like a catalogue, so that clients know how to pay the fees before they make the requests. Basically accessing something like a catalogue route or the index of a website is free and when the user initiates a chargable request, they send a proof that they paid the required fee along with it. The server then verifies the proof and processes the request or rejects it.

For websockets this might be a bit more complicated, because the client would need to pay for subscriptions which are executed by the server, so the client needs to deposit funds in advance which are then used to pay the fees directly on the server. The server could send “low balance” notifications over the websocket to inform the user if they need to deposit more funds to use the service.

Here I am a bit unsure how to implement this properly. Clients could pay a few messages in advance and trust the server to send them their remaining balance back when the websocket closes, but that requires trust and incurs a second transaction fee on the solana blockchain for every closing websocket. Another option would be to manage a user account on the server where users can control how they move funds in and out. That might require too much maintenance for some users though.

The ideal way I would like would be a client wallet that can execute transactions on a third, authorized parties request. So that the client can give the server the permission to withdraw exactly the fees from their wallet when they require it.

Maybe we need an on-chain program owned wallet, which has an owner (the client) who can allow specific services to collect fees from that account to their accounts. The owner would authorize specifc services to request a transaction to their account, and the wallet would schedule a transaction when an authorized service requests it. This would however require an on-chain program account for each client, which the client or the service has to pay rent for.

Could someone who is experienced with Solana and on-chain programs give me some feedback to this chain of thought? Am I misunderstanding something or am I missing some simpler solution to these problems? It would very much help me understand Solana better.

The ideal way I would like would be a client wallet that can execute transactions on a third, authorized parties request. So that the client can give the server the permission to withdraw exactly the fees from their wallet when they require it.

This will likely never be supported by wallets partly due to security concerns, but also because it won’t work with hardware wallets. Hardware wallets require user interaction to sign a transaction.

Maybe we need an on-chain program owned wallet, which has an owner (the client) who can allow specific services to collect fees from that account to their accounts. The owner would authorize specifc services to request a transaction to their account, and the wallet would schedule a transaction when an authorized service requests it. This would however require an on-chain program account for each client, which the client or the service has to pay rent for.

Yes, this is making a lot more sense, and it is indeed a way your problem could be solved elegantly.
Look at how ERC-20 tokens on ethereum work. Those contracts have such a function, called approve()
ERC: Token standard · Issue #20 · ethereum/EIPs (github.com)

Allow _spender to withdraw from your account, multiple times, up to the _value amount. If this function is called again it overwrites the current allowance with _value.

You could make a smart contract “wallet” that holds users funds for them, and they can approve() your server’s account to spend up to a certain amount of the money on it.

This would mean you paying the transaction fees, however, you could just add it to the cost of using the service.

To be honest though I wouldn’t implement this like that. I would simply have users deposit money on a wallet I control to pay in advance, and simply keep track of how much of the money they sent me they used. If they want to, they can withdraw unused funds from my site manually.
This is basically exactly how cryptocurrency exchanges work. It has the minimal possible cost in terms of transactions made and fees. But it is centralized and it involves handling what are technically user’s funds and not necessarily yet your coins.

The smart contract solution I proposed above on the other hand, has the advantage of the user needing to trust you a bit less (though you could still lose their money, and if a hacker gets your wallet, he can steal their funds if they are approved to be taken by you)
Another advantage of the smart contract solution is that users can use multiple independent such paid API services, without needing to split their deposits among them.

1 Like

Another point: in regards to how funds should be taken for API fees, I would suggest against having one transaction made for each API call. Of course it might make sense if a single call is expensive enough to warrant it. But I’d implement it such that it will only make a tx once a certain threshold of due amount is met.
The worst that can happen is the customer has moved their money away somewhere else after doing approve() and executing some API calls, and you don’t get paid for the amount below the threshold.
So the threshold should be low enough that you don’t mind the loss.

Even with one tx per API call, unless you’re gonna wait multiple seconds for the confirmation before returning, you could lose money if the customer removes his funds right as he makes the request.

One way around this would be to make a requirement in the wallet smart contract that a % of total funds approve() d needs to remain on the balance and cannot be withdrawn unless the approval is reversed with another tx.
I would strongly advise against making that % high, or worse, 100%.

1 Like

Thank you for your analysis, it is very helpful.

Yes, this is also what I like about this. That way the same wallet can be reused for multiple services. One downside is that every user has to pay the rent for their specific smart contract, storing the program and configuration for approved withdrawals. But this shouldn’t be an issue for them as the required memory and therefore the rent are not that high and they are using the account already to pay for other services. It’s justified.

In an ideal world I would like to be able to charge users of services for every single request they make, even if it was less than a cent. But even on Solana this is not really feasible. But I am wondering, why does confirmation of transaction take multiple seconds when the network can process 70k tps and is not congested? Shouldn’t it basically be comparable to a regular network message?

But in any case, you are right, waiting for transactions of sub-cent funds for every request is too inefficient. I think your solution with the threshold can work, but it needs to be balanced in such a way that it can’t be abused by just repeatedly using the api from ever changing smart contract accounts, none of which ever pass the threshold on the server. To mitigate this the server could start out with a very low threshold, which will cause slow response rate, but will raise the threshold with the number of transactions paid by the client, as a reputation system. This could make changing accounts unfeasible and will allow recurring clients to use the service at full speed after some fees have been paid.

It might be possible to have multiple users use the same smart contract, with it tracking their balances.
I’m not sure though, I’d have to look more into how Solana specifically works.

70k TPS is throughput, not latency. Solana can process many transactions at a time, but it takes several steps to confirm a transaction. So it does take some time to go from submitting the transaction to it being confirmed.
It’s like having a very wide road with many lanes - many cars can pass at once, but it still takes them time to drive somewhere.

1 Like

I would assume that this would cause centralization and could cause blocking when multiple users try to read the same account. And it would require an extra renting system to kick users who don’t pay for their rent. I think solana is designed in a way that each user can have their own account. This does come with the responsibility of keeping enough funds on the account to pay the rent. But that is just how the system is designed.

Ah, that makes a lot of sense. So many transactions at once will get confirmed basically all at once but after a few seconds. This is something I should keep in mind.

This is great! I would most like to just start implementing this right now. I hope I find time sometime soon, next to the other hundred projects I have planned. :sweat_smile: