track required signers within type system
harrysolovay opened this issue · comments
Could we track specific PublicKey
s / AccountUpdate
s within the type system and use this type information to provide errors when required PrivateKey
s are not supplied to sign
?
Instead defining methods like so:
@method
async setAdmin() {
const admin = this.admin.getAndRequireEquals()
AccountUpdate.createSigned(admin)
this.admin.set(admin)
}
We could use generators and yield account update statements. This way, the signature of setAdmin
contains types returned from the createSigned
call.
@method
*setAdmin() {
const admin = this.admin.getAndRequireEquals()
yield AccountUpdate.createSigned(admin)
this.admin.set(admin)
}
We'd need a unique symbol with which to later specify the key of admin
. I would imagine that one would attach this symbol to the given PublicKey
type.
const adminKey = Symbol()
//
class MyContract {
@state(PublicKey) admin = state<PublicKey<typeof adminKey>>()
// ...
}
Finally, one would sign with a record like so.
tx.sign({
[adminKey]: admin.privateKey
})
Note: devs could tag their
PublicKey
s with anykeyof any
.
If the dev forgets to include the given private key...
Argument of type '{}' is not assignable to parameter of type '{ [adminKey]: PrivateKey; }'.
Property '[adminKey]' is missing in type '{}' but required in type '{ [adminKey]: PrivateKey; }'.ts(2345)
One noteworthy caveat, nested method calls would need to be yield*
ed.
@method
*a() {
// ...
}
@method
*b() {
const aResult = yield* this.a()
}
As I reflect on this issue, I feel less and less confident that this would be a usability gain. The narrower typing of sign
likely isn't worth scaring off generator-opposed devs, nor the internal refactoring that would need to take place. Also, signing will likely be handled in other envs such as wallets. Still going to submit this issue, incase it's thought provoking. Please feel free to close immediately :)