streamflow-finance / js-sdk

Web3 Distribution Layer. For Token vesting and Airdrops
https://app.streamflow.finance
GNU General Public License v3.0
108 stars 31 forks source link

Can't get vesting payouts to work #39

Closed integry closed 2 years ago

integry commented 2 years ago

Great work on the project, from my research it seems like it should be the most complete and user friendly solution to implement SPL token vesting schemes. I would like to use it for our project which requires different vesting schemes for different participants and it looks like a perfect fit as it allows setting up custom schemes via JS (seems like the easiest way to go about setting up bulk payments) or via UI (for one-offs, which we'll have as well), as well as letting recipients to track their vesting status via UI.

So far so good, however the part where I'm having issues is getting the vesting payments to actually reach the final recipients. It doesn't seem to work neither on devnet, nor mainnet. As an example, I have initiated 2 very simple contracts on mainnet (only one payment to be made), however the payments are actually not getting sent to the recipient.

Here's an example of one of the contracts returned by Stream.get: image

My assumption is that by the end time the entire amount minus the fees should have been transferred to the recipient. Am I correct to assume that all the payouts take place automatically without user intervention (or having to "crank" the program to trigger the payouts)?

In addition, I can't see the contracts in the UI either. I tried connecting both as a sender and as a recipient, and the list is always empty: image

I would appreciate any tips if there's something I might be doing wrong. If it helps, I'm attaching a JSON with data returned by Stream.get: stream-get.txt

imprfekt commented 2 years ago

Hey @integry first of all thank you for your kind words, it means a lot to see that our project is helpful.

To answer your question directly, yes, a "cranker" or another service (we call it "automatic withdrawal") is needed to do the actual settlement. This is something we're working on as we speak and should be up & running within 2,3 weeks and then enabling it retroactively for streams created in the meantime.

But until that happens, withdraw instruction should be invoked by recipient. If automaticWithdrawal is set to true, then withdraw can be invoked in a permissionless fashion (i.e. anyone can invoke it)

And regarding your other question, the only difference between the stream and a vesting contract in our UI is the canTopup field. true for the stream, false for the vesting contract. Are you on the right tab (should be vesting contract in your case)

integry commented 2 years ago

Thank you very much for the speedy response, this helped a lot to understand where I got stuck. For the time being we can manage by invoking the withdrawals from our end using the withdraw instruction for the eligible contracts, but it would definitely be more convenient not having to think about it :)

As for the UI issue, I'm definitely in the Vesting tab: image

A side issue with the UI is that it doesn't list any of the self-minted tokens that are present in the connected wallet, so I can't test the option of initiating a vesting contract via UI.

imprfekt commented 2 years ago

Seems like you're on the wrong URL. Try out the new version of the UI: https://streamflow-dev.netlify.app Sorry for the confusion, we're in the middle of transition to v2 and we'll be updating URLs in the following days.

integry commented 2 years ago

Thank you, I see that the new UI now works with mainnet as well, previously it only worked for devnet. However I'm still not able to see the tokens or the initiated contracts: image

image

integry commented 2 years ago

I'm implementing the withdrawal functionality on our end, but unfortunately I'm running into another problem. withdraw instruction returns this error - invalid account data for instruction.

The stream is a simple one, no cliff, a single payout after one second (there's also another one with more complex rules, which fails the same way): image

withdraw call parameters: image

Here's the error: image

Any ideas would be hugely appreciated!

If I could suggest a couple of improvements to the API: 1) Within Stream.get call allow pre-filtering only the streams that are eligible for withdrawal (there is a non-zero amount of tokens available for release) 2) Add a new field to stream data to indicate the amount of tokens that can be released.

Also, I'm wondering if there are any practical limits on how many streams could be set up from a single wallet? The number of recipients for our pre-sale could easily run into thousands. Would you suggest a "sharded" approach to set up a separate payer wallet for every (let's say) 100 recipients or it's not a reason of concern?

diksipav commented 2 years ago

Hello @integry.

For withdrawing issue, only the recipient can withdraw. If you send sender's wallet you'll get an error.

Suggestions for stream not showing problem:

Edit: I updated our FE app, so now you will be able to see newly created tokens both on devnet and mainnet first 5 letters of the token mint.

diksipav commented 2 years ago

@integry are the issues resolved now on your side, or the problems still exist? Can you check if you see your streams on current https://streamflow-dev.netlify.app/

integry commented 2 years ago

Hi Dijana, thank you for the additional suggestions. I haven't been working on this for the last couple of days, but will give another shot over the weekend following your suggestions. The SDK version I'm using is @streamflow/timelock@0.4.1-beta.57

I'm seeing the streams and the token now in the new UI, that's great and moves us much closer to the goal!

Btw, I thought that according to @imprfekt's comment above, the sender can initiate the withdrawal if automaticWithdrawal is set to true when creating the stream. Is it still in the to-do?

I would appreciate if you could chime in on the scaling question as well. I'm going to test it of course, but if you have some thoughts on best practices on setting up lots of contracts, it would be great to know.

Hvala!

diksipav commented 2 years ago

Hello @integry, I would suggest to you to work with @streamflow/stream@2.0.2 version (this is the latest one). I am working on some new updates, so probably new version will be available tomorrow which will change a bit how SDK is used.

Currently automatic withdrawal is still not working, it is in progress. The idea is that if sender sets automatic withdrawal to true when a stream is created, then automatic withdrawal will work when the stream starts. There is no need for additional withdraw calls.

Regarding multiple/batch streams currently we don't have support for that too, you will have to initiate multiple createStream calls. We will work in the upcoming week on implementing support for that.

Thank you very much for your feedback.

integry commented 2 years ago

@DijanaPavlovic , thank you for clarifying. I have switched to the @streamflow/stream@2.0.2 and it appears to work fine without any code changes needed.

So at this point we could be all set... however not being in control of initiating the withdrawals is a pretty huge business risk as we're dependent of the automatic withdrawals being initiated from your end (most preferred option), as well as the UI staying up so that our customers could request the withdrawals manually (least preferred option). However to cover all the bases, I would also like to see the option for us to initiate the withdrawals ourselves (the option that we would be in control of). I don't really see any security risks in this approach as each stream has a specific recipient, so no harm done if a 3rd party initiates the withdrawal and pays the associated network fees (btw, how would those be handled in the automated withdrawal scenario?)

I have a great faith in what you're doing and I'm sure you're going to manage everything just fine. However as we're looking to set up long term vesting contracts (up to 3 years), I need to be certain that we can interact with the blockchain program directly to initiate the withdrawals.

To summarize, the only obstacle that prevents us from committing to Streamflow is the ability to trigger the withdrawals ourselves. I would appreciate it if you could consider adding this capability.

nemanjab17 commented 2 years ago

Hey @integry we anticipated this, if you set automaticWithdrawal to true and set withdrawFrequency to 0, any wallet can initiate withdrawal, and since frequency is 0, our infrastructure will not pick up that specific stream :)

As for how we handle network fees for automatic withdrawal if our infrastructure should execute withdrawals (withdraw freq > 0), upon creation, our program funds our infrastructure wallet with sender's lamports ( number of withdrawals x fixed 5000 lamps ).

integry commented 2 years ago

Thank you, that should settle the concern :) There seems to be an issue with withdrawFrequency though - if I set it's value to 0, it takes it's value from the period field instead. Could you please check if it works correctly at your end?

Relevant part of the stream setup parameters: image

Stream data retrieved via Stream.get: image

integry commented 2 years ago

While we're at it, here are some wishlist items for the JS SDK that could make the manual withdrawal management easier.

1) Implement it all in the SDK (the lazy option :) - something like, Stream.processAllPendingWithdrawals(payerWallet) which would do it's magic and send out all the pending payments using as many transactions as needed. Obviously with this one I would sneakily avoid doing the heavy lifting, but this is something that anyone could use without having to reinvent the wheel.

2) Add filtering options for Stream.get, to only retrieve streams that are eligible for payouts right now (or at a certain timestamp) or filtering by arbitrary values (not really needed, but could be useful when processing the payouts in specific batches, for example)

3) Add a field in stream data that would indicate the amount that can be withdrawn right now.

4) Bulk setup and withdrawals - I realize you can't do too much in a single Solana transaction, so I'm not sure if it would make sense, but perhaps even doing small bundles would make it worthwhile (just a guess from my end, I don't have enough hands on experience with developing on Solana).

Also, I asked that above, but I'll rephrase - would it be an issue to set up 1000 or 10.000 streams from a single sender wallet and retrieve them all via Stream.get? I wonder if you have any ideas regarding practical limits?

Thank you again for all your help!

integry commented 2 years ago

Hey guys, just wondering if you have had a chance to check out the issue with setting the withdrawFrequency value? Thank you :)

diksipav commented 2 years ago

Hello @integry, issue with withdrawFrequency is resolved. You should be able to set automaticWithawal to true, and withdrawFrequency to 0 and it will work as expected (you or anyone else would be able to initiate withdrawals). You should use @streamflow/stream@2.1.0.

integry commented 2 years ago

Hey Dijana and the rest of the team, thank you for the quick fixes and the hard work you're putting into the project!

I installed the new SDK version and ran into some JS issues initially until I discovered that all the addresses should be passed in as instances of PublicKey rather than string as it used to be. For example:

recipient: new PublicKey("recipientaddress"), mint: new PublicKey("mintaddress")

Also I noticed that omitting the partner field (or setting it to null as before) trips up the request setup on the SDK side as well, adding this solved the problem, it seems:

partner: new PublicKey("5SEpbdjFK5FxwTvfsGMXVQTD2v4M2c5tyRTxhdsPkgDw")

Having resolved these, I was happy to see that I can set the withdrawalFrequency independent from period and set up the stream successfully.

So far so good, however it looks like initiating the withdrawals is still failing: image

One of the streams: image

I can see them from the UI, btw - would be great to have the "Withdraw" button in there as well, but that's a minor note: image

I'm testing in production as the costs are negligible. Do you think it would be better to switch to devnet for now?

imprfekt commented 2 years ago

While we're at it, here are some wishlist items for the JS SDK that could make the manual withdrawal management easier.

1. Implement it all in the SDK (the lazy option :) - something like, `Stream.processAllPendingWithdrawals(payerWallet)` which would do it's magic and send out all the pending payments using as many transactions as needed. Obviously with this one I would sneakily avoid doing the heavy lifting, but this is something that anyone could use without having to reinvent the wheel.

2. Add filtering options for `Stream.get`, to only retrieve streams that are eligible for payouts right now (or at a certain timestamp) or filtering by arbitrary values (not really needed, but could be useful when processing the payouts in specific batches, for example)

3. Add a field in stream data that would indicate the amount that can be withdrawn right now.

4. Bulk setup and withdrawals - I realize you can't do too much in a single Solana transaction, so I'm not sure if it would make sense, but perhaps even doing small bundles would make it worthwhile (just a guess from my end, I don't have enough hands on experience with developing on Solana).

Also, I asked that above, but I'll rephrase - would it be an issue to set up 1000 or 10.000 streams from a single sender wallet and retrieve them all via Stream.get? I wonder if you have any ideas regarding practical limits?

Thank you again for all your help!

gm @integry! I'll just chime in on those.

Batch/bulk transactions are on our roadmap for Q1 (in March), where you'll be able to mass create/withdraw/cancel contracts. That should cover points 1. and 4.

In regards to 2. and 3, Solana SDK is (to the best of our knowledge) very limited when it comes to querying the chain and filtering the program accounts. We're querying the chain directly, so 3. is not feasible at the moment as it'd require a state update on all of the program accounts in realtime. We're in the process of making a hybrid architecture to have program accounts temporarily cached on our server to make SDK more powerful, but don't have any ETA on this atm.

I hope this sheds light on those issues.

Thank you for your suggestions and for being patient with us, we want to make it super-simple to integrate, but have some technical and resource constraints (as always). 😄

integry commented 2 years ago

Thank you @imprfekt for sharing the vision on the wishlist items. These are not really essential and we can live without having those, as long as the basic functionality works correctly. Have you had a chance to check my previous post above? If you're confident that it should be working correctly, I can try to put a test case together, which you could run at your end.

diksipav commented 2 years ago

Hello @integry, I am pretty sure it will work fine now. I tested it on our side and it works. Please, install and use the latest -> @streamflow/stream@2.1.1 version.

You still should send string addresses (no PublicKeys) for account addresses. Let us know if it works fine now. : )

integry commented 2 years ago

Excellent, I'll give it a try later today or tomorrow and let you know how it goes. Thanks again!

integry commented 2 years ago

Looks like everything works well now! Thank you very much for being so responsive. Streamflow is going to be a very important part of our token distribution as we're looking forward to launch around mid April.

There are just a couple of followup questions if you don't mind.

Do you have an ETA on the audit? It would be amazing if it's ready by the time we launch our token.

It seems like the source code for the Solana program is not on Github anymore. Is it supposed to be that way or am I missing something?

Thanks so much again!

imprfekt commented 2 years ago

Hey, glad we were able to help!

Audit is done, we’ll be publishing report in the following days, please watch this repo and we’ll add the link.

Correct, the code is closed source, we had problems with competitors who abused the fact it’s open source.

Ask ahead if you have any more questions! :)

On Sat, 5 Mar 2022 at 19:38, Rinalds Uzkalns @.***> wrote:

Looks like everything works well now! Thank you very much for being so responsive. Streamflow is going to be a very important part of our token distribution as we're looking forward to launch around mid April.

There are just a couple of followup questions if you don't mind.

Do you have an ETA on the audit? It would be amazing if it's ready by the time we launch our token.

It seems like the source code for the Solana program is not on Github anymore. Is it supposed to be that way or am I missing something?

Thanks so much again!

— Reply to this email directly, view it on GitHub https://github.com/streamflow-finance/js-sdk/issues/39#issuecomment-1059812615, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABGQNINVVEEFL4GDBQQI6CDU6OS2NANCNFSM5N3VSEFQ . You are receiving this because you were mentioned.Message ID: @.***>