-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(bindings-ts)!: API change: return AssembledTransaction
s, require signAndSend, and support multi-auth workflows
#1034
Conversation
5898251
to
885955a
Compare
885955a
to
e69d1a9
Compare
204476d
to
adf54a6
Compare
360ed32
to
d32b5a1
Compare
561ffc4
to
b49b8bb
Compare
4f630e4
to
4008a99
Compare
ede871b
to
86bbd5b
Compare
7fae2e1
to
6c68f73
Compare
Got it. Yeah I guess that makes sense. Unfortunate it's not more general but I doubt it'll be a major issue. Might be something worth looking into if it can't be reduced to just UX around current
This makes sense to me and I see no downside to this |
want to +1 this comment. I do think it would be better if clients did not have to work with structures that were specific to this lib and not compatible with other tooling( That said, I do realize that you can get to the underlying raw tx and this would be a big departure from the patterns here so I don't suggest any changes. |
0d00195
to
9761d13
Compare
AssembledTransaction
s, require signAndSend, and support multi-auth workflows
@aristidesstaffieri I agree with this assessment, and I think it's worth exploring how to simplify the auth-entry-signing workflow in a follow-up PR. For now, this one works! It's a big change and I'm eager to get it in so we can start building on top of it. Sound good? @tyvdh @Shaptic @aristidesstaffieri I've addressed all feedback and updated the PR description. lmk what you think! |
9761d13
to
1be4a60
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, haven't gone over the code but the interface lgtm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeet it
0e1398b
to
6e9d641
Compare
15d7b26
to
2b888c8
Compare
- switch from `ts-tests/package.json` to an `initialize.sh` script that uses a `.env` if available or defaults to environment variables. As before, this will build, deploy, and generate bindings for the new contracts, plus creating an `alice` and `bob` identities and minting separate amounts of two separate tokens to each of them - add eslint to catch missing `await`s - update to latest stellar-sdk instead of soroban-client - add transaction-rebuilding to increment transaction sequence numbers, so that all tests can pass when run in parallel - add `atomic_swap` and `token` contracts from https://github.com/stellar/soroban-examples to `test-wasms` - add tests for atomic swap functionality inspired by https://github.com/stellar/soroban-react-atomic-swap - let this logic guide needed updates to `bindings typescript`-generated libraries: - don't return flat values - instead, return a `new AssembledTransaction`, a class that has a `result` getter that can be used to get the result of the simulation right away, or can be used to `await tx.signAndSend()`, which then returns a `SentTransaction` - `SentTransaction` contains all possibly-relevant fields from the logic it performs, such as `sendTransactionAll` - `AssembledTransaction` has a `needsNonInvokerSigningBy()` getter and a `signAuthEntries()` to facilitate multi-auth workflows. - Since assembling transactions may now take place across multiple users' browsers, you can also call `json = tx.toJSON()` on an `AssembledTransaction` and then `contract.fromJSON[method](json)` on the next machine to continue signing, as shown in `test-swap.ts` Co-authored-by: Aristides Staffieri <aristides.staffieri@stellar.org> Co-authored-by: George <Shaptic@users.noreply.github.com>
2b888c8
to
0ecb92d
Compare
_work in progress: needs CLI v20.0.3, which must actually include latest bindings logic. Somehow 20.0.2 does not, even though it was tagged post-multi-auth merge https://github.com/stellar/soroban-tools/commits/main/)._ - Pin soroban-cli to latest version, 20.0.3 - Update the contract's SDK version - **Copy in `abundance` source from `token` contract** at stellar/soroban-examples#277. Note that I **did not author most of the changes in the `contracts/abundance` folder**. I _only_ copied in the changes originally authored in the `soroban-examples` repo, then updated for the single tweak that this `abundance` contract already had: 1. comments on the `mint` method; 2. slightly modified `mint` behavior. - New CLI's typescript-bindings-generated libraries now return an `AssembledTransaction`, which has a `result` getter and a `signAndSend` method, as explained in stellar/stellar-cli#1034 - Use `stellar-sdk` rather than `soroban-client`
- Pin soroban-cli to latest version, 20.0.3 - Update the contract's SDK version - **Copy in `abundance` source from `token` contract** at stellar/soroban-examples#277. Note that I **did not author most of the changes in the `contracts/abundance` folder**. I _only_ copied in the changes originally authored in the `soroban-examples` repo, then updated for the single tweak that this `abundance` contract already had: 1. comments on the `mint` method; 2. slightly modified `mint` behavior. - New CLI's typescript-bindings-generated libraries now return an `AssembledTransaction`, which has a `result` getter and a `signAndSend` method, as explained in stellar/stellar-cli#1034 - Use `stellar-sdk` rather than `soroban-client` - Use latest `@stellar/freighter-api`
- Pin soroban-cli to latest version, 20.1.0 - Update the contract's SDK version - **Copy in `abundance` source from `token` contract** at stellar/soroban-examples#277. Note that I **did not author most of the changes in the `contracts/abundance` folder**. I _only_ copied in the changes originally authored in the `soroban-examples` repo, then updated for the single tweak that this `abundance` contract already had: 1. comments on the `mint` method; 2. slightly modified `mint` behavior. - New CLI's typescript-bindings-generated libraries now return an `AssembledTransaction`, which has a `result` getter and a `signAndSend` method, as explained in stellar/stellar-cli#1034 - Use `stellar-sdk` rather than `soroban-client` - Use latest `@stellar/freighter-api`
- Pin soroban-cli to latest version, 20.1.0 - Update the contract's SDK version - **Copy in `abundance` source from `token` contract** at stellar/soroban-examples#277. Note that I **did not author most of the changes in the `contracts/abundance` folder**. I _only_ copied in the changes originally authored in the `soroban-examples` repo, then updated for the single tweak that this `abundance` contract already had: 1. comments on the `mint` method; 2. slightly modified `mint` behavior. - New CLI's typescript-bindings-generated libraries now return an `AssembledTransaction`, which has a `result` getter and a `signAndSend` method, as explained in stellar/stellar-cli#1034 - Use `stellar-sdk` rather than `soroban-client` - Use latest `@stellar/freighter-api`
- Pin soroban-cli to latest version, 20.1.1 - Update the contract's SDK version - **Copy in `abundance` source from `token` contract** at stellar/soroban-examples#277. Note that I **did not author most of the changes in the `contracts/abundance` folder**. I _only_ copied in the changes originally authored in the `soroban-examples` repo, then updated for the single tweak that this `abundance` contract already had: 1. comments on the `mint` method; 2. slightly modified `mint` behavior. - New CLI's typescript-bindings-generated libraries now return an `AssembledTransaction`, which has a `result` getter and a `signAndSend` method, as explained in stellar/stellar-cli#1034 - Use `stellar-sdk` rather than `soroban-client` - Use latest `@stellar/freighter-api`
Overview
Soroban, and Stellar more generally, supports having multiple parties sign the same transaction.
Prior to now, the libraries generated with
soroban contract bindings typescript
did not.This adds multi-auth support to the generated libraries, streamlining it as much as possible while adding minimal overhead to the "normal stuff" that most people will do with these libraries 98% of the time.
Read calls (simulation only)
The biggest change for view calls, which require only a simulation and no signing, is that you now need to get the
result
of a transaction:You can streamline this further using destructuring:
Or just call the variable
result
and it looks very clean:Write calls with one signer
For these, you now need to explicitly sign and send the transaction. This helps you build up the mental model that the transaction is first simulated, that this is good enough for view calls, and that you also need a
signAndSend
step if you want a write call to actually go through.This also allows these libraries to expose information and options in more expectable places, rather than cluttering global interfaces. Examples:
tx.isReadCall
– make explicit logic around read vs write callstx.signAndSend({ secondsToWait: 30 })
– specify how many seconds to wait for the transaction to complete (default: 10)tx.raw
– access the raw SorobanClient transaction that this object wrapstx.simulationData
– get the result of the simulationOnce you
signAndSend()
, the object you get back has different fields that are more relevant to the signing and sending behavior. See SentTransaction for more information.Write calls with >1 signer
Let's consider an Atomic Swap contract. Alice wants to give 10 of her Token A tokens to Bob for 5 of his Token B tokens.
Let's say Alice is also going to be the one signing the final transaction envelope, meaning she is the invoker. So your app, from Alice's browser, simulates the
swap
call:But your app can't
signAndSend
this right away, because Bob needs to sign it first. You can check this:You can verify that
whoElseNeedsToSign
is an array of length1
, containing only Bob's public key.Then, still on Alice's machine, you can serialize the transaction-under-assembly:
And now you need to send it to Bob's browser. How you do this depends on your app. Maybe you send it to a server first, maybe you use WebSockets, or maybe you have Alice text the JSON blob to Bob and have him paste it into your app in his browser (note: this option might be error-prone 😄).
Once you get the JSON blob into your app on Bob's machine, you can deserialize it:
And have Bob sign it. What Bob will actually need to sign is some auth entries within the transaction, not the transaction itself or the transaction envelope. Your app can verify that Bob has the correct wallet selected in Freighter, then:
Under the hood, this uses
signAuthEntry
from the injectedwallet
(@stellar/freighter-api
by default).Now Bob can again serialize the transaction and send back to Alice, where she can finally
signAndSend()
.To see an even more complicated example, where Alice swaps with Bob but the transaction is invoked by yet another party, check out the new test-swap.ts
All the nitty gritty details
Here's a full(er) accounting of everything that changed here:
ts-tests/package.json
to aninitialize.sh
script thatuses a
.env
if available or defaults to environment variables. Asbefore, this will build, deploy, and generate bindings for the new
contracts, plus creating an
alice
identity and minting separateamounts of two separate tokens to the
root
user andalice
await
sso that all tests can pass when run in parallel
atomic_swap
andtoken
contracts fromhttps://github.com/stellar/soroban-examples to
test-wasms
https://github.com/stellar/soroban-react-atomic-swap
bindings typescript
-generatedlibraries:
new AssembledTransaction
, a class that has aresult
getter that can be used to get the result of the simulationright away, or can be used to
await tx.signAndSend()
, which thenreturns a
SentTransaction
SentTransaction
contains all possibly-relevant fieldsfrom the logic it performs, such as
sendTransactionAll
AssembledTransaction
has aneedsNonInvokerSigningBy()
getterand a
signAuthEntriesFor(publicKey, signingFunction)
to facilitatemulti-auth workflows.
users' browsers, you can also call
json = tx.toJSON()
on anAssembledTransaction
and thencontract.fromJSON[method](json)
onthe next machine to continue signing, as shown in
test-swap.ts