-
Notifications
You must be signed in to change notification settings - Fork 91
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
sdk: allow delegates in single client #432
Conversation
sdk/src/driftClient.ts
Outdated
@@ -154,8 +155,8 @@ export class DriftClient { | |||
); | |||
|
|||
this.authority = config.authority ?? this.wallet.publicKey; | |||
const subAccountIds = config.subAccountIds ?? [0]; | |||
this.activeSubAccountId = config.activeSubAccountId ?? subAccountIds[0]; | |||
this.activeSubAccountId = config.activeSubAccountId; |
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.
why'd you get rid of the ?? [0]
?
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.
this way it will start undefined if not specified, then the call to addUsers
will know no default is set and use the first user
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.
i think this might break some backwards compatibility since not every user will call addUsers
sdk/src/driftClient.ts
Outdated
this.createUsers(subAccountIds, this.userAccountSubscriptionConfig); | ||
|
||
// load all or some users and add them to the driftClient | ||
this.addAllUsers( |
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.
i dont think we want to do any async calls in the constructor, thats why the createUsers
call didn't call subscribe before
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.
maybe we have a new DriftClientConfig Param which is authoritySubaccountMap
which allows you to specify the authority & subaccount pairs
sdk/src/tx/retryTxSender.ts
Outdated
@@ -56,7 +56,7 @@ export class RetryTxSender implements TxSender { | |||
opts = this.provider.opts; | |||
} | |||
|
|||
const signedTx = preSigned | |||
const signedTx = preSigned && tx.feePayer |
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.
if it's preSigned, why would it not have a feePayer? seems like there is an issue upstream?
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.
no issue, just sort of a redundancy check but i can remove
sdk/src/driftClient.ts
Outdated
const userAccounts = await this.getUserAccountsForAuthority(this.authority); | ||
public async addAllUsers( | ||
subAccountIds?: number[], | ||
setFirstActive?: boolean, |
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.
when do you set this true
versus false
, trying to understand when we'd use it
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.
at the moment if the user passes a subaccount id to the constructor or updateWallet it defaults the user to that, if not then this flag is true and it defaults to the first user
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.
i feel like the constructor always needs to set the activeSubAccount for backwards compatability
sdk/src/driftClient.ts
Outdated
for (const userAccount of userAccounts) { | ||
await this.addUser(userAccount.subAccountId); | ||
this.addUser(userAccount.subAccountId, this.authority); |
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.
not having await
for these addUser will lead to race conditions?
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.
didn't have any race condition issues with it and tested a lot, wanted to make it faster, will add back
sdk/src/driftClient.ts
Outdated
public async addAllUsers( | ||
subAccountIds?: number[], | ||
setFirstActive?: boolean, | ||
includeDelegates?: boolean |
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.
couldn't you just check that if the this.authority == wallet.pubkey to decide if the user has delegate set?
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.
not sure what you mean by this, this flag indicates we want to load any/all of the accounts delegated to an authority as part of their subscribed driftclient users
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.
yeah i don't think my comment made sense, nvm
sdk/src/driftClient.ts
Outdated
public async addAllUsers(): Promise<void> { | ||
const userAccounts = await this.getUserAccountsForAuthority(this.authority); | ||
public async addAllUsers( | ||
subAccountIds?: number[], |
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.
is this just for the constructor? would be nice if we didn't need to add this as it'd make the function less confusing
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.
it's to allow them to only subscribe to a subset of subaccount ids
sdk/src/driftClient.ts
Outdated
this.userStatsAccountPublicKey = undefined; | ||
|
||
this.users.clear(); | ||
await this.addAllUsers( |
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.
why are you adding the users before the unsubscribe? feel like this is backwards?
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.
mistake, not sure how it wasn't breaking anything
sdk/src/driftClient.ts
Outdated
this.userStatsAccountPublicKey = undefined; | ||
this.users.clear(); | ||
|
||
await this.addAndSubscribeToUsers( |
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.
why'd you move this out of the this.isSubscribed
block? feel like it makes sense to only re-subscribe if you were already subscribed
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.
i think isSubscribed
would still be true from the driftclient being initialized?
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.
this isSubscribed
doesnt get set in the constructor, just if you call subscribe, so it could not be set? why'd you need to move this re-subscribe outta the if block?
sdk/src/driftClient.ts
Outdated
this.accountSubscriber.subscribe() | ||
); | ||
let subscribePromises = [ | ||
this.addAndSubscribeToUsers( |
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.
all the parameters for this function exist on the DriftClient, do you need to pass em as parameters?
sdk/src/driftClientConfig.ts
Outdated
@@ -20,6 +20,8 @@ export type DriftClientConfig = { | |||
env?: DriftEnv; | |||
userStats?: boolean; | |||
authority?: PublicKey; // explicitly pass an authority if signer is delegate | |||
includeDelegates?: boolean; // flag for whether to load delegate accounts as well | |||
authoritySubaccountMap?: [string, number][]; // if passed this will override subAccountIds and includeDelegates |
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.
should it be a PublicKey instead of string
nice job adding comments 🙏
sdk/src/driftClient.ts
Outdated
@@ -129,6 +130,9 @@ export class DriftClient { | |||
authority: PublicKey; | |||
marketLookupTable: PublicKey; | |||
lookupTableAccount: AddressLookupTableAccount; | |||
subAccountIds?: number[]; | |||
includeDelegates?: boolean; | |||
authoritySubaccountMap?: [string, number][]; |
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.
I'm thinking we only have authoritySubaccountMap
and get rid of the subAccountIds
on the actual DriftClient. If the user passes the subAccounts, we just default to creating the map for them given the authority?
sdk/src/driftClient.ts
Outdated
this.userStatsAccountPublicKey = undefined; | ||
this.users.clear(); | ||
|
||
await this.addAndSubscribeToUsers( |
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.
this isSubscribed
doesnt get set in the constructor, just if you call subscribe, so it could not be set? why'd you need to move this re-subscribe outta the if block?
const userAccounts = await this.getUserAccountsForAuthority(this.authority); | ||
for (const userAccount of userAccounts) { | ||
await this.addUser(userAccount.subAccountId); | ||
public async addAndSubscribeToUsers(): Promise<boolean> { |
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.
For this, i'm thinking if we've made the change to just have the DriftClient to only have the map:
- if the map isn't empty, add the users based on the authority + sub account ids in the map
- if it is empty, make the call to getUserAccountsForAuthority/getUserAccountsForDelegates
I think this is desierable because the calls to getUserAccountsForAuthority
and getUserAccountsForDelegate
make getProgramAccount rpc calls, which can be expensive, so good to avoid em if we can
sdk/src/driftClient.ts
Outdated
const subAccountIds = config.subAccountIds ?? [0]; | ||
this.activeSubAccountId = config.activeSubAccountId ?? subAccountIds[0]; | ||
this.activeSubAccountId = config.activeSubAccountId ?? 0; | ||
this.authoritySubaccountMap = config.authoritySubaccountMap ?? undefined; |
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.
think you can get rid of this since you reset it below
sdk/src/driftClient.ts
Outdated
? config.authoritySubaccountMap | ||
: config.subAccountIds | ||
? config.subAccountIds.map((acctId) => [this.authority, acctId]) | ||
: undefined; |
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.
is it possible we just set it as empty if they don't pass anything? all else equal, nice to avoid undefined/null
for (const account of userAccounts.concat(delegatedAccounts)) { | ||
result = | ||
result && | ||
(await this.addUser(account.subAccountId, account.authority)); |
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.
we made it so you can pass in a UserAccount object to user.subscribe to speed up the subscribe logic, we should probably use that here since we already have all the UserAccounts (we can do this in a separate pr later)
sdk/src/driftClient.ts
Outdated
@@ -129,6 +130,8 @@ export class DriftClient { | |||
authority: PublicKey; | |||
marketLookupTable: PublicKey; | |||
lookupTableAccount: AddressLookupTableAccount; | |||
includeDelegates?: boolean; | |||
authoritySubaccountMap?: [PublicKey, number][]; |
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.
sorry last nit pit, should this be a map instead of an array of arrays? if you wanted multiple sub accounts from same pub key, you'd have to do something like:
[
[Pubkey.default(), 0],
[Pubkey.default(), 1],
[Pubkey.default(), 2],
]
with a map it'd be:
new Map([
[Pubkey.default(), [0, 1, 2]]
])
(I think it'd be to be Map<string, number[]> since PublicKey doesnt really work as a key)
Tried to make this as backwards compatible as possible, consumers of the SDK shouldn't need to update unless they were accessing the
driftClient.users
map directly (instead of using something likedriftClient.getUsers()
. Basically with the possibility of delegate accounts sharing the same id as user accounts now, user map is now keyed off a string in the format of "[subAccountId]_[authority]"Consumers will need to pass
includeDelegates
flag in the driftClientConfig (and toupdateWallet
) to have those accounts loaded and subscribed to. Can change this to load them by default if necessary